Home | History | Annotate | Download | only in src
      1 #ifdef HAVE_CONFIG_H
      2 #include <config.h>
      3 #endif
      4 
      5 #ifdef WANT_XTI
      6 #ifndef lint
      7 char	nettest_xti_id[]="\
      8 @(#)nettest_xti.c (c) Copyright 1995-2012 Hewlett-Packard Co. Version 2.6.0";
      9 #else
     10 #define DIRTY
     11 #define WANT_HISTOGRAM
     12 #define WANT_INTERVALS
     13 #endif /* lint */
     14 
     15 #ifdef WIN32
     16 #error XTI Interface tests are not available under Windows
     17 #endif
     18 
     19 /****************************************************************/
     20 /*								*/
     21 /*	nettest_xti.c						*/
     22 /*								*/
     23 /*      the XTI args parsing routine...                         */
     24 /*                                                              */
     25 /*      scan_xti_args()                                         */
     26 /*                                                              */
     27 /*	the actual test routines...				*/
     28 /*								*/
     29 /*	send_xti_tcp_stream()	perform a tcp stream test	*/
     30 /*	recv_xti_tcp_stream()					*/
     31 /*	send_xti_tcp_rr()	perform a tcp request/response	*/
     32 /*	recv_xti_tcp_rr()					*/
     33 /*      send_xti_tcp_conn_rr()  an RR test including connect    */
     34 /*      recv_xti_tcp_conn_rr()                                  */
     35 /*	send_xti_udp_stream()	perform a udp stream test	*/
     36 /*	recv_xti_udp_stream()					*/
     37 /*	send_xti_udp_rr()	perform a udp request/response	*/
     38 /*	recv_xti_udp_rr()					*/
     39 /*								*/
     40 /****************************************************************/
     41 
     42 #ifdef HAVE_CONFIG_H
     43 #include <config.h>
     44 #endif
     45 
     46 #include <sys/types.h>
     47 #include <fcntl.h>
     48 #include <sys/ipc.h>
     49 #include <sys/socket.h>
     50 #include <netinet/in.h>
     51 #include <netdb.h>
     52 #include <errno.h>
     53 #include <signal.h>
     54 #include <stdio.h>
     55 #include <time.h>
     56 #include <malloc.h>
     57  /* xti.h should be included *after* in.h because there are name */
     58  /* conflicts!( Silly standards people... raj 2/95 fortuenately, the */
     59  /* confilcts are on IP_TOP and IP_TTL, whcih netperf does not yet use */
     60 #include <xti.h>
     61 
     62 #include "netlib.h"
     63 #include "netsh.h"
     64 #include "nettest_xti.h"
     65 
     66 #ifdef WANT_HISTOGRAM
     67 #ifdef __sgi
     68 #include <sys/time.h>
     69 #endif /* __sgi */
     70 #include "hist.h"
     71 #endif /* WANT_HISTOGRAM */
     72 
     73 
     74 
     76  /* these variables are specific to the XTI sockets tests. declare */
     77  /* them static to make them global only to this file. */
     78 
     79 static int
     80   rss_size,		/* remote socket send buffer size	*/
     81   rsr_size,		/* remote socket recv buffer size	*/
     82   lss_size,		/* local  socket send buffer size 	*/
     83   lsr_size,		/* local  socket recv buffer size 	*/
     84   req_size = 1,		/* request size                   	*/
     85   rsp_size = 1,		/* response size			*/
     86   send_size,		/* how big are individual sends		*/
     87   recv_size;		/* how big are individual receives	*/
     88 
     89 static  int   confidence_iteration;
     90 static  char  local_cpu_method;
     91 static  char  remote_cpu_method;
     92 
     93  /* different options for the xti				*/
     94 
     95 static int
     96   loc_nodelay,		/* don't/do use NODELAY	locally		*/
     97   rem_nodelay,		/* don't/do use NODELAY remotely	*/
     98   loc_sndavoid,		/* avoid send copies locally		*/
     99   loc_rcvavoid,		/* avoid recv copies locally		*/
    100   rem_sndavoid,		/* avoid send copies remotely		*/
    101   rem_rcvavoid;		/* avoid recv_copies remotely		*/
    102 
    103 static struct t_info info_struct;
    104 
    105 #ifdef WANT_HISTOGRAM
    106 #ifdef HAVE_GETHRTIME
    107 hrtime_t time_one;
    108 hrtime_t time_two;
    109 #else
    110 static struct timeval time_one;
    111 static struct timeval time_two;
    112 #endif /* HAVE_GETHRTIME */
    113 static HIST time_hist;
    114 #endif /* WANT_HISTOGRAM */
    115 
    116 static char loc_xti_device[32] = "/dev/tcp";
    117 static char rem_xti_device[32] = "/dev/tcp";
    118 
    119 static int  xti_flags = 0;
    120 
    121 char xti_usage[] = "\n\
    122 Usage: netperf [global options] -- [test options] \n\
    123 \n\
    124 TCP/UDP XTI API Test Options:\n\
    125     -D [L][,R]        Set XTI_TCP_NODELAY locally and/or remotely (XTI_TCP_*)\n\
    126     -h                Display this text\n\
    127     -m bytes          Set the send size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
    128     -M bytes          Set the recv size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
    129     -r bytes          Set request size (XTI_TCP_RR, XTI_UDP_RR)\n\
    130     -R bytes          Set response size (XTI_TCP_RR, XTI_UDP_RR)\n\
    131     -s send[,recv]    Set local socket send/recv buffer sizes\n\
    132     -S send[,recv]    Set remote socket send/recv buffer sizes\n\
    133     -X dev[,dev]      Set the local/remote XTI device file name\n\
    134 \n\
    135 For those options taking two parms, at least one must be specified;\n\
    136 specifying one value without a comma will set both parms to that\n\
    137 value, specifying a value with a leading comma will set just the second\n\
    138 parm, a value with a trailing comma will set just the first. To set\n\
    139 each parm to unique values, specify both and separate them with a\n\
    140 comma.\n";
    141 
    142 
    143  /* This routine is intended to retrieve interesting aspects of tcp */
    145  /* for the data connection. at first, it attempts to retrieve the */
    146  /* maximum segment size. later, it might be modified to retrieve */
    147  /* other information, but it must be information that can be */
    148  /* retrieved quickly as it is called during the timing of the test. */
    149  /* for that reason, a second routine may be created that can be */
    150  /* called outside of the timing loop */
    151 void
    152 get_xti_info(socket, info_struct)
    153      int socket;
    154      struct t_info *info_struct;
    155 {
    156 
    157 }
    158 
    159 
    160  /* This routine will create a data (listen) socket with the apropriate */
    162  /* options set and return it to the caller. this replaces all the */
    163  /* duplicate code in each of the test routines and should help make */
    164  /* things a little easier to understand. since this routine can be */
    165  /* called by either the netperf or netserver programs, all output */
    166  /* should be directed towards "where." family is generally AF_INET, */
    167  /* and type will be either SOCK_STREAM or SOCK_DGRAM */
    168 SOCKET
    169 create_xti_endpoint(char *name)
    170 {
    171 
    172   SOCKET temp_socket;
    173 
    174   struct t_optmgmt *opt_req;  /* we request an option */
    175   struct t_optmgmt *opt_ret;  /* it tells us what we got */
    176 
    177   /* we use this to pass-in BSD-like socket options through t_optmgmt. */
    178   /* it ends up being about as clear as mud. raj 2/95 */
    179   struct sock_option {
    180     struct t_opthdr myopthdr;
    181     long value;
    182   } *sock_option;
    183 
    184   if (debug) {
    185     fprintf(where,"create_xti_endpoint: attempting to open %s\n",
    186 	    name);
    187     fflush(where);
    188   }
    189 
    190   /*set up the data socket                        */
    191   temp_socket = t_open(name,O_RDWR,NULL);
    192 
    193   if (temp_socket == INVALID_SOCKET){
    194     fprintf(where,
    195 	    "netperf: create_xti_endpoint: t_open %s: errno %d t_errno %d\n",
    196 	    name,
    197 	    errno,
    198 	    t_errno);
    199     fflush(where);
    200     exit(1);
    201   }
    202 
    203   if (debug) {
    204     fprintf(where,"create_xti_endpoint: socket %d obtained...\n",temp_socket);
    205     fflush(where);
    206   }
    207 
    208   /* allocate what we need for option mgmt */
    209   if ((opt_req = (struct t_optmgmt *)t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
    210       NULL) {
    211     fprintf(where,
    212 	    "netperf: create_xti_endpoint: t_alloc: opt_req errno %d\n",
    213 	    errno);
    214     fflush(where);
    215     exit(1);
    216   }
    217 
    218   if (debug) {
    219     fprintf(where,
    220 	    "create_xti_endpoint: opt_req->opt.buf %x maxlen %d len %d\n",
    221 	    opt_req->opt.buf,
    222 	    opt_req->opt.maxlen,
    223 	    opt_req->opt.len);
    224 
    225     fflush(where);
    226   }
    227 
    228   if ((opt_ret = (struct t_optmgmt *) t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
    229       NULL) {
    230     fprintf(where,
    231 	    "netperf: create_xti_endpoint: t_alloc: opt_ret errno %d\n",
    232 	    errno);
    233     fflush(where);
    234     exit(1);
    235   }
    236 
    237   if (debug) {
    238     fprintf(where,
    239 	    "create_xti_endpoint: opt_ret->opt.buf %x maxlen %d len %d\n",
    240 	    opt_ret->opt.buf,
    241 	    opt_ret->opt.maxlen,
    242 	    opt_ret->opt.len);
    243     fflush(where);
    244   }
    245 
    246   /* Modify the local socket size. The reason we alter the send buffer */
    247   /* size here rather than when the connection is made is to take care */
    248   /* of decreases in buffer size. Decreasing the window size after */
    249   /* connection establishment is a TCP no-no. Also, by setting the */
    250   /* buffer (window) size before the connection is established, we can */
    251   /* control the TCP MSS (segment size). The MSS is never more that 1/2 */
    252   /* the minimum receive buffer size at each half of the connection. */
    253   /* This is why we are altering the receive buffer size on the sending */
    254   /* size of a unidirectional transfer. If the user has not requested */
    255   /* that the socket buffers be altered, we will try to find-out what */
    256   /* their values are. If we cannot touch the socket buffer in any way, */
    257   /* we will set the values to -1 to indicate that.  */
    258 
    259 #ifdef XTI_SNDBUF
    260   if (lss_size > 0) {
    261     /* we want to "negotiate" the option */
    262     opt_req->flags = T_NEGOTIATE;
    263   }
    264   else {
    265     /* we want to accept the default, and know what it is. I assume */
    266     /* that when nothing has been changed, that T_CURRENT will return */
    267     /* the same as T_DEFAULT raj 3/95 */
    268     opt_req->flags = T_CURRENT;
    269   }
    270 
    271   /* the first part is for the netbuf that holds the option we want */
    272   /* to negotiate or check */
    273   /* the buffer of the netbuf points at the socket options structure */
    274 
    275   /* we assume that the t_alloc call allocated a buffer that started */
    276   /* on a proper alignment */
    277   sock_option = (struct sock_option *)opt_req->opt.buf;
    278 
    279   /* and next, set the fields in the sock_option structure */
    280   sock_option->myopthdr.level = XTI_GENERIC;
    281   sock_option->myopthdr.name  = XTI_SNDBUF;
    282   sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
    283   sock_option->value        = lss_size;
    284 
    285   opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
    286 
    287   /* now, set-up the stuff to return the value in the end */
    288   /* we assume that the t_alloc call allocated a buffer that started */
    289   /* on a proper alignment */
    290   sock_option = (struct sock_option *)opt_ret->opt.buf;
    291 
    292   /* finally, call t_optmgmt. clear as mud. */
    293   if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
    294     fprintf(where,
    295 	    "netperf: create_xti_endpoint: XTI_SNDBUF option: t_errno %d\n",
    296 	    t_errno);
    297     fflush(where);
    298     exit(1);
    299   }
    300 
    301   if (sock_option->myopthdr.status == T_SUCCESS) {
    302     lss_size = sock_option->value;
    303   }
    304   else {
    305     fprintf(where,"create_xti_endpoint: XTI_SNDBUF option status 0x%.4x",
    306 	    sock_option->myopthdr.status);
    307     fprintf(where," value %d\n",
    308 	    sock_option->value);
    309     fflush(where);
    310     lss_size = -1;
    311   }
    312 
    313   if (lsr_size > 0) {
    314     /* we want to "negotiate" the option */
    315     opt_req->flags = T_NEGOTIATE;
    316   }
    317   else {
    318     /* we want to accept the default, and know what it is. I assume */
    319     /* that when nothing has been changed, that T_CURRENT will return */
    320     /* the same as T_DEFAULT raj 3/95 */
    321     opt_req->flags = T_CURRENT;
    322   }
    323 
    324   /* the first part is for the netbuf that holds the option we want */
    325   /* to negotiate or check */
    326   /* the buffer of the netbuf points at the socket options structure */
    327 
    328   /* we assume that the t_alloc call allocated a buffer that started */
    329   /* on a proper alignment */
    330   sock_option = (struct sock_option *)opt_req->opt.buf;
    331 
    332   /* and next, set the fields in the sock_option structure */
    333   sock_option->myopthdr.level = XTI_GENERIC;
    334   sock_option->myopthdr.name  = XTI_RCVBUF;
    335   sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
    336   sock_option->value        = lsr_size;
    337 
    338   opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
    339 
    340   /* now, set-up the stuff to return the value in the end */
    341   /* we assume that the t_alloc call allocated a buffer that started */
    342   /* on a proper alignment */
    343   sock_option = (struct sock_option *)opt_ret->opt.buf;
    344 
    345   /* finally, call t_optmgmt. clear as mud. */
    346   if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
    347     fprintf(where,
    348 	    "netperf: create_xti_endpoint: XTI_RCVBUF option: t_errno %d\n",
    349 	    t_errno);
    350     fflush(where);
    351     exit(1);
    352   }
    353   lsr_size = sock_option->value;
    354 
    355   /* this needs code */
    356 
    357   if (debug) {
    358     fprintf(where,"netperf: create_xti_endpoint: socket sizes determined...\n");
    359     fprintf(where,"                       send: %d recv: %d\n",
    360 	    lss_size,lsr_size);
    361     fflush(where);
    362   }
    363 
    364 #else /* XTI_SNDBUF */
    365 
    366   lss_size = -1;
    367   lsr_size = -1;
    368 
    369 #endif /* XTI_SNDBUF */
    370 
    371   /* now, we may wish to enable the copy avoidance features on the */
    372   /* local system. of course, this may not be possible... */
    373 
    374   if (loc_rcvavoid) {
    375     fprintf(where,
    376 	    "netperf: create_xti_endpoint: Could not enable receive copy avoidance");
    377     fflush(where);
    378     loc_rcvavoid = 0;
    379   }
    380 
    381   if (loc_sndavoid) {
    382     fprintf(where,
    383 	    "netperf: create_xti_endpoint: Could not enable send copy avoidance");
    384     fflush(where);
    385     loc_sndavoid = 0;
    386   }
    387 
    388   /* Now, we will see about setting the TCP_NODELAY flag on the local */
    389   /* socket. We will only do this for those systems that actually */
    390   /* support the option. If it fails, note the fact, but keep going. */
    391   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
    392   /* will cause an error to be displayed */
    393 
    394 #ifdef TCP_NODELAY
    395   if ((strcmp(test_name,"XTI_TCP_STREAM") == 0) ||
    396       (strcmp(test_name,"XTI_TCP_RR") == 0) ||
    397       (strcmp(test_name,"XTI_TCP_CRR") == 0)) {
    398     if (loc_nodelay) {
    399       /* we want to "negotiate" the option */
    400       opt_req->flags = T_NEGOTIATE;
    401     }
    402     else {
    403       /* we want to accept the default, and know what it is. I assume */
    404       /* that when nothing has been changed, that T_CURRENT will return */
    405       /* the same as T_DEFAULT raj 3/95 */
    406       opt_req->flags = T_CURRENT;
    407     }
    408 
    409     /* the first part is for the netbuf that holds the option we want */
    410     /* to negotiate or check the buffer of the netbuf points at the */
    411     /* socket options structure */
    412 
    413     /* we assume that the t_alloc call allocated a buffer that started */
    414     /* on a proper alignment */
    415     sock_option = (struct sock_option *)opt_req->opt.buf;
    416 
    417     /* and next, set the fields in the sock_option structure */
    418     sock_option->myopthdr.level = INET_TCP;
    419     sock_option->myopthdr.name  = TCP_NODELAY;
    420     sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
    421     sock_option->value          = T_YES;
    422 
    423     opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
    424 
    425     /* now, set-up the stuff to return the value in the end */
    426     /* we assume that the t_alloc call allocated a buffer that started */
    427     /* on a proper alignment */
    428     sock_option = (struct sock_option *)opt_ret->opt.buf;
    429 
    430     /* finally, call t_optmgmt. clear as mud. */
    431     if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
    432       fprintf(where,
    433 	      "create_xti_endpoint: TCP_NODELAY option: errno %d t_errno %d\n",
    434 	      errno,
    435 	      t_errno);
    436       fflush(where);
    437       exit(1);
    438     }
    439     loc_nodelay = sock_option->value;
    440   }
    441 #else /* TCP_NODELAY */
    442 
    443   loc_nodelay = 0;
    444 
    445 #endif /* TCP_NODELAY */
    446 
    447   return(temp_socket);
    448 
    449 }
    450 
    451 
    452 /* This routine implements the TCP unidirectional data transfer test */
    454 /* (a.k.a. stream) for the xti interface. It receives its */
    455 /* parameters via global variables from the shell and writes its */
    456 /* output to the standard output. */
    457 
    458 
    459 void
    460 send_xti_tcp_stream(char remote_host[])
    461 {
    462 
    463   char *tput_title = "\
    464 Recv   Send    Send                          \n\
    465 Socket Socket  Message  Elapsed              \n\
    466 Size   Size    Size     Time     Throughput  \n\
    467 bytes  bytes   bytes    secs.    %s/sec  \n\n";
    468 
    469   char *tput_fmt_0 =
    470     "%7.2f\n";
    471 
    472   char *tput_fmt_1 =
    473     "%6d %6d %6d    %-6.2f   %7.2f   \n";
    474 
    475   char *cpu_title = "\
    476 Recv   Send    Send                          Utilization       Service Demand\n\
    477 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
    478 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
    479 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
    480 
    481   char *cpu_fmt_0 =
    482     "%6.3f %c\n";
    483 
    484   char *cpu_fmt_1 =
    485     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
    486 
    487   char *ksink_fmt = "\n\
    488 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
    489 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
    490 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
    491 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
    492 
    493   char *ksink_fmt2 = "\n\
    494 Maximum\n\
    495 Segment\n\
    496 Size (bytes)\n\
    497 %6d\n";
    498 
    499 
    500   float			elapsed_time;
    501 
    502 #ifdef WANT_INTERVALS
    503   int interval_count;
    504   sigset_t signal_set;
    505 #endif
    506 
    507   /* what we want is to have a buffer space that is at least one */
    508   /* send-size greater than our send window. this will insure that we */
    509   /* are never trying to re-use a buffer that may still be in the hands */
    510   /* of the transport. This buffer will be malloc'd after we have found */
    511   /* the size of the local senc socket buffer. We will want to deal */
    512   /* with alignment and offset concerns as well. */
    513 
    514   int	*message_int_ptr;
    515 
    516   struct ring_elt *send_ring;
    517 
    518   int len;
    519   unsigned int nummessages;
    520   SOCKET send_socket;
    521   int bytes_remaining;
    522   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
    523 
    524   /* with links like fddi, one can send > 32 bits worth of bytes */
    525   /* during a test... ;-) at some point, this should probably become a */
    526   /* 64bit integral type, but those are not entirely common yet */
    527 
    528   double	bytes_sent;
    529 
    530   float	local_cpu_utilization;
    531   float	local_service_demand;
    532   float	remote_cpu_utilization;
    533   float	remote_service_demand;
    534 
    535   double	thruput;
    536 
    537   /* some addressing information */
    538   struct	hostent	        *hp;
    539   struct	sockaddr_in	server;
    540   unsigned      int             addr;
    541 
    542   struct t_call server_call;
    543 
    544   struct	xti_tcp_stream_request_struct	*xti_tcp_stream_request;
    545   struct	xti_tcp_stream_response_struct	*xti_tcp_stream_response;
    546   struct	xti_tcp_stream_results_struct	*xti_tcp_stream_result;
    547 
    548   xti_tcp_stream_request  =
    549     (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
    550   xti_tcp_stream_response =
    551     (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
    552   xti_tcp_stream_result   =
    553     (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
    554 
    555 #ifdef WANT_HISTOGRAM
    556   time_hist = HIST_new();
    557 #endif /* WANT_HISTOGRAM */
    558   /* since we are now disconnected from the code that established the */
    559   /* control socket, and since we want to be able to use different */
    560   /* protocols and such, we are passed the name of the remote host and */
    561   /* must turn that into the test specific addressing information. */
    562 
    563   bzero((char *)&server,
    564 	sizeof(server));
    565 
    566   /* it would seem that while HP-UX will allow an IP address (as a */
    567   /* string) in a call to gethostbyname, other, less enlightened */
    568   /* systems do not. fix from awjacks (at) ca.sandia.gov raj 10/95 */
    569   /* order changed to check for IP address first. raj 7/96 */
    570 
    571   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
    572     /* it was not an IP address, try it as a name */
    573     if ((hp = gethostbyname(remote_host)) == NULL) {
    574       /* we have no idea what it is */
    575       fprintf(where,
    576 	      "establish_control: could not resolve the destination %s\n",
    577 	      remote_host);
    578       fflush(where);
    579       exit(1);
    580     }
    581     else {
    582       /* it was a valid remote_host */
    583       bcopy(hp->h_addr,
    584 	    (char *)&server.sin_addr,
    585 	    hp->h_length);
    586       server.sin_family = hp->h_addrtype;
    587     }
    588   }
    589   else {
    590     /* it was a valid IP address */
    591     server.sin_addr.s_addr = addr;
    592     server.sin_family = AF_INET;
    593   }
    594 
    595   if ( print_headers ) {
    596     /* we want to have some additional, interesting information in */
    597     /* the headers. we know some of it here, but not all, so we will */
    598     /* only print the test title here and will print the results */
    599     /* titles after the test is finished */
    600     fprintf(where,"XTI TCP STREAM TEST");
    601     fprintf(where," to %s", remote_host);
    602     if (iteration_max > 1) {
    603       fprintf(where,
    604 	      " : +/-%3.1f%% @ %2d%% conf.",
    605 	      interval/0.02,
    606 	      confidence_level);
    607       }
    608     if (loc_nodelay || rem_nodelay) {
    609       fprintf(where," : nodelay");
    610     }
    611     if (loc_sndavoid ||
    612 	loc_rcvavoid ||
    613 	rem_sndavoid ||
    614 	rem_rcvavoid) {
    615       fprintf(where," : copy avoidance");
    616     }
    617 #ifdef WANT_HISTOGRAM
    618     fprintf(where," : histogram");
    619 #endif /* WANT_HISTOGRAM */
    620 #ifdef WANT_INTERVALS
    621     fprintf(where," : interval");
    622 #endif /* WANT_INTERVALS */
    623 #ifdef DIRTY
    624     fprintf(where," : dirty data");
    625 #endif /* DIRTY */
    626     fprintf(where,"\n");
    627   }
    628 
    629   send_ring = NULL;
    630   confidence_iteration = 1;
    631   init_stat();
    632 
    633   /* we have a great-big while loop which controls the number of times */
    634   /* we run a particular test. this is for the calculation of a */
    635   /* confidence interval (I really should have stayed awake during */
    636   /* probstats :). If the user did not request confidence measurement */
    637   /* (no confidence is the default) then we will only go though the */
    638   /* loop once. the confidence stuff originates from the folks at IBM */
    639 
    640   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
    641 	 (confidence_iteration <= iteration_min)) {
    642 
    643     /* initialize a few counters. we have to remember that we might be */
    644     /* going through the loop more than once. */
    645 
    646     nummessages    =	0;
    647     bytes_sent     =	0.0;
    648     times_up       = 	0;
    649 
    650     /*set up the data socket                        */
    651     send_socket = create_xti_endpoint(loc_xti_device);
    652 
    653     if (send_socket == INVALID_SOCKET) {
    654       perror("netperf: send_xti_tcp_stream: tcp stream data socket");
    655       exit(1);
    656     }
    657 
    658     if (debug) {
    659       fprintf(where,"send_xti_tcp_stream: send_socket obtained...\n");
    660     }
    661 
    662     /* it would seem that with XTI, there is no implicit bind on a */
    663     /* connect, so we have to make a call to t_bind. this is not */
    664     /* terribly convenient, but I suppose that "standard is better */
    665     /* than better" :) raj 2/95 */
    666 
    667     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
    668       t_error("send_xti_tcp_stream: t_bind");
    669       exit(1);
    670     }
    671 
    672     /* at this point, we have either retrieved the socket buffer sizes, */
    673     /* or have tried to set them, so now, we may want to set the send */
    674     /* size based on that (because the user either did not use a -m */
    675     /* option, or used one with an argument of 0). If the socket buffer */
    676     /* size is not available, we will set the send size to 4KB - no */
    677     /* particular reason, just arbitrary... */
    678     if (send_size == 0) {
    679       if (lss_size > 0) {
    680 	send_size = lss_size;
    681       }
    682       else {
    683 	send_size = 4096;
    684       }
    685     }
    686 
    687     /* set-up the data buffer ring with the requested alignment and offset. */
    688     /* note also that we have allocated a quantity */
    689     /* of memory that is at least one send-size greater than our socket */
    690     /* buffer size. We want to be sure that there are at least two */
    691     /* buffers allocated - this can be a bit of a problem when the */
    692     /* send_size is bigger than the socket size, so we must check... the */
    693     /* user may have wanted to explicitly set the "width" of our send */
    694     /* buffers, we should respect that wish... */
    695 
    696     if (send_width == 0) {
    697       send_width = (lss_size/send_size) + 1;
    698       if (send_width == 1) send_width++;
    699     }
    700 
    701     if (send_ring == NULL) {
    702       /* only allocate the send ring once. this is a networking test, */
    703       /* not a memory allocation test. this way, we do not need a */
    704       /* deallocate_buffer_ring() routine, and I don't feel like */
    705       /* writing one anyway :) raj 11/94 */
    706       send_ring = allocate_buffer_ring(send_width,
    707 				       send_size,
    708 				       local_send_align,
    709 				       local_send_offset);
    710     }
    711 
    712     /* If the user has requested cpu utilization measurements, we must */
    713     /* calibrate the cpu(s). We will perform this task within the tests */
    714     /* themselves. If the user has specified the cpu rate, then */
    715     /* calibrate_local_cpu will return rather quickly as it will have */
    716     /* nothing to do. If local_cpu_rate is zero, then we will go through */
    717     /* all the "normal" calibration stuff and return the rate back. */
    718 
    719     if (local_cpu_usage) {
    720       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
    721     }
    722 
    723     /* Tell the remote end to do a listen. The server alters the socket */
    724     /* paramters on the other side at this point, hence the reason for */
    725     /* all the values being passed in the setup message. If the user did */
    726     /* not specify any of the parameters, they will be passed as 0, which */
    727     /* will indicate to the remote that no changes beyond the system's */
    728     /* default should be used. Alignment is the exception, it will */
    729     /* default to 1, which will be no alignment alterations. */
    730 
    731     netperf_request.content.request_type          = DO_XTI_TCP_STREAM;
    732     xti_tcp_stream_request->send_buf_size  = rss_size;
    733     xti_tcp_stream_request->recv_buf_size  = rsr_size;
    734     xti_tcp_stream_request->receive_size   = recv_size;
    735     xti_tcp_stream_request->no_delay       = rem_nodelay;
    736     xti_tcp_stream_request->recv_alignment = remote_recv_align;
    737     xti_tcp_stream_request->recv_offset    = remote_recv_offset;
    738     xti_tcp_stream_request->measure_cpu    = remote_cpu_usage;
    739     xti_tcp_stream_request->cpu_rate       = remote_cpu_rate;
    740     if (test_time) {
    741       xti_tcp_stream_request->test_length  = test_time;
    742     }
    743     else {
    744       xti_tcp_stream_request->test_length  = test_bytes;
    745     }
    746     xti_tcp_stream_request->so_rcvavoid    = rem_rcvavoid;
    747     xti_tcp_stream_request->so_sndavoid    = rem_sndavoid;
    748 
    749     strcpy(xti_tcp_stream_request->xti_device, rem_xti_device);
    750 
    751 #ifdef __alpha
    752 
    753     /* ok - even on a DEC box, strings are strings. I didn't really want */
    754     /* to ntohl the words of a string. since I don't want to teach the */
    755     /* send_ and recv_ _request and _response routines about the types, */
    756     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
    757     /* solution would be to use XDR, but I am still leary of being able */
    758     /* to find XDR libs on all platforms I want running netperf. raj */
    759     {
    760       int *charword;
    761       int *initword;
    762       int *lastword;
    763 
    764       initword = (int *) xti_tcp_stream_request->xti_device;
    765       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
    766 
    767       for (charword = initword;
    768 	   charword < lastword;
    769 	   charword++) {
    770 
    771 	*charword = ntohl(*charword);
    772       }
    773     }
    774 #endif /* __alpha */
    775 
    776 #ifdef DIRTY
    777     xti_tcp_stream_request->dirty_count         = rem_dirty_count;
    778     xti_tcp_stream_request->clean_count         = rem_clean_count;
    779 #endif /* DIRTY */
    780 
    781 
    782     if (debug > 1) {
    783       fprintf(where,
    784               "netperf: send_xti_tcp_stream: requesting TCP stream test\n");
    785     }
    786 
    787     send_request();
    788 
    789     /* The response from the remote will contain all of the relevant    */
    790     /* socket parameters for this test type. We will put them back into */
    791     /* the variables here so they can be displayed if desired.  The     */
    792     /* remote will have calibrated CPU if necessary, and will have done */
    793     /* all the needed set-up we will have calibrated the cpu locally    */
    794     /* before sending the request, and will grab the counter value right*/
    795     /* after the connect returns. The remote will grab the counter right*/
    796     /* after the accept call. This saves the hassle of extra messages   */
    797     /* being sent for the TCP tests.                                    */
    798 
    799     recv_response();
    800 
    801     if (!netperf_response.content.serv_errno) {
    802       if (debug)
    803         fprintf(where,"remote listen done.\n");
    804       rsr_size         = xti_tcp_stream_response->recv_buf_size;
    805       rss_size         = xti_tcp_stream_response->send_buf_size;
    806       rem_nodelay      = xti_tcp_stream_response->no_delay;
    807       remote_cpu_usage = xti_tcp_stream_response->measure_cpu;
    808       remote_cpu_rate  = xti_tcp_stream_response->cpu_rate;
    809 
    810       /* we have to make sure that the server port number is in */
    811       /* network order */
    812       server.sin_port   = (short)xti_tcp_stream_response->data_port_number;
    813       server.sin_port   = htons(server.sin_port);
    814       rem_rcvavoid      = xti_tcp_stream_response->so_rcvavoid;
    815       rem_sndavoid      = xti_tcp_stream_response->so_sndavoid;
    816     }
    817     else {
    818       Set_errno(netperf_response.content.serv_errno);
    819       perror("netperf: remote error");
    820 
    821       exit(1);
    822     }
    823 
    824     /*Connect up to the remote port on the data socket  */
    825     memset (&server_call, 0, sizeof(server_call));
    826     server_call.addr.maxlen = sizeof(struct sockaddr_in);
    827     server_call.addr.len    = sizeof(struct sockaddr_in);
    828     server_call.addr.buf    = (char *)&server;
    829 
    830     if (t_connect(send_socket,
    831 		  &server_call,
    832 		  NULL) == INVALID_SOCKET){
    833       t_error("netperf: send_xti_tcp_stream: data socket connect failed");
    834       printf(" port: %d\n",ntohs(server.sin_port));
    835       exit(1);
    836     }
    837 
    838     /* Data Socket set-up is finished. If there were problems, either */
    839     /* the connect would have failed, or the previous response would */
    840     /* have indicated a problem. I failed to see the value of the */
    841     /* extra  message after the accept on the remote. If it failed, */
    842     /* we'll see it here. If it didn't, we might as well start pumping */
    843     /* data. */
    844 
    845     /* Set-up the test end conditions. For a stream test, they can be */
    846     /* either time or byte-count based. */
    847 
    848     if (test_time) {
    849       /* The user wanted to end the test after a period of time. */
    850       times_up = 0;
    851       bytes_remaining = 0;
    852       /* in previous revisions, we had the same code repeated throught */
    853       /* all the test suites. this was unnecessary, and meant more */
    854       /* work for me when I wanted to switch to POSIX signals, so I */
    855       /* have abstracted this out into a routine in netlib.c. if you */
    856       /* are experiencing signal problems, you might want to look */
    857       /* there. raj 11/94 */
    858       start_timer(test_time);
    859     }
    860     else {
    861       /* The tester wanted to send a number of bytes. */
    862       bytes_remaining = test_bytes;
    863       times_up = 1;
    864     }
    865 
    866     /* The cpu_start routine will grab the current time and possibly */
    867     /* value of the idle counter for later use in measuring cpu */
    868     /* utilization and/or service demand and thruput. */
    869 
    870     cpu_start(local_cpu_usage);
    871 
    872 #ifdef WANT_INTERVALS
    873     if ((interval_burst) || (demo_mode)) {
    874       /* zero means that we never pause, so we never should need the */
    875       /* interval timer, unless we are in demo_mode */
    876       start_itimer(interval_wate);
    877     }
    878     interval_count = interval_burst;
    879     /* get the signal set for the call to sigsuspend */
    880     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
    881       fprintf(where,
    882               "send_xti_tcp_stream: unable to get sigmask errno %d\n",
    883               errno);
    884       fflush(where);
    885       exit(1);
    886     }
    887 #endif /* WANT_INTERVALS */
    888 
    889     /* before we start, initialize a few variables */
    890 
    891     /* We use an "OR" to control test execution. When the test is */
    892     /* controlled by time, the byte count check will always return false. */
    893     /* When the test is controlled by byte count, the time test will */
    894     /* always return false. When the test is finished, the whole */
    895     /* expression will go false and we will stop sending data. */
    896 
    897     while ((!times_up) || (bytes_remaining > 0)) {
    898 
    899 #ifdef DIRTY
    900       /* we want to dirty some number of consecutive integers in the buffer */
    901       /* we are about to send. we may also want to bring some number of */
    902       /* them cleanly into the cache. The clean ones will follow any dirty */
    903       /* ones into the cache. at some point, we might want to replace */
    904       /* the rand() call with something from a table to reduce our call */
    905       /* overhead during the test, but it is not a high priority item. */
    906       access_buffer(send_ring->buffer_ptr,
    907 		    send_size,
    908 		    loc_dirty_count,
    909 		    loc_clean_count);
    910 #endif /* DIRTY */
    911 
    912 #ifdef WANT_HISTOGRAM
    913       /* timestamp just before we go into send and then again just after */
    914       /* we come out raj 8/94 */
    915       HIST_timestamp(&time_one);
    916 #endif /* WANT_HISTOGRAM */
    917 
    918       if((len=t_snd(send_socket,
    919 		    send_ring->buffer_ptr,
    920 		    send_size,
    921 		    0)) != send_size) {
    922         if ((len >=0) || (errno == EINTR)) {
    923           /* the test was interrupted, must be the end of test */
    924           break;
    925         }
    926         fprintf(where,
    927 		"send_xti_tcp_stream: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
    928 		errno,
    929 		t_errno,
    930 		t_look(send_socket));
    931 	fflush(where);
    932         exit(1);
    933       }
    934 
    935 #ifdef WANT_HISTOGRAM
    936       /* timestamp the exit from the send call and update the histogram */
    937       HIST_timestamp(&time_two);
    938       HIST_add(time_hist,delta_micro(&time_one,&time_two));
    939 #endif /* WANT_HISTOGRAM */
    940 
    941 #ifdef WANT_INTERVALS
    942       if (demo_mode) {
    943         units_this_tick += send_size;
    944       }
    945       /* in this case, the interval count is the count-down couter */
    946       /* to decide to sleep for a little bit */
    947       if ((interval_burst) && (--interval_count == 0)) {
    948         /* call sigsuspend and wait for the interval timer to get us */
    949         /* out */
    950         if (debug) {
    951           fprintf(where,"about to suspend\n");
    952           fflush(where);
    953         }
    954         if (sigsuspend(&signal_set) == EFAULT) {
    955           fprintf(where,
    956                   "send_xti_tcp_stream: fault with signal set!\n");
    957           fflush(where);
    958           exit(1);
    959         }
    960         interval_count = interval_burst;
    961       }
    962 #endif /* WANT_INTERVALS */
    963 
    964       /* now we want to move our pointer to the next position in the */
    965       /* data buffer...we may also want to wrap back to the "beginning" */
    966       /* of the bufferspace, so we will mod the number of messages sent */
    967       /* by the send width, and use that to calculate the offset to add */
    968       /* to the base pointer. */
    969       nummessages++;
    970       send_ring = send_ring->next;
    971       if (bytes_remaining) {
    972         bytes_remaining -= send_size;
    973       }
    974     }
    975 
    976     /* The test is over. Flush the buffers to the remote end. We do a */
    977     /* graceful release to insure that all data has been taken by the */
    978     /* remote. */
    979 
    980     /* but first, if the verbosity is greater than 1, find-out what */
    981     /* the TCP maximum segment_size was (if possible) */
    982     if (verbosity > 1) {
    983       tcp_mss = -1;
    984       get_xti_info(send_socket,info_struct);
    985     }
    986 
    987     if (t_sndrel(send_socket) == -1) {
    988       t_error("netperf: cannot shutdown tcp stream socket");
    989       exit(1);
    990     }
    991 
    992     /* hang a t_rcvrel() off the socket to block until the remote has */
    993     /* brought all the data up into the application. it will do a */
    994     /* t_sedrel to cause a FIN to be sent our way. We will assume that */
    995     /* any exit from the t_rcvrel() call is good... raj 2/95 */
    996 
    997     if (debug > 1) {
    998       fprintf(where,"about to hang a receive for graceful release.\n");
    999       fflush(where);
   1000     }
   1001 
   1002     t_rcvrel(send_socket);
   1003 
   1004     /* this call will always give us the elapsed time for the test, and */
   1005     /* will also store-away the necessaries for cpu utilization */
   1006 
   1007     cpu_stop(local_cpu_usage,&elapsed_time);    /* was cpu being */
   1008                                                 /* measured and how */
   1009                                                 /* long did we really */
   1010                                                 /* run? */
   1011 
   1012     /* Get the statistics from the remote end. The remote will have */
   1013     /* calculated service demand and all those interesting things. If it */
   1014     /* wasn't supposed to care, it will return obvious values. */
   1015 
   1016     recv_response();
   1017     if (!netperf_response.content.serv_errno) {
   1018       if (debug)
   1019         fprintf(where,"remote results obtained\n");
   1020     }
   1021     else {
   1022       Set_errno(netperf_response.content.serv_errno);
   1023       perror("netperf: remote error");
   1024 
   1025       exit(1);
   1026     }
   1027 
   1028     /* We now calculate what our thruput was for the test. In the future, */
   1029     /* we may want to include a calculation of the thruput measured by */
   1030     /* the remote, but it should be the case that for a TCP stream test, */
   1031     /* that the two numbers should be *very* close... We calculate */
   1032     /* bytes_sent regardless of the way the test length was controlled. */
   1033     /* If it was time, we needed to, and if it was by bytes, the user may */
   1034     /* have specified a number of bytes that wasn't a multiple of the */
   1035     /* send_size, so we really didn't send what he asked for ;-) */
   1036 
   1037     bytes_sent  = xti_tcp_stream_result->bytes_received;
   1038 
   1039     thruput     = calc_thruput(bytes_sent);
   1040 
   1041     if (local_cpu_usage || remote_cpu_usage) {
   1042       /* We must now do a little math for service demand and cpu */
   1043       /* utilization for the system(s) */
   1044       /* Of course, some of the information might be bogus because */
   1045       /* there was no idle counter in the kernel(s). We need to make */
   1046       /* a note of this for the user's benefit...*/
   1047       if (local_cpu_usage) {
   1048 
   1049         local_cpu_utilization   = calc_cpu_util(0.0);
   1050         local_service_demand    = calc_service_demand(bytes_sent,
   1051                                                       0.0,
   1052                                                       0.0,
   1053 						      0);
   1054       }
   1055       else {
   1056         local_cpu_utilization   = -1.0;
   1057         local_service_demand    = -1.0;
   1058       }
   1059 
   1060       if (remote_cpu_usage) {
   1061 
   1062         remote_cpu_utilization  = xti_tcp_stream_result->cpu_util;
   1063         remote_service_demand   = calc_service_demand(bytes_sent,
   1064                                                       0.0,
   1065                                                       remote_cpu_utilization,
   1066 						      xti_tcp_stream_result->num_cpus);
   1067       }
   1068       else {
   1069         remote_cpu_utilization = -1.0;
   1070         remote_service_demand  = -1.0;
   1071       }
   1072     }
   1073     else {
   1074       /* we were not measuring cpu, for the confidence stuff, we */
   1075       /* should make it -1.0 */
   1076       local_cpu_utilization  = -1.0;
   1077       local_service_demand   = -1.0;
   1078       remote_cpu_utilization = -1.0;
   1079       remote_service_demand  = -1.0;
   1080     }
   1081 
   1082     /* at this point, we want to calculate the confidence information. */
   1083     /* if debugging is on, calculate_confidence will print-out the */
   1084     /* parameters we pass it */
   1085 
   1086     calculate_confidence(confidence_iteration,
   1087                          elapsed_time,
   1088                          thruput,
   1089                          local_cpu_utilization,
   1090                          remote_cpu_utilization,
   1091                          local_service_demand,
   1092                          remote_service_demand);
   1093 
   1094 
   1095     confidence_iteration++;
   1096   }
   1097 
   1098   /* at this point, we have finished making all the runs that we */
   1099   /* will be making. so, we should extract what the calcuated values */
   1100   /* are for all the confidence stuff. we could make the values */
   1101   /* global, but that seemed a little messy, and it did not seem worth */
   1102   /* all the mucking with header files. so, we create a routine much */
   1103   /* like calcualte_confidence, which just returns the mean values. */
   1104   /* raj 11/94 */
   1105 
   1106   retrieve_confident_values(&elapsed_time,
   1107                             &thruput,
   1108                             &local_cpu_utilization,
   1109                             &remote_cpu_utilization,
   1110                             &local_service_demand,
   1111                             &remote_service_demand);
   1112 
   1113   /* We are now ready to print all the information. If the user */
   1114   /* has specified zero-level verbosity, we will just print the */
   1115   /* local service demand, or the remote service demand. If the */
   1116   /* user has requested verbosity level 1, he will get the basic */
   1117   /* "streamperf" numbers. If the user has specified a verbosity */
   1118   /* of greater than 1, we will display a veritable plethora of */
   1119   /* background information from outside of this block as it it */
   1120   /* not cpu_measurement specific...  */
   1121 
   1122   if (confidence < 0) {
   1123     /* we did not hit confidence, but were we asked to look for it? */
   1124     if (iteration_max > 1) {
   1125       display_confidence();
   1126     }
   1127   }
   1128 
   1129   if (local_cpu_usage || remote_cpu_usage) {
   1130     local_cpu_method = format_cpu_method(cpu_method);
   1131     remote_cpu_method = format_cpu_method(xti_tcp_stream_result->cpu_method);
   1132 
   1133     switch (verbosity) {
   1134     case 0:
   1135       if (local_cpu_usage) {
   1136         fprintf(where,
   1137                 cpu_fmt_0,
   1138                 local_service_demand,
   1139 		local_cpu_method);
   1140       }
   1141       else {
   1142 	fprintf(where,
   1143 		cpu_fmt_0,
   1144 		remote_service_demand,
   1145 		remote_cpu_method);
   1146       }
   1147       break;
   1148     case 1:
   1149     case 2:
   1150       if (print_headers) {
   1151 	fprintf(where,
   1152 		cpu_title,
   1153 		format_units(),
   1154 		local_cpu_method,
   1155 		remote_cpu_method);
   1156       }
   1157 
   1158       fprintf(where,
   1159 	      cpu_fmt_1,		/* the format string */
   1160 	      rsr_size,		        /* remote recvbuf size */
   1161 	      lss_size,		        /* local sendbuf size */
   1162 	      send_size,		/* how large were the sends */
   1163 	      elapsed_time,		/* how long was the test */
   1164 	      thruput, 		        /* what was the xfer rate */
   1165 	      local_cpu_utilization,	/* local cpu */
   1166 	      remote_cpu_utilization,	/* remote cpu */
   1167 	      local_service_demand,	/* local service demand */
   1168 	      remote_service_demand);	/* remote service demand */
   1169       break;
   1170     }
   1171   }
   1172   else {
   1173     /* The tester did not wish to measure service demand. */
   1174 
   1175     switch (verbosity) {
   1176     case 0:
   1177       fprintf(where,
   1178 	      tput_fmt_0,
   1179 	      thruput);
   1180       break;
   1181     case 1:
   1182     case 2:
   1183       if (print_headers) {
   1184 	fprintf(where,tput_title,format_units());
   1185       }
   1186       fprintf(where,
   1187 	      tput_fmt_1,		/* the format string */
   1188 	      rsr_size, 		/* remote recvbuf size */
   1189 	      lss_size, 		/* local sendbuf size */
   1190 	      send_size,		/* how large were the sends */
   1191 	      elapsed_time, 		/* how long did it take */
   1192 	      thruput);/* how fast did it go */
   1193       break;
   1194     }
   1195   }
   1196 
   1197   /* it would be a good thing to include information about some of the */
   1198   /* other parameters that may have been set for this test, but at the */
   1199   /* moment, I do not wish to figure-out all the  formatting, so I will */
   1200   /* just put this comment here to help remind me that it is something */
   1201   /* that should be done at a later time. */
   1202 
   1203   if (verbosity > 1) {
   1204     /* The user wanted to know it all, so we will give it to him. */
   1205     /* This information will include as much as we can find about */
   1206     /* TCP statistics, the alignments of the sends and receives */
   1207     /* and all that sort of rot... */
   1208 
   1209     /* this stuff needs to be worked-out in the presence of confidence */
   1210     /* intervals and multiple iterations of the test... raj 11/94 */
   1211 
   1212     fprintf(where,
   1213 	    ksink_fmt,
   1214 	    "Bytes",
   1215 	    "Bytes",
   1216 	    "Bytes",
   1217 	    local_send_align,
   1218 	    remote_recv_align,
   1219 	    local_send_offset,
   1220 	    remote_recv_offset,
   1221 	    bytes_sent,
   1222 	    bytes_sent / (double)nummessages,
   1223 	    nummessages,
   1224 	    bytes_sent / (double)xti_tcp_stream_result->recv_calls,
   1225 	    xti_tcp_stream_result->recv_calls);
   1226     fprintf(where,
   1227 	    ksink_fmt2,
   1228 	    tcp_mss);
   1229     fflush(where);
   1230 #ifdef WANT_HISTOGRAM
   1231     fprintf(where,"\n\nHistogram of time spent in send() call.\n");
   1232     fflush(where);
   1233     HIST_report(time_hist);
   1234 #endif /* WANT_HISTOGRAM */
   1235   }
   1236 
   1237 }
   1238 
   1239 
   1241 /* This is the server-side routine for the tcp stream test. It is */
   1242 /* implemented as one routine. I could break things-out somewhat, but */
   1243 /* didn't feel it was necessary. */
   1244 
   1245 void
   1246 recv_xti_tcp_stream()
   1247 {
   1248 
   1249   struct sockaddr_in myaddr_in, peeraddr_in;
   1250   struct t_bind      bind_req, bind_resp;
   1251   struct t_call      call_req;
   1252 
   1253   SOCKET       s_listen,s_data;
   1254   int           addrlen;
   1255   int	        len;
   1256   unsigned int	receive_calls;
   1257   float	        elapsed_time;
   1258   double        bytes_received;
   1259 
   1260   struct ring_elt *recv_ring;
   1261 
   1262   int   *message_int_ptr;
   1263   int   i;
   1264 
   1265   struct xti_tcp_stream_request_struct	*xti_tcp_stream_request;
   1266   struct xti_tcp_stream_response_struct	*xti_tcp_stream_response;
   1267   struct xti_tcp_stream_results_struct	*xti_tcp_stream_results;
   1268 
   1269   xti_tcp_stream_request	=
   1270     (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
   1271   xti_tcp_stream_response	=
   1272     (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
   1273   xti_tcp_stream_results	=
   1274     (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
   1275 
   1276   if (debug) {
   1277     fprintf(where,"netserver: recv_xti_tcp_stream: entered...\n");
   1278     fflush(where);
   1279   }
   1280 
   1281   /* We want to set-up the listen socket with all the desired */
   1282   /* parameters and then let the initiator know that all is ready. If */
   1283   /* socket size defaults are to be used, then the initiator will have */
   1284   /* sent us 0's. If the socket sizes cannot be changed, then we will */
   1285   /* send-back what they are. If that information cannot be determined, */
   1286   /* then we send-back -1's for the sizes. If things go wrong for any */
   1287   /* reason, we will drop back ten yards and punt. */
   1288 
   1289   /* If anything goes wrong, we want the remote to know about it. It */
   1290   /* would be best if the error that the remote reports to the user is */
   1291   /* the actual error we encountered, rather than some bogus unexpected */
   1292   /* response type message. */
   1293 
   1294   if (debug) {
   1295     fprintf(where,"recv_xti_tcp_stream: setting the response type...\n");
   1296     fflush(where);
   1297   }
   1298 
   1299   netperf_response.content.response_type = XTI_TCP_STREAM_RESPONSE;
   1300 
   1301   if (debug) {
   1302     fprintf(where,"recv_xti_tcp_stream: the response type is set...\n");
   1303     fflush(where);
   1304   }
   1305 
   1306   /* We now alter the message_ptr variable to be at the desired */
   1307   /* alignment with the desired offset. */
   1308 
   1309   if (debug) {
   1310     fprintf(where,"recv_xti_tcp_stream: requested alignment of %d\n",
   1311 	    xti_tcp_stream_request->recv_alignment);
   1312     fflush(where);
   1313   }
   1314 
   1315   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
   1316   /* can put in OUR values !-) At some point, we may want to nail this */
   1317   /* socket to a particular network-level address, but for now, */
   1318   /* INADDR_ANY should be just fine. */
   1319 
   1320   bzero((char *)&myaddr_in,
   1321 	sizeof(myaddr_in));
   1322   myaddr_in.sin_family      = AF_INET;
   1323   myaddr_in.sin_addr.s_addr = INADDR_ANY;
   1324   myaddr_in.sin_port        = 0;
   1325 
   1326   /* Grab a socket to listen on, and then listen on it. */
   1327 
   1328   if (debug) {
   1329     fprintf(where,"recv_xti_tcp_stream: grabbing a socket...\n");
   1330     fflush(where);
   1331   }
   1332 
   1333   /* create_xti_endpoint expects to find some things in the global */
   1334   /* variables, so set the globals based on the values in the request. */
   1335   /* once the socket has been created, we will set the response values */
   1336   /* based on the updated value of those globals. raj 7/94 */
   1337   lss_size = xti_tcp_stream_request->send_buf_size;
   1338   lsr_size = xti_tcp_stream_request->recv_buf_size;
   1339   loc_nodelay = xti_tcp_stream_request->no_delay;
   1340   loc_rcvavoid = xti_tcp_stream_request->so_rcvavoid;
   1341   loc_sndavoid = xti_tcp_stream_request->so_sndavoid;
   1342 
   1343 #ifdef __alpha
   1344 
   1345   /* ok - even on a DEC box, strings are strings. I din't really want */
   1346   /* to ntohl the words of a string. since I don't want to teach the */
   1347   /* send_ and recv_ _request and _response routines about the types, */
   1348   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   1349   /* solution would be to use XDR, but I am still leary of being able */
   1350   /* to find XDR libs on all platforms I want running netperf. raj */
   1351   {
   1352     int *charword;
   1353     int *initword;
   1354     int *lastword;
   1355 
   1356     initword = (int *) xti_tcp_stream_request->xti_device;
   1357     lastword = initword + ((xti_tcp_stream_request->dev_name_len + 3) / 4);
   1358 
   1359     for (charword = initword;
   1360 	 charword < lastword;
   1361 	 charword++) {
   1362 
   1363       *charword = htonl(*charword);
   1364     }
   1365   }
   1366 
   1367 #endif /* __alpha */
   1368 
   1369   s_listen = create_xti_endpoint(xti_tcp_stream_request->xti_device);
   1370 
   1371   if (s_listen == INVALID_SOCKET) {
   1372     netperf_response.content.serv_errno = errno;
   1373     send_response();
   1374     exit(1);
   1375   }
   1376 
   1377   /* Let's get an address assigned to this socket so we can tell the */
   1378   /* initiator how to reach the data socket. There may be a desire to */
   1379   /* nail this socket to a specific IP address in a multi-homed, */
   1380   /* multi-connection situation, but for now, we'll ignore the issue */
   1381   /* and concentrate on single connection testing. */
   1382 
   1383   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
   1384   bind_req.addr.len    = sizeof(struct sockaddr_in);
   1385   bind_req.addr.buf    = (char *)&myaddr_in;
   1386   bind_req.qlen        = 1;
   1387 
   1388   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
   1389   bind_resp.addr.len    = sizeof(struct sockaddr_in);
   1390   bind_resp.addr.buf    = (char *)&myaddr_in;
   1391   bind_resp.qlen        = 1;
   1392 
   1393   if (t_bind(s_listen,
   1394 	     &bind_req,
   1395 	     &bind_resp) == SOCKET_ERROR) {
   1396     netperf_response.content.serv_errno = t_errno;
   1397     close(s_listen);
   1398     send_response();
   1399 
   1400     exit(1);
   1401   }
   1402 
   1403   if (debug) {
   1404     fprintf(where,
   1405 	    "recv_xti_tcp_stream: t_bind complete port %d\n",
   1406 	    ntohs(myaddr_in.sin_port));
   1407     fflush(where);
   1408   }
   1409 
   1410   /* what sort of sizes did we end-up with? */
   1411   if (xti_tcp_stream_request->receive_size == 0) {
   1412     if (lsr_size > 0) {
   1413       recv_size = lsr_size;
   1414     }
   1415     else {
   1416       recv_size = 4096;
   1417     }
   1418   }
   1419   else {
   1420     recv_size = xti_tcp_stream_request->receive_size;
   1421   }
   1422 
   1423   /* we want to set-up our recv_ring in a manner analagous to what we */
   1424   /* do on the sending side. this is more for the sake of symmetry */
   1425   /* than for the needs of say copy avoidance, but it might also be */
   1426   /* more realistic - this way one could conceivably go with a */
   1427   /* double-buffering scheme when taking the data an putting it into */
   1428   /* the filesystem or something like that. raj 7/94 */
   1429 
   1430   if (recv_width == 0) {
   1431     recv_width = (lsr_size/recv_size) + 1;
   1432     if (recv_width == 1) recv_width++;
   1433   }
   1434 
   1435   recv_ring = allocate_buffer_ring(recv_width,
   1436 				   recv_size,
   1437 				   xti_tcp_stream_request->recv_alignment,
   1438 				   xti_tcp_stream_request->recv_offset);
   1439 
   1440   if (debug) {
   1441     fprintf(where,"recv_xti_tcp_stream: recv alignment and offset set...\n");
   1442     fflush(where);
   1443   }
   1444 
   1445   /* Now myaddr_in contains the port and the internet address this is */
   1446   /* returned to the sender also implicitly telling the sender that the */
   1447   /* socket buffer sizing has been done. */
   1448 
   1449   xti_tcp_stream_response->data_port_number =
   1450     (int) ntohs(myaddr_in.sin_port);
   1451   netperf_response.content.serv_errno   = 0;
   1452 
   1453   /* But wait, there's more. If the initiator wanted cpu measurements, */
   1454   /* then we must call the calibrate routine, which will return the max */
   1455   /* rate back to the initiator. If the CPU was not to be measured, or */
   1456   /* something went wrong with the calibration, we will return a -1 to */
   1457   /* the initiator. */
   1458 
   1459   xti_tcp_stream_response->cpu_rate = 0.0; 	/* assume no cpu */
   1460   if (xti_tcp_stream_request->measure_cpu) {
   1461     xti_tcp_stream_response->measure_cpu = 1;
   1462     xti_tcp_stream_response->cpu_rate =
   1463       calibrate_local_cpu(xti_tcp_stream_request->cpu_rate);
   1464   }
   1465   else {
   1466     xti_tcp_stream_response->measure_cpu = 0;
   1467   }
   1468 
   1469   /* before we send the response back to the initiator, pull some of */
   1470   /* the socket parms from the globals */
   1471   xti_tcp_stream_response->send_buf_size = lss_size;
   1472   xti_tcp_stream_response->recv_buf_size = lsr_size;
   1473   xti_tcp_stream_response->no_delay = loc_nodelay;
   1474   xti_tcp_stream_response->so_rcvavoid = loc_rcvavoid;
   1475   xti_tcp_stream_response->so_sndavoid = loc_sndavoid;
   1476   xti_tcp_stream_response->receive_size = recv_size;
   1477 
   1478   send_response();
   1479 
   1480   /* Now, let's set-up the socket to listen for connections. for xti, */
   1481   /* the t_listen call is blocking by default - this is different */
   1482   /* semantics from BSD - probably has to do with being able to reject */
   1483   /* a call before an accept */
   1484   call_req.addr.maxlen = sizeof(struct sockaddr_in);
   1485   call_req.addr.len    = sizeof(struct sockaddr_in);
   1486   call_req.addr.buf    = (char *)&peeraddr_in;
   1487   call_req.opt.maxlen  = 0;
   1488   call_req.opt.len     = 0;
   1489   call_req.opt.buf     = NULL;
   1490   call_req.udata.maxlen= 0;
   1491   call_req.udata.len   = 0;
   1492   call_req.udata.buf   = 0;
   1493 
   1494   if (t_listen(s_listen, &call_req) == -1) {
   1495     fprintf(where,
   1496 	    "recv_xti_tcp_stream: t_listen: errno %d t_errno %d\n",
   1497 	    errno,
   1498 	    t_errno);
   1499     fflush(where);
   1500     netperf_response.content.serv_errno = t_errno;
   1501     close(s_listen);
   1502     send_response();
   1503     exit(1);
   1504   }
   1505 
   1506   if (debug) {
   1507     fprintf(where,
   1508 	    "recv_xti_tcp_stream: t_listen complete t_look 0x%.4x\n",
   1509 	    t_look(s_listen));
   1510     fflush(where);
   1511   }
   1512 
   1513   /* now just rubber stamp the thing. we want to use the same fd? so */
   1514   /* we will just equate s_data with s_listen. this seems a little */
   1515   /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
   1516   s_data = s_listen;
   1517   if (t_accept(s_listen,
   1518 	       s_data,
   1519 	       &call_req) == -1) {
   1520     fprintf(where,
   1521 	    "recv_xti_tcp_stream: t_accept: errno %d t_errno %d\n",
   1522 	    errno,
   1523 	    t_errno);
   1524     fflush(where);
   1525     close(s_listen);
   1526     exit(1);
   1527   }
   1528 
   1529   if (debug) {
   1530     fprintf(where,
   1531 	    "recv_xti_tcp_stream: t_accept complete t_look 0x%.4x\n",
   1532 	    t_look(s_data));
   1533     fprintf(where,
   1534 	    "                     remote is %s port %d\n",
   1535 	    inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
   1536 	    ntohs(peeraddr_in.sin_port));
   1537     fflush(where);
   1538   }
   1539 
   1540   /* Now it's time to start receiving data on the connection. We will */
   1541   /* first grab the apropriate counters and then start grabbing. */
   1542 
   1543   cpu_start(xti_tcp_stream_request->measure_cpu);
   1544 
   1545   /* The loop will exit when the sender does a t_sndrel, which will */
   1546   /* return T_LOOK error from the t_recv */
   1547 
   1548 #ifdef DIRTY
   1549     /* we want to dirty some number of consecutive integers in the buffer */
   1550     /* we are about to recv. we may also want to bring some number of */
   1551     /* them cleanly into the cache. The clean ones will follow any dirty */
   1552     /* ones into the cache. */
   1553 
   1554   access_buffer(recv_ring->buffer_ptr,
   1555 		recv_size,
   1556 		xti_tcp_stream_request->dirty_count,
   1557 		xti_tcp_stream_request->clean_count);
   1558 
   1559 #endif /* DIRTY */
   1560 
   1561   bytes_received = 0;
   1562   receive_calls  = 0;
   1563 
   1564   while ((len = t_rcv(s_data,
   1565 		      recv_ring->buffer_ptr,
   1566 		      recv_size,
   1567 		      &xti_flags)) != -1) {
   1568     bytes_received += len;
   1569     receive_calls++;
   1570 
   1571     /* more to the next buffer in the recv_ring */
   1572     recv_ring = recv_ring->next;
   1573 
   1574 #ifdef DIRTY
   1575 
   1576   access_buffer(recv_ring->buffer_ptr,
   1577 		recv_size,
   1578 		xti_tcp_stream_request->dirty_count,
   1579 		xti_tcp_stream_request->clean_count);
   1580 
   1581 #endif /* DIRTY */
   1582   }
   1583 
   1584   if (t_look(s_data) == T_ORDREL) {
   1585     /* this is a normal exit path */
   1586     if (debug) {
   1587       fprintf(where,
   1588 	      "recv_xti_tcp_stream: t_rcv T_ORDREL indicated\n");
   1589       fflush(where);
   1590     }
   1591   }
   1592   else {
   1593     /* something went wrong */
   1594     fprintf(where,
   1595 	    "recv_xti_tcp_stream: t_rcv: errno %d t_errno %d len %d",
   1596 	    errno,
   1597 	    t_errno,
   1598 	    len);
   1599     fprintf(where,
   1600 	    " t_look 0x%.4x",
   1601 	    t_look(s_data));
   1602     fflush(where);
   1603     netperf_response.content.serv_errno = t_errno;
   1604     send_response();
   1605     exit(1);
   1606   }
   1607 
   1608   /* receive the release and let the initiator know that we have */
   1609   /* received all the data. raj 3/95 */
   1610 
   1611   if (t_rcvrel(s_data) == -1) {
   1612     netperf_response.content.serv_errno = errno;
   1613     send_response();
   1614     exit(1);
   1615   }
   1616 
   1617   if (debug) {
   1618     fprintf(where,
   1619 	    "recv_xti_tcp_stream: t_rcvrel complete\n");
   1620     fflush(where);
   1621   }
   1622 
   1623   if (t_sndrel(s_data) == -1) {
   1624     netperf_response.content.serv_errno = errno;
   1625     send_response();
   1626     exit(1);
   1627   }
   1628 
   1629   if (debug) {
   1630     fprintf(where,
   1631 	    "recv_xti_tcp_stream: t_sndrel complete\n");
   1632     fflush(where);
   1633   }
   1634 
   1635   cpu_stop(xti_tcp_stream_request->measure_cpu,&elapsed_time);
   1636 
   1637   /* send the results to the sender			*/
   1638 
   1639   if (debug) {
   1640     fprintf(where,
   1641 	    "recv_xti_tcp_stream: got %g bytes\n",
   1642 	    bytes_received);
   1643     fprintf(where,
   1644 	    "recv_xti_tcp_stream: got %d recvs\n",
   1645 	    receive_calls);
   1646     fflush(where);
   1647   }
   1648 
   1649   xti_tcp_stream_results->bytes_received	= bytes_received;
   1650   xti_tcp_stream_results->elapsed_time	= elapsed_time;
   1651   xti_tcp_stream_results->recv_calls	= receive_calls;
   1652 
   1653   if (xti_tcp_stream_request->measure_cpu) {
   1654     xti_tcp_stream_results->cpu_util	= calc_cpu_util(0.0);
   1655   };
   1656 
   1657   if (debug) {
   1658     fprintf(where,
   1659 	    "recv_xti_tcp_stream: test complete, sending results.\n");
   1660     fprintf(where,
   1661 	    "                 bytes_received %g receive_calls %d\n",
   1662 	    bytes_received,
   1663 	    receive_calls);
   1664     fprintf(where,
   1665 	    "                 len %d\n",
   1666 	    len);
   1667     fflush(where);
   1668   }
   1669 
   1670   xti_tcp_stream_results->cpu_method = cpu_method;
   1671   send_response();
   1672 
   1673   /* we are now done with the socket */
   1674   t_close(s_data);
   1675 
   1676 }
   1677 
   1678 
   1680  /* this routine implements the sending (netperf) side of the XTI_TCP_RR */
   1681  /* test. */
   1682 
   1683 void
   1684 send_xti_tcp_rr(char remote_host[])
   1685 {
   1686 
   1687   char *tput_title = "\
   1688 Local /Remote\n\
   1689 Socket Size   Request  Resp.   Elapsed  Trans.\n\
   1690 Send   Recv   Size     Size    Time     Rate         \n\
   1691 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
   1692 
   1693   char *tput_fmt_0 =
   1694     "%7.2f\n";
   1695 
   1696   char *tput_fmt_1_line_1 = "\
   1697 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
   1698   char *tput_fmt_1_line_2 = "\
   1699 %-6d %-6d\n";
   1700 
   1701   char *cpu_title = "\
   1702 Local /Remote\n\
   1703 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
   1704 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
   1705 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
   1706 
   1707   char *cpu_fmt_0 =
   1708     "%6.3f %c\n";
   1709 
   1710   char *cpu_fmt_1_line_1 = "\
   1711 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f\n";
   1712 
   1713   char *cpu_fmt_1_line_2 = "\
   1714 %-6d %-6d\n";
   1715 
   1716   char *ksink_fmt = "\
   1717 Alignment      Offset\n\
   1718 Local  Remote  Local  Remote\n\
   1719 Send   Recv    Send   Recv\n\
   1720 %5d  %5d   %5d  %5d\n";
   1721 
   1722 
   1723   int			timed_out = 0;
   1724   float			elapsed_time;
   1725 
   1726   int	len;
   1727   char	*temp_message_ptr;
   1728   int	nummessages;
   1729   SOCKET send_socket;
   1730   int	trans_remaining;
   1731   double	bytes_xferd;
   1732 
   1733   struct ring_elt *send_ring;
   1734   struct ring_elt *recv_ring;
   1735 
   1736   int	rsp_bytes_left;
   1737   int	rsp_bytes_recvd;
   1738 
   1739   float	local_cpu_utilization;
   1740   float	local_service_demand;
   1741   float	remote_cpu_utilization;
   1742   float	remote_service_demand;
   1743   double	thruput;
   1744 
   1745   struct	hostent	        *hp;
   1746   struct	sockaddr_in	server;
   1747   unsigned      int             addr;
   1748 
   1749   struct t_call server_call;
   1750 
   1751   struct	xti_tcp_rr_request_struct	*xti_tcp_rr_request;
   1752   struct	xti_tcp_rr_response_struct	*xti_tcp_rr_response;
   1753   struct	xti_tcp_rr_results_struct	*xti_tcp_rr_result;
   1754 
   1755 #ifdef WANT_INTERVALS
   1756   int	interval_count;
   1757   sigset_t signal_set;
   1758 #endif /* WANT_INTERVALS */
   1759 
   1760   xti_tcp_rr_request =
   1761     (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
   1762   xti_tcp_rr_response=
   1763     (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
   1764   xti_tcp_rr_result	=
   1765     (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
   1766 
   1767 #ifdef WANT_HISTOGRAM
   1768   time_hist = HIST_new();
   1769 #endif /* WANT_HISTOGRAM */
   1770 
   1771   /* since we are now disconnected from the code that established the */
   1772   /* control socket, and since we want to be able to use different */
   1773   /* protocols and such, we are passed the name of the remote host and */
   1774   /* must turn that into the test specific addressing information. */
   1775 
   1776   bzero((char *)&server,
   1777 	sizeof(server));
   1778 
   1779   /* it would seem that while HP-UX will allow an IP address (as a */
   1780   /* string) in a call to gethostbyname, other, less enlightened */
   1781   /* systems do not. fix from awjacks (at) ca.sandia.gov raj 10/95 */
   1782   /* order changed to check for IP address first. raj 7/96 */
   1783 
   1784   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
   1785     /* it was not an IP address, try it as a name */
   1786     if ((hp = gethostbyname(remote_host)) == NULL) {
   1787       /* we have no idea what it is */
   1788       fprintf(where,
   1789 	      "establish_control: could not resolve the destination %s\n",
   1790 	      remote_host);
   1791       fflush(where);
   1792       exit(1);
   1793     }
   1794     else {
   1795       /* it was a valid remote_host */
   1796       bcopy(hp->h_addr,
   1797 	    (char *)&server.sin_addr,
   1798 	    hp->h_length);
   1799       server.sin_family = hp->h_addrtype;
   1800     }
   1801   }
   1802   else {
   1803     /* it was a valid IP address */
   1804     server.sin_addr.s_addr = addr;
   1805     server.sin_family = AF_INET;
   1806   }
   1807 
   1808   if ( print_headers ) {
   1809     fprintf(where,"XTI TCP REQUEST/RESPONSE TEST");
   1810     fprintf(where," to %s", remote_host);
   1811     if (iteration_max > 1) {
   1812       fprintf(where,
   1813 	      " : +/-%3.1f%% @ %2d%% conf.",
   1814 	      interval/0.02,
   1815 	      confidence_level);
   1816       }
   1817     if (loc_nodelay || rem_nodelay) {
   1818       fprintf(where," : nodelay");
   1819     }
   1820     if (loc_sndavoid ||
   1821 	loc_rcvavoid ||
   1822 	rem_sndavoid ||
   1823 	rem_rcvavoid) {
   1824       fprintf(where," : copy avoidance");
   1825     }
   1826 #ifdef WANT_HISTOGRAM
   1827     fprintf(where," : histogram");
   1828 #endif /* WANT_HISTOGRAM */
   1829 #ifdef WANT_INTERVALS
   1830     fprintf(where," : interval");
   1831 #endif /* WANT_INTERVALS */
   1832 #ifdef DIRTY
   1833     fprintf(where," : dirty data");
   1834 #endif /* DIRTY */
   1835     fprintf(where,"\n");
   1836   }
   1837 
   1838   /* initialize a few counters */
   1839 
   1840   send_ring = NULL;
   1841   recv_ring = NULL;
   1842   confidence_iteration = 1;
   1843   init_stat();
   1844 
   1845   /* we have a great-big while loop which controls the number of times */
   1846   /* we run a particular test. this is for the calculation of a */
   1847   /* confidence interval (I really should have stayed awake during */
   1848   /* probstats :). If the user did not request confidence measurement */
   1849   /* (no confidence is the default) then we will only go though the */
   1850   /* loop once. the confidence stuff originates from the folks at IBM */
   1851 
   1852   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
   1853 	 (confidence_iteration <= iteration_min)) {
   1854 
   1855     /* initialize a few counters. we have to remember that we might be */
   1856     /* going through the loop more than once. */
   1857 
   1858     nummessages     = 0;
   1859     bytes_xferd     = 0.0;
   1860     times_up        = 0;
   1861     timed_out       = 0;
   1862     trans_remaining = 0;
   1863 
   1864     /* set-up the data buffers with the requested alignment and offset. */
   1865     /* since this is a request/response test, default the send_width and */
   1866     /* recv_width to 1 and not two raj 7/94 */
   1867 
   1868     if (send_width == 0) send_width = 1;
   1869     if (recv_width == 0) recv_width = 1;
   1870 
   1871     if (send_ring == NULL) {
   1872       send_ring = allocate_buffer_ring(send_width,
   1873 				       req_size,
   1874 				       local_send_align,
   1875 				       local_send_offset);
   1876     }
   1877 
   1878     if (recv_ring == NULL) {
   1879       recv_ring = allocate_buffer_ring(recv_width,
   1880 				       rsp_size,
   1881 				       local_recv_align,
   1882 				       local_recv_offset);
   1883     }
   1884 
   1885     /*set up the data socket                        */
   1886     send_socket = create_xti_endpoint(loc_xti_device);
   1887 
   1888     if (send_socket == INVALID_SOCKET){
   1889       perror("netperf: send_xti_tcp_rr: tcp stream data socket");
   1890       exit(1);
   1891     }
   1892 
   1893     if (debug) {
   1894       fprintf(where,"send_xti_tcp_rr: send_socket obtained...\n");
   1895     }
   1896 
   1897     /* it would seem that with XTI, there is no implicit bind on a */
   1898     /* connect, so we have to make a call to t_bind. this is not */
   1899     /* terribly convenient, but I suppose that "standard is better */
   1900     /* than better" :) raj 2/95 */
   1901 
   1902     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
   1903       t_error("send_xti_tcp_stream: t_bind");
   1904       exit(1);
   1905     }
   1906 
   1907     /* If the user has requested cpu utilization measurements, we must */
   1908     /* calibrate the cpu(s). We will perform this task within the tests */
   1909     /* themselves. If the user has specified the cpu rate, then */
   1910     /* calibrate_local_cpu will return rather quickly as it will have */
   1911     /* nothing to do. If local_cpu_rate is zero, then we will go through */
   1912     /* all the "normal" calibration stuff and return the rate back.*/
   1913 
   1914     if (local_cpu_usage) {
   1915       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   1916     }
   1917 
   1918     /* Tell the remote end to do a listen. The server alters the socket */
   1919     /* paramters on the other side at this point, hence the reason for */
   1920     /* all the values being passed in the setup message. If the user did */
   1921     /* not specify any of the parameters, they will be passed as 0, which */
   1922     /* will indicate to the remote that no changes beyond the system's */
   1923     /* default should be used. Alignment is the exception, it will */
   1924     /* default to 8, which will be no alignment alterations. */
   1925 
   1926     netperf_request.content.request_type	=	DO_XTI_TCP_RR;
   1927     xti_tcp_rr_request->recv_buf_size	=	rsr_size;
   1928     xti_tcp_rr_request->send_buf_size	=	rss_size;
   1929     xti_tcp_rr_request->recv_alignment  =	remote_recv_align;
   1930     xti_tcp_rr_request->recv_offset	=	remote_recv_offset;
   1931     xti_tcp_rr_request->send_alignment  =	remote_send_align;
   1932     xti_tcp_rr_request->send_offset	=	remote_send_offset;
   1933     xti_tcp_rr_request->request_size	=	req_size;
   1934     xti_tcp_rr_request->response_size	=	rsp_size;
   1935     xti_tcp_rr_request->no_delay	=	rem_nodelay;
   1936     xti_tcp_rr_request->measure_cpu	=	remote_cpu_usage;
   1937     xti_tcp_rr_request->cpu_rate	=	remote_cpu_rate;
   1938     xti_tcp_rr_request->so_rcvavoid	=	rem_rcvavoid;
   1939     xti_tcp_rr_request->so_sndavoid	=	rem_sndavoid;
   1940     if (test_time) {
   1941       xti_tcp_rr_request->test_length	=	test_time;
   1942     }
   1943     else {
   1944       xti_tcp_rr_request->test_length	=	test_trans * -1;
   1945     }
   1946 
   1947     strcpy(xti_tcp_rr_request->xti_device, rem_xti_device);
   1948 
   1949 #ifdef __alpha
   1950 
   1951     /* ok - even on a DEC box, strings are strings. I didn't really want */
   1952     /* to ntohl the words of a string. since I don't want to teach the */
   1953     /* send_ and recv_ _request and _response routines about the types, */
   1954     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   1955     /* solution would be to use XDR, but I am still leary of being able */
   1956     /* to find XDR libs on all platforms I want running netperf. raj */
   1957     {
   1958       int *charword;
   1959       int *initword;
   1960       int *lastword;
   1961 
   1962       initword = (int *) xti_tcp_rr_request->xti_device;
   1963       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
   1964 
   1965       for (charword = initword;
   1966 	   charword < lastword;
   1967 	   charword++) {
   1968 
   1969 	*charword = ntohl(*charword);
   1970       }
   1971     }
   1972 #endif /* __alpha */
   1973 
   1974     if (debug > 1) {
   1975       fprintf(where,"netperf: send_xti_tcp_rr: requesting TCP rr test\n");
   1976     }
   1977 
   1978     send_request();
   1979 
   1980     /* The response from the remote will contain all of the relevant 	*/
   1981     /* socket parameters for this test type. We will put them back into */
   1982     /* the variables here so they can be displayed if desired.  The	*/
   1983     /* remote will have calibrated CPU if necessary, and will have done	*/
   1984     /* all the needed set-up we will have calibrated the cpu locally	*/
   1985     /* before sending the request, and will grab the counter value right*/
   1986     /* after the connect returns. The remote will grab the counter right*/
   1987     /* after the accept call. This saves the hassle of extra messages	*/
   1988     /* being sent for the TCP tests.					*/
   1989 
   1990     recv_response();
   1991 
   1992     if (!netperf_response.content.serv_errno) {
   1993       if (debug)
   1994 	fprintf(where,"remote listen done.\n");
   1995       rsr_size          = xti_tcp_rr_response->recv_buf_size;
   1996       rss_size          = xti_tcp_rr_response->send_buf_size;
   1997       rem_nodelay       = xti_tcp_rr_response->no_delay;
   1998       remote_cpu_usage  = xti_tcp_rr_response->measure_cpu;
   1999       remote_cpu_rate   = xti_tcp_rr_response->cpu_rate;
   2000       /* make sure that port numbers are in network order */
   2001       server.sin_port   = (short)xti_tcp_rr_response->data_port_number;
   2002       server.sin_port   = htons(server.sin_port);
   2003     }
   2004     else {
   2005       Set_errno(netperf_response.content.serv_errno);
   2006       perror("netperf: remote error");
   2007 
   2008       exit(1);
   2009     }
   2010 
   2011     /*Connect up to the remote port on the data socket  */
   2012     memset (&server_call, 0, sizeof(server_call));
   2013     server_call.addr.maxlen = sizeof(struct sockaddr_in);
   2014     server_call.addr.len    = sizeof(struct sockaddr_in);
   2015     server_call.addr.buf    = (char *)&server;
   2016 
   2017     if (t_connect(send_socket,
   2018 		  &server_call,
   2019 		  NULL) == INVALID_SOCKET){
   2020       t_error("netperf: send_xti_tcp_rr: data socket connect failed");
   2021       printf(" port: %d\n",ntohs(server.sin_port));
   2022       exit(1);
   2023     }
   2024 
   2025     /* Data Socket set-up is finished. If there were problems, either the */
   2026     /* connect would have failed, or the previous response would have */
   2027     /* indicated a problem. I failed to see the value of the extra */
   2028     /* message after the accept on the remote. If it failed, we'll see it */
   2029     /* here. If it didn't, we might as well start pumping data. */
   2030 
   2031     /* Set-up the test end conditions. For a request/response test, they */
   2032     /* can be either time or transaction based. */
   2033 
   2034     if (test_time) {
   2035       /* The user wanted to end the test after a period of time. */
   2036       times_up = 0;
   2037       trans_remaining = 0;
   2038       start_timer(test_time);
   2039     }
   2040     else {
   2041       /* The tester wanted to send a number of bytes. */
   2042       trans_remaining = test_bytes;
   2043       times_up = 1;
   2044     }
   2045 
   2046     /* The cpu_start routine will grab the current time and possibly */
   2047     /* value of the idle counter for later use in measuring cpu */
   2048     /* utilization and/or service demand and thruput. */
   2049 
   2050     cpu_start(local_cpu_usage);
   2051 
   2052 #ifdef WANT_INTERVALS
   2053     if ((interval_burst) || (demo_mode)) {
   2054       /* zero means that we never pause, so we never should need the */
   2055       /* interval timer, unless we are in demo_mode */
   2056       start_itimer(interval_wate);
   2057     }
   2058     interval_count = interval_burst;
   2059     /* get the signal set for the call to sigsuspend */
   2060     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
   2061       fprintf(where,
   2062 	      "send_xti_tcp_rr: unable to get sigmask errno %d\n",
   2063 	      errno);
   2064       fflush(where);
   2065       exit(1);
   2066     }
   2067 #endif /* WANT_INTERVALS */
   2068 
   2069     /* We use an "OR" to control test execution. When the test is */
   2070     /* controlled by time, the byte count check will always return false. */
   2071     /* When the test is controlled by byte count, the time test will */
   2072     /* always return false. When the test is finished, the whole */
   2073     /* expression will go false and we will stop sending data. I think I */
   2074     /* just arbitrarily decrement trans_remaining for the timed test, but */
   2075     /* will not do that just yet... One other question is whether or not */
   2076     /* the send buffer and the receive buffer should be the same buffer. */
   2077 
   2078     while ((!times_up) || (trans_remaining > 0)) {
   2079       /* send the request. we assume that if we use a blocking socket, */
   2080       /* the request will be sent at one shot. */
   2081 
   2082 #ifdef WANT_HISTOGRAM
   2083       /* timestamp just before our call to send, and then again just */
   2084       /* after the receive raj 8/94 */
   2085       HIST_timestamp(&time_one);
   2086 #endif /* WANT_HISTOGRAM */
   2087 
   2088       if((len=t_snd(send_socket,
   2089 		    send_ring->buffer_ptr,
   2090 		    req_size,
   2091 		    0)) != req_size) {
   2092 	if ((errno == EINTR) || (errno == 0)) {
   2093 	  /* we hit the end of a */
   2094 	  /* timed test. */
   2095 	  timed_out = 1;
   2096 	  break;
   2097 	}
   2098         fprintf(where,
   2099 		"send_xti_tcp_rr: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
   2100 		errno,
   2101 		t_errno,
   2102 		t_look(send_socket));
   2103 	fflush(where);
   2104         exit(1);
   2105       }
   2106       send_ring = send_ring->next;
   2107 
   2108       /* receive the response */
   2109       rsp_bytes_left = rsp_size;
   2110       temp_message_ptr  = recv_ring->buffer_ptr;
   2111       while(rsp_bytes_left > 0) {
   2112 	if((rsp_bytes_recvd=t_rcv(send_socket,
   2113 				  temp_message_ptr,
   2114 				  rsp_bytes_left,
   2115 				  &xti_flags)) == SOCKET_ERROR) {
   2116 	  if (errno == EINTR) {
   2117 	    /* We hit the end of a timed test. */
   2118 	    timed_out = 1;
   2119 	    break;
   2120 	  }
   2121 	  fprintf(where,
   2122 		  "send_xti_tcp_rr: t_rcv: errno %d t_errno %d t_look 0x%x\n",
   2123 		  errno,
   2124 		  t_errno,
   2125 		  t_look(send_socket));
   2126 	  fflush(where);
   2127 	  exit(1);
   2128 	}
   2129 	rsp_bytes_left -= rsp_bytes_recvd;
   2130 	temp_message_ptr  += rsp_bytes_recvd;
   2131       }
   2132       recv_ring = recv_ring->next;
   2133 
   2134       if (timed_out) {
   2135 	/* we may have been in a nested while loop - we need */
   2136 	/* another call to break. */
   2137 	break;
   2138       }
   2139 
   2140 #ifdef WANT_HISTOGRAM
   2141       HIST_timestamp(&time_two);
   2142       HIST_add(time_hist,delta_micro(&time_one,&time_two));
   2143 #endif /* WANT_HISTOGRAM */
   2144 #ifdef WANT_INTERVALS
   2145       if (demo_mode) {
   2146 	units_this_tick += 1;
   2147       }
   2148       /* in this case, the interval count is the count-down couter */
   2149       /* to decide to sleep for a little bit */
   2150       if ((interval_burst) && (--interval_count == 0)) {
   2151 	/* call sigsuspend and wait for the interval timer to get us */
   2152 	/* out */
   2153 	if (debug) {
   2154 	  fprintf(where,"about to suspend\n");
   2155 	  fflush(where);
   2156 	}
   2157 	if (sigsuspend(&signal_set) == EFAULT) {
   2158 	  fprintf(where,
   2159 		  "send_xti_udp_rr: fault with signal set!\n");
   2160 	  fflush(where);
   2161 	  exit(1);
   2162 	}
   2163 	interval_count = interval_burst;
   2164       }
   2165 #endif /* WANT_INTERVALS */
   2166 
   2167       nummessages++;
   2168       if (trans_remaining) {
   2169 	trans_remaining--;
   2170       }
   2171 
   2172       if (debug > 3) {
   2173 	if ((nummessages % 100) == 0) {
   2174 	  fprintf(where,
   2175 		  "Transaction %d completed\n",
   2176 		  nummessages);
   2177 	  fflush(where);
   2178 	}
   2179       }
   2180     }
   2181 
   2182 
   2183     /* this call will always give us the elapsed time for the test, and */
   2184     /* will also store-away the necessaries for cpu utilization */
   2185 
   2186     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
   2187 						/* measured? how long */
   2188 						/* did we really run? */
   2189 
   2190     /* Get the statistics from the remote end. The remote will have */
   2191     /* calculated service demand and all those interesting things. If it */
   2192     /* wasn't supposed to care, it will return obvious values. */
   2193 
   2194     recv_response();
   2195     if (!netperf_response.content.serv_errno) {
   2196       if (debug)
   2197 	fprintf(where,"remote results obtained\n");
   2198     }
   2199     else {
   2200       Set_errno(netperf_response.content.serv_errno);
   2201       perror("netperf: remote error");
   2202 
   2203       exit(1);
   2204     }
   2205 
   2206     /* We now calculate what our thruput was for the test. */
   2207 
   2208     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
   2209     thruput	= nummessages/elapsed_time;
   2210 
   2211     if (local_cpu_usage || remote_cpu_usage) {
   2212       /* We must now do a little math for service demand and cpu */
   2213       /* utilization for the system(s) */
   2214       /* Of course, some of the information might be bogus because */
   2215       /* there was no idle counter in the kernel(s). We need to make */
   2216       /* a note of this for the user's benefit...*/
   2217       if (local_cpu_usage) {
   2218 	local_cpu_utilization = calc_cpu_util(0.0);
   2219 	/* since calc_service demand is doing ms/Kunit we will */
   2220 	/* multiply the number of transaction by 1024 to get */
   2221 	/* "good" numbers */
   2222 	local_service_demand  = calc_service_demand((double) nummessages*1024,
   2223 						    0.0,
   2224 						    0.0,
   2225 						    0);
   2226       }
   2227       else {
   2228 	local_cpu_utilization	= -1.0;
   2229 	local_service_demand	= -1.0;
   2230       }
   2231 
   2232       if (remote_cpu_usage) {
   2233 	remote_cpu_utilization = xti_tcp_rr_result->cpu_util;
   2234 	/* since calc_service demand is doing ms/Kunit we will */
   2235 	/* multiply the number of transaction by 1024 to get */
   2236 	/* "good" numbers */
   2237 	remote_service_demand = calc_service_demand((double) nummessages*1024,
   2238 						    0.0,
   2239 						    remote_cpu_utilization,
   2240 						    xti_tcp_rr_result->num_cpus);
   2241       }
   2242       else {
   2243 	remote_cpu_utilization = -1.0;
   2244 	remote_service_demand  = -1.0;
   2245       }
   2246 
   2247     }
   2248     else {
   2249       /* we were not measuring cpu, for the confidence stuff, we */
   2250       /* should make it -1.0 */
   2251       local_cpu_utilization	= -1.0;
   2252       local_service_demand	= -1.0;
   2253       remote_cpu_utilization = -1.0;
   2254       remote_service_demand  = -1.0;
   2255     }
   2256 
   2257     /* at this point, we want to calculate the confidence information. */
   2258     /* if debugging is on, calculate_confidence will print-out the */
   2259     /* parameters we pass it */
   2260 
   2261     calculate_confidence(confidence_iteration,
   2262 			 elapsed_time,
   2263 			 thruput,
   2264 			 local_cpu_utilization,
   2265 			 remote_cpu_utilization,
   2266 			 local_service_demand,
   2267 			 remote_service_demand);
   2268 
   2269 
   2270     confidence_iteration++;
   2271 
   2272     /* we are now done with the socket, so close it */
   2273     t_close(send_socket);
   2274 
   2275   }
   2276 
   2277   retrieve_confident_values(&elapsed_time,
   2278 			    &thruput,
   2279 			    &local_cpu_utilization,
   2280 			    &remote_cpu_utilization,
   2281 			    &local_service_demand,
   2282 			    &remote_service_demand);
   2283 
   2284   /* We are now ready to print all the information. If the user */
   2285   /* has specified zero-level verbosity, we will just print the */
   2286   /* local service demand, or the remote service demand. If the */
   2287   /* user has requested verbosity level 1, he will get the basic */
   2288   /* "streamperf" numbers. If the user has specified a verbosity */
   2289   /* of greater than 1, we will display a veritable plethora of */
   2290   /* background information from outside of this block as it it */
   2291   /* not cpu_measurement specific...  */
   2292 
   2293   if (confidence < 0) {
   2294     /* we did not hit confidence, but were we asked to look for it? */
   2295     if (iteration_max > 1) {
   2296       display_confidence();
   2297     }
   2298   }
   2299 
   2300   if (local_cpu_usage || remote_cpu_usage) {
   2301     local_cpu_method = format_cpu_method(cpu_method);
   2302     remote_cpu_method = format_cpu_method(xti_tcp_rr_result->cpu_method);
   2303 
   2304     switch (verbosity) {
   2305     case 0:
   2306       if (local_cpu_usage) {
   2307 	fprintf(where,
   2308 		cpu_fmt_0,
   2309 		local_service_demand,
   2310 		local_cpu_method);
   2311       }
   2312       else {
   2313 	fprintf(where,
   2314 		cpu_fmt_0,
   2315 		remote_service_demand,
   2316 		remote_cpu_method);
   2317       }
   2318       break;
   2319     case 1:
   2320     case 2:
   2321       if (print_headers) {
   2322 	fprintf(where,
   2323 		cpu_title,
   2324 		local_cpu_method,
   2325 		remote_cpu_method);
   2326       }
   2327 
   2328       fprintf(where,
   2329 	      cpu_fmt_1_line_1,		/* the format string */
   2330 	      lss_size,		/* local sendbuf size */
   2331 	      lsr_size,
   2332 	      req_size,		/* how large were the requests */
   2333 	      rsp_size,		/* guess */
   2334 	      elapsed_time,		/* how long was the test */
   2335 	      thruput,
   2336 	      local_cpu_utilization,	/* local cpu */
   2337 	      remote_cpu_utilization,	/* remote cpu */
   2338 	      local_service_demand,	/* local service demand */
   2339 	      remote_service_demand);	/* remote service demand */
   2340       fprintf(where,
   2341 	      cpu_fmt_1_line_2,
   2342 	      rss_size,
   2343 	      rsr_size);
   2344       break;
   2345     }
   2346   }
   2347   else {
   2348     /* The tester did not wish to measure service demand. */
   2349 
   2350     switch (verbosity) {
   2351     case 0:
   2352       fprintf(where,
   2353 	      tput_fmt_0,
   2354 	      thruput);
   2355       break;
   2356     case 1:
   2357     case 2:
   2358       if (print_headers) {
   2359 	fprintf(where,tput_title,format_units());
   2360       }
   2361 
   2362       fprintf(where,
   2363 	      tput_fmt_1_line_1,	/* the format string */
   2364 	      lss_size,
   2365 	      lsr_size,
   2366 	      req_size,		/* how large were the requests */
   2367 	      rsp_size,		/* how large were the responses */
   2368 	      elapsed_time, 		/* how long did it take */
   2369 	      thruput);
   2370       fprintf(where,
   2371 	      tput_fmt_1_line_2,
   2372 	      rss_size, 		/* remote recvbuf size */
   2373 	      rsr_size);
   2374 
   2375       break;
   2376     }
   2377   }
   2378 
   2379   /* it would be a good thing to include information about some of the */
   2380   /* other parameters that may have been set for this test, but at the */
   2381   /* moment, I do not wish to figure-out all the  formatting, so I will */
   2382   /* just put this comment here to help remind me that it is something */
   2383   /* that should be done at a later time. */
   2384 
   2385   /* how to handle the verbose information in the presence of */
   2386   /* confidence intervals is yet to be determined... raj 11/94 */
   2387   if (verbosity > 1) {
   2388     /* The user wanted to know it all, so we will give it to him. */
   2389     /* This information will include as much as we can find about */
   2390     /* TCP statistics, the alignments of the sends and receives */
   2391     /* and all that sort of rot... */
   2392 
   2393     fprintf(where,
   2394 	    ksink_fmt,
   2395 	    local_send_align,
   2396 	    remote_recv_offset,
   2397 	    local_send_offset,
   2398 	    remote_recv_offset);
   2399 
   2400 #ifdef WANT_HISTOGRAM
   2401     fprintf(where,"\nHistogram of request/response times\n");
   2402     fflush(where);
   2403     HIST_report(time_hist);
   2404 #endif /* WANT_HISTOGRAM */
   2405 
   2406   }
   2407 
   2408 }
   2409 
   2410 void
   2412 send_xti_udp_stream(char remote_host[])
   2413 {
   2414   /**********************************************************************/
   2415   /*									*/
   2416   /*               	UDP Unidirectional Send Test                    */
   2417   /*									*/
   2418   /**********************************************************************/
   2419   char *tput_title = "\
   2420 Socket  Message  Elapsed      Messages                \n\
   2421 Size    Size     Time         Okay Errors   Throughput\n\
   2422 bytes   bytes    secs            #      #   %s/sec\n\n";
   2423 
   2424   char *tput_fmt_0 =
   2425     "%7.2f\n";
   2426 
   2427   char *tput_fmt_1 = "\
   2428 %6d  %6d   %-7.2f   %7d %6d    %7.2f\n\
   2429 %6d           %-7.2f   %7d           %7.2f\n\n";
   2430 
   2431 
   2432   char *cpu_title = "\
   2433 Socket  Message  Elapsed      Messages                   CPU      Service\n\
   2434 Size    Size     Time         Okay Errors   Throughput   Util     Demand\n\
   2435 bytes   bytes    secs            #      #   %s/sec %% %c%c     us/KB\n\n";
   2436 
   2437   char *cpu_fmt_0 =
   2438     "%6.2f %c\n";
   2439 
   2440   char *cpu_fmt_1 = "\
   2441 %6d  %6d   %-7.2f   %7d %6d    %7.1f     %-6.2f   %-6.3f\n\
   2442 %6d           %-7.2f   %7d           %7.1f     %-6.2f   %-6.3f\n\n";
   2443 
   2444   unsigned int	messages_recvd;
   2445   unsigned int 	messages_sent;
   2446   unsigned int	failed_sends;
   2447 
   2448   float	elapsed_time,
   2449         recv_elapsed,
   2450         local_cpu_utilization,
   2451         remote_cpu_utilization;
   2452 
   2453   float	 local_service_demand, remote_service_demand;
   2454   double local_thruput, remote_thruput;
   2455   double bytes_sent;
   2456   double bytes_recvd;
   2457 
   2458 
   2459   int	len;
   2460   int	*message_int_ptr;
   2461   struct ring_elt *send_ring;
   2462   SOCKET data_socket;
   2463 
   2464   unsigned int sum_messages_sent;
   2465   unsigned int sum_messages_recvd;
   2466   unsigned int sum_failed_sends;
   2467   double sum_local_thruput;
   2468 
   2469 #ifdef WANT_INTERVALS
   2470   int	interval_count;
   2471   sigset_t signal_set;
   2472 #endif /* WANT_INTERVALS */
   2473 
   2474   struct   hostent     *hp;
   2475   struct   sockaddr_in server;
   2476   unsigned int         addr;
   2477 
   2478   struct t_unitdata unitdata;
   2479 
   2480   struct xti_udp_stream_request_struct	*xti_udp_stream_request;
   2481   struct xti_udp_stream_response_struct	*xti_udp_stream_response;
   2482   struct xti_udp_stream_results_struct	*xti_udp_stream_results;
   2483 
   2484   xti_udp_stream_request  =
   2485     (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
   2486   xti_udp_stream_response =
   2487     (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
   2488   xti_udp_stream_results  =
   2489     (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
   2490 
   2491 #ifdef WANT_HISTOGRAM
   2492   time_hist = HIST_new();
   2493 #endif /* WANT_HISTOGRAM */
   2494 
   2495   /* since we are now disconnected from the code that established the */
   2496   /* control socket, and since we want to be able to use different */
   2497   /* protocols and such, we are passed the name of the remote host and */
   2498   /* must turn that into the test specific addressing information. */
   2499 
   2500   bzero((char *)&server,
   2501 	sizeof(server));
   2502 
   2503   /* it would seem that while HP-UX will allow an IP address (as a */
   2504   /* string) in a call to gethostbyname, other, less enlightened */
   2505   /* systems do not. fix from awjacks (at) ca.sandia.gov raj 10/95 */
   2506   /* order changed to check for IP address first. raj 7/96 */
   2507 
   2508   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
   2509     /* it was not an IP address, try it as a name */
   2510     if ((hp = gethostbyname(remote_host)) == NULL) {
   2511       /* we have no idea what it is */
   2512       fprintf(where,
   2513 	      "establish_control: could not resolve the destination %s\n",
   2514 	      remote_host);
   2515       fflush(where);
   2516       exit(1);
   2517     }
   2518     else {
   2519       /* it was a valid remote_host */
   2520       bcopy(hp->h_addr,
   2521 	    (char *)&server.sin_addr,
   2522 	    hp->h_length);
   2523       server.sin_family = hp->h_addrtype;
   2524     }
   2525   }
   2526   else {
   2527     /* it was a valid IP address */
   2528     server.sin_addr.s_addr = addr;
   2529     server.sin_family = AF_INET;
   2530   }
   2531 
   2532   if ( print_headers ) {
   2533     fprintf(where,"UDP UNIDIRECTIONAL SEND TEST");
   2534     fprintf(where," to %s", remote_host);
   2535     if (iteration_max > 1) {
   2536       fprintf(where,
   2537 	      " : +/-%3.1f%% @ %2d%% conf.",
   2538 	      interval/0.02,
   2539 	      confidence_level);
   2540       }
   2541     if (loc_sndavoid ||
   2542 	loc_rcvavoid ||
   2543 	rem_sndavoid ||
   2544 	rem_rcvavoid) {
   2545       fprintf(where," : copy avoidance");
   2546     }
   2547 #ifdef WANT_HISTOGRAM
   2548     fprintf(where," : histogram");
   2549 #endif /* WANT_HISTOGRAM */
   2550 #ifdef WANT_INTERVALS
   2551     fprintf(where," : interval");
   2552 #endif /* WANT_INTERVALS */
   2553 #ifdef DIRTY
   2554     fprintf(where," : dirty data");
   2555 #endif /* DIRTY */
   2556     fprintf(where,"\n");
   2557   }
   2558 
   2559   send_ring            = NULL;
   2560   confidence_iteration = 1;
   2561   init_stat();
   2562   sum_messages_sent    = 0;
   2563   sum_messages_recvd   = 0;
   2564   sum_failed_sends     = 0;
   2565   sum_local_thruput    = 0.0;
   2566 
   2567   /* we have a great-big while loop which controls the number of times */
   2568   /* we run a particular test. this is for the calculation of a */
   2569   /* confidence interval (I really should have stayed awake during */
   2570   /* probstats :). If the user did not request confidence measurement */
   2571   /* (no confidence is the default) then we will only go though the */
   2572   /* loop once. the confidence stuff originates from the folks at IBM */
   2573 
   2574   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
   2575 	 (confidence_iteration <= iteration_min)) {
   2576 
   2577     /* initialize a few counters. we have to remember that we might be */
   2578     /* going through the loop more than once. */
   2579     messages_sent  = 0;
   2580     messages_recvd = 0;
   2581     failed_sends   = 0;
   2582     times_up       = 0;
   2583 
   2584     /*set up the data socket			*/
   2585     data_socket = create_xti_endpoint(loc_xti_device);
   2586 
   2587     if (data_socket == INVALID_SOCKET) {
   2588       perror("send_xti_udp_stream: create_xti_endpoint");
   2589       exit(1);
   2590     }
   2591 
   2592     if (t_bind(data_socket, NULL, NULL) == SOCKET_ERROR) {
   2593       t_error("send_xti_udp_stream: t_bind");
   2594       exit(1);
   2595     }
   2596 
   2597     /* now, we want to see if we need to set the send_size */
   2598     if (send_size == 0) {
   2599       if (lss_size > 0) {
   2600 	send_size = lss_size;
   2601       }
   2602       else {
   2603 	send_size = 4096;
   2604       }
   2605     }
   2606 
   2607     /* set-up the data buffer with the requested alignment and offset, */
   2608     /* most of the numbers here are just a hack to pick something nice */
   2609     /* and big in an attempt to never try to send a buffer a second time */
   2610     /* before it leaves the node...unless the user set the width */
   2611     /* explicitly. */
   2612     if (send_width == 0) send_width = 32;
   2613 
   2614     if (send_ring == NULL ) {
   2615       send_ring = allocate_buffer_ring(send_width,
   2616 				       send_size,
   2617 				       local_send_align,
   2618 				       local_send_offset);
   2619     }
   2620 
   2621 
   2622     /* if the user supplied a cpu rate, this call will complete rather */
   2623     /* quickly, otherwise, the cpu rate will be retured to us for */
   2624     /* possible display. The Library will keep it's own copy of this data */
   2625     /* for use elsewhere. We will only display it. (Does that make it */
   2626     /* "opaque" to us?) */
   2627 
   2628     if (local_cpu_usage)
   2629       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   2630 
   2631     /* Tell the remote end to set up the data connection. The server */
   2632     /* sends back the port number and alters the socket parameters there. */
   2633     /* Of course this is a datagram service so no connection is actually */
   2634     /* set up, the server just sets up the socket and binds it. */
   2635 
   2636     netperf_request.content.request_type      = DO_XTI_UDP_STREAM;
   2637     xti_udp_stream_request->recv_buf_size  = rsr_size;
   2638     xti_udp_stream_request->message_size   = send_size;
   2639     xti_udp_stream_request->recv_alignment = remote_recv_align;
   2640     xti_udp_stream_request->recv_offset    = remote_recv_offset;
   2641     xti_udp_stream_request->measure_cpu    = remote_cpu_usage;
   2642     xti_udp_stream_request->cpu_rate       = remote_cpu_rate;
   2643     xti_udp_stream_request->test_length    = test_time;
   2644     xti_udp_stream_request->so_rcvavoid    = rem_rcvavoid;
   2645     xti_udp_stream_request->so_sndavoid    = rem_sndavoid;
   2646 
   2647     strcpy(xti_udp_stream_request->xti_device, rem_xti_device);
   2648 
   2649 #ifdef __alpha
   2650 
   2651     /* ok - even on a DEC box, strings are strings. I didn't really want */
   2652     /* to ntohl the words of a string. since I don't want to teach the */
   2653     /* send_ and recv_ _request and _response routines about the types, */
   2654     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   2655     /* solution would be to use XDR, but I am still leary of being able */
   2656     /* to find XDR libs on all platforms I want running netperf. raj */
   2657     {
   2658       int *charword;
   2659       int *initword;
   2660       int *lastword;
   2661 
   2662       initword = (int *) xti_udp_stream_request->xti_device;
   2663       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
   2664 
   2665       for (charword = initword;
   2666 	   charword < lastword;
   2667 	   charword++) {
   2668 
   2669 	*charword = ntohl(*charword);
   2670       }
   2671     }
   2672 #endif /* __alpha */
   2673 
   2674     send_request();
   2675 
   2676     recv_response();
   2677 
   2678     if (!netperf_response.content.serv_errno) {
   2679       if (debug)
   2680 	fprintf(where,"send_xti_udp_stream: remote data connection done.\n");
   2681     }
   2682     else {
   2683       Set_errno(netperf_response.content.serv_errno);
   2684       perror("send_xti_udp_stream: error on remote");
   2685       exit(1);
   2686     }
   2687 
   2688     /* Place the port number returned by the remote into the sockaddr */
   2689     /* structure so our sends can be sent to the correct place. Also get */
   2690     /* some of the returned socket buffer information for user display. */
   2691 
   2692     /* make sure that port numbers are in the proper order */
   2693     server.sin_port = (short)xti_udp_stream_response->data_port_number;
   2694     server.sin_port = htons(server.sin_port);
   2695     rsr_size        = xti_udp_stream_response->recv_buf_size;
   2696     rss_size        = xti_udp_stream_response->send_buf_size;
   2697     remote_cpu_rate = xti_udp_stream_response->cpu_rate;
   2698 
   2699     /* it would seem that XTI does not allow the expedient of */
   2700     /* "connecting" a UDP end-point the way BSD does. so, we will do */
   2701     /* everything with t_sndudata and t_rcvudata. Our "virtual" */
   2702     /* connect here will be to assign the destination portion of the */
   2703     /* t_unitdata struct here, where we would have otherwise called */
   2704     /* t_connect() raj 3/95 */
   2705 
   2706     memset (&unitdata, 0, sizeof(unitdata));
   2707     unitdata.addr.maxlen = sizeof(struct sockaddr_in);
   2708     unitdata.addr.len    = sizeof(struct sockaddr_in);
   2709     unitdata.addr.buf    = (char *)&server;
   2710 
   2711     /* we don't use any options, so might as well set that part here */
   2712     /* too */
   2713 
   2714     unitdata.opt.maxlen = 0;
   2715     unitdata.opt.len    = 0;
   2716     unitdata.opt.buf    = NULL;
   2717 
   2718     /* we need to initialize the send buffer for the first time as */
   2719     /* well since we move to the next pointer after the send call. */
   2720 
   2721     unitdata.udata.maxlen = send_size;
   2722     unitdata.udata.len    = send_size;
   2723     unitdata.udata.buf    = send_ring->buffer_ptr;
   2724 
   2725     /* set up the timer to call us after test_time. one of these days, */
   2726     /* it might be nice to figure-out a nice reliable way to have the */
   2727     /* test controlled by a byte count as well, but since UDP is not */
   2728     /* reliable, that could prove difficult. so, in the meantime, we */
   2729     /* only allow a XTI_UDP_STREAM test to be a timed test. */
   2730 
   2731     if (test_time) {
   2732       times_up = 0;
   2733       start_timer(test_time);
   2734     }
   2735     else {
   2736       fprintf(where,"Sorry, XTI_UDP_STREAM tests must be timed.\n");
   2737       fflush(where);
   2738       exit(1);
   2739     }
   2740 
   2741     /* Get the start count for the idle counter and the start time */
   2742 
   2743     cpu_start(local_cpu_usage);
   2744 
   2745 #ifdef WANT_INTERVALS
   2746     if ((interval_burst) || (demo_mode)) {
   2747       /* zero means that we never pause, so we never should need the */
   2748       /* interval timer, unless we are in demo_mode */
   2749       start_itimer(interval_wate);
   2750     }
   2751     interval_count = interval_burst;
   2752     /* get the signal set for the call to sigsuspend */
   2753     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
   2754       fprintf(where,
   2755 	      "send_xti_udp_stream: unable to get sigmask errno %d\n",
   2756 	      errno);
   2757       fflush(where);
   2758       exit(1);
   2759     }
   2760 #endif /* WANT_INTERVALS */
   2761 
   2762     /* Send datagrams like there was no tomorrow. at somepoint it might */
   2763     /* be nice to set this up so that a quantity of bytes could be sent, */
   2764     /* but we still need some sort of end of test trigger on the receive */
   2765     /* side. that could be a select with a one second timeout, but then */
   2766     /* if there is a test where none of the data arrives for awile and */
   2767     /* then starts again, we would end the test too soon. something to */
   2768     /* think about... */
   2769     while (!times_up) {
   2770 
   2771 #ifdef DIRTY
   2772       /* we want to dirty some number of consecutive integers in the buffer */
   2773       /* we are about to send. we may also want to bring some number of */
   2774       /* them cleanly into the cache. The clean ones will follow any dirty */
   2775       /* ones into the cache. */
   2776 
   2777       access_buffer(send_ring->buffer_ptr,
   2778 		    send_size,
   2779 		    loc_dirty_count,
   2780 		    loc_clean_count);
   2781 
   2782 #endif /* DIRTY */
   2783 
   2784 #ifdef WANT_HISTOGRAM
   2785       HIST_timestamp(&time_one);
   2786 #endif /* WANT_HISTOGRAM */
   2787 
   2788       if ((t_sndudata(data_socket,
   2789 		      &unitdata))  != 0) {
   2790 	if (errno == EINTR)
   2791 	  break;
   2792 	if (errno == ENOBUFS) {
   2793 	  failed_sends++;
   2794 	  continue;
   2795 	}
   2796 	perror("xti_udp_send: data send error");
   2797 	t_error("xti_udp_send: data send error");
   2798 	exit(1);
   2799       }
   2800       messages_sent++;
   2801 
   2802       /* now we want to move our pointer to the next position in the */
   2803       /* data buffer...and update the unitdata structure */
   2804 
   2805       send_ring          = send_ring->next;
   2806       unitdata.udata.buf = send_ring->buffer_ptr;
   2807 
   2808 #ifdef WANT_HISTOGRAM
   2809       /* get the second timestamp */
   2810       HIST_timestamp(&time_two);
   2811       HIST_add(time_hist,delta_micro(&time_one,&time_two));
   2812 #endif /* WANT_HISTOGRAM */
   2813 #ifdef WANT_INTERVALS
   2814       if (demo_mode) {
   2815 	units_this_tick += send_size;
   2816       }
   2817       /* in this case, the interval count is the count-down couter */
   2818       /* to decide to sleep for a little bit */
   2819       if ((interval_burst) && (--interval_count == 0)) {
   2820 	/* call sigsuspend and wait for the interval timer to get us */
   2821 	/* out */
   2822 	if (debug) {
   2823 	  fprintf(where,"about to suspend\n");
   2824 	  fflush(where);
   2825 	}
   2826 	if (sigsuspend(&signal_set) == EFAULT) {
   2827 	  fprintf(where,
   2828 		  "send_xti_udp_stream: fault with signal set!\n");
   2829 	  fflush(where);
   2830 	  exit(1);
   2831 	}
   2832 	interval_count = interval_burst;
   2833       }
   2834 #endif /* WANT_INTERVALS */
   2835 
   2836     }
   2837 
   2838     /* This is a timed test, so the remote will be returning to us after */
   2839     /* a time. We should not need to send any "strange" messages to tell */
   2840     /* the remote that the test is completed, unless we decide to add a */
   2841     /* number of messages to the test. */
   2842 
   2843     /* the test is over, so get stats and stuff */
   2844     cpu_stop(local_cpu_usage,
   2845 	     &elapsed_time);
   2846 
   2847     /* Get the statistics from the remote end	*/
   2848     recv_response();
   2849     if (!netperf_response.content.serv_errno) {
   2850       if (debug)
   2851 	fprintf(where,"send_xti_udp_stream: remote results obtained\n");
   2852     }
   2853     else {
   2854       Set_errno(netperf_response.content.serv_errno);
   2855       perror("send_xti_udp_stream: error on remote");
   2856       exit(1);
   2857     }
   2858 
   2859     bytes_sent    = (double) send_size * (double) messages_sent;
   2860     local_thruput = calc_thruput(bytes_sent);
   2861 
   2862     messages_recvd = xti_udp_stream_results->messages_recvd;
   2863     bytes_recvd    = (double) send_size * (double) messages_recvd;
   2864 
   2865     /* we asume that the remote ran for as long as we did */
   2866 
   2867     remote_thruput = calc_thruput(bytes_recvd);
   2868 
   2869     /* print the results for this socket and message size */
   2870 
   2871     if (local_cpu_usage || remote_cpu_usage) {
   2872       /* We must now do a little math for service demand and cpu */
   2873       /* utilization for the system(s) We pass zeros for the local */
   2874       /* cpu utilization and elapsed time to tell the routine to use */
   2875       /* the libraries own values for those. */
   2876       if (local_cpu_usage) {
   2877 	local_cpu_utilization	= calc_cpu_util(0.0);
   2878 	/* shouldn't this really be based on bytes_recvd, since that is */
   2879 	/* the effective throughput of the test? I think that it should, */
   2880 	/* so will make the change raj 11/94 */
   2881 	local_service_demand	= calc_service_demand(bytes_recvd,
   2882 						      0.0,
   2883 						      0.0,
   2884 						      0);
   2885       }
   2886       else {
   2887 	local_cpu_utilization	= -1.0;
   2888 	local_service_demand	= -1.0;
   2889       }
   2890 
   2891       /* The local calculations could use variables being kept by */
   2892       /* the local netlib routines. The remote calcuations need to */
   2893       /* have a few things passed to them. */
   2894       if (remote_cpu_usage) {
   2895 	remote_cpu_utilization	= xti_udp_stream_results->cpu_util;
   2896 	remote_service_demand	= calc_service_demand(bytes_recvd,
   2897 						      0.0,
   2898 						      remote_cpu_utilization,
   2899 						      xti_udp_stream_results->num_cpus);
   2900       }
   2901       else {
   2902 	remote_cpu_utilization	= -1.0;
   2903 	remote_service_demand	= -1.0;
   2904       }
   2905     }
   2906     else {
   2907       /* we were not measuring cpu, for the confidence stuff, we */
   2908       /* should make it -1.0 */
   2909       local_cpu_utilization  = -1.0;
   2910       local_service_demand   = -1.0;
   2911       remote_cpu_utilization = -1.0;
   2912       remote_service_demand  = -1.0;
   2913     }
   2914 
   2915     /* at this point, we want to calculate the confidence information. */
   2916     /* if debugging is on, calculate_confidence will print-out the */
   2917     /* parameters we pass it */
   2918 
   2919     calculate_confidence(confidence_iteration,
   2920 			 elapsed_time,
   2921 			 remote_thruput,
   2922 			 local_cpu_utilization,
   2923 			 remote_cpu_utilization,
   2924 			 local_service_demand,
   2925 			 remote_service_demand);
   2926 
   2927     /* since the routine calculate_confidence is rather generic, and */
   2928     /* we have a few other parms of interest, we will do a little work */
   2929     /* here to caclulate their average. */
   2930     sum_messages_sent  += messages_sent;
   2931     sum_messages_recvd += messages_recvd;
   2932     sum_failed_sends   += failed_sends;
   2933     sum_local_thruput  += local_thruput;
   2934 
   2935     confidence_iteration++;
   2936 
   2937     /* this datapoint is done, so we don't need the socket any longer */
   2938     close(data_socket);
   2939 
   2940   }
   2941 
   2942   /* we should reach this point once the test is finished */
   2943 
   2944   retrieve_confident_values(&elapsed_time,
   2945 			    &remote_thruput,
   2946 			    &local_cpu_utilization,
   2947 			    &remote_cpu_utilization,
   2948 			    &local_service_demand,
   2949 			    &remote_service_demand);
   2950 
   2951   /* some of the interesting values aren't covered by the generic */
   2952   /* confidence routine */
   2953   messages_sent    = sum_messages_sent / (confidence_iteration -1);
   2954   messages_recvd   = sum_messages_recvd / (confidence_iteration -1);
   2955   failed_sends     = sum_failed_sends / (confidence_iteration -1);
   2956   local_thruput    = sum_local_thruput / (confidence_iteration -1);
   2957 
   2958   /* We are now ready to print all the information. If the user */
   2959   /* has specified zero-level verbosity, we will just print the */
   2960   /* local service demand, or the remote service demand. If the */
   2961   /* user has requested verbosity level 1, he will get the basic */
   2962   /* "streamperf" numbers. If the user has specified a verbosity */
   2963   /* of greater than 1, we will display a veritable plethora of */
   2964   /* background information from outside of this block as it it */
   2965   /* not cpu_measurement specific...  */
   2966 
   2967 
   2968   if (confidence < 0) {
   2969     /* we did not hit confidence, but were we asked to look for it? */
   2970     if (iteration_max > 1) {
   2971       display_confidence();
   2972     }
   2973   }
   2974 
   2975   if (local_cpu_usage || remote_cpu_usage) {
   2976     local_cpu_method = format_cpu_method(cpu_method);
   2977     remote_cpu_method = format_cpu_method(xti_udp_stream_results->cpu_method);
   2978 
   2979     switch (verbosity) {
   2980     case 0:
   2981       if (local_cpu_usage) {
   2982 	fprintf(where,
   2983 		cpu_fmt_0,
   2984 		local_service_demand,
   2985 		local_cpu_method);
   2986       }
   2987       else {
   2988 	fprintf(where,
   2989 		cpu_fmt_0,
   2990 		remote_service_demand,
   2991 		local_cpu_method);
   2992       }
   2993       break;
   2994     case 1:
   2995     case 2:
   2996       if (print_headers) {
   2997 	fprintf(where,
   2998 		cpu_title,
   2999 		format_units(),
   3000 		local_cpu_method,
   3001 		remote_cpu_method);
   3002       }
   3003 
   3004       fprintf(where,
   3005 	      cpu_fmt_1,		/* the format string */
   3006 	      lss_size,		        /* local sendbuf size */
   3007 	      send_size,		/* how large were the sends */
   3008 	      elapsed_time,		/* how long was the test */
   3009 	      messages_sent,
   3010 	      failed_sends,
   3011 	      local_thruput, 		/* what was the xfer rate */
   3012 	      local_cpu_utilization,	/* local cpu */
   3013 	      local_service_demand,	/* local service demand */
   3014 	      rsr_size,
   3015 	      elapsed_time,
   3016 	      messages_recvd,
   3017 	      remote_thruput,
   3018 	      remote_cpu_utilization,	/* remote cpu */
   3019 	      remote_service_demand);	/* remote service demand */
   3020       break;
   3021     }
   3022   }
   3023   else {
   3024     /* The tester did not wish to measure service demand. */
   3025     switch (verbosity) {
   3026     case 0:
   3027       fprintf(where,
   3028 	      tput_fmt_0,
   3029 	      local_thruput);
   3030       break;
   3031     case 1:
   3032     case 2:
   3033       if (print_headers) {
   3034 	fprintf(where,tput_title,format_units());
   3035       }
   3036       fprintf(where,
   3037 	      tput_fmt_1,		/* the format string */
   3038 	      lss_size, 		/* local sendbuf size */
   3039 	      send_size,		/* how large were the sends */
   3040 	      elapsed_time, 		/* how long did it take */
   3041 	      messages_sent,
   3042 	      failed_sends,
   3043 	      local_thruput,
   3044 	      rsr_size, 		/* remote recvbuf size */
   3045 	      elapsed_time,
   3046 	      messages_recvd,
   3047 	      remote_thruput);
   3048       break;
   3049     }
   3050   }
   3051 
   3052   fflush(where);
   3053 #ifdef WANT_HISTOGRAM
   3054   if (verbosity > 1) {
   3055     fprintf(where,"\nHistogram of time spent in send() call\n");
   3056     fflush(where);
   3057     HIST_report(time_hist);
   3058   }
   3059 #endif /* WANT_HISTOGRAM */
   3060 
   3061 }
   3062 
   3063 
   3065  /* this routine implements the receive side (netserver) of the */
   3066  /* XTI_UDP_STREAM performance test. */
   3067 
   3068 void
   3069 recv_xti_udp_stream()
   3070 {
   3071   struct ring_elt *recv_ring;
   3072 
   3073   struct t_bind bind_req, bind_resp;
   3074   struct t_unitdata unitdata;
   3075   int	            flags = 0;
   3076 
   3077   struct sockaddr_in myaddr_in;
   3078   struct sockaddr_in fromaddr_in;
   3079 
   3080   SOCKET s_data;
   3081   int 	addrlen;
   3082   unsigned int	bytes_received = 0;
   3083   float	elapsed_time;
   3084 
   3085   unsigned int	message_size;
   3086   unsigned int	messages_recvd = 0;
   3087 
   3088   struct xti_udp_stream_request_struct	*xti_udp_stream_request;
   3089   struct xti_udp_stream_response_struct	*xti_udp_stream_response;
   3090   struct xti_udp_stream_results_struct	*xti_udp_stream_results;
   3091 
   3092   xti_udp_stream_request  =
   3093     (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
   3094   xti_udp_stream_response =
   3095     (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
   3096   xti_udp_stream_results  =
   3097     (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
   3098 
   3099   if (debug) {
   3100     fprintf(where,"netserver: recv_xti_udp_stream: entered...\n");
   3101     fflush(where);
   3102   }
   3103 
   3104   /* We want to set-up the listen socket with all the desired */
   3105   /* parameters and then let the initiator know that all is ready. If */
   3106   /* socket size defaults are to be used, then the initiator will have */
   3107   /* sent us 0's. If the socket sizes cannot be changed, then we will */
   3108   /* send-back what they are. If that information cannot be determined, */
   3109   /* then we send-back -1's for the sizes. If things go wrong for any */
   3110   /* reason, we will drop back ten yards and punt. */
   3111 
   3112   /* If anything goes wrong, we want the remote to know about it. It */
   3113   /* would be best if the error that the remote reports to the user is */
   3114   /* the actual error we encountered, rather than some bogus unexpected */
   3115   /* response type message. */
   3116 
   3117   if (debug > 1) {
   3118     fprintf(where,"recv_xti_udp_stream: setting the response type...\n");
   3119     fflush(where);
   3120   }
   3121 
   3122   netperf_response.content.response_type = XTI_UDP_STREAM_RESPONSE;
   3123 
   3124   if (debug > 2) {
   3125     fprintf(where,"recv_xti_udp_stream: the response type is set...\n");
   3126     fflush(where);
   3127   }
   3128 
   3129   /* We now alter the message_ptr variable to be at the desired */
   3130   /* alignment with the desired offset. */
   3131 
   3132   if (debug > 1) {
   3133     fprintf(where,"recv_xti_udp_stream: requested alignment of %d\n",
   3134 	    xti_udp_stream_request->recv_alignment);
   3135     fflush(where);
   3136   }
   3137 
   3138   if (recv_width == 0) recv_width = 1;
   3139 
   3140   recv_ring = allocate_buffer_ring(recv_width,
   3141 				   xti_udp_stream_request->message_size,
   3142 				   xti_udp_stream_request->recv_alignment,
   3143 				   xti_udp_stream_request->recv_offset);
   3144 
   3145   if (debug > 1) {
   3146     fprintf(where,"recv_xti_udp_stream: receive alignment and offset set...\n");
   3147     fflush(where);
   3148   }
   3149 
   3150   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
   3151   /* can put in OUR values !-) At some point, we may want to nail this */
   3152   /* socket to a particular network-level address, but for now, */
   3153   /* INADDR_ANY should be just fine. */
   3154 
   3155   bzero((char *)&myaddr_in,
   3156 	sizeof(myaddr_in));
   3157   myaddr_in.sin_family      = AF_INET;
   3158   myaddr_in.sin_addr.s_addr = INADDR_ANY;
   3159   myaddr_in.sin_port        = 0;
   3160 
   3161   /* Grab a socket to listen on, and then listen on it. */
   3162 
   3163   if (debug > 1) {
   3164     fprintf(where,"recv_xti_udp_stream: grabbing a socket...\n");
   3165     fflush(where);
   3166   }
   3167 
   3168   /* create_xti_endpoint expects to find some things in the global */
   3169   /* variables, so set the globals based on the values in the request. */
   3170   /* once the socket has been created, we will set the response values */
   3171   /* based on the updated value of those globals. raj 7/94 */
   3172   lsr_size = xti_udp_stream_request->recv_buf_size;
   3173   loc_rcvavoid = xti_udp_stream_request->so_rcvavoid;
   3174   loc_sndavoid = xti_udp_stream_request->so_sndavoid;
   3175 
   3176 #ifdef __alpha
   3177 
   3178   /* ok - even on a DEC box, strings are strings. I din't really want */
   3179   /* to ntohl the words of a string. since I don't want to teach the */
   3180   /* send_ and recv_ _request and _response routines about the types, */
   3181   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   3182   /* solution would be to use XDR, but I am still leary of being able */
   3183   /* to find XDR libs on all platforms I want running netperf. raj */
   3184   {
   3185     int *charword;
   3186     int *initword;
   3187     int *lastword;
   3188 
   3189     initword = (int *) xti_udp_stream_request->xti_device;
   3190     lastword = initword + ((xti_udp_stream_request->dev_name_len + 3) / 4);
   3191 
   3192     for (charword = initword;
   3193 	 charword < lastword;
   3194 	 charword++) {
   3195 
   3196       *charword = htonl(*charword);
   3197     }
   3198   }
   3199 
   3200 #endif /* __alpha */
   3201 
   3202   s_data = create_xti_endpoint(xti_udp_stream_request->xti_device);
   3203 
   3204   if (s_data == INVALID_SOCKET) {
   3205     netperf_response.content.serv_errno = errno;
   3206     send_response();
   3207     exit(1);
   3208   }
   3209 
   3210   /* Let's get an address assigned to this socket so we can tell the */
   3211   /* initiator how to reach the data socket. There may be a desire to */
   3212   /* nail this socket to a specific IP address in a multi-homed, */
   3213   /* multi-connection situation, but for now, we'll ignore the issue */
   3214   /* and concentrate on single connection testing. */
   3215 
   3216   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
   3217   bind_req.addr.len    = sizeof(struct sockaddr_in);
   3218   bind_req.addr.buf    = (char *)&myaddr_in;
   3219   bind_req.qlen        = 1;
   3220 
   3221   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
   3222   bind_resp.addr.len    = sizeof(struct sockaddr_in);
   3223   bind_resp.addr.buf    = (char *)&myaddr_in;
   3224   bind_resp.qlen        = 1;
   3225 
   3226   if (t_bind(s_data,
   3227 	     &bind_req,
   3228 	     &bind_resp) == SOCKET_ERROR) {
   3229     netperf_response.content.serv_errno = t_errno;
   3230     send_response();
   3231 
   3232     exit(1);
   3233   }
   3234 
   3235   xti_udp_stream_response->test_length =
   3236     xti_udp_stream_request->test_length;
   3237 
   3238   /* Now myaddr_in contains the port and the internet address this is */
   3239   /* returned to the sender also implicitly telling the sender that the */
   3240   /* socket buffer sizing has been done. */
   3241 
   3242   xti_udp_stream_response->data_port_number =
   3243     (int) ntohs(myaddr_in.sin_port);
   3244   netperf_response.content.serv_errno   = 0;
   3245 
   3246   /* But wait, there's more. If the initiator wanted cpu measurements, */
   3247   /* then we must call the calibrate routine, which will return the max */
   3248   /* rate back to the initiator. If the CPU was not to be measured, or */
   3249   /* something went wrong with the calibration, we will return a -1 to */
   3250   /* the initiator. */
   3251 
   3252   xti_udp_stream_response->cpu_rate    = 0.0; /* assume no cpu */
   3253   xti_udp_stream_response->measure_cpu = 0;
   3254   if (xti_udp_stream_request->measure_cpu) {
   3255     /* We will pass the rate into the calibration routine. If the */
   3256     /* user did not specify one, it will be 0.0, and we will do a */
   3257     /* "real" calibration. Otherwise, all it will really do is */
   3258     /* store it away... */
   3259     xti_udp_stream_response->measure_cpu = 1;
   3260     xti_udp_stream_response->cpu_rate =
   3261       calibrate_local_cpu(xti_udp_stream_request->cpu_rate);
   3262   }
   3263 
   3264   message_size	= xti_udp_stream_request->message_size;
   3265   test_time	= xti_udp_stream_request->test_length;
   3266 
   3267   /* before we send the response back to the initiator, pull some of */
   3268   /* the socket parms from the globals */
   3269   xti_udp_stream_response->send_buf_size = lss_size;
   3270   xti_udp_stream_response->recv_buf_size = lsr_size;
   3271   xti_udp_stream_response->so_rcvavoid = loc_rcvavoid;
   3272   xti_udp_stream_response->so_sndavoid = loc_sndavoid;
   3273 
   3274   /* since we are going to call t_rcvudata() instead of t_rcv() we */
   3275   /* need to init the unitdata structure raj 3/95 */
   3276 
   3277   unitdata.addr.maxlen = sizeof(fromaddr_in);
   3278   unitdata.addr.len    = sizeof(fromaddr_in);
   3279   unitdata.addr.buf    = (char *)&fromaddr_in;
   3280 
   3281   unitdata.opt.maxlen = 0;
   3282   unitdata.opt.len    = 0;
   3283   unitdata.opt.buf    = NULL;
   3284 
   3285   unitdata.udata.maxlen = xti_udp_stream_request->message_size;
   3286   unitdata.udata.len    = xti_udp_stream_request->message_size;
   3287   unitdata.udata.buf    = recv_ring->buffer_ptr;
   3288 
   3289   send_response();
   3290 
   3291   /* Now it's time to start receiving data on the connection. We will */
   3292   /* first grab the apropriate counters and then start grabbing. */
   3293 
   3294   cpu_start(xti_udp_stream_request->measure_cpu);
   3295 
   3296   /* The loop will exit when the timer pops, or if we happen to recv a */
   3297   /* message of less than send_size bytes... */
   3298 
   3299   times_up = 0;
   3300   start_timer(test_time + PAD_TIME);
   3301 
   3302   if (debug) {
   3303     fprintf(where,"recv_xti_udp_stream: about to enter inner sanctum.\n");
   3304     fflush(where);
   3305   }
   3306 
   3307   while (!times_up) {
   3308 #ifdef RAJ_DEBUG
   3309     if (debug) {
   3310       fprintf(where,"t_rcvudata, errno %d, t_errno %d",
   3311 	      errno,
   3312 	      t_errno);
   3313       fprintf(where," after %d messages\n",messages_recvd);
   3314       fprintf(where,"addrmax %d addrlen %d addrbuf %x\n",
   3315 	      unitdata.addr.maxlen,
   3316 	      unitdata.addr.len,
   3317 	      unitdata.addr.buf);
   3318       fprintf(where,"optmax %d optlen %d optbuf %x\n",
   3319 	      unitdata.opt.maxlen,
   3320 	      unitdata.opt.len,
   3321 	      unitdata.opt.buf);
   3322       fprintf(where,"udatamax %d udatalen %d udatabuf %x\n",
   3323 	      unitdata.udata.maxlen,
   3324 	      unitdata.udata.len,
   3325 	      unitdata.udata.buf);
   3326       fflush(where);
   3327     }
   3328 #endif /* RAJ_DEBUG */
   3329     if (t_rcvudata(s_data,
   3330 		   &unitdata,
   3331 		   &flags) != 0) {
   3332       if (errno == TNODATA) {
   3333 	continue;
   3334       }
   3335       if (errno != EINTR) {
   3336 	netperf_response.content.serv_errno = t_errno;
   3337 	send_response();
   3338 	exit(1);
   3339       }
   3340       break;
   3341     }
   3342     messages_recvd++;
   3343     recv_ring = recv_ring->next;
   3344     unitdata.udata.buf = recv_ring->buffer_ptr;
   3345   }
   3346 
   3347   if (debug) {
   3348     fprintf(where,"recv_xti_udp_stream: got %d messages.\n",messages_recvd);
   3349     fflush(where);
   3350   }
   3351 
   3352 
   3353   /* The loop now exits due timer or < send_size bytes received. */
   3354 
   3355   cpu_stop(xti_udp_stream_request->measure_cpu,&elapsed_time);
   3356 
   3357   if (times_up) {
   3358     /* we ended on a timer, subtract the PAD_TIME */
   3359     elapsed_time -= (float)PAD_TIME;
   3360   }
   3361   else {
   3362     stop_timer();
   3363   }
   3364 
   3365   if (debug) {
   3366     fprintf(where,"recv_xti_udp_stream: test ended in %f seconds.\n",elapsed_time);
   3367     fflush(where);
   3368   }
   3369 
   3370   bytes_received = (messages_recvd * message_size);
   3371 
   3372   /* send the results to the sender			*/
   3373 
   3374   if (debug) {
   3375     fprintf(where,
   3376 	    "recv_xti_udp_stream: got %d bytes\n",
   3377 	    bytes_received);
   3378     fflush(where);
   3379   }
   3380 
   3381   netperf_response.content.response_type	= XTI_UDP_STREAM_RESULTS;
   3382   xti_udp_stream_results->bytes_received	= bytes_received;
   3383   xti_udp_stream_results->messages_recvd	= messages_recvd;
   3384   xti_udp_stream_results->elapsed_time	= elapsed_time;
   3385   xti_udp_stream_results->cpu_method        = cpu_method;
   3386   if (xti_udp_stream_request->measure_cpu) {
   3387     xti_udp_stream_results->cpu_util	= calc_cpu_util(elapsed_time);
   3388   }
   3389   else {
   3390     xti_udp_stream_results->cpu_util	= -1.0;
   3391   }
   3392 
   3393   if (debug > 1) {
   3394     fprintf(where,
   3395 	    "recv_xti_udp_stream: test complete, sending results.\n");
   3396     fflush(where);
   3397   }
   3398 
   3399   send_response();
   3400 
   3401 }
   3402 
   3403 void send_xti_udp_rr(char remote_host[])
   3405 {
   3406 
   3407   char *tput_title = "\
   3408 Local /Remote\n\
   3409 Socket Size   Request  Resp.   Elapsed  Trans.\n\
   3410 Send   Recv   Size     Size    Time     Rate         \n\
   3411 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
   3412 
   3413   char *tput_fmt_0 =
   3414     "%7.2f\n";
   3415 
   3416   char *tput_fmt_1_line_1 = "\
   3417 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
   3418   char *tput_fmt_1_line_2 = "\
   3419 %-6d %-6d\n";
   3420 
   3421   char *cpu_title = "\
   3422 Local /Remote\n\
   3423 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
   3424 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
   3425 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
   3426 
   3427   char *cpu_fmt_0 =
   3428     "%6.3f %c\n";
   3429 
   3430   char *cpu_fmt_1_line_1 = "\
   3431 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
   3432 
   3433   char *cpu_fmt_1_line_2 = "\
   3434 %-6d %-6d\n";
   3435 
   3436   char *ksink_fmt = "\
   3437 Alignment      Offset\n\
   3438 Local  Remote  Local  Remote\n\
   3439 Send   Recv    Send   Recv\n\
   3440 %5d  %5d   %5d  %5d\n";
   3441 
   3442 
   3443   float			elapsed_time;
   3444 
   3445   struct ring_elt *send_ring;
   3446   struct ring_elt *recv_ring;
   3447 
   3448   struct t_bind bind_req, bind_resp;
   3449   struct t_unitdata unitdata;
   3450   struct t_unitdata send_unitdata;
   3451   struct t_unitdata recv_unitdata;
   3452   int	            flags = 0;
   3453 
   3454   int	len;
   3455   int	nummessages;
   3456   SOCKET send_socket;
   3457   int	trans_remaining;
   3458   int	bytes_xferd;
   3459 
   3460   int	rsp_bytes_recvd;
   3461 
   3462   float	local_cpu_utilization;
   3463   float	local_service_demand;
   3464   float	remote_cpu_utilization;
   3465   float	remote_service_demand;
   3466   double thruput;
   3467 
   3468   struct	hostent	        *hp;
   3469   struct	sockaddr_in	server, myaddr_in;
   3470   unsigned      int             addr;
   3471   int	                        addrlen;
   3472 
   3473   struct	xti_udp_rr_request_struct	*xti_udp_rr_request;
   3474   struct	xti_udp_rr_response_struct	*xti_udp_rr_response;
   3475   struct	xti_udp_rr_results_struct	*xti_udp_rr_result;
   3476 
   3477 #ifdef WANT_INTERVALS
   3478   int	interval_count;
   3479   sigset_t signal_set;
   3480 #endif /* WANT_INTERVALS */
   3481 
   3482   xti_udp_rr_request  =
   3483     (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
   3484   xti_udp_rr_response =
   3485     (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
   3486   xti_udp_rr_result	 =
   3487     (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
   3488 
   3489 #ifdef WANT_HISTOGRAM
   3490   time_hist = HIST_new();
   3491 #endif
   3492 
   3493   /* since we are now disconnected from the code that established the */
   3494   /* control socket, and since we want to be able to use different */
   3495   /* protocols and such, we are passed the name of the remote host and */
   3496   /* must turn that into the test specific addressing information. */
   3497 
   3498   bzero((char *)&server,
   3499 	sizeof(server));
   3500 
   3501   /* it would seem that while HP-UX will allow an IP address (as a */
   3502   /* string) in a call to gethostbyname, other, less enlightened */
   3503   /* systems do not. fix from awjacks (at) ca.sandia.gov raj 10/95 */
   3504   /* order changed to check for IP address first. raj 7/96 */
   3505 
   3506   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
   3507     /* it was not an IP address, try it as a name */
   3508     if ((hp = gethostbyname(remote_host)) == NULL) {
   3509       /* we have no idea what it is */
   3510       fprintf(where,
   3511 	      "establish_control: could not resolve the destination %s\n",
   3512 	      remote_host);
   3513       fflush(where);
   3514       exit(1);
   3515     }
   3516     else {
   3517       /* it was a valid remote_host */
   3518       bcopy(hp->h_addr,
   3519 	    (char *)&server.sin_addr,
   3520 	    hp->h_length);
   3521       server.sin_family = hp->h_addrtype;
   3522     }
   3523   }
   3524   else {
   3525     /* it was a valid IP address */
   3526     server.sin_addr.s_addr = addr;
   3527     server.sin_family = AF_INET;
   3528   }
   3529 
   3530   if ( print_headers ) {
   3531     fprintf(where,"XTI UDP REQUEST/RESPONSE TEST");
   3532         fprintf(where," to %s", remote_host);
   3533     if (iteration_max > 1) {
   3534       fprintf(where,
   3535 	      " : +/-%3.1f%% @ %2d%% conf.",
   3536 	      interval/0.02,
   3537 	      confidence_level);
   3538       }
   3539     if (loc_sndavoid ||
   3540 	loc_rcvavoid ||
   3541 	rem_sndavoid ||
   3542 	rem_rcvavoid) {
   3543       fprintf(where," : copy avoidance");
   3544     }
   3545 #ifdef WANT_HISTOGRAM
   3546     fprintf(where," : histogram");
   3547 #endif /* WANT_HISTOGRAM */
   3548 #ifdef WANT_INTERVALS
   3549     fprintf(where," : interval");
   3550 #endif /* WANT_INTERVALS */
   3551 #ifdef DIRTY
   3552     fprintf(where," : dirty data");
   3553 #endif /* DIRTY */
   3554     fprintf(where,"\n");
   3555   }
   3556 
   3557   /* initialize a few counters */
   3558 
   3559   send_ring     = NULL;
   3560   recv_ring     = NULL;
   3561   nummessages	= 0;
   3562   bytes_xferd	= 0;
   3563   times_up 	= 0;
   3564   confidence_iteration = 1;
   3565   init_stat();
   3566 
   3567 
   3568   /* we have a great-big while loop which controls the number of times */
   3569   /* we run a particular test. this is for the calculation of a */
   3570   /* confidence interval (I really should have stayed awake during */
   3571   /* probstats :). If the user did not request confidence measurement */
   3572   /* (no confidence is the default) then we will only go though the */
   3573   /* loop once. the confidence stuff originates from the folks at IBM */
   3574 
   3575   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
   3576 	 (confidence_iteration <= iteration_min)) {
   3577 
   3578     nummessages     = 0;
   3579     bytes_xferd     = 0.0;
   3580     times_up        = 0;
   3581     trans_remaining = 0;
   3582 
   3583     /* set-up the data buffers with the requested alignment and offset */
   3584 
   3585     if (send_width == 0) send_width = 1;
   3586     if (recv_width == 0) recv_width = 1;
   3587 
   3588     if (send_ring == NULL) {
   3589       send_ring = allocate_buffer_ring(send_width,
   3590 				       req_size,
   3591 				       local_send_align,
   3592 				       local_send_offset);
   3593     }
   3594 
   3595     if (recv_ring == NULL) {
   3596       recv_ring = allocate_buffer_ring(recv_width,
   3597 				       rsp_size,
   3598 				       local_recv_align,
   3599 				       local_recv_offset);
   3600     }
   3601 
   3602   /* since we are going to call t_rcvudata() instead of t_rcv() we */
   3603   /* need to init the unitdata structure raj 8/95 */
   3604 
   3605     memset (&recv_unitdata, 0, sizeof(recv_unitdata));
   3606     recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
   3607     recv_unitdata.addr.len    = sizeof(struct sockaddr_in);
   3608     recv_unitdata.addr.buf    = (char *)&server;
   3609 
   3610     recv_unitdata.opt.maxlen = 0;
   3611     recv_unitdata.opt.len    = 0;
   3612     recv_unitdata.opt.buf    = NULL;
   3613 
   3614     recv_unitdata.udata.maxlen = rsp_size;
   3615     recv_unitdata.udata.len    = rsp_size;
   3616     recv_unitdata.udata.buf    = recv_ring->buffer_ptr;
   3617 
   3618     /* since we are going to call t_sndudata() instead of t_snd() we */
   3619     /* need to init the unitdata structure raj 8/95 */
   3620 
   3621     memset (&send_unitdata, 0, sizeof(send_unitdata));
   3622     send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
   3623     send_unitdata.addr.len    = sizeof(struct sockaddr_in);
   3624     send_unitdata.addr.buf    = (char *)&server;
   3625 
   3626     send_unitdata.opt.maxlen = 0;
   3627     send_unitdata.opt.len    = 0;
   3628     send_unitdata.opt.buf    = NULL;
   3629 
   3630     send_unitdata.udata.maxlen = req_size;
   3631     send_unitdata.udata.len    = req_size;
   3632     send_unitdata.udata.buf    = send_ring->buffer_ptr;
   3633 
   3634     /*set up the data socket                        */
   3635     send_socket = create_xti_endpoint(loc_xti_device);
   3636 
   3637     if (send_socket == INVALID_SOCKET){
   3638       perror("netperf: send_xti_udp_rr: udp rr data socket");
   3639       exit(1);
   3640     }
   3641 
   3642     if (debug) {
   3643       fprintf(where,"send_xti_udp_rr: send_socket obtained...\n");
   3644     }
   3645 
   3646     /* it would seem that with XTI, there is no implicit bind  */
   3647     /* so we have to make a call to t_bind. this is not */
   3648     /* terribly convenient, but I suppose that "standard is better */
   3649     /* than better" :) raj 2/95 */
   3650 
   3651     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
   3652       t_error("send_xti_tcp_stream: t_bind");
   3653       exit(1);
   3654     }
   3655 
   3656     /* If the user has requested cpu utilization measurements, we must */
   3657     /* calibrate the cpu(s). We will perform this task within the tests */
   3658     /* themselves. If the user has specified the cpu rate, then */
   3659     /* calibrate_local_cpu will return rather quickly as it will have */
   3660     /* nothing to do. If local_cpu_rate is zero, then we will go through */
   3661     /* all the "normal" calibration stuff and return the rate back. If */
   3662     /* there is no idle counter in the kernel idle loop, the */
   3663     /* local_cpu_rate will be set to -1. */
   3664 
   3665     if (local_cpu_usage) {
   3666       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   3667     }
   3668 
   3669     /* Tell the remote end to do a listen. The server alters the socket */
   3670     /* paramters on the other side at this point, hence the reason for */
   3671     /* all the values being passed in the setup message. If the user did */
   3672     /* not specify any of the parameters, they will be passed as 0, which */
   3673     /* will indicate to the remote that no changes beyond the system's */
   3674     /* default should be used. Alignment is the exception, it will */
   3675     /* default to 8, which will be no alignment alterations. */
   3676 
   3677     netperf_request.content.request_type	= DO_XTI_UDP_RR;
   3678     xti_udp_rr_request->recv_buf_size	= rsr_size;
   3679     xti_udp_rr_request->send_buf_size	= rss_size;
   3680     xti_udp_rr_request->recv_alignment  = remote_recv_align;
   3681     xti_udp_rr_request->recv_offset	= remote_recv_offset;
   3682     xti_udp_rr_request->send_alignment  = remote_send_align;
   3683     xti_udp_rr_request->send_offset	= remote_send_offset;
   3684     xti_udp_rr_request->request_size	= req_size;
   3685     xti_udp_rr_request->response_size	= rsp_size;
   3686     xti_udp_rr_request->measure_cpu	= remote_cpu_usage;
   3687     xti_udp_rr_request->cpu_rate	= remote_cpu_rate;
   3688     xti_udp_rr_request->so_rcvavoid	= rem_rcvavoid;
   3689     xti_udp_rr_request->so_sndavoid	= rem_sndavoid;
   3690     if (test_time) {
   3691       xti_udp_rr_request->test_length	= test_time;
   3692     }
   3693     else {
   3694       xti_udp_rr_request->test_length	= test_trans * -1;
   3695     }
   3696 
   3697     strcpy(xti_udp_rr_request->xti_device, rem_xti_device);
   3698 
   3699 #ifdef __alpha
   3700 
   3701     /* ok - even on a DEC box, strings are strings. I didn't really want */
   3702     /* to ntohl the words of a string. since I don't want to teach the */
   3703     /* send_ and recv_ _request and _response routines about the types, */
   3704     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   3705     /* solution would be to use XDR, but I am still leary of being able */
   3706     /* to find XDR libs on all platforms I want running netperf. raj */
   3707     {
   3708       int *charword;
   3709       int *initword;
   3710       int *lastword;
   3711 
   3712       initword = (int *) xti_udp_rr_request->xti_device;
   3713       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
   3714 
   3715       for (charword = initword;
   3716 	   charword < lastword;
   3717 	   charword++) {
   3718 
   3719 	*charword = ntohl(*charword);
   3720       }
   3721     }
   3722 #endif /* __alpha */
   3723 
   3724     if (debug > 1) {
   3725       fprintf(where,"netperf: send_xti_udp_rr: requesting UDP r/r test\n");
   3726     }
   3727 
   3728     send_request();
   3729 
   3730     /* The response from the remote will contain all of the relevant 	*/
   3731     /* socket parameters for this test type. We will put them back into */
   3732     /* the variables here so they can be displayed if desired.  The	*/
   3733     /* remote will have calibrated CPU if necessary, and will have done	*/
   3734     /* all the needed set-up we will have calibrated the cpu locally	*/
   3735     /* before sending the request, and will grab the counter value right*/
   3736     /* after the connect returns. The remote will grab the counter right*/
   3737     /* after the accept call. This saves the hassle of extra messages	*/
   3738     /* being sent for the UDP tests.					*/
   3739 
   3740     recv_response();
   3741 
   3742     if (!netperf_response.content.serv_errno) {
   3743       if (debug)
   3744 	fprintf(where,"remote listen done.\n");
   3745       rsr_size	       =	xti_udp_rr_response->recv_buf_size;
   3746       rss_size	       =	xti_udp_rr_response->send_buf_size;
   3747       remote_cpu_usage =	xti_udp_rr_response->measure_cpu;
   3748       remote_cpu_rate  = 	xti_udp_rr_response->cpu_rate;
   3749       /* port numbers in proper order */
   3750       server.sin_port  =	(short)xti_udp_rr_response->data_port_number;
   3751       server.sin_port  = 	htons(server.sin_port);
   3752     }
   3753     else {
   3754       Set_errno(netperf_response.content.serv_errno);
   3755       perror("netperf: remote error");
   3756 
   3757       exit(1);
   3758     }
   3759 
   3760     /* Data Socket set-up is finished. If there were problems, either the */
   3761     /* connect would have failed, or the previous response would have */
   3762     /* indicated a problem. I failed to see the value of the extra */
   3763     /* message after the accept on the remote. If it failed, we'll see it */
   3764     /* here. If it didn't, we might as well start pumping data. */
   3765 
   3766     /* Set-up the test end conditions. For a request/response test, they */
   3767     /* can be either time or transaction based. */
   3768 
   3769     if (test_time) {
   3770       /* The user wanted to end the test after a period of time. */
   3771       times_up = 0;
   3772       trans_remaining = 0;
   3773       start_timer(test_time);
   3774     }
   3775     else {
   3776       /* The tester wanted to send a number of bytes. */
   3777       trans_remaining = test_bytes;
   3778       times_up = 1;
   3779     }
   3780 
   3781     /* The cpu_start routine will grab the current time and possibly */
   3782     /* value of the idle counter for later use in measuring cpu */
   3783     /* utilization and/or service demand and thruput. */
   3784 
   3785     cpu_start(local_cpu_usage);
   3786 
   3787 #ifdef WANT_INTERVALS
   3788     if ((interval_burst) || (demo_mode)) {
   3789       /* zero means that we never pause, so we never should need the */
   3790       /* interval timer, unless we are in demo_mode */
   3791       start_itimer(interval_wate);
   3792     }
   3793     interval_count = interval_burst;
   3794     /* get the signal set for the call to sigsuspend */
   3795     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
   3796       fprintf(where,
   3797 	      "send_xti_udp_rr: unable to get sigmask errno %d\n",
   3798 	      errno);
   3799       fflush(where);
   3800       exit(1);
   3801     }
   3802 #endif /* WANT_INTERVALS */
   3803 
   3804     /* We use an "OR" to control test execution. When the test is */
   3805     /* controlled by time, the byte count check will always return */
   3806     /* false. When the test is controlled by byte count, the time test */
   3807     /* will always return false. When the test is finished, the whole */
   3808     /* expression will go false and we will stop sending data. I think */
   3809     /* I just arbitrarily decrement trans_remaining for the timed */
   3810     /* test, but will not do that just yet... One other question is */
   3811     /* whether or not the send buffer and the receive buffer should be */
   3812     /* the same buffer. */
   3813 
   3814     while ((!times_up) || (trans_remaining > 0)) {
   3815       /* send the request */
   3816 #ifdef WANT_HISTOGRAM
   3817       HIST_timestamp(&time_one);
   3818 #endif
   3819       if((t_sndudata(send_socket,
   3820 		     &send_unitdata)) != 0) {
   3821 	if (errno == EINTR) {
   3822 	  /* We likely hit */
   3823 	  /* test-end time. */
   3824 	  break;
   3825 	}
   3826         fprintf(where,
   3827 		"send_xti_udp_rr: t_sndudata: errno %d t_errno %d t_look 0x%.4x\n",
   3828 		errno,
   3829 		t_errno,
   3830 		t_look(send_socket));
   3831 	fflush(where);
   3832 	exit(1);
   3833       }
   3834       send_ring = send_ring->next;
   3835 
   3836       /* receive the response. with UDP we will get it all, or nothing */
   3837 
   3838       if((t_rcvudata(send_socket,
   3839 		     &recv_unitdata,
   3840 		     &flags)) != 0) {
   3841 	if (errno == TNODATA) {
   3842 	  continue;
   3843 	}
   3844 	if (errno == EINTR) {
   3845 	  /* Again, we have likely hit test-end time */
   3846 	  break;
   3847 	}
   3848 	fprintf(where,
   3849 		"send_xti_udp_rr: t_rcvudata: errno %d t_errno %d t_look 0x%x\n",
   3850 		errno,
   3851 		t_errno,
   3852 		t_look(send_socket));
   3853 	fprintf(where,
   3854 		"recv_unitdata.udata.buf %x\n",recv_unitdata.udata.buf);
   3855 	fprintf(where,
   3856 		"recv_unitdata.udata.maxlen %x\n",recv_unitdata.udata.maxlen);
   3857 	fprintf(where,
   3858 		"recv_unitdata.udata.len %x\n",recv_unitdata.udata.len);
   3859 	fprintf(where,
   3860 		"recv_unitdata.addr.buf %x\n",recv_unitdata.addr.buf);
   3861 	fprintf(where,
   3862 		"recv_unitdata.addr.maxlen %x\n",recv_unitdata.addr.maxlen);
   3863 	fprintf(where,
   3864 		"recv_unitdata.addr.len %x\n",recv_unitdata.addr.len);
   3865 	fflush(where);
   3866 	exit(1);
   3867       }
   3868       recv_ring = recv_ring->next;
   3869 
   3870 #ifdef WANT_HISTOGRAM
   3871       HIST_timestamp(&time_two);
   3872       HIST_add(time_hist,delta_micro(&time_one,&time_two));
   3873 
   3874       /* at this point, we may wish to sleep for some period of */
   3875       /* time, so we see how long that last transaction just took, */
   3876       /* and sleep for the difference of that and the interval. We */
   3877       /* will not sleep if the time would be less than a */
   3878       /* millisecond.  */
   3879 #endif
   3880 #ifdef WANT_INTERVALS
   3881       if (demo_mode) {
   3882 	units_this_tick += 1;
   3883       }
   3884       /* in this case, the interval count is the count-down couter */
   3885       /* to decide to sleep for a little bit */
   3886       if ((interval_burst) && (--interval_count == 0)) {
   3887 	/* call sigsuspend and wait for the interval timer to get us */
   3888 	/* out */
   3889 	if (debug) {
   3890 	  fprintf(where,"about to suspend\n");
   3891 	  fflush(where);
   3892 	}
   3893 	if (sigsuspend(&signal_set) == EFAULT) {
   3894 	  fprintf(where,
   3895 		  "send_xti_udp_rr: fault with signal set!\n");
   3896 	  fflush(where);
   3897 	  exit(1);
   3898 	}
   3899 	interval_count = interval_burst;
   3900       }
   3901 #endif /* WANT_INTERVALS */
   3902 
   3903       nummessages++;
   3904       if (trans_remaining) {
   3905 	trans_remaining--;
   3906       }
   3907 
   3908       if (debug > 3) {
   3909 	if ((nummessages % 100) == 0) {
   3910 	  fprintf(where,"Transaction %d completed\n",nummessages);
   3911 	  fflush(where);
   3912 	}
   3913       }
   3914 
   3915     }
   3916 
   3917     /* this call will always give us the elapsed time for the test, and */
   3918     /* will also store-away the necessaries for cpu utilization */
   3919 
   3920     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
   3921 						/* measured? how long */
   3922 						/* did we really run? */
   3923 
   3924     /* Get the statistics from the remote end. The remote will have */
   3925     /* calculated service demand and all those interesting things. If */
   3926     /* it wasn't supposed to care, it will return obvious values. */
   3927 
   3928     recv_response();
   3929     if (!netperf_response.content.serv_errno) {
   3930       if (debug)
   3931 	fprintf(where,"remote results obtained\n");
   3932     }
   3933     else {
   3934       Set_errno(netperf_response.content.serv_errno);
   3935       perror("netperf: remote error");
   3936 
   3937       exit(1);
   3938     }
   3939 
   3940     /* We now calculate what our thruput was for the test. In the */
   3941     /* future, we may want to include a calculation of the thruput */
   3942     /* measured by the remote, but it should be the case that for a */
   3943     /* UDP rr test, that the two numbers should be *very* close... */
   3944     /* We calculate bytes_sent regardless of the way the test length */
   3945     /* was controlled.  */
   3946 
   3947     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
   3948     thruput	= nummessages / elapsed_time;
   3949 
   3950     if (local_cpu_usage || remote_cpu_usage) {
   3951 
   3952       /* We must now do a little math for service demand and cpu */
   3953       /* utilization for the system(s) Of course, some of the */
   3954       /* information might be bogus because there was no idle counter */
   3955       /* in the kernel(s). We need to make a note of this for the */
   3956       /* user's benefit by placing a code for the metod used in the */
   3957       /* test banner */
   3958 
   3959       if (local_cpu_usage) {
   3960 	local_cpu_utilization = calc_cpu_util(0.0);
   3961 
   3962 	/* since calc_service demand is doing ms/Kunit we will */
   3963 	/* multiply the number of transaction by 1024 to get */
   3964 	/* "good" numbers */
   3965 
   3966 	local_service_demand  = calc_service_demand((double) nummessages*1024,
   3967 						    0.0,
   3968 						    0.0,
   3969 						    0);
   3970       }
   3971       else {
   3972 	local_cpu_utilization	= -1.0;
   3973 	local_service_demand	= -1.0;
   3974       }
   3975 
   3976       if (remote_cpu_usage) {
   3977 	remote_cpu_utilization = xti_udp_rr_result->cpu_util;
   3978 
   3979 	/* since calc_service demand is doing ms/Kunit we will */
   3980 	/* multiply the number of transaction by 1024 to get */
   3981 	/* "good" numbers */
   3982 
   3983 	remote_service_demand  = calc_service_demand((double) nummessages*1024,
   3984 						     0.0,
   3985 						     remote_cpu_utilization,
   3986 						     xti_udp_rr_result->num_cpus);
   3987       }
   3988       else {
   3989 	remote_cpu_utilization = -1.0;
   3990 	remote_service_demand  = -1.0;
   3991       }
   3992     }
   3993     else {
   3994       /* we were not measuring cpu, for the confidence stuff, we */
   3995       /* should make it -1.0 */
   3996       local_cpu_utilization	= -1.0;
   3997       local_service_demand	= -1.0;
   3998       remote_cpu_utilization = -1.0;
   3999       remote_service_demand  = -1.0;
   4000     }
   4001 
   4002     /* at this point, we want to calculate the confidence information. */
   4003     /* if debugging is on, calculate_confidence will print-out the */
   4004     /* parameters we pass it */
   4005 
   4006     calculate_confidence(confidence_iteration,
   4007 			 elapsed_time,
   4008 			 thruput,
   4009 			 local_cpu_utilization,
   4010 			 remote_cpu_utilization,
   4011 			 local_service_demand,
   4012 			 remote_service_demand);
   4013 
   4014 
   4015     confidence_iteration++;
   4016 
   4017     /* we are done with the socket */
   4018     t_close(send_socket);
   4019   }
   4020 
   4021   /* at this point, we have made all the iterations we are going to */
   4022   /* make. */
   4023   retrieve_confident_values(&elapsed_time,
   4024 			    &thruput,
   4025 			    &local_cpu_utilization,
   4026 			    &remote_cpu_utilization,
   4027 			    &local_service_demand,
   4028 			    &remote_service_demand);
   4029 
   4030   /* We are now ready to print all the information. If the user */
   4031   /* has specified zero-level verbosity, we will just print the */
   4032   /* local service demand, or the remote service demand. If the */
   4033   /* user has requested verbosity level 1, he will get the basic */
   4034   /* "streamperf" numbers. If the user has specified a verbosity */
   4035   /* of greater than 1, we will display a veritable plethora of */
   4036   /* background information from outside of this block as it it */
   4037   /* not cpu_measurement specific...  */
   4038 
   4039   if (confidence < 0) {
   4040     /* we did not hit confidence, but were we asked to look for it? */
   4041     if (iteration_max > 1) {
   4042       display_confidence();
   4043     }
   4044   }
   4045 
   4046   if (local_cpu_usage || remote_cpu_usage) {
   4047     local_cpu_method = format_cpu_method(cpu_method);
   4048     remote_cpu_method = format_cpu_method(xti_udp_rr_result->cpu_method);
   4049 
   4050     switch (verbosity) {
   4051     case 0:
   4052       if (local_cpu_usage) {
   4053 	fprintf(where,
   4054 		cpu_fmt_0,
   4055 		local_service_demand,
   4056 		local_cpu_method);
   4057       }
   4058       else {
   4059 	fprintf(where,
   4060 		cpu_fmt_0,
   4061 		remote_service_demand,
   4062 		remote_cpu_method);
   4063       }
   4064       break;
   4065     case 1:
   4066     case 2:
   4067       if (print_headers) {
   4068 	fprintf(where,
   4069 		cpu_title,
   4070 		local_cpu_method,
   4071 		remote_cpu_method);
   4072       }
   4073 
   4074       fprintf(where,
   4075 	      cpu_fmt_1_line_1,		/* the format string */
   4076 	      lss_size,		/* local sendbuf size */
   4077 	      lsr_size,
   4078 	      req_size,		/* how large were the requests */
   4079 	      rsp_size,		/* guess */
   4080 	      elapsed_time,		/* how long was the test */
   4081 	      nummessages/elapsed_time,
   4082 	      local_cpu_utilization,	/* local cpu */
   4083 	      remote_cpu_utilization,	/* remote cpu */
   4084 	      local_service_demand,	/* local service demand */
   4085 	      remote_service_demand);	/* remote service demand */
   4086       fprintf(where,
   4087 	      cpu_fmt_1_line_2,
   4088 	      rss_size,
   4089 	      rsr_size);
   4090       break;
   4091     }
   4092   }
   4093   else {
   4094     /* The tester did not wish to measure service demand. */
   4095     switch (verbosity) {
   4096     case 0:
   4097       fprintf(where,
   4098 	      tput_fmt_0,
   4099 	      nummessages/elapsed_time);
   4100       break;
   4101     case 1:
   4102     case 2:
   4103       if (print_headers) {
   4104 	fprintf(where,tput_title,format_units());
   4105       }
   4106 
   4107       fprintf(where,
   4108 	      tput_fmt_1_line_1,	/* the format string */
   4109 	      lss_size,
   4110 	      lsr_size,
   4111 	      req_size,		/* how large were the requests */
   4112 	      rsp_size,		/* how large were the responses */
   4113 	      elapsed_time, 		/* how long did it take */
   4114 	      nummessages/elapsed_time);
   4115       fprintf(where,
   4116 	      tput_fmt_1_line_2,
   4117 	      rss_size, 		/* remote recvbuf size */
   4118 	      rsr_size);
   4119 
   4120       break;
   4121     }
   4122   }
   4123   fflush(where);
   4124 
   4125   /* it would be a good thing to include information about some of the */
   4126   /* other parameters that may have been set for this test, but at the */
   4127   /* moment, I do not wish to figure-out all the  formatting, so I will */
   4128   /* just put this comment here to help remind me that it is something */
   4129   /* that should be done at a later time. */
   4130 
   4131   /* how to handle the verbose information in the presence of */
   4132   /* confidence intervals is yet to be determined... raj 11/94 */
   4133 
   4134   if (verbosity > 1) {
   4135     /* The user wanted to know it all, so we will give it to him. */
   4136     /* This information will include as much as we can find about */
   4137     /* UDP statistics, the alignments of the sends and receives */
   4138     /* and all that sort of rot... */
   4139 
   4140 #ifdef WANT_HISTOGRAM
   4141     fprintf(where,"\nHistogram of request/reponse times.\n");
   4142     fflush(where);
   4143     HIST_report(time_hist);
   4144 #endif /* WANT_HISTOGRAM */
   4145   }
   4146 }
   4147 
   4148  /* this routine implements the receive side (netserver) of a XTI_UDP_RR */
   4150  /* test. */
   4151 void
   4152   recv_xti_udp_rr()
   4153 {
   4154 
   4155   struct ring_elt *recv_ring;
   4156   struct ring_elt *send_ring;
   4157 
   4158   struct t_bind bind_req, bind_resp;
   4159   struct t_unitdata send_unitdata;
   4160   struct t_unitdata recv_unitdata;
   4161   int	            flags = 0;
   4162 
   4163   struct sockaddr_in myaddr_in, peeraddr_in;
   4164   SOCKET s_data;
   4165   int 	addrlen;
   4166   int	trans_received;
   4167   int	trans_remaining;
   4168   float	elapsed_time;
   4169 
   4170   struct	xti_udp_rr_request_struct	*xti_udp_rr_request;
   4171   struct	xti_udp_rr_response_struct	*xti_udp_rr_response;
   4172   struct	xti_udp_rr_results_struct	*xti_udp_rr_results;
   4173 
   4174 
   4175   /* a little variable initialization */
   4176   memset (&myaddr_in, 0, sizeof(struct sockaddr_in));
   4177   myaddr_in.sin_family      = AF_INET;
   4178   myaddr_in.sin_addr.s_addr = INADDR_ANY;
   4179   myaddr_in.sin_port        = 0;
   4180   memset (&peeraddr_in, 0, sizeof(struct sockaddr_in));
   4181 
   4182   /* and some not so paranoid :) */
   4183   xti_udp_rr_request  =
   4184     (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
   4185   xti_udp_rr_response =
   4186     (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
   4187   xti_udp_rr_results  =
   4188     (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
   4189 
   4190   if (debug) {
   4191     fprintf(where,"netserver: recv_xti_udp_rr: entered...\n");
   4192     fflush(where);
   4193   }
   4194 
   4195   /* We want to set-up the listen socket with all the desired */
   4196   /* parameters and then let the initiator know that all is ready. If */
   4197   /* socket size defaults are to be used, then the initiator will have */
   4198   /* sent us 0's. If the socket sizes cannot be changed, then we will */
   4199   /* send-back what they are. If that information cannot be determined, */
   4200   /* then we send-back -1's for the sizes. If things go wrong for any */
   4201   /* reason, we will drop back ten yards and punt. */
   4202 
   4203   /* If anything goes wrong, we want the remote to know about it. It */
   4204   /* would be best if the error that the remote reports to the user is */
   4205   /* the actual error we encountered, rather than some bogus unexpected */
   4206   /* response type message. */
   4207 
   4208   if (debug) {
   4209     fprintf(where,"recv_xti_udp_rr: setting the response type...\n");
   4210     fflush(where);
   4211   }
   4212 
   4213   netperf_response.content.response_type = XTI_UDP_RR_RESPONSE;
   4214 
   4215   if (debug) {
   4216     fprintf(where,"recv_xti_udp_rr: the response type is set...\n");
   4217     fflush(where);
   4218   }
   4219 
   4220   /* We now alter the message_ptr variables to be at the desired */
   4221   /* alignments with the desired offsets. */
   4222 
   4223   if (debug) {
   4224     fprintf(where,"recv_xti_udp_rr: requested recv alignment of %d offset %d\n",
   4225 	    xti_udp_rr_request->recv_alignment,
   4226 	    xti_udp_rr_request->recv_offset);
   4227     fprintf(where,"recv_xti_udp_rr: requested send alignment of %d offset %d\n",
   4228 	    xti_udp_rr_request->send_alignment,
   4229 	    xti_udp_rr_request->send_offset);
   4230     fflush(where);
   4231   }
   4232 
   4233   if (send_width == 0) send_width = 1;
   4234   if (recv_width == 0) recv_width = 1;
   4235 
   4236   recv_ring = allocate_buffer_ring(recv_width,
   4237 				   xti_udp_rr_request->request_size,
   4238 				   xti_udp_rr_request->recv_alignment,
   4239 				   xti_udp_rr_request->recv_offset);
   4240 
   4241   send_ring = allocate_buffer_ring(send_width,
   4242 				   xti_udp_rr_request->response_size,
   4243 				   xti_udp_rr_request->send_alignment,
   4244 				   xti_udp_rr_request->send_offset);
   4245 
   4246   if (debug) {
   4247     fprintf(where,"recv_xti_udp_rr: receive alignment and offset set...\n");
   4248     fflush(where);
   4249   }
   4250 
   4251   /* create_xti_endpoint expects to find some things in the global */
   4252   /* variables, so set the globals based on the values in the request. */
   4253   /* once the socket has been created, we will set the response values */
   4254   /* based on the updated value of those globals. raj 7/94 */
   4255   lss_size = xti_udp_rr_request->send_buf_size;
   4256   lsr_size = xti_udp_rr_request->recv_buf_size;
   4257   loc_rcvavoid = xti_udp_rr_request->so_rcvavoid;
   4258   loc_sndavoid = xti_udp_rr_request->so_sndavoid;
   4259 
   4260 #ifdef __alpha
   4261 
   4262   /* ok - even on a DEC box, strings are strings. I din't really want */
   4263   /* to ntohl the words of a string. since I don't want to teach the */
   4264   /* send_ and recv_ _request and _response routines about the types, */
   4265   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   4266   /* solution would be to use XDR, but I am still leary of being able */
   4267   /* to find XDR libs on all platforms I want running netperf. raj */
   4268   {
   4269     int *charword;
   4270     int *initword;
   4271     int *lastword;
   4272 
   4273     initword = (int *) xti_udp_rr_request->xti_device;
   4274     lastword = initword + ((xti_udp_rr_request->dev_name_len + 3) / 4);
   4275 
   4276     for (charword = initword;
   4277 	 charword < lastword;
   4278 	 charword++) {
   4279 
   4280       *charword = htonl(*charword);
   4281     }
   4282   }
   4283 
   4284 #endif /* __alpha */
   4285 
   4286   s_data = create_xti_endpoint(xti_udp_rr_request->xti_device);
   4287 
   4288   if (s_data == INVALID_SOCKET) {
   4289     netperf_response.content.serv_errno = errno;
   4290     send_response();
   4291     exit(1);
   4292   }
   4293 
   4294   if (debug) {
   4295     fprintf(where,"recv_xti_udp_rr: endpoint created...\n");
   4296     fflush(where);
   4297   }
   4298 
   4299   /* Let's get an address assigned to this socket so we can tell the */
   4300   /* initiator how to reach the data socket. There may be a desire to */
   4301   /* nail this socket to a specific IP address in a multi-homed, */
   4302   /* multi-connection situation, but for now, we'll ignore the issue */
   4303   /* and concentrate on single connection testing. */
   4304 
   4305   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
   4306   bind_req.addr.len    = sizeof(struct sockaddr_in);
   4307   bind_req.addr.buf    = (char *)&myaddr_in;
   4308   bind_req.qlen        = 1;
   4309 
   4310   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
   4311   bind_resp.addr.len    = sizeof(struct sockaddr_in);
   4312   bind_resp.addr.buf    = (char *)&myaddr_in;
   4313   bind_resp.qlen        = 1;
   4314 
   4315   if (t_bind(s_data,
   4316 	     &bind_req,
   4317 	     &bind_resp) == SOCKET_ERROR) {
   4318     if (debug) {
   4319       fprintf(where,
   4320 	      "recv_xti_udp_rr: t_bind failed, t_errno %d errno %d\n",
   4321 	      t_errno,
   4322 	      errno);
   4323       fflush(where);
   4324     }
   4325 
   4326     netperf_response.content.serv_errno = t_errno;
   4327     send_response();
   4328 
   4329     exit(1);
   4330   }
   4331 
   4332   if (debug) {
   4333     fprintf(where,
   4334 	    "recv_xti_udp_rr: endpoint bound to port %d...\n",
   4335 	    ntohs(myaddr_in.sin_port));
   4336     fflush(where);
   4337   }
   4338 
   4339   xti_udp_rr_response->test_length =
   4340     xti_udp_rr_request->test_length;
   4341 
   4342 
   4343   /* Now myaddr_in contains the port and the internet address this is */
   4344   /* returned to the sender also implicitly telling the sender that the */
   4345   /* socket buffer sizing has been done. */
   4346 
   4347   xti_udp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
   4348   netperf_response.content.serv_errno   = 0;
   4349 
   4350   fprintf(where,"recv port number %d\n",myaddr_in.sin_port);
   4351   fflush(where);
   4352 
   4353   /* But wait, there's more. If the initiator wanted cpu measurements, */
   4354   /* then we must call the calibrate routine, which will return the max */
   4355   /* rate back to the initiator. If the CPU was not to be measured, or */
   4356   /* something went wrong with the calibration, we will return a 0.0 to */
   4357   /* the initiator. */
   4358 
   4359   xti_udp_rr_response->cpu_rate    = 0.0; 	/* assume no cpu */
   4360   xti_udp_rr_response->measure_cpu = 0;
   4361   if (xti_udp_rr_request->measure_cpu) {
   4362     xti_udp_rr_response->measure_cpu = 1;
   4363     xti_udp_rr_response->cpu_rate =
   4364       calibrate_local_cpu(xti_udp_rr_request->cpu_rate);
   4365   }
   4366 
   4367   /* before we send the response back to the initiator, pull some of */
   4368   /* the socket parms from the globals */
   4369   xti_udp_rr_response->send_buf_size = lss_size;
   4370   xti_udp_rr_response->recv_buf_size = lsr_size;
   4371   xti_udp_rr_response->so_rcvavoid   = loc_rcvavoid;
   4372   xti_udp_rr_response->so_sndavoid   = loc_sndavoid;
   4373 
   4374   /* since we are going to call t_rcvudata() instead of t_rcv() we */
   4375   /* need to init the unitdata structure raj 3/95 */
   4376 
   4377   memset (&recv_unitdata, 0, sizeof(recv_unitdata));
   4378   recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
   4379   recv_unitdata.addr.len    = sizeof(struct sockaddr_in);
   4380   recv_unitdata.addr.buf    = (char *)&peeraddr_in;
   4381 
   4382   recv_unitdata.opt.maxlen = 0;
   4383   recv_unitdata.opt.len    = 0;
   4384   recv_unitdata.opt.buf    = NULL;
   4385 
   4386   recv_unitdata.udata.maxlen = xti_udp_rr_request->request_size;
   4387   recv_unitdata.udata.len    = xti_udp_rr_request->request_size;
   4388   recv_unitdata.udata.buf    = recv_ring->buffer_ptr;
   4389 
   4390   /* since we are going to call t_sndudata() instead of t_snd() we */
   4391   /* need to init the unitdata structure raj 8/95 */
   4392 
   4393   memset (&send_unitdata, 0, sizeof(send_unitdata));
   4394   send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
   4395   send_unitdata.addr.len    = sizeof(struct sockaddr_in);
   4396   send_unitdata.addr.buf    = (char *)&peeraddr_in;
   4397 
   4398   send_unitdata.opt.maxlen = 0;
   4399   send_unitdata.opt.len    = 0;
   4400   send_unitdata.opt.buf    = NULL;
   4401 
   4402   send_unitdata.udata.maxlen = xti_udp_rr_request->response_size;
   4403   send_unitdata.udata.len    = xti_udp_rr_request->response_size;
   4404   send_unitdata.udata.buf    = send_ring->buffer_ptr;
   4405 
   4406   send_response();
   4407 
   4408 
   4409   /* Now it's time to start receiving data on the connection. We will */
   4410   /* first grab the apropriate counters and then start grabbing. */
   4411 
   4412   cpu_start(xti_udp_rr_request->measure_cpu);
   4413 
   4414   if (xti_udp_rr_request->test_length > 0) {
   4415     times_up = 0;
   4416     trans_remaining = 0;
   4417     start_timer(xti_udp_rr_request->test_length + PAD_TIME);
   4418   }
   4419   else {
   4420     times_up = 1;
   4421     trans_remaining = xti_udp_rr_request->test_length * -1;
   4422   }
   4423 
   4424   addrlen = sizeof(peeraddr_in);
   4425   bzero((char *)&peeraddr_in, addrlen);
   4426 
   4427   trans_received = 0;
   4428 
   4429   while ((!times_up) || (trans_remaining > 0)) {
   4430 
   4431     /* receive the request from the other side */
   4432     if (t_rcvudata(s_data,
   4433 		   &recv_unitdata,
   4434 		   &flags) != 0) {
   4435       if (errno == TNODATA) {
   4436 	continue;
   4437       }
   4438       if (errno == EINTR) {
   4439 	/* we must have hit the end of test time. */
   4440 	break;
   4441       }
   4442       if (debug) {
   4443 	fprintf(where,
   4444 		"recv_xti_udp_rr: t_rcvudata failed, t_errno %d errno %d\n",
   4445 		t_errno,
   4446 		errno);
   4447 	fflush(where);
   4448       }
   4449       netperf_response.content.serv_errno = t_errno;
   4450       send_response();
   4451       exit(1);
   4452     }
   4453     recv_ring = recv_ring->next;
   4454     recv_unitdata.udata.buf = recv_ring->buffer_ptr;
   4455 
   4456     /* Now, send the response to the remote */
   4457     if (t_sndudata(s_data,
   4458 		   &send_unitdata) != 0) {
   4459       if (errno == EINTR) {
   4460 	/* we have hit end of test time. */
   4461 	break;
   4462       }
   4463       if (debug) {
   4464 	fprintf(where,
   4465 		"recv_xti_udp_rr: t_sndudata failed, t_errno %d errno %d\n",
   4466 		t_errno,
   4467 		errno);
   4468 	fflush(where);
   4469       }
   4470       netperf_response.content.serv_errno = errno;
   4471       send_response();
   4472       exit(1);
   4473     }
   4474     send_ring = send_ring->next;
   4475     send_unitdata.udata.buf = send_ring->buffer_ptr;
   4476 
   4477     trans_received++;
   4478     if (trans_remaining) {
   4479       trans_remaining--;
   4480     }
   4481 
   4482     if (debug) {
   4483       fprintf(where,
   4484 	      "recv_xti_udp_rr: Transaction %d complete.\n",
   4485 	      trans_received);
   4486       fflush(where);
   4487     }
   4488 
   4489   }
   4490 
   4491 
   4492   /* The loop now exits due to timeout or transaction count being */
   4493   /* reached */
   4494 
   4495   cpu_stop(xti_udp_rr_request->measure_cpu,&elapsed_time);
   4496 
   4497   if (times_up) {
   4498     /* we ended the test by time, which was at least 2 seconds */
   4499     /* longer than we wanted to run. so, we want to subtract */
   4500     /* PAD_TIME from the elapsed_time. */
   4501     elapsed_time -= PAD_TIME;
   4502   }
   4503   /* send the results to the sender			*/
   4504 
   4505   if (debug) {
   4506     fprintf(where,
   4507 	    "recv_xti_udp_rr: got %d transactions\n",
   4508 	    trans_received);
   4509     fflush(where);
   4510   }
   4511 
   4512   xti_udp_rr_results->bytes_received = (trans_received *
   4513 				    (xti_udp_rr_request->request_size +
   4514 				     xti_udp_rr_request->response_size));
   4515   xti_udp_rr_results->trans_received = trans_received;
   4516   xti_udp_rr_results->elapsed_time	 = elapsed_time;
   4517   xti_udp_rr_results->cpu_method     = cpu_method;
   4518   if (xti_udp_rr_request->measure_cpu) {
   4519     xti_udp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
   4520   }
   4521 
   4522   if (debug) {
   4523     fprintf(where,
   4524 	    "recv_xti_udp_rr: test complete, sending results.\n");
   4525     fflush(where);
   4526   }
   4527 
   4528   send_response();
   4529 
   4530   /* we are done with the socket now */
   4531   close(s_data);
   4532 
   4533 }
   4534 
   4535  /* this routine implements the receive (netserver) side of a XTI_TCP_RR */
   4537  /* test */
   4538 void
   4539 recv_xti_tcp_rr()
   4540 {
   4541 
   4542   struct ring_elt *send_ring;
   4543   struct ring_elt *recv_ring;
   4544 
   4545   struct sockaddr_in  myaddr_in,  peeraddr_in;
   4546   struct t_bind bind_req, bind_resp;
   4547   struct t_call call_req;
   4548 
   4549   SOCKET s_listen,s_data;
   4550   int 	addrlen;
   4551   char	*temp_message_ptr;
   4552   int	trans_received;
   4553   int	trans_remaining;
   4554   int	bytes_sent;
   4555   int	request_bytes_recvd;
   4556   int	request_bytes_remaining;
   4557   int	timed_out = 0;
   4558   float	elapsed_time;
   4559 
   4560   struct	xti_tcp_rr_request_struct	*xti_tcp_rr_request;
   4561   struct	xti_tcp_rr_response_struct	*xti_tcp_rr_response;
   4562   struct	xti_tcp_rr_results_struct	*xti_tcp_rr_results;
   4563 
   4564   xti_tcp_rr_request =
   4565     (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
   4566   xti_tcp_rr_response =
   4567     (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
   4568   xti_tcp_rr_results =
   4569     (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
   4570 
   4571   if (debug) {
   4572     fprintf(where,"netserver: recv_xti_tcp_rr: entered...\n");
   4573     fflush(where);
   4574   }
   4575 
   4576   /* We want to set-up the listen socket with all the desired */
   4577   /* parameters and then let the initiator know that all is ready. If */
   4578   /* socket size defaults are to be used, then the initiator will have */
   4579   /* sent us 0's. If the socket sizes cannot be changed, then we will */
   4580   /* send-back what they are. If that information cannot be determined, */
   4581   /* then we send-back -1's for the sizes. If things go wrong for any */
   4582   /* reason, we will drop back ten yards and punt. */
   4583 
   4584   /* If anything goes wrong, we want the remote to know about it. It */
   4585   /* would be best if the error that the remote reports to the user is */
   4586   /* the actual error we encountered, rather than some bogus unexpected */
   4587   /* response type message. */
   4588 
   4589   if (debug) {
   4590     fprintf(where,"recv_xti_tcp_rr: setting the response type...\n");
   4591     fflush(where);
   4592   }
   4593 
   4594   netperf_response.content.response_type = XTI_TCP_RR_RESPONSE;
   4595 
   4596   if (debug) {
   4597     fprintf(where,"recv_xti_tcp_rr: the response type is set...\n");
   4598     fflush(where);
   4599   }
   4600 
   4601   /* allocate the recv and send rings with the requested alignments */
   4602   /* and offsets. raj 7/94 */
   4603   if (debug) {
   4604     fprintf(where,"recv_xti_tcp_rr: requested recv alignment of %d offset %d\n",
   4605 	    xti_tcp_rr_request->recv_alignment,
   4606 	    xti_tcp_rr_request->recv_offset);
   4607     fprintf(where,"recv_xti_tcp_rr: requested send alignment of %d offset %d\n",
   4608 	    xti_tcp_rr_request->send_alignment,
   4609 	    xti_tcp_rr_request->send_offset);
   4610     fflush(where);
   4611   }
   4612 
   4613   /* at some point, these need to come to us from the remote system */
   4614   if (send_width == 0) send_width = 1;
   4615   if (recv_width == 0) recv_width = 1;
   4616 
   4617   send_ring = allocate_buffer_ring(send_width,
   4618 				   xti_tcp_rr_request->response_size,
   4619 				   xti_tcp_rr_request->send_alignment,
   4620 				   xti_tcp_rr_request->send_offset);
   4621 
   4622   recv_ring = allocate_buffer_ring(recv_width,
   4623 				   xti_tcp_rr_request->request_size,
   4624 				   xti_tcp_rr_request->recv_alignment,
   4625 				   xti_tcp_rr_request->recv_offset);
   4626 
   4627 
   4628   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
   4629   /* can put in OUR values !-) At some point, we may want to nail this */
   4630   /* socket to a particular network-level address, but for now, */
   4631   /* INADDR_ANY should be just fine. */
   4632 
   4633   bzero((char *)&myaddr_in,
   4634 	sizeof(myaddr_in));
   4635   myaddr_in.sin_family      = AF_INET;
   4636   myaddr_in.sin_addr.s_addr = INADDR_ANY;
   4637   myaddr_in.sin_port        = 0;
   4638 
   4639   /* Grab a socket to listen on, and then listen on it. */
   4640 
   4641   if (debug) {
   4642     fprintf(where,"recv_xti_tcp_rr: grabbing a socket...\n");
   4643     fflush(where);
   4644   }
   4645 
   4646   /* create_xti_endpoint expects to find some things in the global */
   4647   /* variables, so set the globals based on the values in the request. */
   4648   /* once the socket has been created, we will set the response values */
   4649   /* based on the updated value of those globals. raj 7/94 */
   4650   lss_size = xti_tcp_rr_request->send_buf_size;
   4651   lsr_size = xti_tcp_rr_request->recv_buf_size;
   4652   loc_nodelay = xti_tcp_rr_request->no_delay;
   4653   loc_rcvavoid = xti_tcp_rr_request->so_rcvavoid;
   4654   loc_sndavoid = xti_tcp_rr_request->so_sndavoid;
   4655 
   4656 #ifdef __alpha
   4657 
   4658   /* ok - even on a DEC box, strings are strings. I din't really want */
   4659   /* to ntohl the words of a string. since I don't want to teach the */
   4660   /* send_ and recv_ _request and _response routines about the types, */
   4661   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
   4662   /* solution would be to use XDR, but I am still leary of being able */
   4663   /* to find XDR libs on all platforms I want running netperf. raj */
   4664   {
   4665     int *charword;
   4666     int *initword;
   4667     int *lastword;
   4668 
   4669     initword = (int *) xti_tcp_rr_request->xti_device;
   4670     lastword = initword + ((xti_tcp_rr_request->dev_name_len + 3) / 4);
   4671 
   4672     for (charword = initword;
   4673 	 charword < lastword;
   4674 	 charword++) {
   4675 
   4676       *charword = htonl(*charword);
   4677     }
   4678   }
   4679 
   4680 #endif /* __alpha */
   4681 
   4682   s_listen = create_xti_endpoint(xti_tcp_rr_request->xti_device);
   4683 
   4684   if (s_listen == INVALID_SOCKET) {
   4685     netperf_response.content.serv_errno = errno;
   4686     send_response();
   4687 
   4688     exit(1);
   4689   }
   4690 
   4691   /* Let's get an address assigned to this socket so we can tell the */
   4692   /* initiator how to reach the data socket. There may be a desire to */
   4693   /* nail this socket to a specific IP address in a multi-homed, */
   4694   /* multi-connection situation, but for now, we'll ignore the issue */
   4695   /* and concentrate on single connection testing. */
   4696 
   4697   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
   4698   bind_req.addr.len    = sizeof(struct sockaddr_in);
   4699   bind_req.addr.buf    = (char *)&myaddr_in;
   4700   bind_req.qlen        = 1;
   4701 
   4702   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
   4703   bind_resp.addr.len    = sizeof(struct sockaddr_in);
   4704   bind_resp.addr.buf    = (char *)&myaddr_in;
   4705   bind_resp.qlen        = 1;
   4706 
   4707   if (t_bind(s_listen,
   4708 	     &bind_req,
   4709 	     &bind_resp) == SOCKET_ERROR) {
   4710     netperf_response.content.serv_errno = t_errno;
   4711     close(s_listen);
   4712     send_response();
   4713 
   4714     exit(1);
   4715   }
   4716 
   4717   if (debug) {
   4718     fprintf(where,
   4719 	    "recv_xti_tcp_rr: t_bind complete port %d\n",
   4720 	    ntohs(myaddr_in.sin_port));
   4721     fflush(where);
   4722   }
   4723 
   4724   /* Now myaddr_in contains the port and the internet address this is */
   4725   /* returned to the sender also implicitly telling the sender that the */
   4726   /* socket buffer sizing has been done. */
   4727 
   4728   xti_tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
   4729   netperf_response.content.serv_errno   = 0;
   4730 
   4731   /* But wait, there's more. If the initiator wanted cpu measurements, */
   4732   /* then we must call the calibrate routine, which will return the max */
   4733   /* rate back to the initiator. If the CPU was not to be measured, or */
   4734   /* something went wrong with the calibration, we will return a 0.0 to */
   4735   /* the initiator. */
   4736 
   4737   xti_tcp_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
   4738   xti_tcp_rr_response->measure_cpu = 0;
   4739 
   4740   if (xti_tcp_rr_request->measure_cpu) {
   4741     xti_tcp_rr_response->measure_cpu = 1;
   4742     xti_tcp_rr_response->cpu_rate = calibrate_local_cpu(xti_tcp_rr_request->cpu_rate);
   4743   }
   4744 
   4745 
   4746   /* before we send the response back to the initiator, pull some of */
   4747   /* the socket parms from the globals */
   4748   xti_tcp_rr_response->send_buf_size = lss_size;
   4749   xti_tcp_rr_response->recv_buf_size = lsr_size;
   4750   xti_tcp_rr_response->no_delay = loc_nodelay;
   4751   xti_tcp_rr_response->so_rcvavoid = loc_rcvavoid;
   4752   xti_tcp_rr_response->so_sndavoid = loc_sndavoid;
   4753   xti_tcp_rr_response->test_length = xti_tcp_rr_request->test_length;
   4754   send_response();
   4755 
   4756   /* Now, let's set-up the socket to listen for connections. for xti, */
   4757   /* the t_listen call is blocking by default - this is different */
   4758   /* semantics from BSD - probably has to do with being able to reject */
   4759   /* a call before an accept */
   4760   call_req.addr.maxlen = sizeof(struct sockaddr_in);
   4761   call_req.addr.len    = sizeof(struct sockaddr_in);
   4762   call_req.addr.buf    = (char *)&peeraddr_in;
   4763   call_req.opt.maxlen  = 0;
   4764   call_req.opt.len     = 0;
   4765   call_req.opt.buf     = NULL;
   4766   call_req.udata.maxlen= 0;
   4767   call_req.udata.len   = 0;
   4768   call_req.udata.buf   = 0;
   4769 
   4770   if (t_listen(s_listen, &call_req) == -1) {
   4771     fprintf(where,
   4772 	    "recv_xti_tcp_rr: t_listen: errno %d t_errno %d\n",
   4773 	    errno,
   4774 	    t_errno);
   4775     fflush(where);
   4776     netperf_response.content.serv_errno = t_errno;
   4777     close(s_listen);
   4778     send_response();
   4779     exit(1);
   4780   }
   4781 
   4782   if (debug) {
   4783     fprintf(where,
   4784 	    "recv_xti_tcp_rr: t_listen complete t_look 0x%.4x\n",
   4785 	    t_look(s_listen));
   4786     fflush(where);
   4787   }
   4788 
   4789   /* now just rubber stamp the thing. we want to use the same fd? so */
   4790   /* we will just equate s_data with s_listen. this seems a little */
   4791   /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
   4792   s_data = s_listen;
   4793   if (t_accept(s_listen,
   4794 	       s_data,
   4795 	       &call_req) == -1) {
   4796     fprintf(where,
   4797 	    "recv_xti_tcp_rr: t_accept: errno %d t_errno %d\n",
   4798 	    errno,
   4799 	    t_errno);
   4800     fflush(where);
   4801     close(s_listen);
   4802     exit(1);
   4803   }
   4804 
   4805   if (debug) {
   4806     fprintf(where,
   4807 	    "recv_xti_tcp_rr: t_accept complete t_look 0x%.4x",
   4808 	    t_look(s_data));
   4809     fprintf(where,
   4810 	    " remote is %s port %d\n",
   4811 	    inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
   4812 	    ntohs(peeraddr_in.sin_port));
   4813     fflush(where);
   4814   }
   4815 
   4816   /* Now it's time to start receiving data on the connection. We will */
   4817   /* first grab the apropriate counters and then start grabbing. */
   4818 
   4819   cpu_start(xti_tcp_rr_request->measure_cpu);
   4820 
   4821   if (xti_tcp_rr_request->test_length > 0) {
   4822     times_up = 0;
   4823     trans_remaining = 0;
   4824     start_timer(xti_tcp_rr_request->test_length + PAD_TIME);
   4825   }
   4826   else {
   4827     times_up = 1;
   4828     trans_remaining = xti_tcp_rr_request->test_length * -1;
   4829   }
   4830 
   4831   trans_received = 0;
   4832 
   4833   while ((!times_up) || (trans_remaining > 0)) {
   4834     temp_message_ptr = recv_ring->buffer_ptr;
   4835     request_bytes_remaining	= xti_tcp_rr_request->request_size;
   4836     while(request_bytes_remaining > 0) {
   4837       if((request_bytes_recvd=t_rcv(s_data,
   4838 				    temp_message_ptr,
   4839 				    request_bytes_remaining,
   4840 				    &xti_flags)) == SOCKET_ERROR) {
   4841 	if (errno == EINTR) {
   4842 	  /* the timer popped */
   4843 	  timed_out = 1;
   4844 	  break;
   4845 	}
   4846 	fprintf(where,
   4847 		"recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
   4848 		errno,
   4849 		t_errno,
   4850 		request_bytes_recvd);
   4851 	fprintf(where,
   4852 		" t_look 0x%x",
   4853 		t_look(s_data));
   4854 	fflush(where);
   4855 	netperf_response.content.serv_errno = t_errno;
   4856 	send_response();
   4857 	exit(1);
   4858       }
   4859       else {
   4860 	request_bytes_remaining -= request_bytes_recvd;
   4861 	temp_message_ptr  += request_bytes_recvd;
   4862       }
   4863     }
   4864 
   4865     recv_ring = recv_ring->next;
   4866 
   4867     if (timed_out) {
   4868       /* we hit the end of the test based on time - lets */
   4869       /* bail out of here now... */
   4870       if (debug) {
   4871 	fprintf(where,"yo5\n");
   4872 	fflush(where);
   4873       }
   4874       break;
   4875     }
   4876 
   4877     /* Now, send the response to the remote */
   4878     if((bytes_sent=t_snd(s_data,
   4879 			 send_ring->buffer_ptr,
   4880 			 xti_tcp_rr_request->response_size,
   4881 			 0)) == -1) {
   4882       if (errno == EINTR) {
   4883 	/* the test timer has popped */
   4884 	timed_out = 1;
   4885 	if (debug) {
   4886 	  fprintf(where,"yo6\n");
   4887 	  fflush(where);
   4888 	}
   4889 	break;
   4890       }
   4891       fprintf(where,
   4892 	      "recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
   4893 	      errno,
   4894 	      t_errno,
   4895 	      bytes_sent);
   4896       fprintf(where,
   4897 	      " t_look 0x%x",
   4898 	      t_look(s_data));
   4899       fflush(where);
   4900       netperf_response.content.serv_errno = t_errno;
   4901       send_response();
   4902       exit(1);
   4903     }
   4904 
   4905     send_ring = send_ring->next;
   4906 
   4907     trans_received++;
   4908     if (trans_remaining) {
   4909       trans_remaining--;
   4910     }
   4911   }
   4912 
   4913 
   4914   /* The loop now exits due to timeout or transaction count being */
   4915   /* reached */
   4916 
   4917   cpu_stop(xti_tcp_rr_request->measure_cpu,&elapsed_time);
   4918 
   4919   stop_timer(); /* this is probably unnecessary, but it shouldn't hurt */
   4920 
   4921   if (timed_out) {
   4922     /* we ended the test by time, which was at least 2 seconds */
   4923     /* longer than we wanted to run. so, we want to subtract */
   4924     /* PAD_TIME from the elapsed_time. */
   4925     elapsed_time -= PAD_TIME;
   4926   }
   4927 
   4928   /* send the results to the sender			*/
   4929 
   4930   if (debug) {
   4931     fprintf(where,
   4932 	    "recv_xti_tcp_rr: got %d transactions\n",
   4933 	    trans_received);
   4934     fflush(where);
   4935   }
   4936 
   4937   xti_tcp_rr_results->bytes_received = (trans_received *
   4938 					(xti_tcp_rr_request->request_size +
   4939 					 xti_tcp_rr_request->response_size));
   4940   xti_tcp_rr_results->trans_received = trans_received;
   4941   xti_tcp_rr_results->elapsed_time   = elapsed_time;
   4942   xti_tcp_rr_results->cpu_method     = cpu_method;
   4943   if (xti_tcp_rr_request->measure_cpu) {
   4944     xti_tcp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
   4945   }
   4946 
   4947   if (debug) {
   4948     fprintf(where,
   4949 	    "recv_xti_tcp_rr: test complete, sending results.\n");
   4950     fflush(where);
   4951   }
   4952 
   4953   /* we are done with the socket, free it */
   4954   t_close(s_data);
   4955 
   4956   send_response();
   4957 
   4958 }
   4959 
   4960 
   4961 
   4963  /* this test is intended to test the performance of establishing a */
   4964  /* connection, exchanging a request/response pair, and repeating. it */
   4965  /* is expected that this would be a good starting-point for */
   4966  /* comparision of T/TCP with classic TCP for transactional workloads. */
   4967  /* it will also look (can look) much like the communication pattern */
   4968  /* of http for www access. */
   4969 
   4970 void
   4971 send_xti_tcp_conn_rr(char remote_host[])
   4972 {
   4973 
   4974   char *tput_title = "\
   4975 Local /Remote\n\
   4976 Socket Size   Request  Resp.   Elapsed  Trans.\n\
   4977 Send   Recv   Size     Size    Time     Rate         \n\
   4978 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
   4979 
   4980   char *tput_fmt_0 =
   4981     "%7.2f\n";
   4982 
   4983   char *tput_fmt_1_line_1 = "\
   4984 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
   4985   char *tput_fmt_1_line_2 = "\
   4986 %-6d %-6d\n";
   4987 
   4988   char *cpu_title = "\
   4989 Local /Remote\n\
   4990 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
   4991 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
   4992 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
   4993 
   4994   char *cpu_fmt_0 =
   4995     "%6.3f\n";
   4996 
   4997   char *cpu_fmt_1_line_1 = "\
   4998 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
   4999 
   5000   char *cpu_fmt_1_line_2 = "\
   5001 %-6d %-6d\n";
   5002 
   5003   char *ksink_fmt = "\
   5004 Alignment      Offset\n\
   5005 Local  Remote  Local  Remote\n\
   5006 Send   Recv    Send   Recv\n\
   5007 %5d  %5d   %5d  %5d\n";
   5008 
   5009 
   5010   int 			one = 1;
   5011   int			timed_out = 0;
   5012   float			elapsed_time;
   5013 
   5014   int	len;
   5015   struct ring_elt *send_ring;
   5016   struct ring_elt *recv_ring;
   5017   char	*temp_message_ptr;
   5018   int	nummessages;
   5019   SOCKET send_socket;
   5020   int	trans_remaining;
   5021   double	bytes_xferd;
   5022   int	sock_opt_len = sizeof(int);
   5023   int	rsp_bytes_left;
   5024   int	rsp_bytes_recvd;
   5025 
   5026   float	local_cpu_utilization;
   5027   float	local_service_demand;
   5028   float	remote_cpu_utilization;
   5029   float	remote_service_demand;
   5030   double	thruput;
   5031 
   5032   struct	hostent	        *hp;
   5033   struct	sockaddr_in	server;
   5034   struct        sockaddr_in     *myaddr;
   5035   unsigned      int             addr;
   5036   int                           myport;
   5037 
   5038   struct	xti_tcp_conn_rr_request_struct	*xti_tcp_conn_rr_request;
   5039   struct	xti_tcp_conn_rr_response_struct	*xti_tcp_conn_rr_response;
   5040   struct	xti_tcp_conn_rr_results_struct	*xti_tcp_conn_rr_result;
   5041 
   5042   xti_tcp_conn_rr_request =
   5043     (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
   5044   xti_tcp_conn_rr_response =
   5045     (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
   5046   xti_tcp_conn_rr_result =
   5047     (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
   5048 
   5049   /* since we are now disconnected from the code that established the */
   5050   /* control socket, and since we want to be able to use different */
   5051   /* protocols and such, we are passed the name of the remote host and */
   5052   /* must turn that into the test specific addressing information. */
   5053 
   5054   myaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
   5055   if (myaddr == NULL) {
   5056     printf("malloc(%d) failed!\n", sizeof(struct sockaddr_in));
   5057     exit(1);
   5058   }
   5059 
   5060   bzero((char *)&server,
   5061 	sizeof(server));
   5062   bzero((char *)myaddr,
   5063 	sizeof(struct sockaddr_in));
   5064   myaddr->sin_family = AF_INET;
   5065 
   5066   /* it would seem that while HP-UX will allow an IP address (as a */
   5067   /* string) in a call to gethostbyname, other, less enlightened */
   5068   /* systems do not. fix from awjacks (at) ca.sandia.gov raj 10/95 */
   5069   /* order changed to check for IP address first. raj 7/96 */
   5070 
   5071   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
   5072     /* it was not an IP address, try it as a name */
   5073     if ((hp = gethostbyname(remote_host)) == NULL) {
   5074       /* we have no idea what it is */
   5075       fprintf(where,
   5076 	      "establish_control: could not resolve the destination %s\n",
   5077 	      remote_host);
   5078       fflush(where);
   5079       exit(1);
   5080     }
   5081     else {
   5082       /* it was a valid remote_host */
   5083       bcopy(hp->h_addr,
   5084 	    (char *)&server.sin_addr,
   5085 	    hp->h_length);
   5086       server.sin_family = hp->h_addrtype;
   5087     }
   5088   }
   5089   else {
   5090     /* it was a valid IP address */
   5091     server.sin_addr.s_addr = addr;
   5092     server.sin_family = AF_INET;
   5093   }
   5094 
   5095   if ( print_headers ) {
   5096     fprintf(where,"TCP Connect/Request/Response Test\n");
   5097     if (local_cpu_usage || remote_cpu_usage)
   5098       fprintf(where,cpu_title,format_units());
   5099     else
   5100       fprintf(where,tput_title,format_units());
   5101   }
   5102 
   5103   /* initialize a few counters */
   5104 
   5105   nummessages	=	0;
   5106   bytes_xferd	=	0.0;
   5107   times_up 	= 	0;
   5108 
   5109   /* set-up the data buffers with the requested alignment and offset */
   5110   if (send_width == 0) send_width = 1;
   5111   if (recv_width == 0) recv_width = 1;
   5112 
   5113   send_ring = allocate_buffer_ring(send_width,
   5114 				   req_size,
   5115 				   local_send_align,
   5116 				   local_send_offset);
   5117 
   5118   recv_ring = allocate_buffer_ring(recv_width,
   5119 				   rsp_size,
   5120 				   local_recv_align,
   5121 				   local_recv_offset);
   5122 
   5123 
   5124   if (debug) {
   5125     fprintf(where,"send_xti_tcp_conn_rr: send_socket obtained...\n");
   5126   }
   5127 
   5128   /* If the user has requested cpu utilization measurements, we must */
   5129   /* calibrate the cpu(s). We will perform this task within the tests */
   5130   /* themselves. If the user has specified the cpu rate, then */
   5131   /* calibrate_local_cpu will return rather quickly as it will have */
   5132   /* nothing to do. If local_cpu_rate is zero, then we will go through */
   5133   /* all the "normal" calibration stuff and return the rate back.*/
   5134 
   5135   if (local_cpu_usage) {
   5136     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   5137   }
   5138 
   5139   /* Tell the remote end to do a listen. The server alters the socket */
   5140   /* paramters on the other side at this point, hence the reason for */
   5141   /* all the values being passed in the setup message. If the user did */
   5142   /* not specify any of the parameters, they will be passed as 0, which */
   5143   /* will indicate to the remote that no changes beyond the system's */
   5144   /* default should be used. Alignment is the exception, it will */
   5145   /* default to 8, which will be no alignment alterations. */
   5146 
   5147   netperf_request.content.request_type	        =	DO_XTI_TCP_CRR;
   5148   xti_tcp_conn_rr_request->recv_buf_size	=	rsr_size;
   5149   xti_tcp_conn_rr_request->send_buf_size	=	rss_size;
   5150   xti_tcp_conn_rr_request->recv_alignment	=	remote_recv_align;
   5151   xti_tcp_conn_rr_request->recv_offset	=	remote_recv_offset;
   5152   xti_tcp_conn_rr_request->send_alignment	=	remote_send_align;
   5153   xti_tcp_conn_rr_request->send_offset	=	remote_send_offset;
   5154   xti_tcp_conn_rr_request->request_size	=	req_size;
   5155   xti_tcp_conn_rr_request->response_size	=	rsp_size;
   5156   xti_tcp_conn_rr_request->no_delay	        =	rem_nodelay;
   5157   xti_tcp_conn_rr_request->measure_cpu	=	remote_cpu_usage;
   5158   xti_tcp_conn_rr_request->cpu_rate	        =	remote_cpu_rate;
   5159   xti_tcp_conn_rr_request->so_rcvavoid	=	rem_rcvavoid;
   5160   xti_tcp_conn_rr_request->so_sndavoid	=	rem_sndavoid;
   5161   if (test_time) {
   5162     xti_tcp_conn_rr_request->test_length	=	test_time;
   5163   }
   5164   else {
   5165     xti_tcp_conn_rr_request->test_length	=	test_trans * -1;
   5166   }
   5167 
   5168   if (debug > 1) {
   5169     fprintf(where,"netperf: send_xti_tcp_conn_rr: requesting TCP crr test\n");
   5170   }
   5171 
   5172   send_request();
   5173 
   5174   /* The response from the remote will contain all of the relevant 	*/
   5175   /* socket parameters for this test type. We will put them back into 	*/
   5176   /* the variables here so they can be displayed if desired.  The	*/
   5177   /* remote will have calibrated CPU if necessary, and will have done	*/
   5178   /* all the needed set-up we will have calibrated the cpu locally	*/
   5179   /* before sending the request, and will grab the counter value right	*/
   5180   /* after the connect returns. The remote will grab the counter right	*/
   5181   /* after the accept call. This saves the hassle of extra messages	*/
   5182   /* being sent for the TCP tests.					*/
   5183 
   5184   recv_response();
   5185 
   5186   if (!netperf_response.content.serv_errno) {
   5187     rsr_size	=	xti_tcp_conn_rr_response->recv_buf_size;
   5188     rss_size	=	xti_tcp_conn_rr_response->send_buf_size;
   5189     rem_nodelay	=	xti_tcp_conn_rr_response->no_delay;
   5190     remote_cpu_usage=	xti_tcp_conn_rr_response->measure_cpu;
   5191     remote_cpu_rate = 	xti_tcp_conn_rr_response->cpu_rate;
   5192     /* make sure that port numbers are in network order */
   5193     server.sin_port	=	(short)xti_tcp_conn_rr_response->data_port_number;
   5194     server.sin_port =	htons(server.sin_port);
   5195     if (debug) {
   5196       fprintf(where,"remote listen done.\n");
   5197       fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
   5198       fflush(where);
   5199     }
   5200   }
   5201   else {
   5202     Set_errno(netperf_response.content.serv_errno);
   5203     perror("netperf: remote error");
   5204 
   5205     exit(1);
   5206   }
   5207 
   5208   /* Set-up the test end conditions. For a request/response test, they */
   5209   /* can be either time or transaction based. */
   5210 
   5211   if (test_time) {
   5212     /* The user wanted to end the test after a period of time. */
   5213     times_up = 0;
   5214     trans_remaining = 0;
   5215     start_timer(test_time);
   5216   }
   5217   else {
   5218     /* The tester wanted to send a number of bytes. */
   5219     trans_remaining = test_bytes;
   5220     times_up = 1;
   5221   }
   5222 
   5223   /* The cpu_start routine will grab the current time and possibly */
   5224   /* value of the idle counter for later use in measuring cpu */
   5225   /* utilization and/or service demand and thruput. */
   5226 
   5227   cpu_start(local_cpu_usage);
   5228 
   5229   /* We use an "OR" to control test execution. When the test is */
   5230   /* controlled by time, the byte count check will always return false. */
   5231   /* When the test is controlled by byte count, the time test will */
   5232   /* always return false. When the test is finished, the whole */
   5233   /* expression will go false and we will stop sending data. I think I */
   5234   /* just arbitrarily decrement trans_remaining for the timed test, but */
   5235   /* will not do that just yet... One other question is whether or not */
   5236   /* the send buffer and the receive buffer should be the same buffer. */
   5237 
   5238   /* just for grins, start the port numbers at 65530. this should */
   5239   /* quickly flush-out those broken implementations of TCP which treat */
   5240   /* the port number as a signed 16 bit quantity. */
   5241   myport = 65530;
   5242   myaddr->sin_port = htons(myport);
   5243 
   5244   while ((!times_up) || (trans_remaining > 0)) {
   5245 
   5246     /* set up the data socket */
   5247     send_socket = create_xti_endpoint(loc_xti_device);
   5248 
   5249     if (send_socket == INVALID_SOCKET) {
   5250       perror("netperf: send_xti_tcp_conn_rr: tcp stream data socket");
   5251       exit(1);
   5252     }
   5253 
   5254     /* we set SO_REUSEADDR on the premis that no unreserved port */
   5255     /* number on the local system is going to be already connected to */
   5256     /* the remote netserver's port number. we might still have a */
   5257     /* problem if there is a port in the unconnected state. In that */
   5258     /* case, we might want to throw-in a goto to the point where we */
   5259     /* increment the port number by one and try again. of course, this */
   5260     /* could lead to a big load of spinning. one thing that I might */
   5261     /* try later is to have the remote actually allocate a couple of */
   5262     /* port numbers and cycle through those as well. depends on if we */
   5263     /* can get through all the unreserved port numbers in less than */
   5264     /* the length of the TIME_WAIT state raj 8/94 */
   5265     one = 1;
   5266     if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
   5267 		  (char *)&one, sock_opt_len) == SOCKET_ERROR) {
   5268       perror("netperf: send_xti_tcp_conn_rr: so_reuseaddr");
   5269       exit(1);
   5270     }
   5271 
   5272     /* we want to bind our socket to a particular port number. */
   5273     if (bind(send_socket,
   5274 	     (struct sockaddr *)myaddr,
   5275 	     sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
   5276       printf("netperf: send_xti_tcp_conn_rr: tried to bind to port %d\n",
   5277 	     ntohs(myaddr->sin_port));
   5278       perror("netperf: send_xti_tcp_conn_rr: bind");
   5279       exit(1);
   5280     }
   5281 
   5282     /* Connect up to the remote port on the data socket  */
   5283     if (connect(send_socket,
   5284 		(struct sockaddr *)&server,
   5285 		sizeof(server)) == INVALID_SOCKET){
   5286       if (errno == EINTR) {
   5287 	/* we hit the end of a */
   5288 	/* timed test. */
   5289 	timed_out = 1;
   5290 	break;
   5291       }
   5292       perror("netperf: data socket connect failed");
   5293       printf("\tattempted to connect on socket %d to port %d",
   5294 	     send_socket,
   5295 	     ntohs(server.sin_port));
   5296       printf(" from port %d \n",ntohs(myaddr->sin_port));
   5297       exit(1);
   5298     }
   5299 
   5300     /* send the request */
   5301     if((len=send(send_socket,
   5302 		 send_ring->buffer_ptr,
   5303 		 req_size,
   5304 		 0)) != req_size) {
   5305       if (errno == EINTR) {
   5306 	/* we hit the end of a */
   5307 	/* timed test. */
   5308 	timed_out = 1;
   5309 	break;
   5310       }
   5311       perror("send_xti_tcp_conn_rr: data send error");
   5312       exit(1);
   5313     }
   5314     send_ring = send_ring->next;
   5315 
   5316     /* receive the response */
   5317     rsp_bytes_left = rsp_size;
   5318     temp_message_ptr  = recv_ring->buffer_ptr;
   5319     while(rsp_bytes_left > 0) {
   5320       if((rsp_bytes_recvd=recv(send_socket,
   5321 			       temp_message_ptr,
   5322 			       rsp_bytes_left,
   5323 			       0)) == SOCKET_ERROR) {
   5324 	if (errno == EINTR) {
   5325 	  /* We hit the end of a timed test. */
   5326 	  timed_out = 1;
   5327 	  break;
   5328 	}
   5329 	perror("send_xti_tcp_conn_rr: data recv error");
   5330 	exit(1);
   5331       }
   5332       rsp_bytes_left -= rsp_bytes_recvd;
   5333       temp_message_ptr  += rsp_bytes_recvd;
   5334     }
   5335     recv_ring = recv_ring->next;
   5336 
   5337     if (timed_out) {
   5338       /* we may have been in a nested while loop - we need */
   5339       /* another call to break. */
   5340       break;
   5341     }
   5342 
   5343     close(send_socket);
   5344 
   5345     nummessages++;
   5346     if (trans_remaining) {
   5347       trans_remaining--;
   5348     }
   5349 
   5350     if (debug > 3) {
   5351       fprintf(where,
   5352 	      "Transaction %d completed on local port %d\n",
   5353 	      nummessages,
   5354 	      ntohs(myaddr->sin_port));
   5355       fflush(where);
   5356     }
   5357 
   5358 newport:
   5359     /* pick a new port number */
   5360     myport = ntohs(myaddr->sin_port);
   5361     myport++;
   5362     /* we do not want to use the port number that the server is */
   5363     /* sitting at - this would cause us to fail in a loopback test */
   5364 
   5365     if (myport == ntohs(server.sin_port)) myport++;
   5366 
   5367     /* wrap the port number when we get to 65535. NOTE, some broken */
   5368     /* TCP's might treat the port number as a signed 16 bit quantity. */
   5369     /* we aren't interested in testing such broekn implementations :) */
   5370     /* raj 8/94  */
   5371     if (myport == 65535) {
   5372       myport = 5000;
   5373     }
   5374     myaddr->sin_port = htons(myport);
   5375 
   5376     if (debug) {
   5377       if ((myport % 1000) == 0) {
   5378 	printf("port %d\n",myport);
   5379       }
   5380     }
   5381 
   5382   }
   5383 
   5384   /* this call will always give us the elapsed time for the test, and */
   5385   /* will also store-away the necessaries for cpu utilization */
   5386 
   5387   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being measured? */
   5388   /* how long did we really run? */
   5389 
   5390   /* Get the statistics from the remote end. The remote will have */
   5391   /* calculated service demand and all those interesting things. If it */
   5392   /* wasn't supposed to care, it will return obvious values. */
   5393 
   5394   recv_response();
   5395   if (!netperf_response.content.serv_errno) {
   5396     if (debug)
   5397       fprintf(where,"remote results obtained\n");
   5398   }
   5399   else {
   5400     Set_errno(netperf_response.content.serv_errno);
   5401     perror("netperf: remote error");
   5402 
   5403     exit(1);
   5404   }
   5405 
   5406   /* We now calculate what our thruput was for the test. In the future, */
   5407   /* we may want to include a calculation of the thruput measured by */
   5408   /* the remote, but it should be the case that for a TCP stream test, */
   5409   /* that the two numbers should be *very* close... We calculate */
   5410   /* bytes_sent regardless of the way the test length was controlled. */
   5411   /* If it was time, we needed to, and if it was by bytes, the user may */
   5412   /* have specified a number of bytes that wasn't a multiple of the */
   5413   /* send_size, so we really didn't send what he asked for ;-) We use */
   5414   /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
   5415   /* 1024. A future enhancement *might* be to choose from a couple of */
   5416   /* unit selections. */
   5417 
   5418   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
   5419   thruput	= calc_thruput(bytes_xferd);
   5420 
   5421   if (local_cpu_usage || remote_cpu_usage) {
   5422     /* We must now do a little math for service demand and cpu */
   5423     /* utilization for the system(s) */
   5424     /* Of course, some of the information might be bogus because */
   5425     /* there was no idle counter in the kernel(s). We need to make */
   5426     /* a note of this for the user's benefit...*/
   5427     if (local_cpu_usage) {
   5428       if (local_cpu_rate == 0.0) {
   5429 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
   5430 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
   5431 	fflush(where);
   5432       }
   5433       local_cpu_utilization = calc_cpu_util(0.0);
   5434       /* since calc_service demand is doing ms/Kunit we will */
   5435       /* multiply the number of transaction by 1024 to get */
   5436       /* "good" numbers */
   5437       local_service_demand  = calc_service_demand((double) nummessages*1024,
   5438 						  0.0,
   5439 						  0.0,
   5440 						  0);
   5441     }
   5442     else {
   5443       local_cpu_utilization	= -1.0;
   5444       local_service_demand	= -1.0;
   5445     }
   5446 
   5447     if (remote_cpu_usage) {
   5448       if (remote_cpu_rate == 0.0) {
   5449 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
   5450 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
   5451 	fflush(where);
   5452       }
   5453       remote_cpu_utilization = xti_tcp_conn_rr_result->cpu_util;
   5454       /* since calc_service demand is doing ms/Kunit we will */
   5455       /* multiply the number of transaction by 1024 to get */
   5456       /* "good" numbers */
   5457       remote_service_demand = calc_service_demand((double) nummessages*1024,
   5458 						  0.0,
   5459 						  remote_cpu_utilization,
   5460 						  xti_tcp_conn_rr_result->num_cpus);
   5461     }
   5462     else {
   5463       remote_cpu_utilization = -1.0;
   5464       remote_service_demand  = -1.0;
   5465     }
   5466 
   5467     /* We are now ready to print all the information. If the user */
   5468     /* has specified zero-level verbosity, we will just print the */
   5469     /* local service demand, or the remote service demand. If the */
   5470     /* user has requested verbosity level 1, he will get the basic */
   5471     /* "streamperf" numbers. If the user has specified a verbosity */
   5472     /* of greater than 1, we will display a veritable plethora of */
   5473     /* background information from outside of this block as it it */
   5474     /* not cpu_measurement specific...  */
   5475 
   5476     switch (verbosity) {
   5477     case 0:
   5478       if (local_cpu_usage) {
   5479 	fprintf(where,
   5480 		cpu_fmt_0,
   5481 		local_service_demand);
   5482       }
   5483       else {
   5484 	fprintf(where,
   5485 		cpu_fmt_0,
   5486 		remote_service_demand);
   5487       }
   5488       break;
   5489     case 1:
   5490       fprintf(where,
   5491 	      cpu_fmt_1_line_1,		/* the format string */
   5492 	      lss_size,		/* local sendbuf size */
   5493 	      lsr_size,
   5494 	      req_size,		/* how large were the requests */
   5495 	      rsp_size,		/* guess */
   5496 	      elapsed_time,		/* how long was the test */
   5497 	      nummessages/elapsed_time,
   5498 	      local_cpu_utilization,	/* local cpu */
   5499 	      remote_cpu_utilization,	/* remote cpu */
   5500 	      local_service_demand,	/* local service demand */
   5501 	      remote_service_demand);	/* remote service demand */
   5502       fprintf(where,
   5503 	      cpu_fmt_1_line_2,
   5504 	      rss_size,
   5505 	      rsr_size);
   5506       break;
   5507     }
   5508   }
   5509   else {
   5510     /* The tester did not wish to measure service demand. */
   5511     switch (verbosity) {
   5512     case 0:
   5513       fprintf(where,
   5514 	      tput_fmt_0,
   5515 	      nummessages/elapsed_time);
   5516       break;
   5517     case 1:
   5518       fprintf(where,
   5519 	      tput_fmt_1_line_1,	/* the format string */
   5520 	      lss_size,
   5521 	      lsr_size,
   5522 	      req_size,		/* how large were the requests */
   5523 	      rsp_size,		/* how large were the responses */
   5524 	      elapsed_time, 		/* how long did it take */
   5525 	      nummessages/elapsed_time);
   5526       fprintf(where,
   5527 	      tput_fmt_1_line_2,
   5528 	      rss_size, 		/* remote recvbuf size */
   5529 	      rsr_size);
   5530 
   5531       break;
   5532     }
   5533   }
   5534 
   5535   /* it would be a good thing to include information about some of the */
   5536   /* other parameters that may have been set for this test, but at the */
   5537   /* moment, I do not wish to figure-out all the  formatting, so I will */
   5538   /* just put this comment here to help remind me that it is something */
   5539   /* that should be done at a later time. */
   5540 
   5541   if (verbosity > 1) {
   5542     /* The user wanted to know it all, so we will give it to him. */
   5543     /* This information will include as much as we can find about */
   5544     /* TCP statistics, the alignments of the sends and receives */
   5545     /* and all that sort of rot... */
   5546 
   5547     fprintf(where,
   5548 	    ksink_fmt);
   5549   }
   5550 
   5551 }
   5552 
   5553 
   5554 void
   5556 recv_xti_tcp_conn_rr()
   5557 {
   5558 
   5559   char  *message;
   5560   struct	sockaddr_in        myaddr_in,
   5561   peeraddr_in;
   5562   SOCKET s_listen,s_data;
   5563   int 	addrlen;
   5564   char	*recv_message_ptr;
   5565   char	*send_message_ptr;
   5566   char	*temp_message_ptr;
   5567   int	trans_received;
   5568   int	trans_remaining;
   5569   int	bytes_sent;
   5570   int	request_bytes_recvd;
   5571   int	request_bytes_remaining;
   5572   int	timed_out = 0;
   5573   float	elapsed_time;
   5574 
   5575   struct	xti_tcp_conn_rr_request_struct	*xti_tcp_conn_rr_request;
   5576   struct	xti_tcp_conn_rr_response_struct	*xti_tcp_conn_rr_response;
   5577   struct	xti_tcp_conn_rr_results_struct	*xti_tcp_conn_rr_results;
   5578 
   5579   xti_tcp_conn_rr_request =
   5580     (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
   5581   xti_tcp_conn_rr_response =
   5582     (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
   5583   xti_tcp_conn_rr_results =
   5584     (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
   5585 
   5586   if (debug) {
   5587     fprintf(where,"netserver: recv_xti_tcp_conn_rr: entered...\n");
   5588     fflush(where);
   5589   }
   5590 
   5591   /* We want to set-up the listen socket with all the desired */
   5592   /* parameters and then let the initiator know that all is ready. If */
   5593   /* socket size defaults are to be used, then the initiator will have */
   5594   /* sent us 0's. If the socket sizes cannot be changed, then we will */
   5595   /* send-back what they are. If that information cannot be determined, */
   5596   /* then we send-back -1's for the sizes. If things go wrong for any */
   5597   /* reason, we will drop back ten yards and punt. */
   5598 
   5599   /* If anything goes wrong, we want the remote to know about it. It */
   5600   /* would be best if the error that the remote reports to the user is */
   5601   /* the actual error we encountered, rather than some bogus unexpected */
   5602   /* response type message. */
   5603 
   5604   if (debug) {
   5605     fprintf(where,"recv_xti_tcp_conn_rr: setting the response type...\n");
   5606     fflush(where);
   5607   }
   5608 
   5609   netperf_response.content.response_type = XTI_TCP_CRR_RESPONSE;
   5610 
   5611   if (debug) {
   5612     fprintf(where,"recv_xti_tcp_conn_rr: the response type is set...\n");
   5613     fflush(where);
   5614   }
   5615 
   5616   /* set-up the data buffer with the requested alignment and offset */
   5617   message = (char *)malloc(DATABUFFERLEN);
   5618   if (message == NULL) {
   5619     printf("malloc(%d) failed!\n", DATABUFFERLEN);
   5620     exit(1);
   5621   }
   5622 
   5623   /* We now alter the message_ptr variables to be at the desired */
   5624   /* alignments with the desired offsets. */
   5625 
   5626   if (debug) {
   5627     fprintf(where,
   5628 	    "recv_xti_tcp_conn_rr: requested recv alignment of %d offset %d\n",
   5629 	    xti_tcp_conn_rr_request->recv_alignment,
   5630 	    xti_tcp_conn_rr_request->recv_offset);
   5631     fprintf(where,
   5632 	    "recv_xti_tcp_conn_rr: requested send alignment of %d offset %d\n",
   5633 	    xti_tcp_conn_rr_request->send_alignment,
   5634 	    xti_tcp_conn_rr_request->send_offset);
   5635     fflush(where);
   5636   }
   5637 
   5638   recv_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->recv_alignment, xti_tcp_conn_rr_request->recv_offset);
   5639 
   5640   send_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->send_alignment, xti_tcp_conn_rr_request->send_offset);
   5641 
   5642   if (debug) {
   5643     fprintf(where,"recv_xti_tcp_conn_rr: receive alignment and offset set...\n");
   5644     fflush(where);
   5645   }
   5646 
   5647   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
   5648   /* can put in OUR values !-) At some point, we may want to nail this */
   5649   /* socket to a particular network-level address, but for now, */
   5650   /* INADDR_ANY should be just fine. */
   5651 
   5652   bzero((char *)&myaddr_in,
   5653 	sizeof(myaddr_in));
   5654   myaddr_in.sin_family      = AF_INET;
   5655   myaddr_in.sin_addr.s_addr = INADDR_ANY;
   5656   myaddr_in.sin_port        = 0;
   5657 
   5658   /* Grab a socket to listen on, and then listen on it. */
   5659 
   5660   if (debug) {
   5661     fprintf(where,"recv_xti_tcp_conn_rr: grabbing a socket...\n");
   5662     fflush(where);
   5663   }
   5664 
   5665   /* create_xti_endpoint expects to find some things in the global */
   5666   /* variables, so set the globals based on the values in the request. */
   5667   /* once the socket has been created, we will set the response values */
   5668   /* based on the updated value of those globals. raj 7/94 */
   5669   lss_size = xti_tcp_conn_rr_request->send_buf_size;
   5670   lsr_size = xti_tcp_conn_rr_request->recv_buf_size;
   5671   loc_nodelay = xti_tcp_conn_rr_request->no_delay;
   5672   loc_rcvavoid = xti_tcp_conn_rr_request->so_rcvavoid;
   5673   loc_sndavoid = xti_tcp_conn_rr_request->so_sndavoid;
   5674 
   5675   s_listen = create_xti_endpoint(loc_xti_device);
   5676 
   5677   if (s_listen == INVALID_SOCKET) {
   5678     netperf_response.content.serv_errno = errno;
   5679     send_response();
   5680     if (debug) {
   5681       fprintf(where,"could not create data socket\n");
   5682       fflush(where);
   5683     }
   5684     exit(1);
   5685   }
   5686 
   5687   /* Let's get an address assigned to this socket so we can tell the */
   5688   /* initiator how to reach the data socket. There may be a desire to */
   5689   /* nail this socket to a specific IP address in a multi-homed, */
   5690   /* multi-connection situation, but for now, we'll ignore the issue */
   5691   /* and concentrate on single connection testing. */
   5692 
   5693   if (bind(s_listen,
   5694 	   (struct sockaddr *)&myaddr_in,
   5695 	   sizeof(myaddr_in)) == SOCKET_ERROR) {
   5696     netperf_response.content.serv_errno = errno;
   5697     close(s_listen);
   5698     send_response();
   5699     if (debug) {
   5700       fprintf(where,"could not bind\n");
   5701       fflush(where);
   5702     }
   5703     exit(1);
   5704   }
   5705 
   5706   /* Now, let's set-up the socket to listen for connections */
   5707   if (listen(s_listen, 5) == SOCKET_ERROR) {
   5708     netperf_response.content.serv_errno = errno;
   5709     close(s_listen);
   5710     send_response();
   5711     if (debug) {
   5712       fprintf(where,"could not listen\n");
   5713       fflush(where);
   5714     }
   5715     exit(1);
   5716   }
   5717 
   5718   /* now get the port number assigned by the system  */
   5719   addrlen = sizeof(myaddr_in);
   5720   if (getsockname(s_listen,
   5721 		  (struct sockaddr *)&myaddr_in,
   5722 		  &addrlen) == SOCKET_ERROR){
   5723     netperf_response.content.serv_errno = errno;
   5724     close(s_listen);
   5725     send_response();
   5726     if (debug) {
   5727       fprintf(where,"could not geetsockname\n");
   5728       fflush(where);
   5729     }
   5730     exit(1);
   5731   }
   5732 
   5733   /* Now myaddr_in contains the port and the internet address this is */
   5734   /* returned to the sender also implicitly telling the sender that the */
   5735   /* socket buffer sizing has been done. */
   5736 
   5737   xti_tcp_conn_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
   5738   if (debug) {
   5739     fprintf(where,"telling the remote to call me at %d\n",
   5740 	    xti_tcp_conn_rr_response->data_port_number);
   5741     fflush(where);
   5742   }
   5743   netperf_response.content.serv_errno   = 0;
   5744 
   5745   /* But wait, there's more. If the initiator wanted cpu measurements, */
   5746   /* then we must call the calibrate routine, which will return the max */
   5747   /* rate back to the initiator. If the CPU was not to be measured, or */
   5748   /* something went wrong with the calibration, we will return a 0.0 to */
   5749   /* the initiator. */
   5750 
   5751   xti_tcp_conn_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
   5752   if (xti_tcp_conn_rr_request->measure_cpu) {
   5753     xti_tcp_conn_rr_response->measure_cpu = 1;
   5754     xti_tcp_conn_rr_response->cpu_rate =
   5755       calibrate_local_cpu(xti_tcp_conn_rr_request->cpu_rate);
   5756   }
   5757 
   5758 
   5759 
   5760   /* before we send the response back to the initiator, pull some of */
   5761   /* the socket parms from the globals */
   5762   xti_tcp_conn_rr_response->send_buf_size = lss_size;
   5763   xti_tcp_conn_rr_response->recv_buf_size = lsr_size;
   5764   xti_tcp_conn_rr_response->no_delay = loc_nodelay;
   5765   xti_tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
   5766   xti_tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
   5767 
   5768   send_response();
   5769 
   5770   addrlen = sizeof(peeraddr_in);
   5771 
   5772   /* Now it's time to start receiving data on the connection. We will */
   5773   /* first grab the apropriate counters and then start grabbing. */
   5774 
   5775   cpu_start(xti_tcp_conn_rr_request->measure_cpu);
   5776 
   5777   /* The loop will exit when the sender does a shutdown, which will */
   5778   /* return a length of zero   */
   5779 
   5780   if (xti_tcp_conn_rr_request->test_length > 0) {
   5781     times_up = 0;
   5782     trans_remaining = 0;
   5783     start_timer(xti_tcp_conn_rr_request->test_length + PAD_TIME);
   5784   }
   5785   else {
   5786     times_up = 1;
   5787     trans_remaining = xti_tcp_conn_rr_request->test_length * -1;
   5788   }
   5789 
   5790   trans_received = 0;
   5791 
   5792   while ((!times_up) || (trans_remaining > 0)) {
   5793 
   5794     /* accept a connection from the remote */
   5795     if ((s_data=accept(s_listen,
   5796 		       (struct sockaddr *)&peeraddr_in,
   5797 		       &addrlen)) == INVALID_SOCKET) {
   5798       if (errno == EINTR) {
   5799 	/* the timer popped */
   5800 	timed_out = 1;
   5801 	break;
   5802       }
   5803       fprintf(where,"recv_xti_tcp_conn_rr: accept: errno = %d\n",errno);
   5804       fflush(where);
   5805       close(s_listen);
   5806 
   5807       exit(1);
   5808     }
   5809 
   5810     if (debug) {
   5811       fprintf(where,"recv_xti_tcp_conn_rr: accepted data connection.\n");
   5812       fflush(where);
   5813     }
   5814 
   5815     temp_message_ptr	= recv_message_ptr;
   5816     request_bytes_remaining	= xti_tcp_conn_rr_request->request_size;
   5817 
   5818     /* receive the request from the other side */
   5819     while(request_bytes_remaining > 0) {
   5820       if((request_bytes_recvd=recv(s_data,
   5821 				   temp_message_ptr,
   5822 				   request_bytes_remaining,
   5823 				   0)) == SOCKET_ERROR) {
   5824 	if (errno == EINTR) {
   5825 	  /* the timer popped */
   5826 	  timed_out = 1;
   5827 	  break;
   5828 	}
   5829 	netperf_response.content.serv_errno = errno;
   5830 	send_response();
   5831 	exit(1);
   5832       }
   5833       else {
   5834 	request_bytes_remaining -= request_bytes_recvd;
   5835 	temp_message_ptr  += request_bytes_recvd;
   5836       }
   5837     }
   5838 
   5839     if (timed_out) {
   5840       /* we hit the end of the test based on time - lets */
   5841       /* bail out of here now... */
   5842       fprintf(where,"yo5\n");
   5843       fflush(where);
   5844       break;
   5845     }
   5846 
   5847     /* Now, send the response to the remote */
   5848     if((bytes_sent=send(s_data,
   5849 			send_message_ptr,
   5850 			xti_tcp_conn_rr_request->response_size,
   5851 			0)) == SOCKET_ERROR) {
   5852       if (errno == EINTR) {
   5853 	/* the test timer has popped */
   5854 	timed_out = 1;
   5855 	fprintf(where,"yo6\n");
   5856 	fflush(where);
   5857 	break;
   5858       }
   5859       netperf_response.content.serv_errno = 99;
   5860       send_response();
   5861       exit(1);
   5862     }
   5863 
   5864     trans_received++;
   5865     if (trans_remaining) {
   5866       trans_remaining--;
   5867     }
   5868 
   5869     if (debug) {
   5870       fprintf(where,
   5871 	      "recv_xti_tcp_conn_rr: Transaction %d complete\n",
   5872 	      trans_received);
   5873       fflush(where);
   5874     }
   5875 
   5876     /* close the connection */
   5877     close(s_data);
   5878 
   5879   }
   5880 
   5881 
   5882   /* The loop now exits due to timeout or transaction count being */
   5883   /* reached */
   5884 
   5885   cpu_stop(xti_tcp_conn_rr_request->measure_cpu,&elapsed_time);
   5886 
   5887   if (timed_out) {
   5888     /* we ended the test by time, which was at least 2 seconds */
   5889     /* longer than we wanted to run. so, we want to subtract */
   5890     /* PAD_TIME from the elapsed_time. */
   5891     elapsed_time -= PAD_TIME;
   5892   }
   5893   /* send the results to the sender			*/
   5894 
   5895   if (debug) {
   5896     fprintf(where,
   5897 	    "recv_xti_tcp_conn_rr: got %d transactions\n",
   5898 	    trans_received);
   5899     fflush(where);
   5900   }
   5901 
   5902   xti_tcp_conn_rr_results->bytes_received	= (trans_received *
   5903 					   (xti_tcp_conn_rr_request->request_size +
   5904 					    xti_tcp_conn_rr_request->response_size));
   5905   xti_tcp_conn_rr_results->trans_received	= trans_received;
   5906   xti_tcp_conn_rr_results->elapsed_time	= elapsed_time;
   5907   if (xti_tcp_conn_rr_request->measure_cpu) {
   5908     xti_tcp_conn_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
   5909   }
   5910 
   5911   if (debug) {
   5912     fprintf(where,
   5913 	    "recv_xti_tcp_conn_rr: test complete, sending results.\n");
   5914     fflush(where);
   5915   }
   5916 
   5917   send_response();
   5918 
   5919 }
   5920 
   5921 void
   5923 print_xti_usage()
   5924 {
   5925 
   5926   fwrite(xti_usage, sizeof(char), strlen(xti_usage), stdout);
   5927   exit(1);
   5928 
   5929 }
   5930 
   5931 void
   5932 scan_xti_args(int argc, char *argv[])
   5933 {
   5934 #define XTI_ARGS "Dhm:M:r:s:S:Vw:W:X:"
   5935   extern int	optind, opterrs;  /* index of first unused arg 	*/
   5936   extern char	*optarg;	  /* pointer to option string	*/
   5937 
   5938   int		c;
   5939 
   5940   char
   5941     arg1[BUFSIZ],  /* argument holders		*/
   5942     arg2[BUFSIZ];
   5943 
   5944   if (no_control) {
   5945     fprintf(where,
   5946 	    "The XTI tests do not know how to run with no control connection\n");
   5947     exit(-1);
   5948   }
   5949 
   5950   /* Go through all the command line arguments and break them */
   5951   /* out. For those options that take two parms, specifying only */
   5952   /* the first will set both to that value. Specifying only the */
   5953   /* second will leave the first untouched. To change only the */
   5954   /* first, use the form "first," (see the routine break_args.. */
   5955 
   5956   while ((c= getopt(argc, argv, XTI_ARGS)) != EOF) {
   5957     switch (c) {
   5958     case '?':
   5959     case 'h':
   5960       print_xti_usage();
   5961       exit(1);
   5962     case 'D':
   5963       /* set the TCP nodelay flag */
   5964       loc_nodelay = 1;
   5965       rem_nodelay = 1;
   5966       break;
   5967     case 's':
   5968       /* set local socket sizes */
   5969       break_args(optarg,arg1,arg2);
   5970       if (arg1[0])
   5971 	lss_size = convert(arg1);
   5972       if (arg2[0])
   5973 	lsr_size = convert(arg2);
   5974       break;
   5975     case 'S':
   5976       /* set remote socket sizes */
   5977       break_args(optarg,arg1,arg2);
   5978       if (arg1[0])
   5979 	rss_size = convert(arg1);
   5980       if (arg2[0])
   5981 	rsr_size = convert(arg2);
   5982       break;
   5983     case 'r':
   5984       /* set the request/response sizes */
   5985       break_args(optarg,arg1,arg2);
   5986       if (arg1[0])
   5987 	req_size = convert(arg1);
   5988       if (arg2[0])
   5989 	rsp_size = convert(arg2);
   5990       break;
   5991     case 'm':
   5992       /* set the send size */
   5993       send_size = convert(optarg);
   5994       break;
   5995     case 'M':
   5996       /* set the recv size */
   5997       recv_size = convert(optarg);
   5998       break;
   5999     case 'W':
   6000       /* set the "width" of the user space data */
   6001       /* buffer. This will be the number of */
   6002       /* send_size buffers malloc'd in the */
   6003       /* *_STREAM test. It may be enhanced to set */
   6004       /* both send and receive "widths" but for now */
   6005       /* it is just the sending *_STREAM. */
   6006       send_width = convert(optarg);
   6007       break;
   6008     case 'V' :
   6009       /* we want to do copy avoidance and will set */
   6010       /* it for everything, everywhere, if we really */
   6011       /* can. of course, we don't know anything */
   6012       /* about the remote... */
   6013 #ifdef SO_SND_COPYAVOID
   6014       loc_sndavoid = 1;
   6015 #else
   6016       loc_sndavoid = 0;
   6017       printf("Local send copy avoidance not available.\n");
   6018 #endif
   6019 #ifdef SO_RCV_COPYAVOID
   6020       loc_rcvavoid = 1;
   6021 #else
   6022       loc_rcvavoid = 0;
   6023       printf("Local recv copy avoidance not available.\n");
   6024 #endif
   6025       rem_sndavoid = 1;
   6026       rem_rcvavoid = 1;
   6027       break;
   6028     case 'X':
   6029       /* set the xti device file name(s) */
   6030       break_args(optarg,arg1,arg2);
   6031       if (arg1[0])
   6032 	strcpy(loc_xti_device,arg1);
   6033       if (arg2[0])
   6034 	strcpy(rem_xti_device,arg2);
   6035       break;
   6036     };
   6037   }
   6038 }
   6039 #endif /* WANT_XTI */
   6040