nettest_sdp.c revision 8fbc7e6b026f40333767b2383bbaf0c5da473135
1#ifndef lint
2char	nettest_sdp[]="\
3@(#)nettest_sdp.c (c) Copyright 2007 Hewlett-Packard Co. Version 2.4.4";
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
82extern 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
90static 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
95static  int confidence_iteration;
96static  char  local_cpu_method;
97static  char  remote_cpu_method;
98
99#ifdef WANT_HISTOGRAM
100static struct timeval time_one;
101static struct timeval time_two;
102static HIST time_hist;
103#endif /* WANT_HISTOGRAM */
104
105
106char sdp_usage[] = "\n\
107Usage: netperf [global options] -- [test options] \n\
108\n\
109SDP 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\
125For those options taking two parms, at least one must be specified;\n\
126specifying one value without a comma will set both parms to that\n\
127value, specifying a value with a leading comma will set just the second\n\
128parm, a value with a trailing comma will set just the first. To set\n\
129each parm to unique values, specify both and separate them with a\n\
130comma.\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 */
140static
141void
142get_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
166void
167send_sdp_stream(char remote_host[])
168{
169
170  char *tput_title = "\
171Recv   Send    Send                          \n\
172Socket Socket  Message  Elapsed              \n\
173Size   Size    Size     Time     Throughput  \n\
174bytes  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 = "\
183Recv   Send    Send                          Utilization       Service Demand\n\
184Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
185Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
186bytes  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\
195Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
196Local  Remote  Local  Remote  Xfered   Per                 Per\n\
197Send   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\
201Maximum\n\
202Segment\n\
203Size (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
865void
866send_sdp_maerts(char remote_host[])
867{
868
869  char *tput_title = "\
870Recv   Send    Send                          \n\
871Socket Socket  Message  Elapsed              \n\
872Size   Size    Size     Time     Throughput  \n\
873bytes  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 = "\
882Recv   Send    Send                          Utilization       Service Demand\n\
883Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
884Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
885bytes  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\
894Alignment      Offset         %-8.8s %-8.8s    Recvs   %-8.8s Sends\n\
895Local  Remote  Local  Remote  Xfered   Per                 Per\n\
896Recv   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\
900Maximum\n\
901Segment\n\
902Size (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
1567void
1568recv_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
1906void
1907recv_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
2257void
2258send_sdp_rr(char remote_host[])
2259{
2260
2261  char *tput_title = "\
2262Local /Remote\n\
2263Socket Size   Request  Resp.   Elapsed  Trans.\n\
2264Send   Recv   Size     Size    Time     Rate         \n\
2265bytes  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 = "\
2276Local /Remote\n\
2277Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
2278Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
2279bytes  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 = "\
2291Alignment      Offset\n\
2292Local  Remote  Local  Remote\n\
2293Send   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 */
2986void
2987recv_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
3359void
3360print_sdp_usage()
3361{
3362
3363  printf("%s",sdp_usage);
3364  exit(1);
3365
3366}
3367void
3368scan_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