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