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