• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifdef lint
2 #define WANT_UNIX
3 #define DIRTY
4 #define WANT_INTERVALS
5 #endif /* lint */
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #ifdef WIN32
12 #error Unix Domain Sockets are not available under Windows
13 #endif
14 
15 #ifdef WANT_UNIX
16 char	nettest_unix_id[]="\
17 @(#)nettest_unix.c (c) Copyright 1994-2012 Hewlett-Packard Co. Version 2.6.0";
18 
19 /****************************************************************/
20 /*								*/
21 /*	nettest_bsd.c						*/
22 /*								*/
23 /*      the BSD sockets parsing routine...                      */
24 /*                                                              */
25 /*      scan_unix_args()                                        */
26 /*                                                              */
27 /*	the actual test routines...				*/
28 /*								*/
29 /*	send_stream_stream()  perform a stream stream test	*/
30 /*	recv_stream_stream()					*/
31 /*	send_stream_rr()      perform a stream request/response	*/
32 /*	recv_stream_rr()					*/
33 /*	send_dg_stream()      perform a dg stream test	        */
34 /*	recv_dg_stream()					*/
35 /*	send_dg_rr()	      perform a dg request/response	*/
36 /*	recv_dg_rr()						*/
37 /*	loc_cpu_rate()	      determine the local cpu maxrate   */
38 /*	rem_cpu_rate()	      find the remote cpu maxrate	*/
39 /*								*/
40 /****************************************************************/
41 
42  /* at some point, I might want to go-in and see if I really need all
43     these includes, but for the moment, we'll let them all just sit
44     there. raj 8/94 */
45 #include <sys/types.h>
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <sys/ipc.h>
50 #include <sys/socket.h>
51 #include <errno.h>
52 #include <signal.h>
53 #include <sys/un.h>
54 #include <unistd.h>
55 #include <string.h>
56 #include <time.h>
57 #include <sys/time.h>
58 
59 #ifdef NOSTDLIBH
60 #include <malloc.h>
61 #else /* NOSTDLIBH */
62 #include <stdlib.h>
63 #endif /* NOSTDLIBH */
64 
65 #include <sys/stat.h>
66 
67 
68 #include "netlib.h"
69 #include "netsh.h"
70 #include "nettest_unix.h"
71 
72 
73 
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 
80 static char
81   path_prefix[32];
82 
83 static 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 
98 char unix_usage[] = "\n\
99 Usage: netperf [global options] -- [test options] \n\
100 \n\
101 STREAM/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\
110 For those options taking two parms, at least one must be specified;\n\
111 specifying one value without a comma will set both parms to that\n\
112 value, specifying a value with a leading comma will set just the second\n\
113 parm, a value with a trailing comma will set just the first. To set\n\
114 each parm to unique values, specify both and separate them with a\n\
115 comma.\n";
116 
117 /* this routing initializes all the test specific variables */
118 
119 static void
init_test_vars()120 init_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 */
144 SOCKET
create_unix_socket(int family,int type)145 create_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 
196 void
send_stream_stream(char remote_host[])197 send_stream_stream(char remote_host[])
198 {
199 
200   char *tput_title = "\
201 Recv   Send    Send                          \n\
202 Socket Socket  Message  Elapsed              \n\
203 Size   Size    Size     Time     Throughput  \n\
204 bytes  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 = "\
213 Recv   Send    Send                          Utilization    Service Demand\n\
214 Socket Socket  Message  Elapsed              Send   Recv    Send    Recv\n\
215 Size   Size    Size     Time     Throughput  local  remote  local   remote\n\
216 bytes  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\
225 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
226 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
227 Send   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 
703 void
recv_stream_stream()704 recv_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 
1027 void
send_stream_rr(char remote_host[])1028 send_stream_rr(char remote_host[])
1029 {
1030 
1031   char *tput_title = "\
1032 Local /Remote\n\
1033 Socket Size   Request  Resp.   Elapsed  Trans.\n\
1034 Send   Recv   Size     Size    Time     Rate         \n\
1035 bytes  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 = "\
1046 Local /Remote\n\
1047 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
1048 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
1049 bytes  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 = "\
1061 Alignment      Offset\n\
1062 Local  Remote  Local  Remote\n\
1063 Send   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 
1514 void
send_dg_stream(char remote_host[])1515 send_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\
1524 Size    Size     Time         Okay Errors   Throughput\n\
1525 bytes   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\
1537 Size    Size     Time         Okay Errors   Throughput   Util    Demand\n\
1538 bytes   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 
1929 void
recv_dg_stream()1930 recv_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 
2178 void
send_dg_rr(char remote_host[])2179 send_dg_rr(char remote_host[])
2180 {
2181 
2182   char *tput_title = "\
2183 Local /Remote\n\
2184 Socket Size   Request  Resp.   Elapsed  Trans.\n\
2185 Send   Recv   Size     Size    Time     Rate         \n\
2186 bytes  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 = "\
2197 Local /Remote\n\
2198 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
2199 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
2200 bytes  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. */
2738 void
recv_dg_rr()2739 recv_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 
3026 void
recv_stream_rr()3027 recv_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 
3355 void
print_unix_usage()3356 print_unix_usage()
3357 {
3358 
3359   fwrite(unix_usage, sizeof(char), strlen(unix_usage), stdout);
3360   exit(1);
3361 
3362 }
3363 void
scan_unix_args(int argc,char * argv[])3364 scan_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