Home | History | Annotate | Download | only in src
      1 #ifdef lint
      2 #define WANT_UNIX
      3 #define DIRTY
      4 #define WANT_INTERVALS
      5 #endif /* lint */
      6 
      7 #ifdef HAVE_CONFIG_H
      8 #include <config.h>
      9 #endif
     10 
     11 #ifdef WIN32
     12 #error Unix Domain Sockets are not available under Windows
     13 #endif
     14 
     15 #ifdef WANT_UNIX
     16 char	nettest_unix_id[]="\
     17 @(#)nettest_unix.c (c) Copyright 1994-2012 Hewlett-Packard Co. Version 2.6.0";
     18 
     19 /****************************************************************/
     20 /*								*/
     21 /*	nettest_bsd.c						*/
     22 /*								*/
     23 /*      the BSD sockets parsing routine...                      */
     24 /*                                                              */
     25 /*      scan_unix_args()                                        */
     26 /*                                                              */
     27 /*	the actual test routines...				*/
     28 /*								*/
     29 /*	send_stream_stream()  perform a stream stream test	*/
     30 /*	recv_stream_stream()					*/
     31 /*	send_stream_rr()      perform a stream request/response	*/
     32 /*	recv_stream_rr()					*/
     33 /*	send_dg_stream()      perform a dg stream test	        */
     34 /*	recv_dg_stream()					*/
     35 /*	send_dg_rr()	      perform a dg request/response	*/
     36 /*	recv_dg_rr()						*/
     37 /*	loc_cpu_rate()	      determine the local cpu maxrate   */
     38 /*	rem_cpu_rate()	      find the remote cpu maxrate	*/
     39 /*								*/
     40 /****************************************************************/
     41 
     42  /* at some point, I might want to go-in and see if I really need all
     43     these includes, but for the moment, we'll let them all just sit
     44     there. raj 8/94 */
     45 #include <sys/types.h>
     46 #include <fcntl.h>
     47 #include <stdio.h>
     48 #include <stdlib.h>
     49 #include <sys/ipc.h>
     50 #include <sys/socket.h>
     51 #include <errno.h>
     52 #include <signal.h>
     53 #include <sys/un.h>
     54 #include <unistd.h>
     55 #include <string.h>
     56 #include <time.h>
     57 #include <sys/time.h>
     58 
     59 #ifdef NOSTDLIBH
     60 #include <malloc.h>
     61 #else /* NOSTDLIBH */
     62 #include <stdlib.h>
     63 #endif /* NOSTDLIBH */
     64 
     65 #include <sys/stat.h>
     66 
     67 
     68 #include "netlib.h"
     69 #include "netsh.h"
     70 #include "nettest_unix.h"
     71 
     72 
     73 
     75 /* these variables are specific to the UNIX sockets tests. declare
     76     them static to make them global only to this file. */
     77 
     78 #define UNIX_PRFX "netperf."
     79 #define UNIX_LENGTH_MAX 0xFFFF - 28
     80 
     81 static char
     82   path_prefix[32];
     83 
     84 static int
     85   rss_size,		/* remote socket send buffer size */
     86   rsr_size,		/* remote socket recv buffer size	*/
     87   lss_size_req,		/* requested local socket send buffer size */
     88   lsr_size_req,		/* requested local socket recv buffer size */
     89   lss_size,		/* local  socket send buffer size 	*/
     90   lsr_size,		/* local  socket recv buffer size 	*/
     91   req_size = 1,		/* request size                   	*/
     92   rsp_size = 1,		/* response size			*/
     93   send_size,		/* how big are individual sends		*/
     94   recv_size;		/* how big are individual receives	*/
     95 
     96  /* different options for the sockets				*/
     97 
     98 
     99 char unix_usage[] = "\n\
    100 Usage: netperf [global options] -- [test options] \n\
    101 \n\
    102 STREAM/DG UNIX Sockets Test Options:\n\
    103     -h                Display this text\n\
    104     -m bytes          Set the send size (STREAM_STREAM, DG_STREAM)\n\
    105     -M bytes          Set the recv size (STREAM_STREAM, DG_STREAM)\n\
    106     -p dir            Set the directory where pipes are created\n\
    107     -r req,res        Set request,response size (STREAM_RR, DG_RR)\n\
    108     -s send[,recv]    Set local socket send/recv buffer sizes\n\
    109     -S send[,recv]    Set remote socket send/recv buffer sizes\n\
    110 \n\
    111 For those options taking two parms, at least one must be specified;\n\
    112 specifying one value without a comma will set both parms to that\n\
    113 value, specifying a value with a leading comma will set just the second\n\
    114 parm, a value with a trailing comma will set just the first. To set\n\
    115 each parm to unique values, specify both and separate them with a\n\
    116 comma.\n";
    117 
    118 /* this routing initializes all the test specific variables */
    120 
    121 static void
    122 init_test_vars()
    123 {
    124   rss_size  = 0;
    125   rsr_size  = 0;
    126   lss_size_req = -1;
    127   lsr_size_req = -1;
    128   lss_size  = 0;
    129   lsr_size  = 0;
    130   req_size  = 1;
    131   rsp_size  = 1;
    132   send_size = 0;
    133   recv_size = 0;
    134 
    135   strcpy(path_prefix,"/tmp");
    136 
    137 }
    138 
    139 /* This routine will create a data (listen) socket with the apropriate
    141    options set and return it to the caller. this replaces all the
    142    duplicate code in each of the test routines and should help make
    143    things a little easier to understand. since this routine can be
    144    called by either the netperf or netserver programs, all output
    145    should be directed towards "where." family is generally AF_UNIX,
    146    and type will be either SOCK_STREAM or SOCK_DGRAM */
    147 SOCKET
    148 create_unix_socket(int family, int type)
    149 {
    150 
    151   SOCKET temp_socket;
    152 
    153   /*set up the data socket                        */
    154   temp_socket = socket(family,
    155 		       type,
    156 		       0);
    157 
    158   if (temp_socket == INVALID_SOCKET){
    159     fprintf(where,
    160 	    "netperf: create_unix_socket: socket: %d\n",
    161 	    errno);
    162     fflush(where);
    163     exit(1);
    164   }
    165 
    166   if (debug) {
    167     fprintf(where,"create_unix_socket: socket %d obtained...\n",temp_socket);
    168     fflush(where);
    169   }
    170 
    171   /* Modify the local socket size. The reason we alter the send buffer
    172      size here rather than when the connection is made is to take care
    173      of decreases in buffer size. Decreasing the window size after
    174      connection establishment is a STREAM no-no. Also, by setting the
    175      buffer (window) size before the connection is established, we can
    176      control the STREAM MSS (segment size). The MSS is never more that
    177      1/2 the minimum receive buffer size at each half of the
    178      connection.  This is why we are altering the receive buffer size
    179      on the sending size of a unidirectional transfer. If the user has
    180      not requested that the socket buffers be altered, we will try to
    181      find-out what their values are. If we cannot touch the socket
    182      buffer in any way, we will set the values to -1 to indicate
    183      that.  */
    184 
    185   set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
    186   set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
    187 
    188   return(temp_socket);
    189 
    190 }
    191 
    192 
    193 /* This routine implements the STREAM unidirectional data transfer
    195    test (a.k.a. stream) for the sockets interface. It receives its
    196    parameters via global variables from the shell and writes its
    197    output to the standard output. */
    198 
    199 
    200 void
    201 send_stream_stream(char remote_host[])
    202 {
    203 
    204   char *tput_title = "\
    205 Recv   Send    Send                          \n\
    206 Socket Socket  Message  Elapsed              \n\
    207 Size   Size    Size     Time     Throughput  \n\
    208 bytes  bytes   bytes    secs.    %s/sec  \n\n";
    209 
    210   char *tput_fmt_0 =
    211     "%7.2f\n";
    212 
    213   char *tput_fmt_1 =
    214     "%5d  %5d  %6d    %-6.2f   %7.2f   \n";
    215 
    216   char *cpu_title = "\
    217 Recv   Send    Send                          Utilization    Service Demand\n\
    218 Socket Socket  Message  Elapsed              Send   Recv    Send    Recv\n\
    219 Size   Size    Size     Time     Throughput  local  remote  local   remote\n\
    220 bytes  bytes   bytes    secs.    %-8.8s/s  %%      %%       us/KB   us/KB\n\n";
    221 
    222   char *cpu_fmt_0 =
    223     "%6.3f\n";
    224 
    225   char *cpu_fmt_1 =
    226     "%5d  %5d  %6d    %-6.2f     %7.2f   %-6.2f %-6.2f  %-6.3f  %-6.3f\n";
    227 
    228   char *ksink_fmt = "\n\
    229 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
    230 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
    231 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
    232 %5d   %5d  %5d   %5d %6.4g  %6.2f     %6d %6.2f   %6d\n";
    233 
    234 
    235   float			elapsed_time;
    236 
    237 #ifdef WANT_INTERVALS
    238   int interval_count;
    239 #endif
    240 
    241   /* what we want is to have a buffer space that is at least one
    242      send-size greater than our send window. this will insure that we
    243      are never trying to re-use a buffer that may still be in the
    244      hands of the transport. This buffer will be malloc'd after we
    245      have found the size of the local senc socket buffer. We will want
    246      to deal with alignment and offset concerns as well. */
    247 
    248 #ifdef DIRTY
    249   int	*message_int_ptr;
    250 #endif
    251 #include <sys/stat.h>
    252 
    253   struct ring_elt *send_ring;
    254 
    255   int	len = 0;
    256   int	nummessages;
    257   SOCKET send_socket;
    258   int	bytes_remaining;
    259   /* with links like fddi, one can send > 32 bits worth of bytes
    260      during a test... ;-) */
    261   double	bytes_sent;
    262 
    263 #ifdef DIRTY
    264   int	i;
    265 #endif /* DIRTY */
    266 
    267   float	local_cpu_utilization;
    268   float	local_service_demand;
    269   float	remote_cpu_utilization;
    270   float	remote_service_demand;
    271   double	thruput;
    272 
    273   struct	sockaddr_un	server;
    274 
    275   struct	stream_stream_request_struct	*stream_stream_request;
    276   struct	stream_stream_response_struct	*stream_stream_response;
    277   struct	stream_stream_results_struct	*stream_stream_result;
    278 
    279   stream_stream_request  =
    280     (struct stream_stream_request_struct *)netperf_request.content.test_specific_data;
    281   stream_stream_response =
    282     (struct stream_stream_response_struct *)netperf_response.content.test_specific_data;
    283   stream_stream_result   =
    284     (struct stream_stream_results_struct *)netperf_response.content.test_specific_data;
    285 
    286   /* since we are now disconnected from the code that established the
    287      control socket, and since we want to be able to use different
    288      protocols and such, we are passed the name of the remote host and
    289      must turn that into the test specific addressing information. */
    290 
    291   bzero((char *)&server,
    292 	sizeof(server));
    293   server.sun_family = AF_UNIX;
    294 
    295 
    296   if ( print_headers ) {
    297     fprintf(where,"STREAM STREAM TEST\n");
    298     if (local_cpu_usage || remote_cpu_usage)
    299       fprintf(where,cpu_title,format_units());
    300     else
    301       fprintf(where,tput_title,format_units());
    302   }
    303 
    304   /* initialize a few counters */
    305 
    306   nummessages	=	0;
    307   bytes_sent	=	0.0;
    308   times_up 	= 	0;
    309 
    310   /*set up the data socket                        */
    311   send_socket = create_unix_socket(AF_UNIX,
    312 				   SOCK_STREAM);
    313 
    314   if (send_socket == INVALID_SOCKET){
    315     perror("netperf: send_stream_stream: stream stream data socket");
    316     exit(1);
    317   }
    318 
    319   if (debug) {
    320     fprintf(where,"send_stream_stream: send_socket obtained...\n");
    321   }
    322 
    323   /* at this point, we have either retrieved the socket buffer sizes,
    324      or have tried to set them, so now, we may want to set the send
    325      size based on that (because the user either did not use a -m
    326      option, or used one with an argument of 0). If the socket buffer
    327      size is not available, we will set the send size to 4KB - no
    328      particular reason, just arbitrary... */
    329   if (send_size == 0) {
    330     if (lss_size > 0) {
    331       send_size = lss_size;
    332     }
    333     else {
    334       send_size = 4096;
    335     }
    336   }
    337 
    338   /* set-up the data buffer ring with the requested alignment and
    339      offset.  note also that we have allocated a quantity of memory
    340      that is at least one send-size greater than our socket buffer
    341      size. We want to be sure that there are at least two buffers
    342      allocated - this can be a bit of a problem when the send_size is
    343      bigger than the socket size, so we must check... the user may
    344      have wanted to explicitly set the "width" of our send buffers, we
    345      should respect that wish... */
    346   if (send_width == 0) {
    347     send_width = (lss_size/send_size) + 1;
    348     if (send_width == 1) send_width++;
    349   }
    350 
    351   send_ring = allocate_buffer_ring(send_width,
    352 				   send_size,
    353 				   local_send_align,
    354 				   local_send_offset);
    355 
    356   /* If the user has requested cpu utilization measurements, we must
    357      calibrate the cpu(s). We will perform this task within the tests
    358      themselves. If the user has specified the cpu rate, then
    359      calibrate_local_cpu will return rather quickly as it will have
    360      nothing to do. If local_cpu_rate is zero, then we will go through
    361      all the "normal" calibration stuff and return the rate back.*/
    362 
    363   if (local_cpu_usage) {
    364     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
    365   }
    366 
    367   /* Tell the remote end to do a listen. The server alters the socket
    368      paramters on the other side at this point, hence the reason for
    369      all the values being passed in the setup message. If the user did
    370      not specify any of the parameters, they will be passed as 0,
    371      which will indicate to the remote that no changes beyond the
    372      system's default should be used. Alignment is the exception, it
    373      will default to 1, which will be no alignment alterations. */
    374 
    375   netperf_request.content.request_type	=	DO_STREAM_STREAM;
    376   stream_stream_request->send_buf_size	=	rss_size;
    377   stream_stream_request->recv_buf_size	=	rsr_size;
    378   stream_stream_request->receive_size	=	recv_size;
    379   stream_stream_request->recv_alignment	=	remote_recv_align;
    380   stream_stream_request->recv_offset	=	remote_recv_offset;
    381   stream_stream_request->measure_cpu	=	remote_cpu_usage;
    382   stream_stream_request->cpu_rate	=	remote_cpu_rate;
    383   if (test_time) {
    384     stream_stream_request->test_length	=	test_time;
    385   }
    386   else {
    387     stream_stream_request->test_length	=	test_bytes;
    388   }
    389 #ifdef DIRTY
    390   stream_stream_request->dirty_count    =       rem_dirty_count;
    391   stream_stream_request->clean_count    =       rem_clean_count;
    392 #endif /* DIRTY */
    393 
    394 
    395   if (debug > 1) {
    396     fprintf(where,
    397 	    "netperf: send_stream_stream: requesting STREAM stream test\n");
    398   }
    399 
    400   send_request();
    401 
    402   /* The response from the remote will contain all of the relevant
    403      socket parameters for this test type. We will put them back into
    404      the variables here so they can be displayed if desired.  The
    405      remote will have calibrated CPU if necessary, and will have done
    406      all the needed set-up we will have calibrated the cpu locally
    407      before sending the request, and will grab the counter value right
    408      after the connect returns. The remote will grab the counter right
    409      after the accept call. This saves the hassle of extra messages
    410      being sent for the STREAM tests.  */
    411 
    412   recv_response();
    413 
    414   if (!netperf_response.content.serv_errno) {
    415     if (debug)
    416       fprintf(where,"remote listen done.\n");
    417     rsr_size	        =	stream_stream_response->recv_buf_size;
    418     rss_size	        =	stream_stream_response->send_buf_size;
    419     remote_cpu_usage    =	stream_stream_response->measure_cpu;
    420     remote_cpu_rate     = 	stream_stream_response->cpu_rate;
    421     strcpy(server.sun_path,stream_stream_response->unix_path);
    422   }
    423   else {
    424     Set_errno(netperf_response.content.serv_errno);
    425     perror("netperf: send_stream_stream: remote error");
    426     exit(1);
    427   }
    428 
    429   /*Connect up to the remote port on the data socket  */
    430   if (connect(send_socket,
    431 	      (struct sockaddr *)&server,
    432 	      sizeof(server)) == INVALID_SOCKET){
    433     perror("netperf: send_stream_stream: data socket connect failed");
    434     printf(" path: %s\n",server.sun_path);
    435     exit(1);
    436   }
    437 
    438   /* Data Socket set-up is finished. If there were problems, either
    439      the connect would have failed, or the previous response would
    440      have indicated a problem. I failed to see the value of the extra
    441      message after the accept on the remote. If it failed, we'll see
    442      it here. If it didn't, we might as well start pumping data. */
    443 
    444   /* Set-up the test end conditions. For a stream test, they can be
    445      either time or byte-count based. */
    446 
    447   if (test_time) {
    448     /* The user wanted to end the test after a period of time. */
    449     times_up = 0;
    450     bytes_remaining = 0;
    451     start_timer(test_time);
    452   }
    453   else {
    454     /* The tester wanted to send a number of bytes. */
    455     bytes_remaining = test_bytes;
    456     times_up = 1;
    457   }
    458 
    459   /* The cpu_start routine will grab the current time and possibly
    460      value of the idle counter for later use in measuring cpu
    461      utilization and/or service demand and thruput. */
    462 
    463   cpu_start(local_cpu_usage);
    464 
    465   /* We use an "OR" to control test execution. When the test is
    466      controlled by time, the byte count check will always return
    467      false.  When the test is controlled by byte count, the time test
    468      will always return false. When the test is finished, the whole
    469      expression will go false and we will stop sending data. */
    470 
    471 #ifdef DIRTY
    472   /* initialize the random number generator for putting dirty stuff
    473      into the send buffer. raj */
    474   srand((int) getpid());
    475 #endif
    476 
    477   while ((!times_up) || (bytes_remaining > 0)) {
    478 
    479 #ifdef DIRTY
    480     /* we want to dirty some number of consecutive integers in the
    481        buffer we are about to send. we may also want to bring some
    482        number of them cleanly into the cache. The clean ones will
    483        follow any dirty ones into the cache. at some point, we might
    484        want to replace the rand() call with something from a table to
    485        reduce our call overhead during the test, but it is not a high
    486        priority item. */
    487     message_int_ptr = (int *)(send_ring->buffer_ptr);
    488     for (i = 0; i < loc_dirty_count; i++) {
    489       *message_int_ptr = rand();
    490       message_int_ptr++;
    491     }
    492     for (i = 0; i < loc_clean_count; i++) {
    493       loc_dirty_count = *message_int_ptr;
    494       message_int_ptr++;
    495     }
    496 #endif /* DIRTY */
    497 
    498     if((len=send(send_socket,
    499 		 send_ring->buffer_ptr,
    500 		 send_size,
    501 		 0)) != send_size) {
    502       if ((len >=0) || (errno == EINTR)) {
    503 	/* the test was interrupted, must be the end of test */
    504 	break;
    505       }
    506       perror("netperf: data send error");
    507       printf("len was %d\n",len);
    508       exit(1);
    509     }
    510 #ifdef WANT_INTERVALS
    511     for (interval_count = 0;
    512 	 interval_count < interval_wate;
    513 	 interval_count++);
    514 #endif
    515 
    516     /* now we want to move our pointer to the next position in the
    517        data buffer...we may also want to wrap back to the "beginning"
    518        of the bufferspace, so we will mod the number of messages sent
    519        by the send width, and use that to calculate the offset to add
    520        to the base pointer. */
    521     nummessages++;
    522     send_ring = send_ring->next;
    523     if (bytes_remaining) {
    524       bytes_remaining -= send_size;
    525     }
    526   }
    527 
    528   /* The test is over. Flush the buffers to the remote end. We do a
    529      graceful release to insure that all data has been taken by the
    530      remote. */
    531 
    532   if (close(send_socket) == -1) {
    533     perror("netperf: send_stream_stream: cannot close socket");
    534     exit(1);
    535   }
    536 
    537   /* this call will always give us the elapsed time for the test, and
    538      will also store-away the necessaries for cpu utilization */
    539 
    540   cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured
    541 					      and how long did we
    542 					      really run? */
    543 
    544   /* Get the statistics from the remote end. The remote will have
    545      calculated service demand and all those interesting things. If it
    546      wasn't supposed to care, it will return obvious values. */
    547 
    548   recv_response();
    549   if (!netperf_response.content.serv_errno) {
    550     if (debug)
    551       fprintf(where,"remote results obtained\n");
    552   }
    553   else {
    554     Set_errno(netperf_response.content.serv_errno);
    555     perror("netperf: remote error");
    556 
    557     exit(1);
    558   }
    559 
    560   /* We now calculate what our thruput was for the test. In the
    561      future, we may want to include a calculation of the thruput
    562      measured by the remote, but it should be the case that for a
    563      STREAM stream test, that the two numbers should be *very*
    564      close... We calculate bytes_sent regardless of the way the test
    565      length was controlled.  If it was time, we needed to, and if it
    566      was by bytes, the user may have specified a number of bytes that
    567      wasn't a multiple of the send_size, so we really didn't send what
    568      he asked for ;-) */
    569 
    570   bytes_sent	= ((double) send_size * (double) nummessages) + len;
    571   thruput	= calc_thruput(bytes_sent);
    572 
    573   if (local_cpu_usage || remote_cpu_usage) {
    574     /* We must now do a little math for service demand and cpu
    575        utilization for the system(s) Of course, some of the
    576        information might be bogus because there was no idle counter in
    577        the kernel(s). We need to make a note of this for the user's
    578        benefit...*/
    579     if (local_cpu_usage) {
    580       if (local_cpu_rate == 0.0) {
    581 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
    582 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
    583 	fflush(where);
    584       }
    585       local_cpu_utilization	= calc_cpu_util(0.0);
    586       local_service_demand	= calc_service_demand(bytes_sent,
    587 						      0.0,
    588 						      0.0,
    589 						      0);
    590     }
    591     else {
    592       local_cpu_utilization	= -1.0;
    593       local_service_demand	= -1.0;
    594     }
    595 
    596     if (remote_cpu_usage) {
    597       if (remote_cpu_rate == 0.0) {
    598 	fprintf(where,"DANGER   DANGER  DANGER   DANGER   DANGER  DANGER   DANGER!\n");
    599 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
    600 	fflush(where);
    601       }
    602       remote_cpu_utilization	= stream_stream_result->cpu_util;
    603       remote_service_demand	= calc_service_demand(bytes_sent,
    604 						      0.0,
    605 						      remote_cpu_utilization,
    606 						      stream_stream_result->num_cpus);
    607     }
    608     else {
    609       remote_cpu_utilization = -1.0;
    610       remote_service_demand  = -1.0;
    611     }
    612 
    613     /* We are now ready to print all the information. If the user has
    614        specified zero-level verbosity, we will just print the local
    615        service demand, or the remote service demand. If the user has
    616        requested verbosity level 1, he will get the basic "streamperf"
    617        numbers. If the user has specified a verbosity of greater than
    618        1, we will display a veritable plethora of background
    619        information from outside of this block as it it not
    620        cpu_measurement specific...  */
    621 
    622     switch (verbosity) {
    623     case 0:
    624       if (local_cpu_usage) {
    625 	fprintf(where,
    626 		cpu_fmt_0,
    627 		local_service_demand);
    628       }
    629       else {
    630 	fprintf(where,
    631 		cpu_fmt_0,
    632 		remote_service_demand);
    633       }
    634       break;
    635     case 1:
    636     case 2:
    637       fprintf(where,
    638 	      cpu_fmt_1,		/* the format string */
    639 	      rsr_size,		        /* remote recvbuf size */
    640 	      lss_size,		        /* local sendbuf size */
    641 	      send_size,		/* how large were the sends */
    642 	      elapsed_time,		/* how long was the test */
    643 	      thruput, 		        /* what was the xfer rate */
    644 	      local_cpu_utilization,	/* local cpu */
    645 	      remote_cpu_utilization,	/* remote cpu */
    646 	      local_service_demand,	/* local service demand */
    647 	      remote_service_demand);	/* remote service demand */
    648       break;
    649     }
    650   }
    651   else {
    652     /* The tester did not wish to measure service demand. */
    653     switch (verbosity) {
    654     case 0:
    655       fprintf(where,
    656 	      tput_fmt_0,
    657 	      thruput);
    658       break;
    659     case 1:
    660     case 2:
    661       fprintf(where,
    662 	      tput_fmt_1,    /* the format string */
    663 	      rsr_size,      /* remote recvbuf size */
    664 	      lss_size,      /* local sendbuf size */
    665 	      send_size,     /* how large were the sends */
    666 	      elapsed_time,  /* how long did it take */
    667 	      thruput);      /* how fast did it go */
    668       break;
    669     }
    670   }
    671 
    672   /* it would be a good thing to include information about some of the
    673      other parameters that may have been set for this test, but at the
    674      moment, I do not wish to figure-out all the formatting, so I will
    675      just put this comment here to help remind me that it is something
    676      that should be done at a later time. */
    677 
    678   if (verbosity > 1) {
    679     /* The user wanted to know it all, so we will give it to him.
    680        This information will include as much as we can find about
    681        STREAM statistics, the alignments of the sends and receives and
    682        all that sort of rot... */
    683 
    684     fprintf(where,
    685 	    ksink_fmt,
    686 	    "Bytes",
    687 	    "Bytes",
    688 	    "Bytes",
    689 	    local_send_align,
    690 	    remote_recv_align,
    691 	    local_send_offset,
    692 	    remote_recv_offset,
    693 	    bytes_sent,
    694 	    bytes_sent / (double)nummessages,
    695 	    nummessages,
    696 	    bytes_sent / (double)stream_stream_result->recv_calls,
    697 	    stream_stream_result->recv_calls);
    698   }
    699 
    700 }
    701 
    702 
    704 /* This is the server-side routine for the stream stream test. It is
    705    implemented as one routine. I could break things-out somewhat, but
    706    didn't feel it was necessary. */
    707 
    708 void
    709 recv_stream_stream()
    710 {
    711 
    712   struct sockaddr_un myaddr_un, peeraddr_un;
    713   SOCKET s_listen,s_data;
    714   netperf_socklen_t addrlen;
    715   int	len;
    716   int	receive_calls = 0;
    717   float	elapsed_time;
    718   int   bytes_received;
    719 
    720   struct ring_elt *recv_ring;
    721 
    722 #ifdef DIRTY
    723   char	*message_ptr;
    724   int   *message_int_ptr;
    725   int   dirty_count;
    726   int   clean_count;
    727   int   i;
    728 #endif
    729 
    730   struct	stream_stream_request_struct	*stream_stream_request;
    731   struct	stream_stream_response_struct	*stream_stream_response;
    732   struct	stream_stream_results_struct	*stream_stream_results;
    733 
    734   stream_stream_request	=
    735     (struct stream_stream_request_struct *)netperf_request.content.test_specific_data;
    736   stream_stream_response	=
    737     (struct stream_stream_response_struct *)netperf_response.content.test_specific_data;
    738   stream_stream_results	=
    739     (struct stream_stream_results_struct *)netperf_response.content.test_specific_data;
    740 
    741   if (debug) {
    742     fprintf(where,"netserver: recv_stream_stream: entered...\n");
    743     fflush(where);
    744   }
    745 
    746   /* We want to set-up the listen socket with all the desired
    747      parameters and then let the initiator know that all is ready. If
    748      socket size defaults are to be used, then the initiator will have
    749      sent us 0's. If the socket sizes cannot be changed, then we will
    750      send-back what they are. If that information cannot be
    751      determined, then we send-back -1's for the sizes. If things go
    752      wrong for any reason, we will drop back ten yards and punt. */
    753 
    754   /* If anything goes wrong, we want the remote to know about it. It
    755      would be best if the error that the remote reports to the user is
    756      the actual error we encountered, rather than some bogus
    757      unexpected response type message. */
    758 
    759   if (debug) {
    760     fprintf(where,"recv_stream_stream: setting the response type...\n");
    761     fflush(where);
    762   }
    763 
    764   netperf_response.content.response_type = STREAM_STREAM_RESPONSE;
    765 
    766   if (debug) {
    767     fprintf(where,"recv_stream_stream: the response type is set...\n");
    768     fflush(where);
    769   }
    770 
    771   /* We now alter the message_ptr variable to be at the desired
    772      alignment with the desired offset. */
    773 
    774   if (debug) {
    775     fprintf(where,"recv_stream_stream: requested alignment of %d\n",
    776 	    stream_stream_request->recv_alignment);
    777     fflush(where);
    778   }
    779 
    780   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we
    781      can put in OUR values !-) At some point, we may want to nail this
    782      socket to a particular network-level address, but for now,
    783      INADDR_ANY should be just fine. */
    784 
    785   bzero((char *)&myaddr_un,
    786 	sizeof(myaddr_un));
    787   myaddr_un.sun_family      = AF_UNIX;
    788 
    789   /* Grab a socket to listen on, and then listen on it. */
    790 
    791   if (debug) {
    792     fprintf(where,"recv_stream_stream: grabbing a socket...\n");
    793     fflush(where);
    794   }
    795 
    796   /* create_unix_socket expects to find some things in the global
    797      variables, so set the globals based on the values in the request.
    798      once the socket has been created, we will set the response values
    799      based on the updated value of those globals. raj 7/94 */
    800   lss_size_req = stream_stream_request->send_buf_size;
    801   lsr_size_req = stream_stream_request->recv_buf_size;
    802 
    803   s_listen = create_unix_socket(AF_UNIX,
    804 				SOCK_STREAM);
    805 
    806   if (s_listen == INVALID_SOCKET) {
    807     netperf_response.content.serv_errno = errno;
    808     send_response();
    809     exit(1);
    810   }
    811 
    812   /* Let's get an address assigned to this socket so we can tell the
    813      initiator how to reach the data socket. There may be a desire to
    814      nail this socket to a specific IP address in a multi-homed,
    815      multi-connection situation, but for now, we'll ignore the issue
    816      and concentrate on single connection testing. */
    817 
    818   strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
    819   if (debug) {
    820     fprintf(where,"selected a path of %s\n",myaddr_un.sun_path);
    821     fflush(where);
    822   }
    823   if (bind(s_listen,
    824 	   (struct sockaddr *)&myaddr_un,
    825 	   sizeof(myaddr_un)) == SOCKET_ERROR) {
    826     netperf_response.content.serv_errno = errno;
    827     fprintf(where,"could not bind to path\n");
    828     close(s_listen);
    829     send_response();
    830 
    831     exit(1);
    832   }
    833 
    834   chmod(myaddr_un.sun_path, 0666);
    835 
    836   /* what sort of sizes did we end-up with? */
    837   if (stream_stream_request->receive_size == 0) {
    838     if (lsr_size > 0) {
    839       recv_size = lsr_size;
    840     }
    841     else {
    842       recv_size = 4096;
    843     }
    844   }
    845   else {
    846     recv_size = stream_stream_request->receive_size;
    847   }
    848 
    849   /* we want to set-up our recv_ring in a manner analagous to what we
    850      do on the sending side. this is more for the sake of symmetry
    851      than for the needs of say copy avoidance, but it might also be
    852      more realistic - this way one could conceivably go with a
    853      double-buffering scheme when taking the data an putting it into
    854      the filesystem or something like that. raj 7/94 */
    855 
    856   if (recv_width == 0) {
    857     recv_width = (lsr_size/recv_size) + 1;
    858     if (recv_width == 1) recv_width++;
    859   }
    860 
    861   recv_ring = allocate_buffer_ring(recv_width,
    862 				   recv_size,
    863 				   stream_stream_request->recv_alignment,
    864 				   stream_stream_request->recv_offset);
    865 
    866   if (debug) {
    867     fprintf(where,"recv_stream_stream: receive alignment and offset set...\n");
    868     fflush(where);
    869   }
    870 
    871   /* Now, let's set-up the socket to listen for connections */
    872   if (listen(s_listen, 5) == SOCKET_ERROR) {
    873     netperf_response.content.serv_errno = errno;
    874     close(s_listen);
    875     send_response();
    876 
    877     exit(1);
    878   }
    879 
    880   /* now get the port number assigned by the system  */
    881   addrlen = sizeof(myaddr_un);
    882   if (getsockname(s_listen,
    883 		  (struct sockaddr *)&myaddr_un,
    884 		  &addrlen) == SOCKET_ERROR){
    885     netperf_response.content.serv_errno = errno;
    886     close(s_listen);
    887     send_response();
    888 
    889     exit(1);
    890   }
    891 
    892   /* Now myaddr_un contains the path returned to the sender also
    893      implicitly telling the sender that the socket buffer sizing has
    894      been done. */
    895   strcpy(stream_stream_response->unix_path,myaddr_un.sun_path);
    896   netperf_response.content.serv_errno   = 0;
    897 
    898   /* But wait, there's more. If the initiator wanted cpu measurements,
    899      then we must call the calibrate routine, which will return the
    900      max rate back to the initiator. If the CPU was not to be
    901      measured, or something went wrong with the calibration, we will
    902      return a -1 to the initiator. */
    903 
    904   stream_stream_response->cpu_rate = 0.0; 	/* assume no cpu */
    905   if (stream_stream_request->measure_cpu) {
    906     stream_stream_response->measure_cpu = 1;
    907     stream_stream_response->cpu_rate =
    908       calibrate_local_cpu(stream_stream_request->cpu_rate);
    909   }
    910 
    911   /* before we send the response back to the initiator, pull some of
    912      the socket parms from the globals */
    913   stream_stream_response->send_buf_size = lss_size;
    914   stream_stream_response->recv_buf_size = lsr_size;
    915   stream_stream_response->receive_size = recv_size;
    916 
    917   send_response();
    918 
    919   addrlen = sizeof(peeraddr_un);
    920 
    921   if ((s_data=accept(s_listen,
    922 		     (struct sockaddr *)&peeraddr_un,
    923 		     &addrlen)) == INVALID_SOCKET) {
    924     /* Let's just punt. The remote will be given some information */
    925     close(s_listen);
    926     exit(1);
    927   }
    928 
    929   /* Now it's time to start receiving data on the connection. We will
    930      first grab the apropriate counters and then start grabbing. */
    931 
    932   cpu_start(stream_stream_request->measure_cpu);
    933 
    934   /* The loop will exit when the sender does a shutdown, which will
    935      return a length of zero  */
    936 
    937 #ifdef DIRTY
    938   /* we want to dirty some number of consecutive integers in the
    939      buffer we are about to recv. we may also want to bring some
    940      number of them cleanly into the cache. The clean ones will follow
    941      any dirty ones into the cache. */
    942 
    943   dirty_count = stream_stream_request->dirty_count;
    944   clean_count = stream_stream_request->clean_count;
    945   message_int_ptr = (int *)recv_ring->buffer_ptr;
    946   for (i = 0; i < dirty_count; i++) {
    947     *message_int_ptr = rand();
    948     message_int_ptr++;
    949   }
    950   for (i = 0; i < clean_count; i++) {
    951     dirty_count = *message_int_ptr;
    952     message_int_ptr++;
    953   }
    954 #endif /* DIRTY */
    955   bytes_received = 0;
    956 
    957   while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
    958     if (len == SOCKET_ERROR) {
    959       netperf_response.content.serv_errno = errno;
    960       send_response();
    961       exit(1);
    962     }
    963     bytes_received += len;
    964     receive_calls++;
    965 
    966     /* more to the next buffer in the recv_ring */
    967     recv_ring = recv_ring->next;
    968 
    969 #ifdef DIRTY
    970     message_int_ptr = (int *)(recv_ring->buffer_ptr);
    971     for (i = 0; i < dirty_count; i++) {
    972       *message_int_ptr = rand();
    973       message_int_ptr++;
    974     }
    975     for (i = 0; i < clean_count; i++) {
    976       dirty_count = *message_int_ptr;
    977       message_int_ptr++;
    978     }
    979 #endif /* DIRTY */
    980   }
    981 
    982   /* The loop now exits due to zero bytes received. we will have
    983      counted one too many messages received, so decrement the
    984      receive_calls counter by one. raj 7/94 */
    985   receive_calls--;
    986 
    987   /* perform a shutdown to signal the sender that we have received all
    988      the data sent. raj 4/93 */
    989 
    990   if (shutdown(s_data,1) == SOCKET_ERROR) {
    991       netperf_response.content.serv_errno = errno;
    992       send_response();
    993       exit(1);
    994     }
    995 
    996   cpu_stop(stream_stream_request->measure_cpu,&elapsed_time);
    997 
    998   /* send the results to the sender			*/
    999 
   1000   if (debug) {
   1001     fprintf(where,
   1002 	    "recv_stream_stream: got %d bytes\n",
   1003 	    bytes_received);
   1004     fprintf(where,
   1005 	    "recv_stream_stream: got %d recvs\n",
   1006 	    receive_calls);
   1007     fflush(where);
   1008   }
   1009 
   1010   stream_stream_results->bytes_received	= bytes_received;
   1011   stream_stream_results->elapsed_time	= elapsed_time;
   1012   stream_stream_results->recv_calls	= receive_calls;
   1013 
   1014   if (stream_stream_request->measure_cpu) {
   1015     stream_stream_results->cpu_util	= calc_cpu_util(0.0);
   1016   };
   1017 
   1018   if (debug > 1) {
   1019     fprintf(where,
   1020 	    "recv_stream_stream: test complete, sending results.\n");
   1021     fflush(where);
   1022   }
   1023 
   1024   send_response();
   1025   unlink(myaddr_un.sun_path);
   1026 }
   1027 
   1028 
   1030 /* this routine implements the sending (netperf) side of the STREAM_RR
   1031    test. */
   1032 
   1033 void
   1034 send_stream_rr(char remote_host[])
   1035 {
   1036 
   1037   char *tput_title = "\
   1038 Local /Remote\n\
   1039 Socket Size   Request  Resp.   Elapsed  Trans.\n\
   1040 Send   Recv   Size     Size    Time     Rate         \n\
   1041 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
   1042 
   1043   char *tput_fmt_0 =
   1044     "%7.2f\n";
   1045 
   1046   char *tput_fmt_1_line_1 = "\
   1047 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
   1048   char *tput_fmt_1_line_2 = "\
   1049 %-6d %-6d\n";
   1050 
   1051   char *cpu_title = "\
   1052 Local /Remote\n\
   1053 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
   1054 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
   1055 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
   1056 
   1057   char *cpu_fmt_0 =
   1058     "%6.3f\n";
   1059 
   1060   char *cpu_fmt_1_line_1 = "\
   1061 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
   1062 
   1063   char *cpu_fmt_1_line_2 = "\
   1064 %-6d %-6d\n";
   1065 
   1066   char *ksink_fmt = "\
   1067 Alignment      Offset\n\
   1068 Local  Remote  Local  Remote\n\
   1069 Send   Recv    Send   Recv\n\
   1070 %5d  %5d   %5d  %5d\n";
   1071 
   1072 
   1073   int			timed_out = 0;
   1074   float			elapsed_time;
   1075 
   1076   int	len;
   1077   char	*temp_message_ptr;
   1078   int	nummessages;
   1079   SOCKET send_socket;
   1080   int	trans_remaining;
   1081   double	bytes_xferd;
   1082 
   1083   struct ring_elt *send_ring;
   1084   struct ring_elt *recv_ring;
   1085 
   1086   int	rsp_bytes_left;
   1087   int	rsp_bytes_recvd;
   1088 
   1089   float	local_cpu_utilization;
   1090   float	local_service_demand;
   1091   float	remote_cpu_utilization;
   1092   float	remote_service_demand;
   1093   double	thruput;
   1094 
   1095   struct	sockaddr_un	server;
   1096 
   1097   struct	stream_rr_request_struct	*stream_rr_request;
   1098   struct	stream_rr_response_struct	*stream_rr_response;
   1099   struct	stream_rr_results_struct	*stream_rr_result;
   1100 
   1101   stream_rr_request =
   1102     (struct stream_rr_request_struct *)netperf_request.content.test_specific_data;
   1103   stream_rr_response=
   1104     (struct stream_rr_response_struct *)netperf_response.content.test_specific_data;
   1105   stream_rr_result	=
   1106     (struct stream_rr_results_struct *)netperf_response.content.test_specific_data;
   1107 
   1108   /* since we are now disconnected from the code that established the
   1109      control socket, and since we want to be able to use different
   1110      protocols and such, we are passed the name of the remote host and
   1111      must turn that into the test specific addressing information. */
   1112 
   1113   bzero((char *)&server,
   1114 	sizeof(server));
   1115 
   1116   server.sun_family = AF_UNIX;
   1117 
   1118 
   1119   if ( print_headers ) {
   1120     fprintf(where,"STREAM REQUEST/RESPONSE TEST\n");
   1121     if (local_cpu_usage || remote_cpu_usage)
   1122       fprintf(where,cpu_title,format_units());
   1123     else
   1124       fprintf(where,tput_title,format_units());
   1125   }
   1126 
   1127   /* initialize a few counters */
   1128 
   1129   nummessages	=	0;
   1130   bytes_xferd	=	0.0;
   1131   times_up 	= 	0;
   1132 
   1133   /* set-up the data buffers with the requested alignment and offset.
   1134      since this is a request/response test, default the send_width and
   1135      recv_width to 1 and not two raj 7/94 */
   1136 
   1137   if (send_width == 0) send_width = 1;
   1138   if (recv_width == 0) recv_width = 1;
   1139 
   1140   send_ring = allocate_buffer_ring(send_width,
   1141 				   req_size,
   1142 				   local_send_align,
   1143 				   local_send_offset);
   1144 
   1145   recv_ring = allocate_buffer_ring(recv_width,
   1146 				   rsp_size,
   1147 				   local_recv_align,
   1148 				   local_recv_offset);
   1149 
   1150   /*set up the data socket                        */
   1151   send_socket = create_unix_socket(AF_UNIX,
   1152 				   SOCK_STREAM);
   1153 
   1154   if (send_socket == INVALID_SOCKET){
   1155     perror("netperf: send_stream_rr: stream stream data socket");
   1156     exit(1);
   1157   }
   1158 
   1159   if (debug) {
   1160     fprintf(where,"send_stream_rr: send_socket obtained...\n");
   1161   }
   1162 
   1163   /* If the user has requested cpu utilization measurements, we must
   1164      calibrate the cpu(s). We will perform this task within the tests
   1165      themselves. If the user has specified the cpu rate, then
   1166      calibrate_local_cpu will return rather quickly as it will have
   1167      nothing to do. If local_cpu_rate is zero, then we will go through
   1168      all the "normal" calibration stuff and return the rate back.*/
   1169 
   1170   if (local_cpu_usage) {
   1171     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   1172   }
   1173 
   1174   /* Tell the remote end to do a listen. The server alters the socket
   1175      paramters on the other side at this point, hence the reason for
   1176      all the values being passed in the setup message. If the user did
   1177      not specify any of the parameters, they will be passed as 0,
   1178      which will indicate to the remote that no changes beyond the
   1179      system's default should be used. Alignment is the exception, it
   1180      will default to 8, which will be no alignment alterations. */
   1181 
   1182   netperf_request.content.request_type	=	DO_STREAM_RR;
   1183   stream_rr_request->recv_buf_size	=	rsr_size;
   1184   stream_rr_request->send_buf_size	=	rss_size;
   1185   stream_rr_request->recv_alignment=	remote_recv_align;
   1186   stream_rr_request->recv_offset	=	remote_recv_offset;
   1187   stream_rr_request->send_alignment=	remote_send_align;
   1188   stream_rr_request->send_offset	=	remote_send_offset;
   1189   stream_rr_request->request_size	=	req_size;
   1190   stream_rr_request->response_size	=	rsp_size;
   1191   stream_rr_request->measure_cpu	=	remote_cpu_usage;
   1192   stream_rr_request->cpu_rate	=	remote_cpu_rate;
   1193   if (test_time) {
   1194     stream_rr_request->test_length	=	test_time;
   1195   }
   1196   else {
   1197     stream_rr_request->test_length	=	test_trans * -1;
   1198   }
   1199 
   1200   if (debug > 1) {
   1201     fprintf(where,"netperf: send_stream_rr: requesting STREAM rr test\n");
   1202   }
   1203 
   1204   send_request();
   1205 
   1206   /* The response from the remote will contain all of the relevant
   1207      socket parameters for this test type. We will put them back into
   1208      the variables here so they can be displayed if desired.  The
   1209      remote will have calibrated CPU if necessary, and will have done
   1210      all the needed set-up we will have calibrated the cpu locally
   1211      before sending the request, and will grab the counter value right
   1212      after the connect returns. The remote will grab the counter right
   1213      after the accept call. This saves the hassle of extra messages
   1214      being sent for the STREAM tests.  */
   1215 
   1216   recv_response();
   1217 
   1218   if (!netperf_response.content.serv_errno) {
   1219     if (debug)
   1220       fprintf(where,"remote listen done.\n");
   1221     rsr_size	=	stream_rr_response->recv_buf_size;
   1222     rss_size	=	stream_rr_response->send_buf_size;
   1223     remote_cpu_usage=	stream_rr_response->measure_cpu;
   1224     remote_cpu_rate = 	stream_rr_response->cpu_rate;
   1225     /* make sure that port numbers are in network order */
   1226     strcpy(server.sun_path,stream_rr_response->unix_path);
   1227   }
   1228   else {
   1229     Set_errno(netperf_response.content.serv_errno);
   1230     perror("netperf: remote error");
   1231 
   1232     exit(1);
   1233   }
   1234 
   1235   /*Connect up to the remote port on the data socket  */
   1236   if (connect(send_socket,
   1237 	      (struct sockaddr *)&server,
   1238 	      sizeof(server)) == INVALID_SOCKET){
   1239     perror("netperf: data socket connect failed");
   1240 
   1241     exit(1);
   1242   }
   1243 
   1244   /* Data Socket set-up is finished. If there were problems, either
   1245      the connect would have failed, or the previous response would
   1246      have indicated a problem. I failed to see the value of the extra
   1247      message after the accept on the remote. If it failed, we'll see
   1248      it here. If it didn't, we might as well start pumping data. */
   1249 
   1250   /* Set-up the test end conditions. For a request/response test, they
   1251      can be either time or transaction based. */
   1252 
   1253   if (test_time) {
   1254     /* The user wanted to end the test after a period of time. */
   1255     times_up = 0;
   1256     trans_remaining = 0;
   1257     start_timer(test_time);
   1258   }
   1259   else {
   1260     /* The tester wanted to send a number of bytes. */
   1261     trans_remaining = test_bytes;
   1262     times_up = 1;
   1263   }
   1264 
   1265   /* The cpu_start routine will grab the current time and possibly
   1266      value of the idle counter for later use in measuring cpu
   1267      utilization and/or service demand and thruput. */
   1268 
   1269   cpu_start(local_cpu_usage);
   1270 
   1271   /* We use an "OR" to control test execution. When the test is
   1272      controlled by time, the byte count check will always return
   1273      false.  When the test is controlled by byte count, the time test
   1274      will always return false. When the test is finished, the whole
   1275      expression will go false and we will stop sending data. I think I
   1276      just arbitrarily decrement trans_remaining for the timed test,
   1277      but will not do that just yet... One other question is whether or
   1278      not the send buffer and the receive buffer should be the same
   1279      buffer. */
   1280 
   1281   while ((!times_up) || (trans_remaining > 0)) {
   1282     /* send the request. we assume that if we use a blocking socket,
   1283        the request will be sent at one shot. */
   1284     if((len=send(send_socket,
   1285 		 send_ring->buffer_ptr,
   1286 		 req_size,
   1287 		 0)) != req_size) {
   1288       if (errno == EINTR) {
   1289 	/* we hit the end of a timed test. */
   1290 	timed_out = 1;
   1291 	break;
   1292       }
   1293       perror("send_stream_rr: data send error");
   1294       exit(1);
   1295     }
   1296     send_ring = send_ring->next;
   1297 
   1298     /* receive the response */
   1299     rsp_bytes_left = rsp_size;
   1300     temp_message_ptr  = recv_ring->buffer_ptr;
   1301     while(rsp_bytes_left > 0) {
   1302       if((rsp_bytes_recvd=recv(send_socket,
   1303 			       temp_message_ptr,
   1304 			       rsp_bytes_left,
   1305 			       0)) == SOCKET_ERROR) {
   1306 	if (errno == EINTR) {
   1307 	  /* We hit the end of a timed test. */
   1308 	  timed_out = 1;
   1309 	  break;
   1310 	}
   1311 	perror("send_stream_rr: data recv error");
   1312 	exit(1);
   1313       }
   1314       rsp_bytes_left -= rsp_bytes_recvd;
   1315       temp_message_ptr  += rsp_bytes_recvd;
   1316     }
   1317     recv_ring = recv_ring->next;
   1318 
   1319     if (timed_out) {
   1320       /* we may have been in a nested while loop - we need
   1321          another call to break. */
   1322       break;
   1323     }
   1324 
   1325     nummessages++;
   1326     if (trans_remaining) {
   1327       trans_remaining--;
   1328     }
   1329 
   1330     if (debug > 3) {
   1331       fprintf(where,
   1332 	      "Transaction %d completed\n",
   1333 	      nummessages);
   1334       fflush(where);
   1335     }
   1336   }
   1337 
   1338   /* At this point we used to call shutdown on the data socket to be
   1339      sure all the data was delivered, but this was not germane in a
   1340      request/response test, and it was causing the tests to "hang"
   1341      when they were being controlled by time. So, I have replaced this
   1342      shutdown call with a call to close that can be found later in the
   1343      procedure. */
   1344 
   1345   /* this call will always give us the elapsed time for the test, and
   1346      will also store-away the necessaries for cpu utilization */
   1347 
   1348   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being
   1349 						   measured? how long
   1350 						   did we really
   1351 						   run? */
   1352 
   1353   /* Get the statistics from the remote end. The remote will have
   1354      calculated service demand and all those interesting things. If it
   1355      wasn't supposed to care, it will return obvious values. */
   1356 
   1357   recv_response();
   1358   if (!netperf_response.content.serv_errno) {
   1359     if (debug)
   1360       fprintf(where,"remote results obtained\n");
   1361   }
   1362   else {
   1363     Set_errno(netperf_response.content.serv_errno);
   1364     perror("netperf: remote error");
   1365 
   1366     exit(1);
   1367   }
   1368 
   1369   /* We now calculate what our thruput was for the test. In the
   1370      future, we may want to include a calculation of the thruput
   1371      measured by the remote, but it should be the case that for a
   1372      STREAM stream test, that the two numbers should be *very*
   1373      close... We calculate bytes_sent regardless of the way the test
   1374      length was controlled.  If it was time, we needed to, and if it
   1375      was by bytes, the user may have specified a number of bytes that
   1376      wasn't a multiple of the send_size, so we really didn't send what
   1377      he asked for ;-) We use Kbytes/s as the units of thruput for a
   1378      STREAM stream test, where K = 1024. A future enhancement *might*
   1379      be to choose from a couple of unit selections. */
   1380 
   1381   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
   1382   thruput	= calc_thruput(bytes_xferd);
   1383 
   1384   if (local_cpu_usage || remote_cpu_usage) {
   1385     /* We must now do a little math for service demand and cpu
   1386        utilization for the system(s) Of course, some of the
   1387        information might be bogus because there was no idle counter in
   1388        the kernel(s). We need to make a note of this for the user's
   1389        benefit...*/
   1390     if (local_cpu_usage) {
   1391       if (local_cpu_rate == 0.0) {
   1392 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
   1393 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
   1394 	fflush(where);
   1395       }
   1396       local_cpu_utilization = calc_cpu_util(0.0);
   1397       /* since calc_service demand is doing ms/Kunit we will multiply
   1398          the number of transaction by 1024 to get "good" numbers */
   1399       local_service_demand  = calc_service_demand((double) nummessages*1024,
   1400 						  0.0,
   1401 						  0.0,
   1402 						  0);
   1403     }
   1404     else {
   1405       local_cpu_utilization	= -1.0;
   1406       local_service_demand	= -1.0;
   1407     }
   1408 
   1409     if (remote_cpu_usage) {
   1410       if (remote_cpu_rate == 0.0) {
   1411 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
   1412 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
   1413 	fflush(where);
   1414       }
   1415       remote_cpu_utilization = stream_rr_result->cpu_util;
   1416       /* since calc_service demand is doing ms/Kunit we will multiply
   1417          the number of transaction by 1024 to get "good" numbers */
   1418       remote_service_demand = calc_service_demand((double) nummessages*1024,
   1419 						  0.0,
   1420 						  remote_cpu_utilization,
   1421 						  stream_rr_result->num_cpus);
   1422     }
   1423     else {
   1424       remote_cpu_utilization = -1.0;
   1425       remote_service_demand  = -1.0;
   1426     }
   1427 
   1428     /* We are now ready to print all the information. If the user has
   1429        specified zero-level verbosity, we will just print the local
   1430        service demand, or the remote service demand. If the user has
   1431        requested verbosity level 1, he will get the basic "streamperf"
   1432        numbers. If the user has specified a verbosity of greater than
   1433        1, we will display a veritable plethora of background
   1434        information from outside of this block as it it not
   1435        cpu_measurement specific...  */
   1436 
   1437     switch (verbosity) {
   1438     case 0:
   1439       if (local_cpu_usage) {
   1440 	fprintf(where,
   1441 		cpu_fmt_0,
   1442 		local_service_demand);
   1443       }
   1444       else {
   1445 	fprintf(where,
   1446 		cpu_fmt_0,
   1447 		remote_service_demand);
   1448       }
   1449       break;
   1450     case 1:
   1451       fprintf(where,
   1452 	      cpu_fmt_1_line_1,		/* the format string */
   1453 	      lss_size,		/* local sendbuf size */
   1454 	      lsr_size,
   1455 	      req_size,		/* how large were the requests */
   1456 	      rsp_size,		/* guess */
   1457 	      elapsed_time,		/* how long was the test */
   1458 	      nummessages/elapsed_time,
   1459 	      local_cpu_utilization,	/* local cpu */
   1460 	      remote_cpu_utilization,	/* remote cpu */
   1461 	      local_service_demand,	/* local service demand */
   1462 	      remote_service_demand);	/* remote service demand */
   1463       fprintf(where,
   1464 	      cpu_fmt_1_line_2,
   1465 	      rss_size,
   1466 	      rsr_size);
   1467       break;
   1468     }
   1469   }
   1470   else {
   1471     /* The tester did not wish to measure service demand. */
   1472     switch (verbosity) {
   1473     case 0:
   1474       fprintf(where,
   1475 	      tput_fmt_0,
   1476 	      nummessages/elapsed_time);
   1477       break;
   1478     case 1:
   1479       fprintf(where,
   1480 	      tput_fmt_1_line_1,	/* the format string */
   1481 	      lss_size,
   1482 	      lsr_size,
   1483 	      req_size,		/* how large were the requests */
   1484 	      rsp_size,		/* how large were the responses */
   1485 	      elapsed_time, 		/* how long did it take */
   1486 	      nummessages/elapsed_time);
   1487       fprintf(where,
   1488 	      tput_fmt_1_line_2,
   1489 	      rss_size, 		/* remote recvbuf size */
   1490 	      rsr_size);
   1491 
   1492       break;
   1493     }
   1494   }
   1495 
   1496   /* it would be a good thing to include information about some of the
   1497      other parameters that may have been set for this test, but at the
   1498      moment, I do not wish to figure-out all the formatting, so I will
   1499      just put this comment here to help remind me that it is something
   1500      that should be done at a later time. */
   1501 
   1502   if (verbosity > 1) {
   1503     /* The user wanted to know it all, so we will give it to him.
   1504        This information will include as much as we can find about
   1505        STREAM statistics, the alignments of the sends and receives and
   1506        all that sort of rot... */
   1507 
   1508     fprintf(where,
   1509     	    "%s",
   1510 	    ksink_fmt);
   1511   }
   1512   /* The test is over. Kill the data socket */
   1513 
   1514   if (close(send_socket) == -1) {
   1515     perror("send_stream_rr: cannot shutdown stream stream socket");
   1516   }
   1517 
   1518 }
   1519 
   1520 void
   1522 send_dg_stream(char remote_host[])
   1523 {
   1524   /*********************************************************************/
   1525   /*								       */
   1526   /*               	DG Unidirectional Send Test                    */
   1527   /*								       */
   1528   /*********************************************************************/
   1529   char *tput_title =
   1530     "Socket  Message  Elapsed      Messages                \n\
   1531 Size    Size     Time         Okay Errors   Throughput\n\
   1532 bytes   bytes    secs            #      #   %s/sec\n\n";
   1533 
   1534   char *tput_fmt_0 =
   1535     "%7.2f\n";
   1536 
   1537   char *tput_fmt_1 =
   1538     "%5d   %5d    %-7.2f   %7d %6d    %7.2f\n\
   1539 %5d            %-7.2f   %7d           %7.2f\n\n";
   1540 
   1541 
   1542   char *cpu_title =
   1543     "Socket  Message  Elapsed      Messages                   CPU     Service\n\
   1544 Size    Size     Time         Okay Errors   Throughput   Util    Demand\n\
   1545 bytes   bytes    secs            #      #   %s/sec   %%       us/KB\n\n";
   1546 
   1547   char *cpu_fmt_0 =
   1548     "%6.2f\n";
   1549 
   1550   char *cpu_fmt_1 =
   1551     "%5d   %5d    %-7.2f   %7d %6d    %7.1f      %-6.2f  %-6.3f\n\
   1552 %5d            %-7.2f   %7d           %7.1f      %-6.2f  %-6.3f\n\n";
   1553 
   1554   int	messages_recvd;
   1555   float	elapsed_time,
   1556   local_cpu_utilization,
   1557   remote_cpu_utilization;
   1558 
   1559   float	local_service_demand, remote_service_demand;
   1560   double	local_thruput, remote_thruput;
   1561   double	bytes_sent;
   1562   double	bytes_recvd;
   1563 
   1564 
   1565   int	len;
   1566   struct ring_elt *send_ring;
   1567   int	failed_sends;
   1568   int	failed_cows;
   1569   int 	messages_sent;
   1570   SOCKET data_socket;
   1571 
   1572 
   1573 #ifdef WANT_INTERVALS
   1574   int	interval_count;
   1575 #endif /* WANT_INTERVALS */
   1576 #ifdef DIRTY
   1577   int	*message_int_ptr;
   1578   int	i;
   1579 #endif /* DIRTY */
   1580 
   1581   struct	sockaddr_un	server;
   1582 
   1583   struct	dg_stream_request_struct	*dg_stream_request;
   1584   struct	dg_stream_response_struct	*dg_stream_response;
   1585   struct	dg_stream_results_struct	*dg_stream_results;
   1586 
   1587   dg_stream_request	= (struct dg_stream_request_struct *)netperf_request.content.test_specific_data;
   1588   dg_stream_response	= (struct dg_stream_response_struct *)netperf_response.content.test_specific_data;
   1589   dg_stream_results	= (struct dg_stream_results_struct *)netperf_response.content.test_specific_data;
   1590 
   1591   /* since we are now disconnected from the code that established the
   1592      control socket, and since we want to be able to use different
   1593      protocols and such, we are passed the name of the remote host and
   1594      must turn that into the test specific addressing information. */
   1595 
   1596   bzero((char *)&server,
   1597 	sizeof(server));
   1598 
   1599   server.sun_family = AF_UNIX;
   1600 
   1601   if ( print_headers ) {
   1602     printf("DG UNIDIRECTIONAL SEND TEST\n");
   1603     if (local_cpu_usage || remote_cpu_usage)
   1604       printf(cpu_title,format_units());
   1605     else
   1606       printf(tput_title,format_units());
   1607   }
   1608 
   1609   failed_sends	= 0;
   1610   failed_cows	= 0;
   1611   messages_sent	= 0;
   1612   times_up	= 0;
   1613 
   1614   /*set up the data socket			*/
   1615   data_socket = create_unix_socket(AF_UNIX,
   1616 				   SOCK_DGRAM);
   1617 
   1618   if (data_socket == INVALID_SOCKET){
   1619     perror("dg_send: data socket");
   1620     exit(1);
   1621   }
   1622 
   1623   /* now, we want to see if we need to set the send_size */
   1624   if (send_size == 0) {
   1625     if (lss_size > 0) {
   1626       send_size = (lss_size < UNIX_LENGTH_MAX ? lss_size : UNIX_LENGTH_MAX);
   1627     }
   1628     else {
   1629       send_size = 4096;
   1630     }
   1631   }
   1632 
   1633 
   1634   /* set-up the data buffer with the requested alignment and offset,
   1635      most of the numbers here are just a hack to pick something nice
   1636      and big in an attempt to never try to send a buffer a second time
   1637      before it leaves the node...unless the user set the width
   1638      explicitly. */
   1639   if (send_width == 0) send_width = 32;
   1640 
   1641   send_ring = allocate_buffer_ring(send_width,
   1642 				   send_size,
   1643 				   local_send_align,
   1644 				   local_send_offset);
   1645 
   1646   /* At this point, we want to do things like disable DG checksumming
   1647      and measure the cpu rate and all that so we are ready to go
   1648      immediately after the test response message is delivered. */
   1649 
   1650   /* if the user supplied a cpu rate, this call will complete rather
   1651      quickly, otherwise, the cpu rate will be retured to us for
   1652      possible display. The Library will keep it's own copy of this
   1653      data for use elsewhere. We will only display it. (Does that make
   1654      it "opaque" to us?) */
   1655 
   1656   if (local_cpu_usage)
   1657     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   1658 
   1659   /* Tell the remote end to set up the data connection. The server
   1660      sends back the port number and alters the socket parameters
   1661      there.  Of course this is a datagram service so no connection is
   1662      actually set up, the server just sets up the socket and binds
   1663      it. */
   1664 
   1665   netperf_request.content.request_type = DO_DG_STREAM;
   1666   dg_stream_request->recv_buf_size	= rsr_size;
   1667   dg_stream_request->message_size	= send_size;
   1668   dg_stream_request->recv_alignment	= remote_recv_align;
   1669   dg_stream_request->recv_offset	= remote_recv_offset;
   1670   dg_stream_request->measure_cpu	= remote_cpu_usage;
   1671   dg_stream_request->cpu_rate		= remote_cpu_rate;
   1672   dg_stream_request->test_length	= test_time;
   1673 
   1674   send_request();
   1675 
   1676   recv_response();
   1677 
   1678   if (!netperf_response.content.serv_errno) {
   1679     if (debug)
   1680       fprintf(where,"send_dg_stream: remote data connection done.\n");
   1681   }
   1682   else {
   1683     Set_errno(netperf_response.content.serv_errno);
   1684     perror("send_dg_stream: error on remote");
   1685     exit(1);
   1686   }
   1687 
   1688   /* Place the port number returned by the remote into the sockaddr
   1689      structure so our sends can be sent to the correct place. Also get
   1690      some of the returned socket buffer information for user
   1691      display. */
   1692 
   1693   /* make sure that port numbers are in the proper order */
   1694   strcpy(server.sun_path,dg_stream_response->unix_path);
   1695   rsr_size	= dg_stream_response->recv_buf_size;
   1696   rss_size	= dg_stream_response->send_buf_size;
   1697   remote_cpu_rate	= dg_stream_response->cpu_rate;
   1698 
   1699   /* We "connect" up to the remote post to allow is to use the send
   1700      call instead of the sendto call. Presumeably, this is a little
   1701      simpler, and a little more efficient. I think that it also means
   1702      that we can be informed of certain things, but am not sure
   1703      yet... */
   1704 
   1705   if (connect(data_socket,
   1706 	      (struct sockaddr *)&server,
   1707 	      sizeof(server)) == INVALID_SOCKET){
   1708     perror("send_dg_stream: data socket connect failed");
   1709     exit(1);
   1710   }
   1711 
   1712   /* set up the timer to call us after test_time  */
   1713   start_timer(test_time);
   1714 
   1715   /* Get the start count for the idle counter and the start time */
   1716 
   1717   cpu_start(local_cpu_usage);
   1718 
   1719 #ifdef WANT_INTERVALS
   1720   interval_count = interval_burst;
   1721 #endif
   1722 
   1723   /* Send datagrams like there was no tomorrow. at somepoint it might
   1724      be nice to set this up so that a quantity of bytes could be sent,
   1725      but we still need some sort of end of test trigger on the receive
   1726      side. that could be a select with a one second timeout, but then
   1727      if there is a test where none of the data arrives for awile and
   1728      then starts again, we would end the test too soon. something to
   1729      think about... */
   1730   while (!times_up) {
   1731 
   1732 #ifdef DIRTY
   1733     /* we want to dirty some number of consecutive integers in the
   1734        buffer we are about to send. we may also want to bring some
   1735        number of them cleanly into the cache. The clean ones will
   1736        follow any dirty ones into the cache. */
   1737     message_int_ptr = (int *)(send_ring->buffer_ptr);
   1738     for (i = 0; i < loc_dirty_count; i++) {
   1739       *message_int_ptr = 4;
   1740       message_int_ptr++;
   1741     }
   1742     for (i = 0; i < loc_clean_count; i++) {
   1743       loc_dirty_count = *message_int_ptr;
   1744       message_int_ptr++;
   1745     }
   1746 #endif /* DIRTY */
   1747 
   1748     if ((len=send(data_socket,
   1749 		  send_ring->buffer_ptr,
   1750 		  send_size,
   1751 		  0))  != send_size) {
   1752       if ((len >= 0) || (errno == EINTR))
   1753 	break;
   1754       if (errno == ENOBUFS) {
   1755 	failed_sends++;
   1756 	continue;
   1757       }
   1758       perror("dg_send: data send error");
   1759       exit(1);
   1760     }
   1761     messages_sent++;
   1762 
   1763     /* now we want to move our pointer to the next position in the
   1764        data buffer... */
   1765 
   1766     send_ring = send_ring->next;
   1767 
   1768 
   1769 #ifdef WANT_INTERVALS
   1770     /* in this case, the interval count is the count-down couter to
   1771        decide to sleep for a little bit */
   1772     if ((interval_burst) && (--interval_count == 0)) {
   1773       /* call the sleep routine for some milliseconds, if our timer
   1774          popped while we were in there, we want to break out of the
   1775          loop. */
   1776       if (msec_sleep(interval_wate)) {
   1777 	break;
   1778       }
   1779       interval_count = interval_burst;
   1780     }
   1781 
   1782 #endif
   1783 
   1784   }
   1785 
   1786   /* This is a timed test, so the remote will be returning to us after
   1787      a time. We should not need to send any "strange" messages to tell
   1788      the remote that the test is completed, unless we decide to add a
   1789      number of messages to the test. */
   1790 
   1791   /* the test is over, so get stats and stuff */
   1792   cpu_stop(local_cpu_usage,
   1793 	   &elapsed_time);
   1794 
   1795   /* Get the statistics from the remote end  */
   1796   recv_response();
   1797   if (!netperf_response.content.serv_errno) {
   1798     if (debug)
   1799       fprintf(where,"send_dg_stream: remote results obtained\n");
   1800   }
   1801   else {
   1802     Set_errno(netperf_response.content.serv_errno);
   1803     perror("send_dg_stream: error on remote");
   1804     exit(1);
   1805   }
   1806 
   1807   bytes_sent	= send_size * messages_sent;
   1808   local_thruput	= calc_thruput(bytes_sent);
   1809 
   1810   messages_recvd	= dg_stream_results->messages_recvd;
   1811   bytes_recvd	= send_size * messages_recvd;
   1812 
   1813   /* we asume that the remote ran for as long as we did */
   1814 
   1815   remote_thruput	= calc_thruput(bytes_recvd);
   1816 
   1817   /* print the results for this socket and message size */
   1818 
   1819   if (local_cpu_usage || remote_cpu_usage) {
   1820     /* We must now do a little math for service demand and cpu
   1821        utilization for the system(s) We pass zeros for the local cpu
   1822        utilization and elapsed time to tell the routine to use the
   1823        libraries own values for those. */
   1824     if (local_cpu_usage) {
   1825       if (local_cpu_rate == 0.0) {
   1826 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
   1827 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
   1828 	fflush(where);
   1829       }
   1830 
   1831       local_cpu_utilization	= calc_cpu_util(0.0);
   1832       local_service_demand	= calc_service_demand(bytes_sent,
   1833 						      0.0,
   1834 						      0.0,
   1835 						      0);
   1836     }
   1837     else {
   1838       local_cpu_utilization	= -1.0;
   1839       local_service_demand	= -1.0;
   1840     }
   1841 
   1842     /* The local calculations could use variables being kept by the
   1843        local netlib routines. The remote calcuations need to have a
   1844        few things passed to them. */
   1845     if (remote_cpu_usage) {
   1846       if (remote_cpu_rate == 0.0) {
   1847 	fprintf(where,"DANGER   DANGER  DANGER   DANGER  DANGER   DANGER   DANGER!\n");
   1848 	fprintf(where,"REMOTE CPU usage numbers based on process information only!\n");
   1849 	fflush(where);
   1850       }
   1851 
   1852       remote_cpu_utilization	= dg_stream_results->cpu_util;
   1853       remote_service_demand	= calc_service_demand(bytes_recvd,
   1854 						      0.0,
   1855 						      remote_cpu_utilization,
   1856 						      dg_stream_results->num_cpus);
   1857     }
   1858     else {
   1859       remote_cpu_utilization	= -1.0;
   1860       remote_service_demand	= -1.0;
   1861     }
   1862 
   1863     /* We are now ready to print all the information. If the user has
   1864        specified zero-level verbosity, we will just print the local
   1865        service demand, or the remote service demand. If the user has
   1866        requested verbosity level 1, he will get the basic "streamperf"
   1867        numbers. If the user has specified a verbosity of greater than
   1868        1, we will display a veritable plethora of background
   1869        information from outside of this block as it it not
   1870        cpu_measurement specific...  */
   1871 
   1872     switch (verbosity) {
   1873     case 0:
   1874       if (local_cpu_usage) {
   1875 	fprintf(where,
   1876 		cpu_fmt_0,
   1877 		local_service_demand);
   1878       }
   1879       else {
   1880 	fprintf(where,
   1881 		cpu_fmt_0,
   1882 		remote_service_demand);
   1883       }
   1884       break;
   1885     case 1:
   1886       fprintf(where,
   1887 	      cpu_fmt_1,	    /* the format string */
   1888 	      lss_size,		    /* local sendbuf size */
   1889 	      send_size,	    /* how large were the sends */
   1890 	      elapsed_time,	    /* how long was the test */
   1891 	      messages_sent,
   1892 	      failed_sends,
   1893 	      local_thruput, 	    /* what was the xfer rate */
   1894 	      local_cpu_utilization,/* local cpu */
   1895 	      local_service_demand, /* local service demand */
   1896 	      rsr_size,
   1897 	      elapsed_time,
   1898 	      messages_recvd,
   1899 	      remote_thruput,
   1900 	      remote_cpu_utilization,	/* remote cpu */
   1901 	      remote_service_demand);	/* remote service demand */
   1902       break;
   1903     }
   1904   }
   1905   else {
   1906     /* The tester did not wish to measure service demand. */
   1907     switch (verbosity) {
   1908     case 0:
   1909       fprintf(where,
   1910 	      tput_fmt_0,
   1911 	      local_thruput);
   1912       break;
   1913     case 1:
   1914       fprintf(where,
   1915 	      tput_fmt_1,		/* the format string */
   1916 	      lss_size, 		/* local sendbuf size */
   1917 	      send_size,		/* how large were the sends */
   1918 	      elapsed_time, 		/* how long did it take */
   1919 	      messages_sent,
   1920 	      failed_sends,
   1921 	      local_thruput,
   1922 	      rsr_size, 		/* remote recvbuf size */
   1923 	      elapsed_time,
   1924 	      messages_recvd,
   1925 	      remote_thruput
   1926 	      );
   1927       break;
   1928     }
   1929   }
   1930 }
   1931 
   1932 
   1934  /* this routine implements the receive side (netserver) of the
   1935     DG_STREAM performance test. */
   1936 
   1937 void
   1938 recv_dg_stream()
   1939 {
   1940   struct ring_elt *recv_ring;
   1941 
   1942   struct sockaddr_un myaddr_un;
   1943   SOCKET s_data;
   1944   int	len = 0;
   1945   int	bytes_received = 0;
   1946   float	elapsed_time;
   1947 
   1948   int	message_size;
   1949   int	messages_recvd = 0;
   1950 
   1951   struct	dg_stream_request_struct	*dg_stream_request;
   1952   struct	dg_stream_response_struct	*dg_stream_response;
   1953   struct	dg_stream_results_struct	*dg_stream_results;
   1954 
   1955   dg_stream_request  =
   1956     (struct dg_stream_request_struct *)netperf_request.content.test_specific_data;
   1957   dg_stream_response =
   1958     (struct dg_stream_response_struct *)netperf_response.content.test_specific_data;
   1959   dg_stream_results  =
   1960     (struct dg_stream_results_struct *)netperf_response.content.test_specific_data;
   1961 
   1962   if (debug) {
   1963     fprintf(where,"netserver: recv_dg_stream: entered...\n");
   1964     fflush(where);
   1965   }
   1966 
   1967   /* We want to set-up the listen socket with all the desired
   1968      parameters and then let the initiator know that all is ready. If
   1969      socket size defaults are to be used, then the initiator will have
   1970      sent us 0's. If the socket sizes cannot be changed, then we will
   1971      send-back what they are. If that information cannot be
   1972      determined, then we send-back -1's for the sizes. If things go
   1973      wrong for any reason, we will drop back ten yards and punt. */
   1974 
   1975   /* If anything goes wrong, we want the remote to know about it. It
   1976      would be best if the error that the remote reports to the user is
   1977      the actual error we encountered, rather than some bogus
   1978      unexpected response type message. */
   1979 
   1980   if (debug > 1) {
   1981     fprintf(where,"recv_dg_stream: setting the response type...\n");
   1982     fflush(where);
   1983   }
   1984 
   1985   netperf_response.content.response_type = DG_STREAM_RESPONSE;
   1986 
   1987   if (debug > 2) {
   1988     fprintf(where,"recv_dg_stream: the response type is set...\n");
   1989     fflush(where);
   1990   }
   1991 
   1992   /* We now alter the message_ptr variable to be at the desired
   1993      alignment with the desired offset. */
   1994 
   1995   if (debug > 1) {
   1996     fprintf(where,"recv_dg_stream: requested alignment of %d\n",
   1997 	    dg_stream_request->recv_alignment);
   1998     fflush(where);
   1999   }
   2000 
   2001   if (recv_width == 0) recv_width = 1;
   2002 
   2003   recv_ring = allocate_buffer_ring(recv_width,
   2004 				   dg_stream_request->message_size,
   2005 				   dg_stream_request->recv_alignment,
   2006 				   dg_stream_request->recv_offset);
   2007 
   2008   if (debug > 1) {
   2009     fprintf(where,"recv_dg_stream: receive alignment and offset set...\n");
   2010     fflush(where);
   2011   }
   2012 
   2013   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we
   2014      can put in OUR values !-) At some point, we may want to nail this
   2015      socket to a particular network-level address, but for now,
   2016      INADDR_ANY should be just fine. */
   2017 
   2018   bzero((char *)&myaddr_un,
   2019 	sizeof(myaddr_un));
   2020   myaddr_un.sun_family      = AF_UNIX;
   2021 
   2022   /* Grab a socket to listen on, and then listen on it. */
   2023 
   2024   if (debug > 1) {
   2025     fprintf(where,"recv_dg_stream: grabbing a socket...\n");
   2026     fflush(where);
   2027   }
   2028 
   2029   /* create_unix_socket expects to find some things in the global
   2030      variables, so set the globals based on the values in the request.
   2031      once the socket has been created, we will set the response values
   2032      based on the updated value of those globals. raj 7/94 */
   2033   lsr_size = dg_stream_request->recv_buf_size;
   2034 
   2035   s_data = create_unix_socket(AF_UNIX,
   2036 			      SOCK_DGRAM);
   2037 
   2038   if (s_data == INVALID_SOCKET) {
   2039     netperf_response.content.serv_errno = errno;
   2040     send_response();
   2041     exit(1);
   2042   }
   2043 
   2044   /* Let's get an address assigned to this socket so we can tell the
   2045      initiator how to reach the data socket. There may be a desire to
   2046      nail this socket to a specific IP address in a multi-homed,
   2047      multi-connection situation, but for now, we'll ignore the issue
   2048      and concentrate on single connection testing. */
   2049 
   2050   strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
   2051   if (bind(s_data,
   2052 	   (struct sockaddr *)&myaddr_un,
   2053 	   sizeof(myaddr_un)) == SOCKET_ERROR) {
   2054     netperf_response.content.serv_errno = errno;
   2055     send_response();
   2056     exit(1);
   2057   }
   2058 
   2059   chmod(myaddr_un.sun_path, 0666);
   2060 
   2061   dg_stream_response->test_length = dg_stream_request->test_length;
   2062 
   2063   /* Now myaddr_un contains the port and the internet address this is
   2064      returned to the sender also implicitly telling the sender that
   2065      the socket buffer sizing has been done. */
   2066 
   2067   strcpy(dg_stream_response->unix_path,myaddr_un.sun_path);
   2068   netperf_response.content.serv_errno   = 0;
   2069 
   2070   /* But wait, there's more. If the initiator wanted cpu measurements,
   2071      then we must call the calibrate routine, which will return the
   2072      max rate back to the initiator. If the CPU was not to be
   2073      measured, or something went wrong with the calibration, we will
   2074      return a -1 to the initiator. */
   2075 
   2076   dg_stream_response->cpu_rate = 0.0; 	/* assume no cpu */
   2077   if (dg_stream_request->measure_cpu) {
   2078     /* We will pass the rate into the calibration routine. If the user
   2079        did not specify one, it will be 0.0, and we will do a "real"
   2080        calibration. Otherwise, all it will really do is store it
   2081        away... */
   2082     dg_stream_response->measure_cpu = 1;
   2083     dg_stream_response->cpu_rate =
   2084       calibrate_local_cpu(dg_stream_request->cpu_rate);
   2085   }
   2086 
   2087   message_size	= dg_stream_request->message_size;
   2088   test_time	= dg_stream_request->test_length;
   2089 
   2090   /* before we send the response back to the initiator, pull some of
   2091      the socket parms from the globals */
   2092   dg_stream_response->send_buf_size = lss_size;
   2093   dg_stream_response->recv_buf_size = lsr_size;
   2094 
   2095   send_response();
   2096 
   2097   /* Now it's time to start receiving data on the connection. We will
   2098      first grab the apropriate counters and then start grabbing. */
   2099 
   2100   cpu_start(dg_stream_request->measure_cpu);
   2101 
   2102   /* The loop will exit when the timer pops, or if we happen to recv a
   2103      message of less than send_size bytes... */
   2104 
   2105   times_up = 0;
   2106   start_timer(test_time + PAD_TIME);
   2107 
   2108   if (debug) {
   2109     fprintf(where,"recv_dg_stream: about to enter inner sanctum.\n");
   2110     fflush(where);
   2111   }
   2112 
   2113   while (!times_up) {
   2114     if ((len = recv(s_data,
   2115 		    recv_ring->buffer_ptr,
   2116 		    message_size,
   2117 		    0)) != message_size) {
   2118       if ((len == SOCKET_ERROR) && (errno != EINTR)) {
   2119 	netperf_response.content.serv_errno = errno;
   2120 	send_response();
   2121 	exit(1);
   2122       }
   2123       break;
   2124     }
   2125     messages_recvd++;
   2126     recv_ring = recv_ring->next;
   2127   }
   2128 
   2129   if (debug) {
   2130     fprintf(where,"recv_dg_stream: got %d messages.\n",messages_recvd);
   2131     fflush(where);
   2132   }
   2133 
   2134 
   2135   /* The loop now exits due timer or < send_size bytes received. */
   2136 
   2137   cpu_stop(dg_stream_request->measure_cpu,&elapsed_time);
   2138 
   2139   if (times_up) {
   2140     /* we ended on a timer, subtract the PAD_TIME */
   2141     elapsed_time -= (float)PAD_TIME;
   2142   }
   2143   else {
   2144     stop_timer();
   2145   }
   2146 
   2147   if (debug) {
   2148     fprintf(where,"recv_dg_stream: test ended in %f seconds.\n",elapsed_time);
   2149     fflush(where);
   2150   }
   2151 
   2152 
   2153   /* We will count the "off" message that got us out of the loop */
   2154   bytes_received = (messages_recvd * message_size) + len;
   2155 
   2156   /* send the results to the sender			*/
   2157 
   2158   if (debug) {
   2159     fprintf(where,
   2160 	    "recv_dg_stream: got %d bytes\n",
   2161 	    bytes_received);
   2162     fflush(where);
   2163   }
   2164 
   2165   netperf_response.content.response_type		= DG_STREAM_RESULTS;
   2166   dg_stream_results->bytes_received	= bytes_received;
   2167   dg_stream_results->messages_recvd	= messages_recvd;
   2168   dg_stream_results->elapsed_time	= elapsed_time;
   2169   if (dg_stream_request->measure_cpu) {
   2170     dg_stream_results->cpu_util	= calc_cpu_util(elapsed_time);
   2171   }
   2172   else {
   2173     dg_stream_results->cpu_util	= -1.0;
   2174   }
   2175 
   2176   if (debug > 1) {
   2177     fprintf(where,
   2178 	    "recv_dg_stream: test complete, sending results.\n");
   2179     fflush(where);
   2180   }
   2181 
   2182   send_response();
   2183 
   2184 }
   2185 
   2186 void
   2188 send_dg_rr(char remote_host[])
   2189 {
   2190 
   2191   char *tput_title = "\
   2192 Local /Remote\n\
   2193 Socket Size   Request  Resp.   Elapsed  Trans.\n\
   2194 Send   Recv   Size     Size    Time     Rate         \n\
   2195 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
   2196 
   2197   char *tput_fmt_0 =
   2198     "%7.2f\n";
   2199 
   2200   char *tput_fmt_1_line_1 = "\
   2201 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
   2202   char *tput_fmt_1_line_2 = "\
   2203 %-6d %-6d\n";
   2204 
   2205   char *cpu_title = "\
   2206 Local /Remote\n\
   2207 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
   2208 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
   2209 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
   2210 
   2211   char *cpu_fmt_0 =
   2212     "%6.3f\n";
   2213 
   2214   char *cpu_fmt_1_line_1 = "\
   2215 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
   2216 
   2217   char *cpu_fmt_1_line_2 = "\
   2218 %-6d %-6d\n";
   2219 
   2220   float			elapsed_time;
   2221 
   2222   /* we add MAXALIGNMENT and MAXOFFSET to insure that there is enough
   2223      space for a maximally aligned, maximally sized message. At some
   2224      point, we may want to actually make this even larger and cycle
   2225      through the thing one piece at a time.*/
   2226 
   2227   int	len;
   2228   char	*send_message_ptr;
   2229   char	*recv_message_ptr;
   2230   char	*temp_message_ptr;
   2231   int	nummessages;
   2232   SOCKET send_socket;
   2233   int	trans_remaining;
   2234   int	bytes_xferd;
   2235 
   2236   int	rsp_bytes_recvd;
   2237 
   2238   float	local_cpu_utilization;
   2239   float	local_service_demand;
   2240   float	remote_cpu_utilization;
   2241   float	remote_service_demand;
   2242   double	thruput;
   2243 
   2244 #ifdef WANT_INTERVALS
   2245   /* timing stuff */
   2246 #define	MAX_KEPT_TIMES	1024
   2247   int	time_index = 0;
   2248   int	unused_buckets;
   2249   int	kept_times[MAX_KEPT_TIMES];
   2250   int	sleep_usecs;
   2251   unsigned	int	total_times=0;
   2252   struct	timezone	dummy_zone;
   2253   struct	timeval		send_time;
   2254   struct	timeval		recv_time;
   2255   struct	timeval		sleep_timeval;
   2256 #endif
   2257 
   2258   struct	sockaddr_un	server, myaddr_un;
   2259 
   2260   struct	dg_rr_request_struct	*dg_rr_request;
   2261   struct	dg_rr_response_struct	*dg_rr_response;
   2262   struct	dg_rr_results_struct	*dg_rr_result;
   2263 
   2264   dg_rr_request	=
   2265     (struct dg_rr_request_struct *)netperf_request.content.test_specific_data;
   2266   dg_rr_response=
   2267     (struct dg_rr_response_struct *)netperf_response.content.test_specific_data;
   2268   dg_rr_result	=
   2269     (struct dg_rr_results_struct *)netperf_response.content.test_specific_data;
   2270 
   2271   /* we want to zero out the times, so we can detect unused entries. */
   2272 #ifdef WANT_INTERVALS
   2273   time_index = 0;
   2274   while (time_index < MAX_KEPT_TIMES) {
   2275     kept_times[time_index] = 0;
   2276     time_index += 1;
   2277   }
   2278   time_index = 0;
   2279 #endif
   2280 
   2281   /* since we are now disconnected from the code that established the
   2282      control socket, and since we want to be able to use different
   2283      protocols and such, we are passed the name of the remote host and
   2284      must turn that into the test specific addressing information. */
   2285 
   2286   bzero((char *)&server,
   2287 	sizeof(server));
   2288   server.sun_family = AF_UNIX;
   2289 
   2290   bzero((char *)&myaddr_un,
   2291 	sizeof(myaddr_un));
   2292   myaddr_un.sun_family = AF_UNIX;
   2293 
   2294   strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
   2295 
   2296   if ( print_headers ) {
   2297     fprintf(where,"DG REQUEST/RESPONSE TEST\n");
   2298     if (local_cpu_usage || remote_cpu_usage)
   2299       fprintf(where,cpu_title,format_units());
   2300     else
   2301       fprintf(where,tput_title,format_units());
   2302   }
   2303 
   2304   /* initialize a few counters */
   2305 
   2306   nummessages	=	0;
   2307   bytes_xferd	=	0;
   2308   times_up 	= 	0;
   2309 
   2310   /* set-up the data buffer with the requested alignment and offset */
   2311   temp_message_ptr = (char *)malloc(DATABUFFERLEN);
   2312   if (temp_message_ptr == NULL) {
   2313     printf("malloc(%d) failed!\n", DATABUFFERLEN);
   2314     exit(1);
   2315   }
   2316   send_message_ptr = (char *)(( (long)temp_message_ptr +
   2317 			(long) local_send_align - 1) &
   2318 			~((long) local_send_align - 1));
   2319   send_message_ptr = send_message_ptr + local_send_offset;
   2320   temp_message_ptr = (char *)malloc(DATABUFFERLEN);
   2321   if (temp_message_ptr == NULL) {
   2322     printf("malloc(%d) failed!\n", DATABUFFERLEN);
   2323     exit(1);
   2324   }
   2325   recv_message_ptr = (char *)(( (long)temp_message_ptr +
   2326 			(long) local_recv_align - 1) &
   2327 			~((long) local_recv_align - 1));
   2328   recv_message_ptr = recv_message_ptr + local_recv_offset;
   2329 
   2330   /*set up the data socket                        */
   2331   send_socket = create_unix_socket(AF_UNIX,
   2332 				   SOCK_DGRAM);
   2333 
   2334   if (send_socket == INVALID_SOCKET){
   2335     perror("netperf: send_dg_rr: dg rr data socket");
   2336     exit(1);
   2337   }
   2338 
   2339   if (debug) {
   2340     fprintf(where,"send_dg_rr: send_socket obtained...\n");
   2341   }
   2342 
   2343 
   2344   /* If the user has requested cpu utilization measurements, we must
   2345      calibrate the cpu(s). We will perform this task within the tests
   2346      themselves. If the user has specified the cpu rate, then
   2347      calibrate_local_cpu will return rather quickly as it will have
   2348      nothing to do. If local_cpu_rate is zero, then we will go through
   2349      all the "normal" calibration stuff and return the rate back. If
   2350      there is no idle counter in the kernel idle loop, the
   2351      local_cpu_rate will be set to -1. */
   2352 
   2353   if (local_cpu_usage) {
   2354     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
   2355   }
   2356 
   2357   /* Tell the remote end to do a listen. The server alters the socket
   2358      paramters on the other side at this point, hence the reason for
   2359      all the values being passed in the setup message. If the user did
   2360      not specify any of the parameters, they will be passed as 0,
   2361      which will indicate to the remote that no changes beyond the
   2362      system's default should be used. Alignment is the exception, it
   2363      will default to 8, which will be no alignment alterations. */
   2364 
   2365   netperf_request.content.request_type	=	DO_DG_RR;
   2366   dg_rr_request->recv_buf_size	=	rsr_size;
   2367   dg_rr_request->send_buf_size	=	rss_size;
   2368   dg_rr_request->recv_alignment	=	remote_recv_align;
   2369   dg_rr_request->recv_offset	=	remote_recv_offset;
   2370   dg_rr_request->send_alignment	=	remote_send_align;
   2371   dg_rr_request->send_offset	=	remote_send_offset;
   2372   dg_rr_request->request_size	=	req_size;
   2373   dg_rr_request->response_size	=	rsp_size;
   2374   dg_rr_request->measure_cpu	=	remote_cpu_usage;
   2375   dg_rr_request->cpu_rate	=	remote_cpu_rate;
   2376   if (test_time) {
   2377     dg_rr_request->test_length	=	test_time;
   2378   }
   2379   else {
   2380     dg_rr_request->test_length	=	test_trans * -1;
   2381   }
   2382 
   2383   if (debug > 1) {
   2384     fprintf(where,"netperf: send_dg_rr: requesting DG request/response test\n");
   2385   }
   2386 
   2387   send_request();
   2388 
   2389   /* The response from the remote will contain all of the relevant
   2390      socket parameters for this test type. We will put them back into
   2391      the variables here so they can be displayed if desired.  The
   2392      remote will have calibrated CPU if necessary, and will have done
   2393      all the needed set-up we will have calibrated the cpu locally
   2394      before sending the request, and will grab the counter value right
   2395      after the connect returns. The remote will grab the counter right
   2396      after the accept call. This saves the hassle of extra messages
   2397      being sent for the DG tests.  */
   2398 
   2399   recv_response();
   2400 
   2401   if (!netperf_response.content.serv_errno) {
   2402     if (debug)
   2403       fprintf(where,"remote listen done.\n");
   2404     rsr_size	=	dg_rr_response->recv_buf_size;
   2405     rss_size	=	dg_rr_response->send_buf_size;
   2406     remote_cpu_usage=	dg_rr_response->measure_cpu;
   2407     remote_cpu_rate = 	dg_rr_response->cpu_rate;
   2408     /* port numbers in proper order */
   2409     strcpy(server.sun_path,dg_rr_response->unix_path);
   2410   }
   2411   else {
   2412     Set_errno(netperf_response.content.serv_errno);
   2413     perror("netperf: remote error");
   2414 
   2415     exit(1);
   2416   }
   2417 
   2418   /* Connect up to the remote port on the data socket. This will set
   2419      the default destination address on this socket. we need to bind
   2420      out socket so that the remote gets something from a recvfrom  */
   2421   if (bind(send_socket,
   2422 	   (struct sockaddr *)&myaddr_un,
   2423 	   sizeof(myaddr_un)) == SOCKET_ERROR) {
   2424     perror("netperf: send_dg_rr");
   2425     unlink(myaddr_un.sun_path);
   2426     close(send_socket);
   2427     exit(1);
   2428   }
   2429 
   2430   if (connect(send_socket,
   2431 	      (struct sockaddr *)&server,
   2432 	      sizeof(server)) == INVALID_SOCKET ) {
   2433     perror("netperf: data socket connect failed");
   2434     exit(1);
   2435   }
   2436 
   2437   /* Data Socket set-up is finished. If there were problems, either
   2438      the connect would have failed, or the previous response would
   2439      have indicated a problem. I failed to see the value of the extra
   2440      message after the accept on the remote. If it failed, we'll see
   2441      it here. If it didn't, we might as well start pumping data. */
   2442 
   2443   /* Set-up the test end conditions. For a request/response test, they
   2444      can be either time or transaction based. */
   2445 
   2446   if (test_time) {
   2447     /* The user wanted to end the test after a period of time. */
   2448     times_up = 0;
   2449     trans_remaining = 0;
   2450     start_timer(test_time);
   2451   }
   2452   else {
   2453     /* The tester wanted to send a number of bytes. */
   2454     trans_remaining = test_bytes;
   2455     times_up = 1;
   2456   }
   2457 
   2458   /* The cpu_start routine will grab the current time and possibly
   2459      value of the idle counter for later use in measuring cpu
   2460      utilization and/or service demand and thruput. */
   2461 
   2462   cpu_start(local_cpu_usage);
   2463 
   2464   /* We use an "OR" to control test execution. When the test is
   2465      controlled by time, the byte count check will always return
   2466      false.  When the test is controlled by byte count, the time test
   2467      will always return false. When the test is finished, the whole
   2468      expression will go false and we will stop sending data. I think I
   2469      just arbitrarily decrement trans_remaining for the timed test,
   2470      but will not do that just yet... One other question is whether or
   2471      not the send buffer and the receive buffer should be the same
   2472      buffer. */
   2473   while ((!times_up) || (trans_remaining > 0)) {
   2474     /* send the request */
   2475 #ifdef WANT_INTERVALS
   2476     gettimeofday(&send_time,&dummy_zone);
   2477 #endif
   2478     if((len=send(send_socket,
   2479 		 send_message_ptr,
   2480 		 req_size,
   2481 		 0)) != req_size) {
   2482       if (errno == EINTR) {
   2483 	/* We likely hit */
   2484 	/* test-end time. */
   2485 	break;
   2486       }
   2487       perror("send_dg_rr: data send error");
   2488       exit(1);
   2489     }
   2490 
   2491     /* receive the response. with DG we will get it all, or nothing */
   2492 
   2493     if((rsp_bytes_recvd=recv(send_socket,
   2494 			     recv_message_ptr,
   2495 			     rsp_size,
   2496 			     0)) != rsp_size) {
   2497       if (errno == EINTR) {
   2498 	/* Again, we have likely hit test-end time */
   2499 	break;
   2500       }
   2501       perror("send_dg_rr: data recv error");
   2502       exit(1);
   2503     }
   2504 #ifdef WANT_INTERVALS
   2505     gettimeofday(&recv_time,&dummy_zone);
   2506 
   2507     /* now we do some arithmatic on the two timevals */
   2508     if (recv_time.tv_usec < send_time.tv_usec) {
   2509       /* we wrapped around a second */
   2510       recv_time.tv_usec += 1000000;
   2511       recv_time.tv_sec  -= 1;
   2512     }
   2513 
   2514     /* and store it away */
   2515     kept_times[time_index] = (recv_time.tv_sec - send_time.tv_sec) * 1000000;
   2516     kept_times[time_index] += (recv_time.tv_usec - send_time.tv_usec);
   2517 
   2518     /* at this point, we may wish to sleep for some period of time, so
   2519        we see how long that last transaction just took, and sleep for
   2520        the difference of that and the interval. We will not sleep if
   2521        the time would be less than a millisecond.  */
   2522     if (interval_usecs > 0) {
   2523       sleep_usecs = interval_usecs - kept_times[time_index];
   2524       if (sleep_usecs > 1000) {
   2525 	/* we sleep */
   2526 	sleep_timeval.tv_sec = sleep_usecs / 1000000;
   2527 	sleep_timeval.tv_usec = sleep_usecs % 1000000;
   2528 	select(0,
   2529 	       0,
   2530 	       0,
   2531 	       0,
   2532 	       &sleep_timeval);
   2533       }
   2534     }
   2535 
   2536     /* now up the time index */
   2537     time_index = (time_index +1)%MAX_KEPT_TIMES;
   2538 #endif
   2539     nummessages++;
   2540     if (trans_remaining) {
   2541       trans_remaining--;
   2542     }
   2543 
   2544     if (debug > 3) {
   2545       fprintf(where,"Transaction %d completed\n",nummessages);
   2546       fflush(where);
   2547     }
   2548 
   2549   }
   2550 
   2551   /* The test is over. Flush the buffers to the remote end. We do a
   2552      graceful release to insure that all data has been taken by the
   2553      remote. Of course, since this was a request/response test, there
   2554      should be no data outstanding on the socket ;-) */
   2555 
   2556   if (shutdown(send_socket,1) == SOCKET_ERROR) {
   2557     perror("netperf: cannot shutdown dg stream socket");
   2558 
   2559     exit(1);
   2560   }
   2561 
   2562   /* this call will always give us the elapsed time for the test, and
   2563      will also store-away the necessaries for cpu utilization */
   2564 
   2565   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being
   2566 						   measured? how long
   2567 						   did we really
   2568 						   run? */
   2569 
   2570   /* Get the statistics from the remote end. The remote will have
   2571      calculated service demand and all those interesting things. If it
   2572      wasn't supposed to care, it will return obvious values. */
   2573 
   2574   recv_response();
   2575   if (!netperf_response.content.serv_errno) {
   2576     if (debug)
   2577       fprintf(where,"remote results obtained\n");
   2578   }
   2579   else {
   2580     Set_errno(netperf_response.content.serv_errno);
   2581     perror("netperf: remote error");
   2582 
   2583     exit(1);
   2584   }
   2585 
   2586   /* We now calculate what our thruput was for the test. In the
   2587      future, we may want to include a calculation of the thruput
   2588      measured by the remote, but it should be the case that for a DG
   2589      stream test, that the two numbers should be *very* close... We
   2590      calculate bytes_sent regardless of the way the test length was
   2591      controlled.  If it was time, we needed to, and if it was by
   2592      bytes, the user may have specified a number of bytes that wasn't
   2593      a multiple of the send_size, so we really didn't send what he
   2594      asked for ;-) We use */
   2595 
   2596   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
   2597   thruput		= calc_thruput(bytes_xferd);
   2598 
   2599   if (local_cpu_usage || remote_cpu_usage) {
   2600     /* We must now do a little math for service demand and cpu
   2601        utilization for the system(s) Of course, some of the
   2602        information might be bogus because there was no idle counter in
   2603        the kernel(s). We need to make a note of this for the user's
   2604        benefit...*/
   2605     if (local_cpu_usage) {
   2606       if (local_cpu_rate == 0.0) {
   2607 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
   2608 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
   2609 	fflush(where);
   2610       }
   2611       local_cpu_utilization = calc_cpu_util(0.0);
   2612       /* since calc_service demand is doing ms/Kunit we will multiply
   2613          the number of transaction by 1024 to get "good" numbers */
   2614       local_service_demand  = calc_service_demand((double) nummessages*1024,
   2615 						  0.0,
   2616 						  0.0,
   2617 						  0);
   2618     }
   2619     else {
   2620       local_cpu_utilization	= -1.0;
   2621       local_service_demand	= -1.0;
   2622     }
   2623 
   2624     if (remote_cpu_usage) {
   2625       if (remote_cpu_rate == 0.0) {
   2626 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
   2627 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
   2628 	fflush(where);
   2629       }
   2630       remote_cpu_utilization = dg_rr_result->cpu_util;
   2631       /* since calc_service demand is doing ms/Kunit we will multiply
   2632          the number of transaction by 1024 to get "good" numbers */
   2633       remote_service_demand  = calc_service_demand((double) nummessages*1024,
   2634 						   0.0,
   2635 						   remote_cpu_utilization,
   2636 						   dg_rr_result->num_cpus);
   2637     }
   2638     else {
   2639       remote_cpu_utilization = -1.0;
   2640       remote_service_demand  = -1.0;
   2641     }
   2642 
   2643     /* We are now ready to print all the information. If the user has
   2644        specified zero-level verbosity, we will just print the local
   2645        service demand, or the remote service demand. If the user has
   2646        requested verbosity level 1, he will get the basic "streamperf"
   2647        numbers. If the user has specified a verbosity of greater than
   2648        1, we will display a veritable plethora of background
   2649        information from outside of this block as it it not
   2650        cpu_measurement specific...  */
   2651 
   2652     switch (verbosity) {
   2653     case 0:
   2654       if (local_cpu_usage) {
   2655 	fprintf(where,
   2656 		cpu_fmt_0,
   2657 		local_service_demand);
   2658       }
   2659       else {
   2660 	fprintf(where,
   2661 		cpu_fmt_0,
   2662 		remote_service_demand);
   2663       }
   2664       break;
   2665     case 1:
   2666     case 2:
   2667       fprintf(where,
   2668 	      cpu_fmt_1_line_1,	/* the format string */
   2669 	      lss_size,		/* local sendbuf size */
   2670 	      lsr_size,
   2671 	      req_size,		/* how large were the requests */
   2672 	      rsp_size,		/* guess */
   2673 	      elapsed_time,	/* how long was the test */
   2674 	      nummessages/elapsed_time,
   2675 	      local_cpu_utilization,	/* local cpu */
   2676 	      remote_cpu_utilization,	/* remote cpu */
   2677 	      local_service_demand,	/* local service demand */
   2678 	      remote_service_demand);	/* remote service demand */
   2679       fprintf(where,
   2680 	      cpu_fmt_1_line_2,
   2681 	      rss_size,
   2682 	      rsr_size);
   2683       break;
   2684     }
   2685   }
   2686   else {
   2687     /* The tester did not wish to measure service demand. */
   2688     switch (verbosity) {
   2689     case 0:
   2690       fprintf(where,
   2691 	      tput_fmt_0,
   2692 	      nummessages/elapsed_time);
   2693       break;
   2694     case 1:
   2695     case 2:
   2696       fprintf(where,
   2697 	      tput_fmt_1_line_1,	/* the format string */
   2698 	      lss_size,
   2699 	      lsr_size,
   2700 	      req_size,		/* how large were the requests */
   2701 	      rsp_size,		/* how large were the responses */
   2702 	      elapsed_time, 		/* how long did it take */
   2703 	      nummessages/elapsed_time);
   2704       fprintf(where,
   2705 	      tput_fmt_1_line_2,
   2706 	      rss_size, 		/* remote recvbuf size */
   2707 	      rsr_size);
   2708 
   2709       break;
   2710     }
   2711   }
   2712 
   2713   /* it would be a good thing to include information about some of the
   2714      other parameters that may have been set for this test, but at the
   2715      moment, I do not wish to figure-out all the formatting, so I will
   2716      just put this comment here to help remind me that it is something
   2717      that should be done at a later time. */
   2718 
   2719   if (verbosity > 1) {
   2720     /* The user wanted to know it all, so we will give it to him.
   2721        This information will include as much as we can find about DG
   2722        statistics, the alignments of the sends and receives and all
   2723        that sort of rot... */
   2724 
   2725 #ifdef WANT_INTERVALS
   2726     kept_times[MAX_KEPT_TIMES] = 0;
   2727     time_index = 0;
   2728     while (time_index < MAX_KEPT_TIMES) {
   2729       if (kept_times[time_index] > 0) {
   2730 	total_times += kept_times[time_index];
   2731       }
   2732       else
   2733 	unused_buckets++;
   2734       time_index += 1;
   2735     }
   2736     total_times /= (MAX_KEPT_TIMES-unused_buckets);
   2737     fprintf(where,
   2738 	    "Average response time %d usecs\n",
   2739 	    total_times);
   2740 #endif
   2741   }
   2742   unlink(myaddr_un.sun_path);
   2743 }
   2744 
   2745  /* this routine implements the receive side (netserver) of a DG_RR
   2747     test. */
   2748 void
   2749 recv_dg_rr()
   2750 {
   2751 
   2752   struct ring_elt *recv_ring;
   2753   struct ring_elt *send_ring;
   2754 
   2755   struct	sockaddr_un        myaddr_un,
   2756   peeraddr_un;
   2757   SOCKET s_data;
   2758   netperf_socklen_t addrlen;
   2759   int	trans_received = 0;
   2760   int	trans_remaining;
   2761   float	elapsed_time;
   2762 
   2763   struct	dg_rr_request_struct	*dg_rr_request;
   2764   struct	dg_rr_response_struct	*dg_rr_response;
   2765   struct	dg_rr_results_struct	*dg_rr_results;
   2766 
   2767   dg_rr_request  =
   2768     (struct dg_rr_request_struct *)netperf_request.content.test_specific_data;
   2769   dg_rr_response =
   2770     (struct dg_rr_response_struct *)netperf_response.content.test_specific_data;
   2771   dg_rr_results  =
   2772     (struct dg_rr_results_struct *)netperf_response.content.test_specific_data;
   2773 
   2774   if (debug) {
   2775     fprintf(where,"netserver: recv_dg_rr: entered...\n");
   2776     fflush(where);
   2777   }
   2778 
   2779   /* We want to set-up the listen socket with all the desired
   2780      parameters and then let the initiator know that all is ready. If
   2781      socket size defaults are to be used, then the initiator will have
   2782      sent us 0's. If the socket sizes cannot be changed, then we will
   2783      send-back what they are. If that information cannot be
   2784      determined, then we send-back -1's for the sizes. If things go
   2785      wrong for any reason, we will drop back ten yards and punt. */
   2786 
   2787   /* If anything goes wrong, we want the remote to know about it. It
   2788      would be best if the error that the remote reports to the user is
   2789      the actual error we encountered, rather than some bogus
   2790      unexpected response type message. */
   2791 
   2792   if (debug) {
   2793     fprintf(where,"recv_dg_rr: setting the response type...\n");
   2794     fflush(where);
   2795   }
   2796 
   2797   netperf_response.content.response_type = DG_RR_RESPONSE;
   2798 
   2799   if (debug) {
   2800     fprintf(where,"recv_dg_rr: the response type is set...\n");
   2801     fflush(where);
   2802   }
   2803 
   2804   /* We now alter the message_ptr variables to be at the desired
   2805      alignments with the desired offsets. */
   2806 
   2807   if (debug) {
   2808     fprintf(where,"recv_dg_rr: requested recv alignment of %d offset %d\n",
   2809 	    dg_rr_request->recv_alignment,
   2810 	    dg_rr_request->recv_offset);
   2811     fprintf(where,"recv_dg_rr: requested send alignment of %d offset %d\n",
   2812 	    dg_rr_request->send_alignment,
   2813 	    dg_rr_request->send_offset);
   2814     fflush(where);
   2815   }
   2816 
   2817   if (send_width == 0) send_width = 1;
   2818   if (recv_width == 0) recv_width = 1;
   2819 
   2820   recv_ring = allocate_buffer_ring(recv_width,
   2821 				   dg_rr_request->request_size,
   2822 				   dg_rr_request->recv_alignment,
   2823 				   dg_rr_request->recv_offset);
   2824 
   2825   send_ring = allocate_buffer_ring(send_width,
   2826 				   dg_rr_request->response_size,
   2827 				   dg_rr_request->send_alignment,
   2828 				   dg_rr_request->send_offset);
   2829 
   2830   if (debug) {
   2831     fprintf(where,"recv_dg_rr: receive alignment and offset set...\n");
   2832     fflush(where);
   2833   }
   2834 
   2835   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we
   2836      can put in OUR values !-) At some point, we may want to nail this
   2837      socket to a particular network-level address, but for now,
   2838      INADDR_ANY should be just fine. */
   2839 
   2840   bzero((char *)&myaddr_un,
   2841 	sizeof(myaddr_un));
   2842   myaddr_un.sun_family      = AF_UNIX;
   2843 
   2844   /* Grab a socket to listen on, and then listen on it. */
   2845 
   2846   if (debug) {
   2847     fprintf(where,"recv_dg_rr: grabbing a socket...\n");
   2848     fflush(where);
   2849   }
   2850 
   2851 
   2852   /* create_unix_socket expects to find some things in the global
   2853      variables, so set the globals based on the values in the request.
   2854      once the socket has been created, we will set the response values
   2855      based on the updated value of those globals. raj 7/94 */
   2856   lss_size_req = dg_rr_request->send_buf_size;
   2857   lsr_size_req = dg_rr_request->recv_buf_size;
   2858 
   2859   s_data = create_unix_socket(AF_UNIX,
   2860 			      SOCK_DGRAM);
   2861 
   2862   if (s_data == INVALID_SOCKET) {
   2863     netperf_response.content.serv_errno = errno;
   2864     send_response();
   2865 
   2866     exit(1);
   2867   }
   2868 
   2869   /* Let's get an address assigned to this socket so we can tell the
   2870      initiator how to reach the data socket. There may be a desire to
   2871      nail this socket to a specific IP address in a multi-homed,
   2872      multi-connection situation, but for now, we'll ignore the issue
   2873      and concentrate on single connection testing. */
   2874 
   2875   strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
   2876   if (bind(s_data,
   2877 	   (struct sockaddr *)&myaddr_un,
   2878 	   sizeof(myaddr_un)) == SOCKET_ERROR) {
   2879     netperf_response.content.serv_errno = errno;
   2880     unlink(myaddr_un.sun_path);
   2881     close(s_data);
   2882     send_response();
   2883 
   2884     exit(1);
   2885   }
   2886 
   2887   /* Now myaddr_un contains the port and the internet address this is
   2888      returned to the sender also implicitly telling the sender that
   2889      the socket buffer sizing has been done. */
   2890 
   2891   strcpy(dg_rr_response->unix_path,myaddr_un.sun_path);
   2892   netperf_response.content.serv_errno   = 0;
   2893 
   2894   /* But wait, there's more. If the initiator wanted cpu measurements,
   2895      then we must call the calibrate routine, which will return the
   2896      max rate back to the initiator. If the CPU was not to be
   2897      measured, or something went wrong with the calibration, we will
   2898      return a 0.0 to the initiator. */
   2899 
   2900   dg_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
   2901   if (dg_rr_request->measure_cpu) {
   2902     dg_rr_response->measure_cpu = 1;
   2903     dg_rr_response->cpu_rate = calibrate_local_cpu(dg_rr_request->cpu_rate);
   2904   }
   2905 
   2906   /* before we send the response back to the initiator, pull some of
   2907      the socket parms from the globals */
   2908   dg_rr_response->send_buf_size = lss_size;
   2909   dg_rr_response->recv_buf_size = lsr_size;
   2910 
   2911   send_response();
   2912 
   2913 
   2914   /* Now it's time to start receiving data on the connection. We will
   2915      first grab the apropriate counters and then start grabbing. */
   2916 
   2917   cpu_start(dg_rr_request->measure_cpu);
   2918 
   2919   if (dg_rr_request->test_length > 0) {
   2920     times_up = 0;
   2921     trans_remaining = 0;
   2922     start_timer(dg_rr_request->test_length + PAD_TIME);
   2923   }
   2924   else {
   2925     times_up = 1;
   2926     trans_remaining = dg_rr_request->test_length * -1;
   2927   }
   2928 
   2929   addrlen = sizeof(peeraddr_un);
   2930   bzero((char *)&peeraddr_un, addrlen);
   2931 
   2932   while ((!times_up) || (trans_remaining > 0)) {
   2933 
   2934     /* receive the request from the other side */
   2935     fprintf(where,"socket %d ptr %p size %d\n",
   2936 	    s_data,
   2937 	    recv_ring->buffer_ptr,
   2938 	    dg_rr_request->request_size);
   2939     fflush(where);
   2940     if (recvfrom(s_data,
   2941 		 recv_ring->buffer_ptr,
   2942 		 dg_rr_request->request_size,
   2943 		 0,
   2944 		 (struct sockaddr *)&peeraddr_un,
   2945 		 &addrlen) != dg_rr_request->request_size) {
   2946       if (errno == EINTR) {
   2947 	/* we must have hit the end of test time. */
   2948 	break;
   2949       }
   2950       netperf_response.content.serv_errno = errno;
   2951       fprintf(where,"error on recvfrom errno %d\n",errno);
   2952       fflush(where);
   2953       send_response();
   2954       unlink(myaddr_un.sun_path);
   2955       exit(1);
   2956     }
   2957     recv_ring = recv_ring->next;
   2958 
   2959     /* Now, send the response to the remote */
   2960     if (sendto(s_data,
   2961 	       send_ring->buffer_ptr,
   2962 	       dg_rr_request->response_size,
   2963 	       0,
   2964 	       (struct sockaddr *)&peeraddr_un,
   2965 	       addrlen) != dg_rr_request->response_size) {
   2966       if (errno == EINTR) {
   2967 	/* we have hit end of test time. */
   2968 	break;
   2969       }
   2970       netperf_response.content.serv_errno = errno;
   2971       fprintf(where,"error on recvfrom errno %d\n",errno);
   2972       fflush(where);
   2973       unlink(myaddr_un.sun_path);
   2974       send_response();
   2975       exit(1);
   2976     }
   2977     send_ring = send_ring->next;
   2978 
   2979     trans_received++;
   2980     if (trans_remaining) {
   2981       trans_remaining--;
   2982     }
   2983 
   2984     if (debug) {
   2985       fprintf(where,
   2986 	      "recv_dg_rr: Transaction %d complete.\n",
   2987 	      trans_received);
   2988       fflush(where);
   2989     }
   2990 
   2991   }
   2992 
   2993 
   2994   /* The loop now exits due to timeout or transaction count being
   2995      reached */
   2996 
   2997   cpu_stop(dg_rr_request->measure_cpu,&elapsed_time);
   2998 
   2999   if (times_up) {
   3000     /* we ended the test by time, which was at least 2 seconds longer
   3001        than we wanted to run. so, we want to subtract PAD_TIME from
   3002        the elapsed_time. */
   3003     elapsed_time -= PAD_TIME;
   3004   }
   3005   /* send the results to the sender			*/
   3006 
   3007   if (debug) {
   3008     fprintf(where,
   3009 	    "recv_dg_rr: got %d transactions\n",
   3010 	    trans_received);
   3011     fflush(where);
   3012   }
   3013 
   3014   dg_rr_results->bytes_received	= (trans_received *
   3015 					   (dg_rr_request->request_size +
   3016 					    dg_rr_request->response_size));
   3017   dg_rr_results->trans_received	= trans_received;
   3018   dg_rr_results->elapsed_time	= elapsed_time;
   3019   if (dg_rr_request->measure_cpu) {
   3020     dg_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
   3021   }
   3022 
   3023   if (debug) {
   3024     fprintf(where,
   3025 	    "recv_dg_rr: test complete, sending results.\n");
   3026     fflush(where);
   3027   }
   3028 
   3029   send_response();
   3030   unlink(myaddr_un.sun_path);
   3031 
   3032 }
   3033  /* this routine implements the receive (netserver) side of a
   3034     STREAM_RR test */
   3035 
   3036 void
   3038 recv_stream_rr()
   3039 {
   3040 
   3041   struct ring_elt *send_ring;
   3042   struct ring_elt *recv_ring;
   3043 
   3044   struct	sockaddr_un        myaddr_un,
   3045   peeraddr_un;
   3046   SOCKET s_listen,s_data;
   3047   netperf_socklen_t addrlen;
   3048   char	*temp_message_ptr;
   3049   int	trans_received = 0;
   3050   int	trans_remaining;
   3051   int	bytes_sent;
   3052   int	request_bytes_recvd;
   3053   int	request_bytes_remaining;
   3054   int	timed_out = 0;
   3055   float	elapsed_time;
   3056 
   3057   struct	stream_rr_request_struct	*stream_rr_request;
   3058   struct	stream_rr_response_struct	*stream_rr_response;
   3059   struct	stream_rr_results_struct	*stream_rr_results;
   3060 
   3061   stream_rr_request =
   3062     (struct stream_rr_request_struct *)netperf_request.content.test_specific_data;
   3063   stream_rr_response =
   3064     (struct stream_rr_response_struct *)netperf_response.content.test_specific_data;
   3065   stream_rr_results =
   3066     (struct stream_rr_results_struct *)netperf_response.content.test_specific_data;
   3067 
   3068   if (debug) {
   3069     fprintf(where,"netserver: recv_stream_rr: entered...\n");
   3070     fflush(where);
   3071   }
   3072 
   3073   /* We want to set-up the listen socket with all the desired
   3074      parameters and then let the initiator know that all is ready. If
   3075      socket size defaults are to be used, then the initiator will have
   3076      sent us 0's. If the socket sizes cannot be changed, then we will
   3077      send-back what they are. If that information cannot be
   3078      determined, then we send-back -1's for the sizes. If things go
   3079      wrong for any reason, we will drop back ten yards and punt. */
   3080 
   3081   /* If anything goes wrong, we want the remote to know about it. It
   3082      would be best if the error that the remote reports to the user is
   3083      the actual error we encountered, rather than some bogus
   3084      unexpected response type message. */
   3085 
   3086   if (debug) {
   3087     fprintf(where,"recv_stream_rr: setting the response type...\n");
   3088     fflush(where);
   3089   }
   3090 
   3091   netperf_response.content.response_type = STREAM_RR_RESPONSE;
   3092 
   3093   if (debug) {
   3094     fprintf(where,"recv_stream_rr: the response type is set...\n");
   3095     fflush(where);
   3096   }
   3097 
   3098   /* allocate the recv and send rings with the requested alignments
   3099      and offsets. raj 7/94 */
   3100   if (debug) {
   3101     fprintf(where,"recv_stream_rr: requested recv alignment of %d offset %d\n",
   3102 	    stream_rr_request->recv_alignment,
   3103 	    stream_rr_request->recv_offset);
   3104     fprintf(where,"recv_stream_rr: requested send alignment of %d offset %d\n",
   3105 	    stream_rr_request->send_alignment,
   3106 	    stream_rr_request->send_offset);
   3107     fflush(where);
   3108   }
   3109 
   3110   /* at some point, these need to come to us from the remote system */
   3111   if (send_width == 0) send_width = 1;
   3112   if (recv_width == 0) recv_width = 1;
   3113 
   3114   send_ring = allocate_buffer_ring(send_width,
   3115 				   stream_rr_request->response_size,
   3116 				   stream_rr_request->send_alignment,
   3117 				   stream_rr_request->send_offset);
   3118 
   3119   recv_ring = allocate_buffer_ring(recv_width,
   3120 				   stream_rr_request->request_size,
   3121 				   stream_rr_request->recv_alignment,
   3122 				   stream_rr_request->recv_offset);
   3123 
   3124 
   3125   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we
   3126      can put in OUR values !-) At some point, we may want to nail this
   3127      socket to a particular network-level address, but for now,
   3128      INADDR_ANY should be just fine. */
   3129 
   3130   bzero((char *)&myaddr_un,
   3131 	sizeof(myaddr_un));
   3132   myaddr_un.sun_family      = AF_UNIX;
   3133 
   3134   /* Grab a socket to listen on, and then listen on it. */
   3135 
   3136   if (debug) {
   3137     fprintf(where,"recv_stream_rr: grabbing a socket...\n");
   3138     fflush(where);
   3139   }
   3140 
   3141   /* create_unix_socket expects to find some things in the global
   3142      variables, so set the globals based on the values in the request.
   3143      once the socket has been created, we will set the response values
   3144      based on the updated value of those globals. raj 7/94 */
   3145   lss_size_req = stream_rr_request->send_buf_size;
   3146   lsr_size_req = stream_rr_request->recv_buf_size;
   3147 
   3148   s_listen = create_unix_socket(AF_UNIX,
   3149 				SOCK_STREAM);
   3150 
   3151   if (s_listen == INVALID_SOCKET) {
   3152     netperf_response.content.serv_errno = errno;
   3153     send_response();
   3154 
   3155     exit(1);
   3156   }
   3157 
   3158   /* Let's get an address assigned to this socket so we can tell the
   3159      initiator how to reach the data socket. There may be a desire to
   3160      nail this socket to a specific IP address in a multi-homed,
   3161      multi-connection situation, but for now, we'll ignore the issue
   3162      and concentrate on single connection testing. */
   3163 
   3164   strcpy(myaddr_un.sun_path,tempnam(path_prefix,"netperf."));
   3165   if (bind(s_listen,
   3166 	   (struct sockaddr *)&myaddr_un,
   3167 	   sizeof(myaddr_un)) == SOCKET_ERROR) {
   3168     netperf_response.content.serv_errno = errno;
   3169     unlink(myaddr_un.sun_path);
   3170     close(s_listen);
   3171     send_response();
   3172 
   3173     exit(1);
   3174   }
   3175 
   3176   /* Now, let's set-up the socket to listen for connections */
   3177   if (listen(s_listen, 5) == SOCKET_ERROR) {
   3178     netperf_response.content.serv_errno = errno;
   3179     close(s_listen);
   3180     send_response();
   3181 
   3182     exit(1);
   3183   }
   3184 
   3185   /* Now myaddr_un contains the port and the internet address this is
   3186      returned to the sender also implicitly telling the sender that
   3187      the socket buffer sizing has been done. */
   3188 
   3189   strcpy(stream_rr_response->unix_path,myaddr_un.sun_path);
   3190   netperf_response.content.serv_errno   = 0;
   3191 
   3192   /* But wait, there's more. If the initiator wanted cpu measurements,
   3193      then we must call the calibrate routine, which will return the
   3194      max rate back to the initiator. If the CPU was not to be
   3195      measured, or something went wrong with the calibration, we will
   3196      return a 0.0 to the initiator. */
   3197 
   3198   stream_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
   3199   if (stream_rr_request->measure_cpu) {
   3200     stream_rr_response->measure_cpu = 1;
   3201     stream_rr_response->cpu_rate = calibrate_local_cpu(stream_rr_request->cpu_rate);
   3202   }
   3203 
   3204 
   3205   /* before we send the response back to the initiator, pull some of
   3206      the socket parms from the globals */
   3207   stream_rr_response->send_buf_size = lss_size;
   3208   stream_rr_response->recv_buf_size = lsr_size;
   3209 
   3210   send_response();
   3211 
   3212   addrlen = sizeof(peeraddr_un);
   3213 
   3214   if ((s_data = accept(s_listen,
   3215 		       (struct sockaddr *)&peeraddr_un,
   3216 		       &addrlen)) == INVALID_SOCKET) {
   3217     /* Let's just punt. The remote will be given some information */
   3218     close(s_listen);
   3219 
   3220     exit(1);
   3221   }
   3222 
   3223   if (debug) {
   3224     fprintf(where,"recv_stream_rr: accept completes on the data connection.\n");
   3225     fflush(where);
   3226   }
   3227 
   3228   /* Now it's time to start receiving data on the connection. We will
   3229      first grab the apropriate counters and then start grabbing. */
   3230 
   3231   cpu_start(stream_rr_request->measure_cpu);
   3232 
   3233   /* The loop will exit when the sender does a shutdown, which will
   3234      return a length of zero  */
   3235 
   3236   if (stream_rr_request->test_length > 0) {
   3237     times_up = 0;
   3238     trans_remaining = 0;
   3239     start_timer(stream_rr_request->test_length + PAD_TIME);
   3240   }
   3241   else {
   3242     times_up = 1;
   3243     trans_remaining = stream_rr_request->test_length * -1;
   3244   }
   3245 
   3246   while ((!times_up) || (trans_remaining > 0)) {
   3247     temp_message_ptr = recv_ring->buffer_ptr;
   3248     request_bytes_remaining	= stream_rr_request->request_size;
   3249 
   3250     /* receive the request from the other side */
   3251     if (debug) {
   3252       fprintf(where,"about to receive for trans %d\n",trans_received);
   3253       fprintf(where,"temp_message_ptr is %p\n",temp_message_ptr);
   3254       fflush(where);
   3255     }
   3256     while(request_bytes_remaining > 0) {
   3257       if((request_bytes_recvd=recv(s_data,
   3258 				   temp_message_ptr,
   3259 				   request_bytes_remaining,
   3260 				   0)) == SOCKET_ERROR) {
   3261 	if (errno == EINTR) {
   3262 	  /* the timer popped */
   3263 	  timed_out = 1;
   3264 	  break;
   3265 	}
   3266 	netperf_response.content.serv_errno = errno;
   3267 	send_response();
   3268 	exit(1);
   3269       }
   3270       else {
   3271 	request_bytes_remaining -= request_bytes_recvd;
   3272 	temp_message_ptr  += request_bytes_recvd;
   3273       }
   3274       if (debug) {
   3275 	fprintf(where,"just received for trans %d\n",trans_received);
   3276 	fflush(where);
   3277       }
   3278     }
   3279 
   3280     recv_ring = recv_ring->next;
   3281 
   3282     if (timed_out) {
   3283       /* we hit the end of the test based on time - lets
   3284          bail out of here now... */
   3285       fprintf(where,"yo5\n");
   3286       fflush(where);
   3287       break;
   3288     }
   3289 
   3290     /* Now, send the response to the remote */
   3291     if (debug) {
   3292       fprintf(where,"about to send for trans %d\n",trans_received);
   3293       fflush(where);
   3294     }
   3295     if((bytes_sent=send(s_data,
   3296 			send_ring->buffer_ptr,
   3297 			stream_rr_request->response_size,
   3298 			0)) == SOCKET_ERROR) {
   3299       if (errno == EINTR) {
   3300 	/* the test timer has popped */
   3301 	timed_out = 1;
   3302 	fprintf(where,"yo6\n");
   3303 	fflush(where);
   3304 	break;
   3305       }
   3306       netperf_response.content.serv_errno = 997;
   3307       send_response();
   3308       exit(1);
   3309     }
   3310 
   3311     send_ring = send_ring->next;
   3312 
   3313     trans_received++;
   3314     if (trans_remaining) {
   3315       trans_remaining--;
   3316     }
   3317 
   3318     if (debug) {
   3319       fprintf(where,
   3320 	      "recv_stream_rr: Transaction %d complete\n",
   3321 	      trans_received);
   3322       fflush(where);
   3323     }
   3324   }
   3325 
   3326 
   3327   /* The loop now exits due to timeout or transaction count being
   3328      reached */
   3329 
   3330   cpu_stop(stream_rr_request->measure_cpu,&elapsed_time);
   3331 
   3332   if (timed_out) {
   3333     /* we ended the test by time, which was at least 2 seconds longer
   3334        than we wanted to run. so, we want to subtract PAD_TIME from
   3335        the elapsed_time. */
   3336     elapsed_time -= PAD_TIME;
   3337   }
   3338   /* send the results to the sender			*/
   3339 
   3340   if (debug) {
   3341     fprintf(where,
   3342 	    "recv_stream_rr: got %d transactions\n",
   3343 	    trans_received);
   3344     fflush(where);
   3345   }
   3346 
   3347   stream_rr_results->bytes_received	= (trans_received *
   3348 					   (stream_rr_request->request_size +
   3349 					    stream_rr_request->response_size));
   3350   stream_rr_results->trans_received	= trans_received;
   3351   stream_rr_results->elapsed_time	= elapsed_time;
   3352   if (stream_rr_request->measure_cpu) {
   3353     stream_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
   3354   }
   3355 
   3356   if (debug) {
   3357     fprintf(where,
   3358 	    "recv_stream_rr: test complete, sending results.\n");
   3359     fflush(where);
   3360   }
   3361 
   3362   send_response();
   3363   unlink(myaddr_un.sun_path);
   3364 }
   3365 
   3366 void
   3368 print_unix_usage()
   3369 {
   3370 
   3371   fwrite(unix_usage, sizeof(char), strlen(unix_usage), stdout);
   3372   exit(1);
   3373 
   3374 }
   3375 void
   3376 scan_unix_args(int argc, char *argv[])
   3377 {
   3378 #define UNIX_ARGS "hm:M:p:r:s:S:"
   3379   extern char	*optarg;	  /* pointer to option string	*/
   3380 
   3381   int		c;
   3382 
   3383   char
   3384     arg1[BUFSIZ],  /* argument holders		*/
   3385     arg2[BUFSIZ];
   3386 
   3387   init_test_vars();
   3388 
   3389   if (no_control) {
   3390     fprintf(where,
   3391 	    "The UNIX tests do not know how to run with no control connection\n");
   3392     exit(-1);
   3393   }
   3394 
   3395   /* Go through all the command line arguments and break them out. For
   3396      those options that take two parms, specifying only the first will
   3397      set both to that value. Specifying only the second will leave the
   3398      first untouched. To change only the first, use the form "first,"
   3399      (see the routine break_args.. */
   3400 
   3401   while ((c= getopt(argc, argv, UNIX_ARGS)) != EOF) {
   3402     switch (c) {
   3403     case '?':
   3404     case 'h':
   3405       print_unix_usage();
   3406       exit(1);
   3407     case 'p':
   3408       /* set the path prefix (directory) that should be used for the
   3409          pipes. at some point, there should be some error checking. */
   3410       strcpy(path_prefix,optarg);
   3411       break;
   3412     case 's':
   3413       /* set local socket sizes */
   3414       break_args(optarg,arg1,arg2);
   3415       if (arg1[0])
   3416 	lss_size_req = convert(arg1);
   3417       if (arg2[0])
   3418 	lsr_size_req = convert(arg2);
   3419       break;
   3420     case 'S':
   3421       /* set remote socket sizes */
   3422       break_args(optarg,arg1,arg2);
   3423       if (arg1[0])
   3424 	rss_size = convert(arg1);
   3425       if (arg2[0])
   3426 	rsr_size = convert(arg2);
   3427       break;
   3428     case 'r':
   3429       /* set the request/response sizes */
   3430       break_args(optarg,arg1,arg2);
   3431       if (arg1[0])
   3432 	req_size = convert(arg1);
   3433       if (arg2[0])
   3434 	rsp_size = convert(arg2);
   3435       break;
   3436     case 'm':
   3437       /* set the send size */
   3438       send_size = convert(optarg);
   3439       break;
   3440     case 'M':
   3441       /* set the recv size */
   3442       recv_size = convert(optarg);
   3443       break;
   3444     };
   3445   }
   3446 }
   3447 #endif /* WANT_UNIX */
   3448