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