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