1 #ifndef lint
2 char	nettest_id[]="\
3 @(#)nettest_bsd.c (c) Copyright 1993-2004 Hewlett-Packard Co. Version 2.4.3";
4 #endif /* lint */
5 
6 
7 /****************************************************************/
8 /*								*/
9 /*	nettest_bsd.c						*/
10 /*								*/
11 /*      the BSD sockets parsing routine...                      */
12 /*       ...with the addition of Windows NT, this is now also   */
13 /*          a Winsock test... sigh :)                           */
14 /*                                                              */
15 /*      scan_sockets_args()                                     */
16 /*                                                              */
17 /*	the actual test routines...				*/
18 /*								*/
19 /*	send_tcp_stream()	perform a tcp stream test	*/
20 /*	recv_tcp_stream()					*/
21 /*      send_tcp_maerts()       perform a tcp stream test       */
22 /*      recv_tcp_maerts()       in the other direction          */
23 /*	send_tcp_rr()		perform a tcp request/response	*/
24 /*	recv_tcp_rr()						*/
25 /*      send_tcp_conn_rr()      an RR test including connect    */
26 /*      recv_tcp_conn_rr()                                      */
27 /*      send_tcp_cc()           a connect/disconnect test with  */
28 /*      recv_tcp_cc()           no RR                           */
29 /*	send_udp_stream()	perform a udp stream test	*/
30 /*	recv_udp_stream()					*/
31 /*	send_udp_rr()		perform a udp request/response	*/
32 /*	recv_udp_rr()						*/
33 /*	loc_cpu_rate()		determine the local cpu maxrate */
34 /*	rem_cpu_rate()		find the remote cpu maxrate	*/
35 /*								*/
36 /****************************************************************/
37 
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41 
42 #include <stdio.h>
43 #if HAVE_SYS_TYPES_H
44 # include <sys/types.h>
45 #endif
46 #if HAVE_SYS_STAT_H
47 # include <sys/stat.h>
48 #endif
49 #if STDC_HEADERS
50 # include <stdlib.h>
51 # include <stddef.h>
52 #else
53 # if HAVE_STDLIB_H
54 #  include <stdlib.h>
55 # endif
56 #endif
57 #if HAVE_STRING_H
58 # if !STDC_HEADERS && HAVE_MEMORY_H
59 #  include <memory.h>
60 # endif
61 # include <string.h>
62 #endif
63 #if HAVE_STRINGS_H
64 # include <strings.h>
65 #endif
66 #if HAVE_INTTYPES_H
67 # include <inttypes.h>
68 #else
69 # if HAVE_STDINT_H
70 #  include <stdint.h>
71 # endif
72 #endif
73 #if HAVE_UNISTD_H
74 # include <unistd.h>
75 #endif
76 
77 #include <fcntl.h>
78 #ifndef WIN32
79 #include <errno.h>
80 #include <signal.h>
81 #endif
82 
83 #if TIME_WITH_SYS_TIME
84 # include <sys/time.h>
85 # include <time.h>
86 #else
87 # if HAVE_SYS_TIME_H
88 #  include <sys/time.h>
89 # else
90 #  include <time.h>
91 # endif
92 #endif
93 
94 #ifdef NOSTDLIBH
95 #include <malloc.h>
96 #endif /* NOSTDLIBH */
97 
98 #ifndef WIN32
99 #if !defined(__VMS)
100 #include <sys/ipc.h>
101 #endif /* !defined(__VMS) */
102 #include <sys/socket.h>
103 #include <netinet/in.h>
104 #include <netinet/tcp.h>
105 #include <arpa/inet.h>
106 #include <netdb.h>
107 #else /* WIN32 */
108 #include <process.h>
109 #define netperf_socklen_t socklen_t
110 #include <winsock2.h>
111 
112 /* while it is unlikely that anyone running Windows 2000 or NT 4 is
113    going to be trying to compile this, if they are they will want to
114    define DONT_IPV6 in the sources file */
115 #ifndef DONT_IPV6
116 #include <ws2tcpip.h>
117 #endif
118 #include <windows.h>
119 
120 #define sleep(x) Sleep((x)*1000)
121 
122 #define __func__ __FUNCTION__
123 #endif /* WIN32 */
124 
125 /* We don't want to use bare constants in the shutdown() call.  In the
126    extremely unlikely event that SHUT_WR isn't defined, we will define
127    it to the value we used to be passing to shutdown() anyway.  raj
128    2007-02-08 */
129 #if !defined(SHUT_WR)
130 #define SHUT_WR 1
131 #endif
132 
133 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
134 # include "missing/getaddrinfo.h"
135 #endif
136 
137 #include "netlib.h"
138 #include "netsh.h"
139 #include "nettest_bsd.h"
140 
141 #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO)
142 #include "hist.h"
143 #endif /* WANT_HISTOGRAM */
144 
145 /* make first_burst_size unconditional so we can use it easily enough
146    when calculating transaction latency for the TCP_RR test. raj
147    2007-06-08 */
148 int first_burst_size=0;
149 
150 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun__))
151 #include <sys/sendfile.h>
152 #endif /* HAVE_SENDFILE && (__linux || __sun__) */
153 
154 
155 
156 /* these variables are specific to the BSD sockets tests, but can
157  * be used elsewhere if needed.  They are externed through nettest_bsd.h
158  */
159 
160 int
161   rss_size_req = -1,	/* requested remote socket send buffer size */
162   rsr_size_req = -1,	/* requested remote socket recv buffer size */
163   rss_size,		/* remote socket send buffer size	*/
164   rsr_size,		/* remote socket recv buffer size	*/
165   lss_size_req = -1,	/* requested local socket send buffer size */
166   lsr_size_req = -1,	/* requested local socket recv buffer size */
167   lss_size,		/* local  socket send buffer size 	*/
168   lsr_size,		/* local  socket recv buffer size 	*/
169   req_size = 1,		/* request size                   	*/
170   rsp_size = 1,		/* response size			*/
171   send_size,		/* how big are individual sends		*/
172   recv_size;		/* how big are individual receives	*/
173 
174 static  int confidence_iteration;
175 static  char  local_cpu_method;
176 static  char  remote_cpu_method;
177 
178 /* these will control the width of port numbers we try to use in the */
179 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
180 static int client_port_min = 5000;
181 static int client_port_max = 65535;
182 
183  /* different options for the sockets				*/
184 
185 int
186   loc_nodelay,		/* don't/do use NODELAY	locally		*/
187   rem_nodelay,		/* don't/do use NODELAY remotely	*/
188 #ifdef TCP_CORK
189   loc_tcpcork=0,        /* don't/do use TCP_CORK locally        */
190   rem_tcpcork=0,        /* don't/do use TCP_CORK remotely       */
191 #endif /* TCP_CORK */
192   loc_sndavoid,		/* avoid send copies locally		*/
193   loc_rcvavoid,		/* avoid recv copies locally		*/
194   rem_sndavoid,		/* avoid send copies remotely		*/
195   rem_rcvavoid, 	/* avoid recv_copies remotely		*/
196   local_connected = 0,  /* local socket type, connected/non-connected */
197   remote_connected = 0; /* remote socket type, connected/non-connected */
198 
199 #ifdef WANT_HISTOGRAM
200 #ifdef HAVE_GETHRTIME
201 static hrtime_t time_one;
202 static hrtime_t time_two;
203 #elif HAVE_GET_HRT
204 #include "hrt.h"
205 static hrt_t time_one;
206 static hrt_t time_two;
207 #elif defined(WIN32)
208 static LARGE_INTEGER time_one;
209 static LARGE_INTEGER time_two;
210 #else
211 static struct timeval time_one;
212 static struct timeval time_two;
213 #endif /* HAVE_GETHRTIME */
214 static HIST time_hist;
215 #endif /* WANT_HISTOGRAM */
216 
217 #ifdef WANT_INTERVALS
218 int interval_count;
219 #ifndef WANT_SPIN
220 sigset_t signal_set;
221 #define INTERVALS_INIT() \
222     if (interval_burst) { \
223       /* zero means that we never pause, so we never should need the \
224          interval timer. we used to use it for demo mode, but we deal \
225 	 with that with a variant on watching the clock rather than \
226 	 waiting for a timer. raj 2006-02-06 */ \
227       start_itimer(interval_wate); \
228     } \
229     interval_count = interval_burst; \
230     /* get the signal set for the call to sigsuspend */ \
231     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \
232       fprintf(where, \
233 	      "%s: unable to get sigmask errno %d\n", \
234 	      __func__, \
235 	      errno); \
236       fflush(where); \
237       exit(1); \
238     }
239 
240 #define INTERVALS_WAIT() \
241       /* in this case, the interval count is the count-down couter \
242 	 to decide to sleep for a little bit */ \
243       if ((interval_burst) && (--interval_count == 0)) { \
244 	/* call sigsuspend and wait for the interval timer to get us \
245 	   out */ \
246 	if (debug > 1) { \
247 	  fprintf(where,"about to suspend\n"); \
248 	  fflush(where); \
249 	} \
250 	if (sigsuspend(&signal_set) == EFAULT) { \
251 	  fprintf(where, \
252 		  "%s: fault with sigsuspend.\n", \
253                   __func__); \
254 	  fflush(where); \
255 	  exit(1); \
256 	} \
257 	interval_count = interval_burst; \
258       }
259 #else
260 /* first out timestamp */
261 #ifdef HAVE_GETHRTIME
262 static hrtime_t intvl_one;
263 static hrtime_t intvl_two;
264 static hrtime_t *intvl_one_ptr = &intvl_one;
265 static hrtime_t *intvl_two_ptr = &intvl_two;
266 static hrtime_t *temp_intvl_ptr = &intvl_one;
267 #elif defined(WIN32)
268 static LARGE_INTEGER intvl_one;
269 static LARGE_INTEGER intvl_two;
270 static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
271 static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
272 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
273 #else
274 static struct timeval intvl_one;
275 static struct timeval intvl_two;
276 static struct timeval *intvl_one_ptr = &intvl_one;
277 static struct timeval *intvl_two_ptr = &intvl_two;
278 static struct timeval *temp_intvl_ptr = &intvl_one;
279 #endif
280 
281 #define INTERVALS_INIT() \
282       if (interval_burst) { \
283 	HIST_timestamp(intvl_one_ptr); \
284       } \
285       interval_count = interval_burst; \
286 
287 #define INTERVALS_WAIT() \
288       /* in this case, the interval count is the count-down couter \
289 	 to decide to sleep for a little bit */ \
290       if ((interval_burst) && (--interval_count == 0)) { \
291 	/* call sigsuspend and wait for the interval timer to get us \
292 	   out */ \
293 	if (debug > 1) { \
294 	  fprintf(where,"about to spin suspend\n"); \
295 	  fflush(where); \
296 	} \
297         HIST_timestamp(intvl_two_ptr); \
298         while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \
299 	  HIST_timestamp(intvl_two_ptr); \
300 	} \
301 	temp_intvl_ptr = intvl_one_ptr; \
302 	intvl_one_ptr = intvl_two_ptr; \
303 	intvl_two_ptr = temp_intvl_ptr; \
304 	interval_count = interval_burst; \
305       }
306 #endif
307 #endif
308 
309 #ifdef WANT_DEMO
310 #ifdef HAVE_GETHRTIME
311 static hrtime_t demo_one;
312 static hrtime_t demo_two;
313 static hrtime_t *demo_one_ptr = &demo_one;
314 static hrtime_t *demo_two_ptr = &demo_two;
315 static hrtime_t *temp_demo_ptr = &demo_one;
316 #elif defined(WIN32)
317 static LARGE_INTEGER demo_one;
318 static LARGE_INTEGER demo_two;
319 static LARGE_INTEGER *demo_one_ptr = &demo_one;
320 static LARGE_INTEGER *demo_two_ptr = &demo_two;
321 static LARGE_INTEGER *temp_demo_ptr = &demo_one;
322 #else
323 static struct timeval demo_one;
324 static struct timeval demo_two;
325 static struct timeval *demo_one_ptr = &demo_one;
326 static struct timeval *demo_two_ptr = &demo_two;
327 static struct timeval *temp_demo_ptr = &demo_one;
328 #endif
329 
330 /* for a _STREAM test, "a" should be lss_size and "b" should be
331    rsr_size. for a _MAERTS test, "a" should be lsr_size and "b" should
332    be rss_size. raj 2005-04-06 */
333 #define DEMO_STREAM_SETUP(a,b) \
334     if ((demo_mode) && (demo_units == 0)) { \
335       /* take our default value of demo_units to be the larger of \
336 	 twice the remote's SO_RCVBUF or twice our SO_SNDBUF */ \
337       if (a > b) { \
338 	demo_units = 2*a; \
339       } \
340       else { \
341 	demo_units = 2*b; \
342       } \
343     }
344 
345 #define DEMO_STREAM_INTERVAL(units) \
346       if (demo_mode) { \
347 	double actual_interval; \
348 	units_this_tick += units; \
349 	if (units_this_tick >= demo_units) { \
350 	  /* time to possibly update demo_units and maybe output an \
351 	     interim result */ \
352 	  HIST_timestamp(demo_two_ptr); \
353 	  actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \
354 	  /* we always want to fine-tune demo_units here whether we \
355 	     emit an interim result or not.  if we are short, this \
356 	     will lengthen demo_units.  if we are long, this will \
357 	     shorten it */ \
358 	  demo_units = demo_units * (demo_interval / actual_interval); \
359 	  if (actual_interval >= demo_interval) { \
360 	    /* time to emit an interim result */ \
361 	    fprintf(where, \
362 		    "Interim result: %7.2f %s/s over %.2f seconds\n", \
363 		    calc_thruput_interval(units_this_tick, \
364 					  actual_interval/1000000.0), \
365 		    format_units(), \
366 		    actual_interval/1000000.0); \
367             fflush(where); \
368 	    units_this_tick = 0.0; \
369 	    /* now get a new starting timestamp.  we could be clever \
370 	       and swap pointers - the math we do probably does not \
371 	       take all that long, but for now this will suffice */ \
372 	    temp_demo_ptr = demo_one_ptr; \
373 	    demo_one_ptr = demo_two_ptr; \
374 	    demo_two_ptr = temp_demo_ptr; \
375 	  } \
376 	} \
377       }
378 
379 #define DEMO_RR_SETUP(a) \
380     if ((demo_mode) && (demo_units == 0)) { \
381       /* take whatever we are given */ \
382 	demo_units = a; \
383     }
384 
385 #define DEMO_RR_INTERVAL(units) \
386       if (demo_mode) { \
387 	double actual_interval; \
388 	units_this_tick += units; \
389 	if (units_this_tick >= demo_units) { \
390 	  /* time to possibly update demo_units and maybe output an \
391 	     interim result */ \
392 	  HIST_timestamp(demo_two_ptr); \
393 	  actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \
394 	  /* we always want to fine-tune demo_units here whether we \
395 	     emit an interim result or not.  if we are short, this \
396 	     will lengthen demo_units.  if we are long, this will \
397 	     shorten it */ \
398 	  demo_units = demo_units * (demo_interval / actual_interval); \
399 	  if (actual_interval >= demo_interval) { \
400 	    /* time to emit an interim result */ \
401 	    fprintf(where, \
402 		    "Interim result: %.2f %s/s over %.2f seconds\n", \
403                     units_this_tick / (actual_interval/1000000.0), \
404 		    "Trans", \
405 		    actual_interval/1000000.0); \
406 	    units_this_tick = 0.0; \
407 	    /* now get a new starting timestamp.  we could be clever \
408 	       and swap pointers - the math we do probably does not \
409 	       take all that long, but for now this will suffice */ \
410 	    temp_demo_ptr = demo_one_ptr; \
411 	    demo_one_ptr = demo_two_ptr; \
412 	    demo_two_ptr = temp_demo_ptr; \
413 	  } \
414 	} \
415       }
416 #endif
417 
418 char sockets_usage[] = "\n\
419 Usage: netperf [global options] -- [test options] \n\
420 \n\
421 TCP/UDP BSD Sockets Test Options:\n\
422     -b number         Send number requests at start of _RR tests\n\
423     -C                Set TCP_CORK when available\n\
424     -D [L][,R]        Set TCP_NODELAY locally and/or remotely (TCP_*)\n\
425     -h                Display this text\n\
426     -H name,fam       Use name (or IP) and family as target of data connection\n\
427     -L name,fam       Use name (or IP) and family as source of data connection\n\
428     -m bytes          Set the send size (TCP_STREAM, UDP_STREAM)\n\
429     -M bytes          Set the recv size (TCP_STREAM, UDP_STREAM)\n\
430     -n                Use the connected socket for UDP locally\n\
431     -N                Use the connected socket for UDP remotely\n\
432     -p min[,max]      Set the min/max port numbers for TCP_CRR, TCP_TRR\n\
433     -P local[,remote] Set the local/remote port for the data socket\n\
434     -r req,[rsp]      Set request/response sizes (TCP_RR, UDP_RR)\n\
435     -s send[,recv]    Set local socket send/recv buffer sizes\n\
436     -S send[,recv]    Set remote socket send/recv buffer sizes\n\
437     -4                Use AF_INET (eg IPv4) on both ends of the data conn\n\
438     -6                Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
439 \n\
440 For those options taking two parms, at least one must be specified;\n\
441 specifying one value without a comma will set both parms to that\n\
442 value, specifying a value with a leading comma will set just the second\n\
443 parm, a value with a trailing comma will set just the first. To set\n\
444 each parm to unique values, specify both and separate them with a\n\
445 comma.\n";
446 
447 
448 
449 /* these routines convert between the AF address space and the NF
450    address space since the numeric values of AF_mumble are not the
451    same across the platforms. raj 2005-02-08 */
452 
453 int
nf_to_af(int nf)454 nf_to_af(int nf) {
455   switch(nf) {
456   case NF_INET:
457     return AF_INET;
458     break;
459   case NF_UNSPEC:
460     return AF_UNSPEC;
461     break;
462   case NF_INET6:
463 #if defined(AF_INET6)
464     return AF_INET6;
465 #else
466     return AF_UNSPEC;
467 #endif
468     break;
469   default:
470     return AF_UNSPEC;
471     break;
472   }
473 }
474 
475 int
af_to_nf(int af)476 af_to_nf(int af) {
477 
478   switch(af) {
479   case AF_INET:
480     return NF_INET;
481     break;
482   case AF_UNSPEC:
483     return NF_UNSPEC;
484     break;
485 #if defined(AF_INET6)
486   case AF_INET6:
487     return NF_INET6;
488     break;
489 #endif
490   default:
491     return NF_UNSPEC;
492     break;
493   }
494 }
495 
496 
497  /* This routine is intended to retrieve interesting aspects of tcp */
498  /* for the data connection. at first, it attempts to retrieve the */
499  /* maximum segment size. later, it might be modified to retrieve */
500  /* other information, but it must be information that can be */
501  /* retrieved quickly as it is called during the timing of the test. */
502  /* for that reason, a second routine may be created that can be */
503  /* called outside of the timing loop */
504 static
505 void
get_tcp_info(SOCKET socket,int * mss)506 get_tcp_info(SOCKET socket, int *mss)
507 {
508 
509 #ifdef TCP_MAXSEG
510   netperf_socklen_t sock_opt_len;
511 
512   sock_opt_len = sizeof(netperf_socklen_t);
513   if (getsockopt(socket,
514 		 getprotobyname("tcp")->p_proto,
515 		 TCP_MAXSEG,
516 		 (char *)mss,
517 		 &sock_opt_len) == SOCKET_ERROR) {
518     fprintf(where,
519 	    "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n",
520 	    errno);
521     fflush(where);
522     *mss = -1;
523   }
524 #else
525   *mss = -1;
526 #endif /* TCP_MAXSEG */
527 }
528 
529 
530 /* return a pointer to a completed addrinfo chain - prefer
531    data_address to controlhost and utilize the specified address
532    family */
533 
534 struct addrinfo *
complete_addrinfo(char * controlhost,char * data_address,char * port,int family,int type,int protocol,int flags)535 complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags)
536 {
537   struct addrinfo hints;
538   struct addrinfo *res;
539   struct addrinfo *temp_res;
540 
541 #define CHANGED_SOCK_TYPE  0x1
542 #define CHANGED_PROTOCOL   0x2
543 #define CHANGED_SCTP       0x4
544   int    change_info = 0;
545   static int change_warning_displayed = 0;
546 
547   int count = 0;
548   int error = 0;
549 
550   char *hostname;
551 
552   /* take data-address over controlhost */
553   if (data_address)
554     hostname = data_address;
555   else
556     hostname = controlhost;
557 
558   if (debug) {
559     fprintf(where,
560 	    "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n",
561 	    hostname,
562 	    port,
563 	    inet_ftos(family),
564 	    inet_ttos(type),
565 	    inet_ptos(protocol),
566 	    flags);
567     fflush(where);
568   }
569 
570   memset(&hints, 0, sizeof(hints));
571   hints.ai_family = family;
572   hints.ai_socktype = type;
573   hints.ai_protocol = protocol;
574   hints.ai_flags = flags|AI_CANONNAME;
575 
576   count = 0;
577   do {
578     error = getaddrinfo((char *)hostname,
579                         (char *)port,
580                         &hints,
581                         &res);
582     count += 1;
583     if (error == EAI_AGAIN) {
584       if (debug) {
585         fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
586         fflush(where);
587       }
588       sleep(1);
589     }
590     /* while you see this kludge first, it is actually the second, the
591        first being the one for Solaris below. The need for this kludge
592        came after implementing the Solaris broken getaddrinfo kludge -
593        now we see a kludge in Linux getaddrinfo where if it is given
594        SOCK_STREAM and IPPROTO_SCTP it barfs with a -7
595        EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if
596        we were asking for IPPROTO_SCTP and if so, kludge, again... raj
597        2008-10-13 */
598 #ifdef WANT_SCTP
599     if (EAI_SOCKTYPE == error
600 #ifdef EAI_BADHINTS
601         || EAI_BADHINTS == error
602 #endif
603         ) {
604       /* we ass-u-me this is the Linux getaddrinfo bug, clear the
605 	 hints.ai_protocol field, and set some state "remembering"
606 	 that we did this so the code for the Solaris kludge can do
607 	 the fix-up for us.  also flip error over to EAI_AGAIN and
608 	 make sure we don't "count" this time around the loop. */
609       hints.ai_protocol = 0;
610       error = EAI_AGAIN;
611       count -= 1;
612       change_info |= CHANGED_SCTP;
613     }
614 #endif
615   } while ((error == EAI_AGAIN) && (count <= 5));
616 
617   if (error) {
618     fprintf(where,
619 	    "complete_addrinfo: could not resolve '%s' port '%s' af %d",
620 	    hostname,
621 	    port,
622 	    family);
623     fprintf(where,
624 	    "\n\tgetaddrinfo returned %d %s\n",
625 	    error,
626 	    gai_strerror(error));
627     fflush(where);
628     exit(-1);
629   }
630 
631   /* there exists at least one platform - Solaris 10 - that does not
632      seem to completely honor the ai_protocol and/or ai_socktype one
633      sets in the hints parm to the getaddrinfo call.  so, we need to
634      walk the list of entries returned and if either of those do not
635      match what we asked for, we need to go ahead and set them
636      "correctly" this is based in part on some earlier SCTP-only code
637      from previous revisions.  raj 2006-10-09 */
638 
639   temp_res = res;
640 
641   while (temp_res) {
642 
643     if ((type)  &&
644 	(temp_res->ai_socktype != type)) {
645       change_info |= CHANGED_SOCK_TYPE;
646       if (debug) {
647 	fprintf(where,
648 		"WARNING! Changed bogus getaddrinfo socket type %d to %d\n",
649 		temp_res->ai_socktype,
650 		type);
651 	fflush(where);
652       }
653       temp_res->ai_socktype = type;
654     }
655 
656     if ((protocol) &&
657 	(temp_res->ai_protocol != protocol)) {
658       change_info |= CHANGED_PROTOCOL;
659       if (debug) {
660 	fprintf(where,
661 		"WARNING! Changed bogus getaddrinfo protocol %d to %d\n",
662 		temp_res->ai_protocol,
663 		protocol);
664 	fflush(where);
665       }
666       temp_res->ai_protocol = protocol;
667     }
668     temp_res = temp_res->ai_next;
669   }
670 
671   if ((change_info & CHANGED_SOCK_TYPE) &&
672       !(change_warning_displayed & CHANGED_SOCK_TYPE)) {
673     change_warning_displayed |= CHANGED_SOCK_TYPE;
674     fprintf(where,
675 	    "WARNING! getaddrinfo returned a socket type which did not\n");
676     fprintf(where,
677 	    "match the requested type.  Please contact your vendor for\n");
678     fprintf(where,
679 	    "a fix to this bug in getaddrinfo()\n");
680     fflush(where);
681   }
682 
683   /* if we dropped the protocol hint, it would be for a protocol that
684      getaddrinfo() wasn't supporting yet, not for the bug that it took
685      our hint and still returned zero. raj 2006-10-16 */
686   if ((change_info & CHANGED_PROTOCOL) &&
687       !(change_warning_displayed & CHANGED_PROTOCOL) &&
688       (hints.ai_protocol != 0)) {
689     change_warning_displayed |= CHANGED_PROTOCOL;
690     fprintf(where,
691 	    "WARNING! getaddrinfo returned a protocol other than the\n");
692     fprintf(where,
693 	    "requested protocol.  Please contact your vendor for\n");
694     fprintf(where,
695 	    "a fix to this bug in getaddrinfo()\n");
696     fflush(where);
697   }
698 
699   if ((change_info & CHANGED_SCTP) &&
700       !(change_warning_displayed & CHANGED_SCTP)) {
701     change_warning_displayed |= CHANGED_SCTP;
702     fprintf(where,
703 	    "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n");
704     fprintf(where,
705 	    "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
706     fflush(where);
707   }
708 
709 
710   if (debug) {
711     dump_addrinfo(where, res, hostname, port, family);
712   }
713 
714   return(res);
715 }
716 
717 void
complete_addrinfos(struct addrinfo ** remote,struct addrinfo ** local,char remote_host[],int type,int protocol,int flags)718 complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) {
719 
720   *remote = complete_addrinfo(remote_host,
721 			      remote_data_address,
722 			      remote_data_port,
723 			      remote_data_family,
724 			      type,
725 			      protocol,
726 			      flags);
727 
728   /* OK, if the user has not specified a local data endpoint address
729      (test-specific -L), pick the local data endpoint address based on
730      the remote data family info (test-specific -H or -4 or -6
731      option).  if the user has not specified remote data addressing
732      info (test-specific -H, -4 -6) pick something based on the local
733      control connection address (ie the global -L option). */
734 
735   if (NULL == local_data_address) {
736     local_data_address = malloc(HOSTNAMESIZE);
737     if (NULL == remote_data_address) {
738       if (debug) {
739 	fprintf(where,
740 		"local_data_address not set, using local_host_name of '%s'\n",
741 		local_host_name);
742 	fflush(where);
743       }
744       strcpy(local_data_address,local_host_name);
745     }
746     else {
747       if (debug) {
748 	fprintf(where,
749 		"local_data_address not set, using address family info\n");
750 	fflush(where);
751       }
752       /* by default, use 0.0.0.0 - assume IPv4 */
753       strcpy(local_data_address,"0.0.0.0");
754 #if defined(AF_INET6)
755       if ((AF_INET6 == local_data_family) ||
756 	  ((AF_UNSPEC == local_data_family) &&
757 	   (AF_INET6 == remote_data_family)) ||
758 	  ((AF_UNSPEC == local_data_family) &&
759 	   (AF_INET6 == (*remote)->ai_family))) {
760 	strcpy(local_data_address,"::0");
761       }
762 #endif
763     }
764   }
765 
766   *local = complete_addrinfo("what to put here?",
767 			     local_data_address,
768 			     local_data_port,
769 			     local_data_family,
770 			     type,
771 			     protocol,
772 			     flags|AI_PASSIVE);
773 
774 }
775 
776 void
set_hostname_and_port(char * hostname,char * portstr,int family,int port)777 set_hostname_and_port(char *hostname, char *portstr, int family, int port)
778 {
779   strcpy(hostname,"0.0.0.0");
780 #if defined AF_INET6
781   if (AF_INET6 == family) {
782     strcpy(hostname,"::0");
783   }
784 #endif
785 
786   sprintf(portstr, "%u", port);
787 
788 }
789 
790 static unsigned short
get_port_number(struct addrinfo * res)791 get_port_number(struct addrinfo *res)
792 {
793  switch(res->ai_family) {
794   case AF_INET: {
795     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
796     return(ntohs(foo->sin_port));
797     break;
798   }
799 #if defined(AF_INET6)
800   case AF_INET6: {
801     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
802     return(ntohs(foo->sin6_port));
803     break;
804   }
805 #endif
806   default:
807     fprintf(where,
808 	    "Unexpected Address Family of %u\n",res->ai_family);
809     fflush(where);
810     exit(-1);
811   }
812 }
813 
814 /* this routine will set the port number of the sockaddr in the
815    addrinfo to the specified value, based on the address family */
816 void
set_port_number(struct addrinfo * res,unsigned short port)817 set_port_number(struct addrinfo *res, unsigned short port)
818 {
819   switch(res->ai_family) {
820   case AF_INET: {
821     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
822     foo->sin_port = htons(port);
823     break;
824   }
825 #if defined(AF_INET6)
826   case AF_INET6: {
827     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
828     foo->sin6_port = htons(port);
829     break;
830   }
831 #endif
832   default:
833     fprintf(where,
834 	    "Unexpected Address Family of %u\n",res->ai_family);
835     fflush(where);
836     exit(-1);
837   }
838 }
839 
840 
841 
842  /* This routine will create a data (listen) socket with the
843   apropriate options set and return it to the caller. this replaces
844   all the duplicate code in each of the test routines and should help
845   make things a little easier to understand. since this routine can be
846   called by either the netperf or netserver programs, all output
847   should be directed towards "where." family is generally AF_INET and
848   type will be either SOCK_STREAM or SOCK_DGRAM.  This routine will
849   also be used by the "SCTP" tests, hence the slightly strange-looking
850   SCTP stuff in the classic bsd sockets test file... vlad/raj
851   2005-03-15 */
852 
853 SOCKET
create_data_socket(struct addrinfo * res)854 create_data_socket(struct addrinfo *res)
855 {
856 
857   SOCKET temp_socket;
858   int one;
859   int    on  = 1;
860 
861 
862   /*set up the data socket                        */
863   temp_socket = socket(res->ai_family,
864 		       res->ai_socktype,
865 		       res->ai_protocol);
866 
867   if (temp_socket == INVALID_SOCKET){
868     fprintf(where,
869 	    "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n",
870 	    errno,
871 	    inet_ftos(res->ai_family),
872 	    inet_ttos(res->ai_socktype),
873 	    inet_ptos(res->ai_protocol),
874 	    strerror(errno));
875     fflush(where);
876     exit(1);
877   }
878 
879   if (debug) {
880     fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket);
881     fflush(where);
882   }
883 
884   /* Modify the local socket size. The reason we alter the send buffer
885    size here rather than when the connection is made is to take care
886    of decreases in buffer size. Decreasing the window size after
887    connection establishment is a TCP no-no. Also, by setting the
888    buffer (window) size before the connection is established, we can
889    control the TCP MSS (segment size). The MSS is never (well, should
890    never be) more that 1/2 the minimum receive buffer size at each
891    half of the connection.  This is why we are altering the receive
892    buffer size on the sending size of a unidirectional transfer. If
893    the user has not requested that the socket buffers be altered, we
894    will try to find-out what their values are. If we cannot touch the
895    socket buffer in any way, we will set the values to -1 to indicate
896    that.  */
897 
898   /* all the oogy nitty gritty stuff moved from here into the routine
899      being called below, per patches from davidm to workaround the bug
900      in Linux getsockopt().  raj 2004-06-15 */
901   set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
902   set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
903 
904   /* now, we may wish to enable the copy avoidance features on the */
905   /* local system. of course, this may not be possible... */
906 
907 #ifdef SO_RCV_COPYAVOID
908   if (loc_rcvavoid) {
909     if (setsockopt(temp_socket,
910 		   SOL_SOCKET,
911 		   SO_RCV_COPYAVOID,
912 		   (const char *)&loc_rcvavoid,
913 		   sizeof(int)) == SOCKET_ERROR) {
914       fprintf(where,
915 	      "netperf: create_data_socket: Could not enable receive copy avoidance");
916       fflush(where);
917       loc_rcvavoid = 0;
918     }
919   }
920 #else
921   /* it wasn't compiled in... */
922   loc_rcvavoid = 0;
923 #endif /* SO_RCV_COPYAVOID */
924 
925 #ifdef SO_SND_COPYAVOID
926   if (loc_sndavoid) {
927     if (setsockopt(temp_socket,
928 		   SOL_SOCKET,
929 		   SO_SND_COPYAVOID,
930 		   (const char *)&loc_sndavoid,
931 		   sizeof(int)) == SOCKET_ERROR) {
932       fprintf(where,
933 	      "netperf: create_data_socket: Could not enable send copy avoidance");
934       fflush(where);
935       loc_sndavoid = 0;
936     }
937   }
938 #else
939   /* it was not compiled in... */
940   loc_sndavoid = 0;
941 #endif
942 
943   /* Now, we will see about setting the TCP_NODELAY flag on the local */
944   /* socket. We will only do this for those systems that actually */
945   /* support the option. If it fails, note the fact, but keep going. */
946   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
947   /* will cause an error to be displayed */
948 
949   /* well..... long ago and far away that would have happened, in
950      particular because we would always use IPPROTO_TCP here.
951      however, now we are using res->ai_protocol, which will be
952      IPPROT_UDP, and while HP-UX, and I suspect no-one else on the
953      planet has a UDP_mumble option that overlaps with TCP_NODELAY,
954      sure as knuth made little green programs, linux has a UDP_CORK
955      option that is defined as a value of 1, which is the same a
956      TCP_NODELAY under Linux.  So, when asking for -D and
957      "TCP_NODELAY" under Linux, we are actually setting UDP_CORK
958      instead of getting an error like every other OS on the
959      planet. joy and rupture. this stops a UDP_RR test cold sooo we
960      have to make sure that res->ai_protocol actually makes sense for
961      a _NODELAY setsockopt() or a UDP_RR test on Linux where someone
962      mistakenly sets -D will hang.  raj 2005-04-21 */
963 
964 #if defined(TCP_NODELAY) || defined(SCTP_NODELAY)
965   if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) {
966 
967     /* strictly speaking, since the if defined above is an OR, we
968        should probably check against TCP_NODELAY being defined here.
969        however, the likelihood of SCTP_NODELAY being defined and
970        TCP_NODELAY _NOT_ being defined is, probably :), epsilon.  raj
971        2005-03-15 */
972 
973     int option = TCP_NODELAY;
974 
975     /* I suspect that WANT_SCTP would suffice here since that is the
976        only time we would have called getaddrinfo with a hints asking
977        for SCTP, but just in case there is an SCTP implementation out
978        there _without_ SCTP_NODELAY... raj 2005-03-15 */
979 
980 #if defined(WANT_SCTP) && defined(SCTP_NODELAY)
981     if (IPPROTO_SCTP == res->ai_protocol) {
982       option = SCTP_NODELAY;
983     }
984 #endif
985 
986     one = 1;
987     if(setsockopt(temp_socket,
988 		  res->ai_protocol,
989 		  option,
990 		  (char *)&one,
991 		  sizeof(one)) == SOCKET_ERROR) {
992       fprintf(where,
993 	      "netperf: create_data_socket: nodelay: errno %d\n",
994 	      errno);
995       fflush(where);
996     }
997 
998     if (debug > 1) {
999       fprintf(where,
1000 	      "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n");
1001       fflush(where);
1002     }
1003   }
1004 #else /* TCP_NODELAY */
1005 
1006   loc_nodelay = 0;
1007 
1008 #endif /* TCP_NODELAY */
1009 
1010 #if defined(TCP_CORK)
1011 
1012     if (loc_tcpcork != 0) {
1013       /* the user wishes for us to set TCP_CORK on the socket */
1014       int one = 1;
1015       if (setsockopt(temp_socket,
1016 		     getprotobyname("tcp")->p_proto,
1017 		     TCP_CORK,
1018 		     (char *)&one,
1019 		     sizeof(one)) == SOCKET_ERROR) {
1020 	perror("netperf: sendfile_tcp_stream: tcp_cork");
1021 	exit(1);
1022       }
1023       if (debug) {
1024 	fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
1025       }
1026     }
1027 
1028 #endif /* TCP_CORK */
1029 
1030   /* since some of the UDP tests do not do anything to cause an
1031      implicit bind() call, we need to be rather explicit about our
1032      bind() call here. even if the address and/or the port are zero
1033      (INADDR_ANY etc). raj 2004-07-20 */
1034 
1035   if (setsockopt(temp_socket,
1036 		 SOL_SOCKET,
1037 		 SO_REUSEADDR,
1038 		 (const char *)&on,
1039 		 sizeof(on)) < 0) {
1040     fprintf(where,
1041 	    "netperf: create_data_socket: SO_REUSEADDR failed %d\n",
1042 	    errno);
1043     fflush(where);
1044   }
1045 
1046   if (bind(temp_socket,
1047 	   res->ai_addr,
1048 	   res->ai_addrlen) < 0) {
1049     if (debug) {
1050       fprintf(where,
1051 	      "netperf: create_data_socket: data socket bind failed errno %d\n",
1052 	      errno);
1053       fprintf(where," port: %d\n",get_port_number(res));
1054       fflush(where);
1055     }
1056   }
1057 
1058 
1059   return(temp_socket);
1060 
1061 }
1062 
1063 #ifdef KLUDGE_SOCKET_OPTIONS
1064 
1065 
1066  /* This routine is for those BROKEN systems which do not correctly */
1067  /* pass socket attributes through calls such as accept(). It should */
1068  /* only be called for those broken systems. I *really* don't want to */
1069  /* have this, but even broken systems must be measured. raj 11/95 */
1070 void
kludge_socket_options(int temp_socket)1071 kludge_socket_options(int temp_socket)
1072 {
1073 
1074   set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
1075   set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
1076 
1077   /* now, we may wish to enable the copy avoidance features on the */
1078   /* local system. of course, this may not be possible... */
1079   /* those calls were only valid for HP-UX, and I know that HP-UX is */
1080   /* written correctly, and so we do not need to include those calls */
1081   /* in this kludgy routine. raj 11/95 */
1082 
1083 
1084   /* Now, we will see about setting the TCP_NODELAY flag on the local */
1085   /* socket. We will only do this for those systems that actually */
1086   /* support the option. If it fails, note the fact, but keep going. */
1087   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
1088   /* will cause an error to be displayed */
1089 
1090 #ifdef TCP_NODELAY
1091   if (loc_nodelay) {
1092     one = 1;
1093     if(setsockopt(temp_socket,
1094 		  getprotobyname("tcp")->p_proto,
1095 		  TCP_NODELAY,
1096 		  (char *)&one,
1097 		  sizeof(one)) == SOCKET_ERROR) {
1098       fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n",
1099 	      errno);
1100       fflush(where);
1101     }
1102 
1103     if (debug > 1) {
1104       fprintf(where,
1105 	      "netperf: kludge_socket_options: TCP_NODELAY requested...\n");
1106       fflush(where);
1107     }
1108   }
1109 #else /* TCP_NODELAY */
1110 
1111   loc_nodelay = 0;
1112 
1113 #endif /* TCP_NODELAY */
1114 
1115   }
1116 
1117 #endif /* KLUDGE_SOCKET_OPTIONS */
1118 
1119 
1120 static void *
get_address_address(struct addrinfo * info)1121 get_address_address(struct addrinfo *info)
1122 {
1123   struct sockaddr_in *sin;
1124 #if defined(AF_INET6)
1125   struct sockaddr_in6 *sin6;
1126 #endif
1127 
1128   switch(info->ai_family) {
1129   case AF_INET:
1130     sin = (struct sockaddr_in *)info->ai_addr;
1131     return(&(sin->sin_addr));
1132     break;
1133 #if defined(AF_INET6)
1134   case AF_INET6:
1135     sin6 = (struct sockaddr_in6 *)info->ai_addr;
1136     return(&(sin6->sin6_addr));
1137     break;
1138 #endif
1139   default:
1140     fprintf(stderr,"we never expected to get here in get_address_address\n");
1141     fflush(stderr);
1142     exit(-1);
1143   }
1144 }
1145 
1146 #if defined(WIN32)
1147 /* +*+ Why isn't this in the winsock headers yet? */
1148 const char *
1149 inet_ntop(int af, const void *src, char *dst, size_t size);
1150 #endif
1151 
1152 /* This routine is a generic test header printer for the topmost header */
1153 void
print_top_test_header(char test_name[],struct addrinfo * source,struct addrinfo * destination)1154 print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination)
1155 {
1156 
1157 #if defined(AF_INET6)
1158   char address_buf[INET6_ADDRSTRLEN];
1159 #else
1160   char address_buf[16]; /* magic constant */
1161 #endif
1162 
1163   /* we want to have some additional, interesting information in */
1164   /* the headers. we know some of it here, but not all, so we will */
1165   /* only print the test title here and will print the results */
1166   /* titles after the test is finished */
1167   fprintf(where, "%s", test_name);
1168   address_buf[0] = '\0';
1169   inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf));
1170   fprintf(where,
1171 	  " from %s (%s) port %u %s",
1172 	  source->ai_canonname,
1173 	  address_buf,
1174 	  get_port_number(source),
1175 	  inet_ftos(source->ai_family));
1176   address_buf[0] = '\0';
1177   inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf));
1178   fprintf(where,
1179 	  " to %s (%s) port %u %s",
1180 	  destination->ai_canonname,
1181 	  address_buf,
1182 	  get_port_number(destination),
1183 	  inet_ftos(destination->ai_family));
1184 
1185   if (iteration_max > 1) {
1186     fprintf(where,
1187 	    " : +/-%3.1f%% @ %2d%% conf. %s",
1188 	    interval/0.02,
1189 	    confidence_level,
1190 	    result_confidence_only ? " on result only" : "");
1191   }
1192   if ((loc_nodelay > 0) || (rem_nodelay > 0)) {
1193     fprintf(where," : nodelay");
1194   }
1195   if ((loc_sndavoid > 0) ||
1196       (loc_rcvavoid > 0) ||
1197       (rem_sndavoid > 0) ||
1198       (rem_rcvavoid > 0)) {
1199     fprintf(where," : copy avoidance");
1200   }
1201 
1202   if (no_control) {
1203     fprintf(where," : no control");
1204   }
1205 
1206 #ifdef WANT_HISTOGRAM
1207   fprintf(where," : histogram");
1208 #endif /* WANT_HISTOGRAM */
1209 
1210 #ifdef WANT_INTERVALS
1211 #ifndef WANT_SPIN
1212   fprintf(where," : interval");
1213 #else
1214   fprintf(where," : spin interval");
1215 #endif
1216 #endif /* WANT_INTERVALS */
1217 
1218 #ifdef DIRTY
1219   fprintf(where," : dirty data");
1220 #endif /* DIRTY */
1221 #ifdef WANT_DEMO
1222   fprintf(where," : demo");
1223 #endif
1224 #ifdef WANT_FIRST_BURST
1225   /* a little hokey perhaps, but we really only want this to be
1226      emitted for tests where it actually is used, which means a
1227      "REQUEST/RESPONSE" test. raj 2005-11-10 */
1228   if (strstr(test_name,"REQUEST/RESPONSE")) {
1229     fprintf(where," : first burst %d",first_burst_size);
1230   }
1231 #endif
1232   if (cpu_binding_requested) {
1233     fprintf(where," : cpu bind");
1234   }
1235   fprintf(where,"\n");
1236 
1237 }
1238 
1239 
1240 /* This routine implements the TCP unidirectional data transfer test */
1241 /* (a.k.a. stream) for the sockets interface. It receives its */
1242 /* parameters via global variables from the shell and writes its */
1243 /* output to the standard output. */
1244 
1245 
1246 void
send_tcp_stream(char remote_host[])1247 send_tcp_stream(char remote_host[])
1248 {
1249 
1250   char *tput_title = "\
1251 Recv   Send    Send                          \n\
1252 Socket Socket  Message  Elapsed              \n\
1253 Size   Size    Size     Time     Throughput  \n\
1254 bytes  bytes   bytes    secs.    %s/sec  \n\n";
1255 
1256   char *tput_fmt_0 =
1257     "%7.2f %s\n";
1258 
1259   char *tput_fmt_1 =
1260     "%6d %6d %6d    %-6.2f   %7.2f   %s\n";
1261 
1262   char *cpu_title = "\
1263 Recv   Send    Send                          Utilization       Service Demand\n\
1264 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
1265 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
1266 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
1267 
1268   char *cpu_fmt_0 =
1269     "%6.3f %c %s\n";
1270 
1271   char *cpu_fmt_1 =
1272     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %s\n";
1273 
1274   char *ksink_fmt = "\n\
1275 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
1276 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
1277 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
1278 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
1279 
1280   char *ksink_fmt2 = "\n\
1281 Maximum\n\
1282 Segment\n\
1283 Size (bytes)\n\
1284 %6d\n";
1285 
1286 
1287   float			elapsed_time;
1288 
1289   /* what we want is to have a buffer space that is at least one */
1290   /* send-size greater than our send window. this will insure that we */
1291   /* are never trying to re-use a buffer that may still be in the hands */
1292   /* of the transport. This buffer will be malloc'd after we have found */
1293   /* the size of the local senc socket buffer. We will want to deal */
1294   /* with alignment and offset concerns as well. */
1295 
1296   struct ring_elt *send_ring;
1297 
1298   int len;
1299   unsigned int nummessages = 0;
1300   SOCKET send_socket;
1301   int bytes_remaining;
1302   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
1303 
1304   /* with links like fddi, one can send > 32 bits worth of bytes */
1305   /* during a test... ;-) at some point, this should probably become a */
1306   /* 64bit integral type, but those are not entirely common yet */
1307 
1308   unsigned long long local_bytes_sent = 0;
1309   double	bytes_sent = 0.0;
1310 
1311   float	local_cpu_utilization;
1312   float	local_service_demand;
1313   float	remote_cpu_utilization;
1314   float	remote_service_demand;
1315 
1316   double	thruput;
1317 
1318   struct addrinfo *remote_res;
1319   struct addrinfo *local_res;
1320 
1321   struct	tcp_stream_request_struct	*tcp_stream_request;
1322   struct	tcp_stream_response_struct	*tcp_stream_response;
1323   struct	tcp_stream_results_struct	*tcp_stream_result;
1324 
1325   tcp_stream_request  =
1326     (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
1327   tcp_stream_response =
1328     (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
1329   tcp_stream_result   =
1330     (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
1331 
1332 #ifdef WANT_HISTOGRAM
1333   if (verbosity > 1) {
1334     time_hist = HIST_new();
1335   }
1336 #endif /* WANT_HISTOGRAM */
1337   /* since we are now disconnected from the code that established the */
1338   /* control socket, and since we want to be able to use different */
1339   /* protocols and such, we are passed the name of the remote host and */
1340   /* must turn that into the test specific addressing information. */
1341 
1342   /* complete_addrinfos will either succede or exit the process */
1343   complete_addrinfos(&remote_res,
1344 		     &local_res,
1345 		     remote_host,
1346 		     SOCK_STREAM,
1347 		     IPPROTO_TCP,
1348 		     0);
1349 
1350   if ( print_headers ) {
1351     print_top_test_header("TCP STREAM TEST",local_res,remote_res);
1352   }
1353 
1354   send_ring = NULL;
1355   confidence_iteration = 1;
1356   init_stat();
1357 
1358   /* we have a great-big while loop which controls the number of times */
1359   /* we run a particular test. this is for the calculation of a */
1360   /* confidence interval (I really should have stayed awake during */
1361   /* probstats :). If the user did not request confidence measurement */
1362   /* (no confidence is the default) then we will only go though the */
1363   /* loop once. the confidence stuff originates from the folks at IBM */
1364 
1365   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
1366 	 (confidence_iteration <= iteration_min)) {
1367 
1368     /* initialize a few counters. we have to remember that we might be */
1369     /* going through the loop more than once. */
1370 
1371     nummessages    =	0;
1372     bytes_sent     =	0.0;
1373     times_up       = 	0;
1374 
1375     /*set up the data socket                        */
1376     send_socket = create_data_socket(local_res);
1377 
1378     if (send_socket == INVALID_SOCKET){
1379       perror("netperf: send_tcp_stream: tcp stream data socket");
1380       exit(1);
1381     }
1382 
1383     if (debug) {
1384       fprintf(where,"send_tcp_stream: send_socket obtained...\n");
1385     }
1386 
1387     /* at this point, we have either retrieved the socket buffer sizes, */
1388     /* or have tried to set them, so now, we may want to set the send */
1389     /* size based on that (because the user either did not use a -m */
1390     /* option, or used one with an argument of 0). If the socket buffer */
1391     /* size is not available, we will set the send size to 4KB - no */
1392     /* particular reason, just arbitrary... */
1393     if (send_size == 0) {
1394       if (lss_size > 0) {
1395 	send_size = lss_size;
1396       }
1397       else {
1398 	send_size = 4096;
1399       }
1400     }
1401 
1402     /* set-up the data buffer ring with the requested alignment and offset. */
1403     /* note also that we have allocated a quantity */
1404     /* of memory that is at least one send-size greater than our socket */
1405     /* buffer size. We want to be sure that there are at least two */
1406     /* buffers allocated - this can be a bit of a problem when the */
1407     /* send_size is bigger than the socket size, so we must check... the */
1408     /* user may have wanted to explicitly set the "width" of our send */
1409     /* buffers, we should respect that wish... */
1410     if (send_width == 0) {
1411       send_width = (lss_size/send_size) + 1;
1412       if (send_width == 1) send_width++;
1413     }
1414 
1415     if (send_ring == NULL) {
1416       /* only allocate the send ring once. this is a networking test, */
1417       /* not a memory allocation test. this way, we do not need a */
1418       /* deallocate_buffer_ring() routine, and I don't feel like */
1419       /* writing one anyway :) raj 11/94 */
1420       send_ring = allocate_buffer_ring(send_width,
1421 				       send_size,
1422 				       local_send_align,
1423 				       local_send_offset);
1424     }
1425 
1426     /* If the user has requested cpu utilization measurements, we must */
1427     /* calibrate the cpu(s). We will perform this task within the tests */
1428     /* themselves. If the user has specified the cpu rate, then */
1429     /* calibrate_local_cpu will return rather quickly as it will have */
1430     /* nothing to do. If local_cpu_rate is zero, then we will go through */
1431     /* all the "normal" calibration stuff and return the rate back. */
1432 
1433     if (local_cpu_usage) {
1434       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1435     }
1436 
1437     if (!no_control) {
1438       /* Tell the remote end to do a listen. The server alters the
1439 	 socket paramters on the other side at this point, hence the
1440 	 reason for all the values being passed in the setup
1441 	 message. If the user did not specify any of the parameters,
1442 	 they will be passed as 0, which will indicate to the remote
1443 	 that no changes beyond the system's default should be
1444 	 used. Alignment is the exception, it will default to 1, which
1445 	 will be no alignment alterations. */
1446 
1447       netperf_request.content.request_type =	DO_TCP_STREAM;
1448       tcp_stream_request->send_buf_size	=	rss_size_req;
1449       tcp_stream_request->recv_buf_size	=	rsr_size_req;
1450       tcp_stream_request->receive_size	=	recv_size;
1451       tcp_stream_request->no_delay	=	rem_nodelay;
1452       tcp_stream_request->recv_alignment	=	remote_recv_align;
1453       tcp_stream_request->recv_offset	=	remote_recv_offset;
1454       tcp_stream_request->measure_cpu	=	remote_cpu_usage;
1455       tcp_stream_request->cpu_rate	=	remote_cpu_rate;
1456       if (test_time) {
1457 	tcp_stream_request->test_length	=	test_time;
1458       }
1459       else {
1460 	tcp_stream_request->test_length	=	test_bytes;
1461       }
1462       tcp_stream_request->so_rcvavoid	=	rem_rcvavoid;
1463       tcp_stream_request->so_sndavoid	=	rem_sndavoid;
1464 #ifdef DIRTY
1465       tcp_stream_request->dirty_count     =       rem_dirty_count;
1466       tcp_stream_request->clean_count     =       rem_clean_count;
1467 #endif /* DIRTY */
1468       tcp_stream_request->port            =    atoi(remote_data_port);
1469       tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
1470       if (debug > 1) {
1471 	fprintf(where,
1472 		"netperf: send_tcp_stream: requesting TCP stream test\n");
1473       }
1474 
1475       send_request();
1476 
1477       /* The response from the remote will contain all of the relevant
1478          socket parameters for this test type. We will put them back
1479          into the variables here so they can be displayed if desired.
1480          The remote will have calibrated CPU if necessary, and will
1481          have done all the needed set-up we will have calibrated the
1482          cpu locally before sending the request, and will grab the
1483          counter value right after the connect returns. The remote
1484          will grab the counter right after the accept call. This saves
1485          the hassle of extra messages being sent for the TCP
1486          tests.  */
1487 
1488       recv_response();
1489 
1490       if (!netperf_response.content.serv_errno) {
1491 	if (debug)
1492 	  fprintf(where,"remote listen done.\n");
1493 	rsr_size	      =	tcp_stream_response->recv_buf_size;
1494 	rss_size	      =	tcp_stream_response->send_buf_size;
1495 	rem_nodelay     =	tcp_stream_response->no_delay;
1496 	remote_cpu_usage=	tcp_stream_response->measure_cpu;
1497 	remote_cpu_rate = tcp_stream_response->cpu_rate;
1498 
1499 	/* we have to make sure that the server port number is in
1500 	   network order */
1501 	set_port_number(remote_res,
1502 			(short)tcp_stream_response->data_port_number);
1503 
1504 	rem_rcvavoid	= tcp_stream_response->so_rcvavoid;
1505 	rem_sndavoid	= tcp_stream_response->so_sndavoid;
1506       }
1507       else {
1508 	Set_errno(netperf_response.content.serv_errno);
1509 	fprintf(where,
1510 		"netperf: remote error %d",
1511 		netperf_response.content.serv_errno);
1512 	perror("");
1513 	fflush(where);
1514 
1515 	exit(1);
1516       }
1517     }
1518 
1519 #ifdef WANT_DEMO
1520     DEMO_STREAM_SETUP(lss_size,rsr_size)
1521 #endif
1522 
1523     /*Connect up to the remote port on the data socket  */
1524     if (connect(send_socket,
1525 		remote_res->ai_addr,
1526 		remote_res->ai_addrlen) == INVALID_SOCKET){
1527       perror("netperf: send_tcp_stream: data socket connect failed");
1528       exit(1);
1529     }
1530 
1531     /* Data Socket set-up is finished. If there were problems, either */
1532     /* the connect would have failed, or the previous response would */
1533     /* have indicated a problem. I failed to see the value of the */
1534     /* extra  message after the accept on the remote. If it failed, */
1535     /* we'll see it here. If it didn't, we might as well start pumping */
1536     /* data. */
1537 
1538     /* Set-up the test end conditions. For a stream test, they can be */
1539     /* either time or byte-count based. */
1540 
1541     if (test_time) {
1542       /* The user wanted to end the test after a period of time. */
1543       times_up = 0;
1544       bytes_remaining = 0;
1545       /* in previous revisions, we had the same code repeated throught */
1546       /* all the test suites. this was unnecessary, and meant more */
1547       /* work for me when I wanted to switch to POSIX signals, so I */
1548       /* have abstracted this out into a routine in netlib.c. if you */
1549       /* are experiencing signal problems, you might want to look */
1550       /* there. raj 11/94 */
1551       start_timer(test_time);
1552     }
1553     else {
1554       /* The tester wanted to send a number of bytes. */
1555       bytes_remaining = test_bytes;
1556       times_up = 1;
1557     }
1558 
1559     /* The cpu_start routine will grab the current time and possibly */
1560     /* value of the idle counter for later use in measuring cpu */
1561     /* utilization and/or service demand and thruput. */
1562 
1563     cpu_start(local_cpu_usage);
1564 
1565     /* we only start the interval timer if we are using the
1566        timer-timed intervals rather than the sit and spin ones. raj
1567        2006-02-06 */
1568 #if defined(WANT_INTERVALS)
1569     INTERVALS_INIT();
1570 #endif /* WANT_INTERVALS */
1571 
1572     /* before we start, initialize a few variables */
1573 
1574 #ifdef WANT_DEMO
1575       if (demo_mode) {
1576 	HIST_timestamp(demo_one_ptr);
1577       }
1578 #endif
1579 
1580 
1581     /* We use an "OR" to control test execution. When the test is */
1582     /* controlled by time, the byte count check will always return false. */
1583     /* When the test is controlled by byte count, the time test will */
1584     /* always return false. When the test is finished, the whole */
1585     /* expression will go false and we will stop sending data. */
1586 
1587     while ((!times_up) || (bytes_remaining > 0)) {
1588 
1589 #ifdef DIRTY
1590       access_buffer(send_ring->buffer_ptr,
1591 		    send_size,
1592 		    loc_dirty_count,
1593 		    loc_clean_count);
1594 #endif /* DIRTY */
1595 
1596 #ifdef WANT_HISTOGRAM
1597       if (verbosity > 1) {
1598 	/* timestamp just before we go into send and then again just
1599 	 after we come out raj 8/94 */
1600 	/* but lets only do this if there is going to be a histogram
1601 	   displayed */
1602 	HIST_timestamp(&time_one);
1603       }
1604 #endif /* WANT_HISTOGRAM */
1605 
1606       if((len=send(send_socket,
1607 		   send_ring->buffer_ptr,
1608 		   send_size,
1609 		   0)) != send_size) {
1610       if ((len >=0) || SOCKET_EINTR(len)) {
1611 	    /* the test was interrupted, must be the end of test */
1612 	    break;
1613 	  }
1614 	perror("netperf: data send error");
1615 	printf("len was %d\n",len);
1616 	exit(1);
1617       }
1618 
1619       local_bytes_sent += send_size;
1620 
1621 #ifdef WANT_HISTOGRAM
1622       if (verbosity > 1) {
1623 	/* timestamp the exit from the send call and update the histogram */
1624 	HIST_timestamp(&time_two);
1625 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
1626       }
1627 #endif /* WANT_HISTOGRAM */
1628 
1629 #ifdef WANT_DEMO
1630       DEMO_STREAM_INTERVAL(send_size)
1631 #endif
1632 
1633 #if defined(WANT_INTERVALS)
1634       INTERVALS_WAIT();
1635 #endif /* WANT_INTERVALS */
1636 
1637       /* now we want to move our pointer to the next position in the */
1638       /* data buffer...we may also want to wrap back to the "beginning" */
1639       /* of the bufferspace, so we will mod the number of messages sent */
1640       /* by the send width, and use that to calculate the offset to add */
1641       /* to the base pointer. */
1642       nummessages++;
1643       send_ring = send_ring->next;
1644       if (bytes_remaining) {
1645 	bytes_remaining -= send_size;
1646       }
1647     }
1648 
1649     /* The test is over. Flush the buffers to the remote end. We do a */
1650     /* graceful release to insure that all data has been taken by the */
1651     /* remote. */
1652 
1653     /* but first, if the verbosity is greater than 1, find-out what */
1654     /* the TCP maximum segment_size was (if possible) */
1655     if (verbosity > 1) {
1656       tcp_mss = -1;
1657       get_tcp_info(send_socket,&tcp_mss);
1658     }
1659 
1660     if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
1661       perror("netperf: cannot shutdown tcp stream socket");
1662       exit(1);
1663     }
1664 
1665     /* hang a recv() off the socket to block until the remote has */
1666     /* brought all the data up into the application. it will do a */
1667     /* shutdown to cause a FIN to be sent our way. We will assume that */
1668     /* any exit from the recv() call is good... raj 4/93 */
1669 
1670     recv(send_socket, send_ring->buffer_ptr, send_size, 0);
1671 
1672     /* this call will always give us the elapsed time for the test, and */
1673     /* will also store-away the necessaries for cpu utilization */
1674 
1675     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
1676 						/* measured and how */
1677 						/* long did we really */
1678 						/* run? */
1679 
1680     /* we are finished with the socket, so close it to prevent hitting */
1681     /* the limit on maximum open files. */
1682 
1683     close(send_socket);
1684 
1685     if (!no_control) {
1686       /* Get the statistics from the remote end. The remote will have
1687 	 calculated service demand and all those interesting
1688 	 things. If it wasn't supposed to care, it will return obvious
1689 	 values. */
1690 
1691       recv_response();
1692       if (!netperf_response.content.serv_errno) {
1693 	if (debug)
1694 	  fprintf(where,"remote results obtained\n");
1695       }
1696       else {
1697 	Set_errno(netperf_response.content.serv_errno);
1698 	fprintf(where,
1699 		"netperf: remote error %d",
1700 		netperf_response.content.serv_errno);
1701 	perror("");
1702 	fflush(where);
1703 
1704 	exit(1);
1705       }
1706 
1707       /* We now calculate what our thruput was for the test. In the
1708 	 future, we may want to include a calculation of the thruput
1709 	 measured by the remote, but it should be the case that for a
1710 	 TCP stream test, that the two numbers should be *very*
1711 	 close... We calculate bytes_sent regardless of the way the
1712 	 test length was controlled.  If it was time, we needed to,
1713 	 and if it was by bytes, the user may have specified a number
1714 	 of bytes that wasn't a multiple of the send_size, so we
1715 	 really didn't send what he asked for ;-) */
1716 
1717       bytes_sent	= ntohd(tcp_stream_result->bytes_received);
1718     }
1719     else {
1720       bytes_sent = (double)local_bytes_sent;
1721     }
1722 
1723     thruput	= calc_thruput(bytes_sent);
1724 
1725     if (local_cpu_usage || remote_cpu_usage) {
1726       /* We must now do a little math for service demand and cpu */
1727       /* utilization for the system(s) */
1728       /* Of course, some of the information might be bogus because */
1729       /* there was no idle counter in the kernel(s). We need to make */
1730       /* a note of this for the user's benefit...*/
1731       if (local_cpu_usage) {
1732 
1733 	local_cpu_utilization	= calc_cpu_util(0.0);
1734 	local_service_demand	= calc_service_demand(bytes_sent,
1735 						      0.0,
1736 						      0.0,
1737 						      0);
1738       }
1739       else {
1740 	local_cpu_utilization	= (float) -1.0;
1741 	local_service_demand	= (float) -1.0;
1742       }
1743 
1744       if (remote_cpu_usage) {
1745 
1746 	remote_cpu_utilization	= tcp_stream_result->cpu_util;
1747 	remote_service_demand	= calc_service_demand(bytes_sent,
1748 						      0.0,
1749 						      remote_cpu_utilization,
1750 						      tcp_stream_result->num_cpus);
1751       }
1752       else {
1753 	remote_cpu_utilization = (float) -1.0;
1754 	remote_service_demand  = (float) -1.0;
1755       }
1756     }
1757     else {
1758       /* we were not measuring cpu, for the confidence stuff, we */
1759       /* should make it -1.0 */
1760       local_cpu_utilization	= (float) -1.0;
1761       local_service_demand	= (float) -1.0;
1762       remote_cpu_utilization = (float) -1.0;
1763       remote_service_demand  = (float) -1.0;
1764     }
1765 
1766     /* at this point, we want to calculate the confidence information. */
1767     /* if debugging is on, calculate_confidence will print-out the */
1768     /* parameters we pass it */
1769 
1770     calculate_confidence(confidence_iteration,
1771 			 elapsed_time,
1772 			 thruput,
1773 			 local_cpu_utilization,
1774 			 remote_cpu_utilization,
1775 			 local_service_demand,
1776 			 remote_service_demand);
1777 
1778 
1779     confidence_iteration++;
1780   }
1781 
1782   /* at this point, we have finished making all the runs that we */
1783   /* will be making. so, we should extract what the calcuated values */
1784   /* are for all the confidence stuff. we could make the values */
1785   /* global, but that seemed a little messy, and it did not seem worth */
1786   /* all the mucking with header files. so, we create a routine much */
1787   /* like calcualte_confidence, which just returns the mean values. */
1788   /* raj 11/94 */
1789 
1790   retrieve_confident_values(&elapsed_time,
1791 			    &thruput,
1792 			    &local_cpu_utilization,
1793 			    &remote_cpu_utilization,
1794 			    &local_service_demand,
1795 			    &remote_service_demand);
1796 
1797   /* We are now ready to print all the information. If the user */
1798   /* has specified zero-level verbosity, we will just print the */
1799   /* local service demand, or the remote service demand. If the */
1800   /* user has requested verbosity level 1, he will get the basic */
1801   /* "streamperf" numbers. If the user has specified a verbosity */
1802   /* of greater than 1, we will display a veritable plethora of */
1803   /* background information from outside of this block as it it */
1804   /* not cpu_measurement specific...  */
1805 
1806   if (confidence < 0) {
1807     /* we did not hit confidence, but were we asked to look for it? */
1808     if (iteration_max > 1) {
1809       display_confidence();
1810     }
1811   }
1812 
1813   if (local_cpu_usage || remote_cpu_usage) {
1814     local_cpu_method = format_cpu_method(cpu_method);
1815     remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
1816 
1817     switch (verbosity) {
1818     case 0:
1819       if (local_cpu_usage) {
1820 	fprintf(where,
1821 		cpu_fmt_0,
1822 		local_service_demand,
1823 		local_cpu_method,
1824 		((print_headers) ||
1825 		 (result_brand == NULL)) ? "" : result_brand);
1826       }
1827       else {
1828 	fprintf(where,
1829 		cpu_fmt_0,
1830 		remote_service_demand,
1831 		remote_cpu_method,
1832 		((print_headers) ||
1833 		 (result_brand == NULL)) ? "" : result_brand);
1834       }
1835       break;
1836     case 1:
1837     case 2:
1838       if (print_headers) {
1839 		fprintf(where,
1840 		cpu_title,
1841 		format_units(),
1842 		local_cpu_method,
1843 		remote_cpu_method);
1844       }
1845 
1846       fprintf(where,
1847 	      cpu_fmt_1,		/* the format string */
1848 	      rsr_size,		        /* remote recvbuf size */
1849 	      lss_size,		        /* local sendbuf size */
1850 	      send_size,		/* how large were the sends */
1851 	      elapsed_time,		/* how long was the test */
1852 	      thruput, 		        /* what was the xfer rate */
1853 	      local_cpu_utilization,	/* local cpu */
1854 	      remote_cpu_utilization,	/* remote cpu */
1855 	      local_service_demand,	/* local service demand */
1856 	      remote_service_demand,	/* remote service demand */
1857 	      ((print_headers) ||
1858 	       (result_brand == NULL)) ? "" : result_brand);
1859       break;
1860     }
1861   }
1862   else {
1863     /* The tester did not wish to measure service demand. */
1864 
1865     switch (verbosity) {
1866     case 0:
1867       fprintf(where,
1868 	      tput_fmt_0,
1869 	      thruput,
1870 	      ((print_headers) ||
1871 	       (result_brand == NULL)) ? "" : result_brand);
1872       break;
1873     case 1:
1874     case 2:
1875       if (print_headers) {
1876 		fprintf(where,tput_title,format_units());
1877       }
1878       fprintf(where,
1879 	      tput_fmt_1,		/* the format string */
1880 	      rsr_size, 		/* remote recvbuf size */
1881 	      lss_size, 		/* local sendbuf size */
1882 	      send_size,		/* how large were the sends */
1883 	      elapsed_time, 		/* how long did it take */
1884 	      thruput,                  /* how fast did it go */
1885 	      ((print_headers) ||
1886 	       (result_brand == NULL)) ? "" : result_brand);
1887       break;
1888     }
1889   }
1890 
1891   /* it would be a good thing to include information about some of the */
1892   /* other parameters that may have been set for this test, but at the */
1893   /* moment, I do not wish to figure-out all the  formatting, so I will */
1894   /* just put this comment here to help remind me that it is something */
1895   /* that should be done at a later time. */
1896 
1897   if (verbosity > 1) {
1898     /* The user wanted to know it all, so we will give it to him. */
1899     /* This information will include as much as we can find about */
1900     /* TCP statistics, the alignments of the sends and receives */
1901     /* and all that sort of rot... */
1902 
1903     /* this stuff needs to be worked-out in the presence of confidence */
1904     /* intervals and multiple iterations of the test... raj 11/94 */
1905 
1906     fprintf(where,
1907 	    ksink_fmt,
1908 	    "Bytes",
1909 	    "Bytes",
1910 	    "Bytes",
1911 	    local_send_align,
1912 	    remote_recv_align,
1913 	    local_send_offset,
1914 	    remote_recv_offset,
1915 	    bytes_sent,
1916 	    bytes_sent / (double)nummessages,
1917 	    nummessages,
1918 	    bytes_sent / (double)tcp_stream_result->recv_calls,
1919 	    tcp_stream_result->recv_calls);
1920     fprintf(where,
1921 	    ksink_fmt2,
1922 	    tcp_mss);
1923     fflush(where);
1924 #ifdef WANT_HISTOGRAM
1925     fprintf(where,"\n\nHistogram of time spent in send() call.\n");
1926     fflush(where);
1927     HIST_report(time_hist);
1928 #endif /* WANT_HISTOGRAM */
1929   }
1930 
1931 }
1932 
1933 
1934 
1935 /* This routine implements the netperf-side TCP unidirectional data
1936    transfer test (a.k.a. stream) for the sockets interface where the
1937    data flow is from the netserver to the netperf.  It receives its
1938    parameters via global variables from the shell and writes its
1939    output to the standard output. */
1940 
1941 
1942 void
send_tcp_maerts(char remote_host[])1943 send_tcp_maerts(char remote_host[])
1944 {
1945 
1946   char *tput_title = "\
1947 Recv   Send    Send                          \n\
1948 Socket Socket  Message  Elapsed              \n\
1949 Size   Size    Size     Time     Throughput  \n\
1950 bytes  bytes   bytes    secs.    %s/sec  \n\n";
1951 
1952   char *tput_fmt_0 =
1953     "%7.2f %s\n";
1954 
1955   char *tput_fmt_1 =
1956     "%6d %6d %6d    %-6.2f   %7.2f    %s \n";
1957 
1958   char *cpu_title = "\
1959 Recv   Send    Send                          Utilization       Service Demand\n\
1960 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
1961 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
1962 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
1963 
1964   char *cpu_fmt_0 =
1965     "%6.3f %c %s\n";
1966 
1967   char *cpu_fmt_1 =
1968     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %s\n";
1969 
1970   char *ksink_fmt = "\n\
1971 Alignment      Offset         %-8.8s %-8.8s    Recvs   %-8.8s Sends\n\
1972 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
1973 Recv   Send    Recv   Send             Recv (avg)          Send (avg)\n\
1974 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
1975 
1976   char *ksink_fmt2 = "\n\
1977 Maximum\n\
1978 Segment\n\
1979 Size (bytes)\n\
1980 %6d\n";
1981 
1982 
1983   float			elapsed_time;
1984 
1985   /* what we want is to have a buffer space that is at least one */
1986   /* recv-size greater than our recv window. this will insure that we */
1987   /* are never trying to re-use a buffer that may still be in the hands */
1988   /* of the transport. This buffer will be malloc'd after we have found */
1989   /* the size of the local senc socket buffer. We will want to deal */
1990   /* with alignment and offset concerns as well. */
1991 
1992   struct ring_elt *recv_ring;
1993 
1994   int len;
1995   unsigned int nummessages = 0;
1996   SOCKET recv_socket;
1997   int bytes_remaining;
1998   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
1999 
2000   /* with links like fddi, one can recv > 32 bits worth of bytes */
2001   /* during a test... ;-) at some point, this should probably become a */
2002   /* 64bit integral type, but those are not entirely common yet */
2003   double	bytes_sent = 0.0;
2004   unsigned long long local_bytes_recvd = 0;
2005 
2006   float	local_cpu_utilization;
2007   float	local_service_demand;
2008   float	remote_cpu_utilization;
2009   float	remote_service_demand;
2010 
2011   double	thruput;
2012 
2013   struct addrinfo *remote_res;
2014   struct addrinfo *local_res;
2015 
2016   struct	tcp_maerts_request_struct	*tcp_maerts_request;
2017   struct	tcp_maerts_response_struct	*tcp_maerts_response;
2018   struct	tcp_maerts_results_struct	*tcp_maerts_result;
2019 
2020   tcp_maerts_request  =
2021     (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
2022   tcp_maerts_response =
2023     (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
2024   tcp_maerts_result   =
2025     (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
2026 
2027 #ifdef WANT_HISTOGRAM
2028   if (verbosity > 1) {
2029     time_hist = HIST_new();
2030   }
2031 #endif /* WANT_HISTOGRAM */
2032   /* since we are now disconnected from the code that established the */
2033   /* control socket, and since we want to be able to use different */
2034   /* protocols and such, we are passed the name of the remote host and */
2035   /* must turn that into the test specific addressing information. */
2036 
2037   complete_addrinfos(&remote_res,
2038 		     &local_res,
2039 		     remote_host,
2040 		     SOCK_STREAM,
2041 		     IPPROTO_TCP,
2042 		     0);
2043 
2044   if ( print_headers ) {
2045     print_top_test_header("TCP MAERTS TEST",local_res,remote_res);
2046   }
2047 
2048   recv_ring = NULL;
2049   confidence_iteration = 1;
2050   init_stat();
2051 
2052   /* we have a great-big while loop which controls the number of times */
2053   /* we run a particular test. this is for the calculation of a */
2054   /* confidence interval (I really should have stayed awake during */
2055   /* probstats :). If the user did not request confidence measurement */
2056   /* (no confidence is the default) then we will only go though the */
2057   /* loop once. the confidence stuff originates from the folks at IBM */
2058 
2059   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2060 	 (confidence_iteration <= iteration_min)) {
2061 
2062     /* initialize a few counters. we have to remember that we might be */
2063     /* going through the loop more than once. */
2064 
2065     nummessages    =	0;
2066     bytes_sent     =	0.0;
2067     times_up       = 	0;
2068 
2069     /*set up the data socket                        */
2070     recv_socket = create_data_socket(local_res);
2071 
2072     if (recv_socket == INVALID_SOCKET){
2073       perror("netperf: send_tcp_maerts: tcp stream data socket");
2074       exit(1);
2075     }
2076 
2077     if (debug) {
2078       fprintf(where,"send_tcp_maerts: recv_socket obtained...\n");
2079     }
2080 
2081     /* at this point, we have either retrieved the socket buffer sizes, */
2082     /* or have tried to set them, so now, we may want to set the recv */
2083     /* size based on that (because the user either did not use a -m */
2084     /* option, or used one with an argument of 0). If the socket buffer */
2085     /* size is not available, we will set the recv size to 4KB - no */
2086     /* particular reason, just arbitrary... */
2087     if (recv_size == 0) {
2088       if (lsr_size > 0) {
2089 	recv_size = lsr_size;
2090       }
2091       else {
2092 	recv_size = 4096;
2093       }
2094     }
2095 
2096     /* set-up the data buffer ring with the requested alignment and offset. */
2097     /* note also that we have allocated a quantity */
2098     /* of memory that is at least one recv-size greater than our socket */
2099     /* buffer size. We want to be sure that there are at least two */
2100     /* buffers allocated - this can be a bit of a problem when the */
2101     /* recv_size is bigger than the socket size, so we must check... the */
2102     /* user may have wanted to explicitly set the "width" of our recv */
2103     /* buffers, we should respect that wish... */
2104     if (recv_width == 0) {
2105       recv_width = (lsr_size/recv_size) + 1;
2106       if (recv_width == 1) recv_width++;
2107     }
2108 
2109     if (recv_ring == NULL) {
2110       /* only allocate the recv ring once. this is a networking test, */
2111       /* not a memory allocation test. this way, we do not need a */
2112       /* deallocate_buffer_ring() routine, and I don't feel like */
2113       /* writing one anyway :) raj 11/94 */
2114       recv_ring = allocate_buffer_ring(recv_width,
2115 				       recv_size,
2116 				       local_recv_align,
2117 				       local_recv_offset);
2118     }
2119 
2120     /* If the user has requested cpu utilization measurements, we must */
2121     /* calibrate the cpu(s). We will perform this task within the tests */
2122     /* themselves. If the user has specified the cpu rate, then */
2123     /* calibrate_local_cpu will return rather quickly as it will have */
2124     /* nothing to do. If local_cpu_rate is zero, then we will go through */
2125     /* all the "normal" calibration stuff and return the rate back. */
2126 
2127     if (local_cpu_usage) {
2128       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2129     }
2130 
2131     if (!no_control) {
2132       /* Tell the remote end to do a listen. The server alters the
2133 	 socket paramters on the other side at this point, hence the
2134 	 reason for all the values being passed in the setup
2135 	 message. If the user did not specify any of the parameters,
2136 	 they will be passed as 0, which will indicate to the remote
2137 	 that no changes beyond the system's default should be
2138 	 used. Alignment is the exception, it will default to 1, which
2139 	 will be no alignment alterations. */
2140 
2141       netperf_request.content.request_type	=	DO_TCP_MAERTS;
2142       tcp_maerts_request->send_buf_size	=	rss_size_req;
2143       tcp_maerts_request->recv_buf_size	=	rsr_size_req;
2144       tcp_maerts_request->send_size	=	send_size;
2145       tcp_maerts_request->no_delay	=	rem_nodelay;
2146       tcp_maerts_request->send_alignment	=	remote_send_align;
2147       tcp_maerts_request->send_offset	=	remote_send_offset;
2148       tcp_maerts_request->measure_cpu	=	remote_cpu_usage;
2149       tcp_maerts_request->cpu_rate	=	remote_cpu_rate;
2150       if (test_time) {
2151 	tcp_maerts_request->test_length	=	test_time;
2152       }
2153       else {
2154 	tcp_maerts_request->test_length	=	test_bytes;
2155       }
2156       tcp_maerts_request->so_rcvavoid	=	rem_rcvavoid;
2157       tcp_maerts_request->so_sndavoid	=	rem_sndavoid;
2158 #ifdef DIRTY
2159       tcp_maerts_request->dirty_count       =       rem_dirty_count;
2160       tcp_maerts_request->clean_count       =       rem_clean_count;
2161 #endif /* DIRTY */
2162       tcp_maerts_request->port            = atoi(remote_data_port);
2163       tcp_maerts_request->ipfamily        = af_to_nf(remote_res->ai_family);
2164       if (debug > 1) {
2165 	fprintf(where,
2166 		"netperf: send_tcp_maerts: requesting TCP maerts test\n");
2167       }
2168 
2169       send_request();
2170 
2171       /* The response from the remote will contain all of the relevant
2172 	 socket parameters for this test type. We will put them back
2173 	 into the variables here so they can be displayed if desired.
2174 	 The remote will have calibrated CPU if necessary, and will
2175 	 have done all the needed set-up we will have calibrated the
2176 	 cpu locally before sending the request, and will grab the
2177 	 counter value right after the connect returns. The remote
2178 	 will grab the counter right after the accept call. This saves
2179 	 the hassle of extra messages being sent for the TCP
2180 	 tests.  */
2181 
2182       recv_response();
2183 
2184       if (!netperf_response.content.serv_errno) {
2185 	if (debug)
2186 	  fprintf(where,"remote listen done.\n");
2187 	rsr_size	=	tcp_maerts_response->recv_buf_size;
2188 	rss_size	=	tcp_maerts_response->send_buf_size;
2189 	rem_nodelay     =	tcp_maerts_response->no_delay;
2190 	remote_cpu_usage=	tcp_maerts_response->measure_cpu;
2191 	remote_cpu_rate = tcp_maerts_response->cpu_rate;
2192 	send_size       = tcp_maerts_response->send_size;
2193 
2194 	/* we have to make sure that the server port number is in
2195 	 network order */
2196       set_port_number(remote_res,
2197 		      (short)tcp_maerts_response->data_port_number);
2198       rem_rcvavoid	= tcp_maerts_response->so_rcvavoid;
2199       rem_sndavoid	= tcp_maerts_response->so_sndavoid;
2200       }
2201       else {
2202 	Set_errno(netperf_response.content.serv_errno);
2203 	fprintf(where,
2204 		"netperf: remote error %d",
2205 		netperf_response.content.serv_errno);
2206 	perror("");
2207 	fflush(where);
2208 
2209 	exit(1);
2210       }
2211     }
2212 
2213 #ifdef WANT_DEMO
2214     DEMO_STREAM_SETUP(lsr_size,rss_size)
2215 #endif
2216 
2217     /*Connect up to the remote port on the data socket  */
2218     if (connect(recv_socket,
2219 		remote_res->ai_addr,
2220 		remote_res->ai_addrlen) == INVALID_SOCKET){
2221       perror("netperf: send_tcp_maerts: data socket connect failed");
2222       exit(1);
2223     }
2224 
2225     /* Data Socket set-up is finished. If there were problems, either */
2226     /* the connect would have failed, or the previous response would */
2227     /* have indicated a problem. I failed to see the value of the */
2228     /* extra  message after the accept on the remote. If it failed, */
2229     /* we'll see it here. If it didn't, we might as well start pumping */
2230     /* data. */
2231 
2232     /* Set-up the test end conditions. For a maerts test, they can be */
2233     /* either time or byte-count based. */
2234 
2235     if (test_time) {
2236       /* The user wanted to end the test after a period of time. */
2237       times_up = 0;
2238       bytes_remaining = 0;
2239       /* in previous revisions, we had the same code repeated throught */
2240       /* all the test suites. this was unnecessary, and meant more */
2241       /* work for me when I wanted to switch to POSIX signals, so I */
2242       /* have abstracted this out into a routine in netlib.c. if you */
2243       /* are experiencing signal problems, you might want to look */
2244       /* there. raj 11/94 */
2245       if (!no_control) {
2246 	/* this is a netperf to netserver test, netserver will close
2247 	   to tell us the test is over, so use PAD_TIME to avoid
2248 	   causing the netserver fits. */
2249 	start_timer(test_time + PAD_TIME);
2250       }
2251       else {
2252 	/* this is a netperf to data source test, no PAD_TIME */
2253 	start_timer(test_time);
2254       }
2255     }
2256     else {
2257       /* The tester wanted to recv a number of bytes. we don't do that
2258 	 in a TCP_MAERTS test. sorry. raj 2002-06-21 */
2259       printf("netperf: send_tcp_maerts: test must be timed\n");
2260       exit(1);
2261     }
2262 
2263     /* The cpu_start routine will grab the current time and possibly */
2264     /* value of the idle counter for later use in measuring cpu */
2265     /* utilization and/or service demand and thruput. */
2266 
2267     cpu_start(local_cpu_usage);
2268 
2269 #ifdef WANT_INTERVALS
2270     INTERVALS_INIT();
2271 #endif /* WANT_INTERVALS */
2272 
2273     /* before we start, initialize a few variables */
2274 
2275 #ifdef WANT_DEMO
2276     if (demo_mode) {
2277       HIST_timestamp(demo_one_ptr);
2278     }
2279 #endif
2280 
2281     /* the test will continue until we either get a zero-byte recv()
2282        on the socket or our failsafe timer expires. most of the time
2283        we trust that we get a zero-byte recieve from the socket. raj
2284        2002-06-21 */
2285 
2286 #ifdef WANT_HISTOGRAM
2287     if (verbosity > 1) {
2288       /* timestamp just before we go into recv and then again just
2289 	 after we come out raj 8/94 */
2290       /* but only if we are actually going to display a histogram. raj
2291 	 2006-02-07 */
2292       HIST_timestamp(&time_one);
2293     }
2294 #endif /* WANT_HISTOGRAM */
2295 
2296     while ((!times_up) && (len=recv(recv_socket,
2297 				    recv_ring->buffer_ptr,
2298 				    recv_size,
2299 				    0)) > 0 ) {
2300 
2301 #ifdef WANT_HISTOGRAM
2302       if (verbosity > 1) {
2303 	/* timestamp the exit from the recv call and update the histogram */
2304 	HIST_timestamp(&time_two);
2305 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
2306       }
2307 #endif /* WANT_HISTOGRAM */
2308 
2309 #ifdef DIRTY
2310       access_buffer(recv_ring->buffer_ptr,
2311 		    recv_size,
2312 		    loc_dirty_count,
2313 		    loc_clean_count);
2314 #endif /* DIRTY */
2315 
2316 #ifdef WANT_DEMO
2317       DEMO_STREAM_INTERVAL(len);
2318 #endif
2319 
2320 #ifdef WANT_INTERVALS
2321       INTERVALS_WAIT();
2322 #endif /* WANT_INTERVALS */
2323 
2324       /* now we want to move our pointer to the next position in the */
2325       /* data buffer...we may also want to wrap back to the "beginning" */
2326       /* of the bufferspace, so we will mod the number of messages sent */
2327       /* by the recv width, and use that to calculate the offset to add */
2328       /* to the base pointer. */
2329       nummessages++;
2330       recv_ring = recv_ring->next;
2331       if (bytes_remaining) {
2332 	bytes_remaining -= len;
2333       }
2334 
2335       local_bytes_recvd += len;
2336 
2337 #ifdef WANT_HISTOGRAM
2338       if (verbosity > 1) {
2339 	/* make sure we timestamp just before we go into recv  */
2340 	/* raj 2004-06-15 */
2341 	HIST_timestamp(&time_one);
2342       }
2343 #endif /* WANT_HISTOGRAM */
2344 
2345     }
2346 
2347     /* an EINTR is to be expected when this is a no_control test */
2348     if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
2349       perror("send_tcp_maerts: data recv error");
2350       printf("len was %d\n",len);
2351       exit(1);
2352     }
2353 
2354     /* if we get here, it must mean we had a recv return of 0 before
2355        the watchdog timer expired, or the watchdog timer expired and
2356        this was a no_control test */
2357 
2358     /* The test is over. Flush the buffers to the remote end. We do a
2359        graceful release to tell the  remote we have all the data. */
2360 
2361     /* but first, if the verbosity is greater than 1, find-out what */
2362     /* the TCP maximum segment_size was (if possible) */
2363     if (verbosity > 1) {
2364       tcp_mss = -1;
2365       get_tcp_info(recv_socket,&tcp_mss);
2366     }
2367 
2368     if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
2369       perror("netperf: cannot shutdown tcp maerts socket");
2370       exit(1);
2371     }
2372 
2373     stop_timer();
2374 
2375     /* this call will always give us the local elapsed time for the
2376        test, and will also store-away the necessaries for cpu
2377        utilization */
2378 
2379     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
2380 						/* measured and how */
2381 						/* long did we really */
2382 						/* run? */
2383 
2384     /* we are finished with the socket, so close it to prevent hitting */
2385     /* the limit on maximum open files. */
2386 
2387     close(recv_socket);
2388 
2389     if (!no_control) {
2390       /* Get the statistics from the remote end. The remote will have
2391          calculated service demand and all those interesting
2392          things. If it wasn't supposed to care, it will return obvious
2393          values. */
2394 
2395       recv_response();
2396       if (!netperf_response.content.serv_errno) {
2397 	if (debug)
2398 	  fprintf(where,"remote results obtained\n");
2399       }
2400       else {
2401 	Set_errno(netperf_response.content.serv_errno);
2402 	fprintf(where,
2403 		"netperf: remote error %d",
2404 		netperf_response.content.serv_errno);
2405 	perror("");
2406 	fflush(where);
2407 
2408 	exit(1);
2409       }
2410 
2411       /* We now calculate what our thruput was for the test. In the
2412 	 future, we may want to include a calculation of the thruput
2413 	 measured by the remote, but it should be the case that for a
2414 	 TCP maerts test, that the two numbers should be *very*
2415 	 close... We calculate bytes_sent regardless of the way the
2416 	 test length was controlled.  If it was time, we needed to,
2417 	 and if it was by bytes, the user may have specified a number
2418 	 of bytes that wasn't a multiple of the recv_size, so we
2419 	 really didn't recv what he asked for ;-) */
2420 
2421       bytes_sent	= ntohd(tcp_maerts_result->bytes_sent);
2422     }
2423     else {
2424       bytes_sent = (double)local_bytes_recvd;
2425     }
2426 
2427 
2428     thruput	= calc_thruput(bytes_sent);
2429 
2430     if (local_cpu_usage || remote_cpu_usage) {
2431       /* We must now do a little math for service demand and cpu */
2432       /* utilization for the system(s) */
2433       /* Of course, some of the information might be bogus because */
2434       /* there was no idle counter in the kernel(s). We need to make */
2435       /* a note of this for the user's benefit...*/
2436       if (local_cpu_usage) {
2437 
2438 	local_cpu_utilization	= calc_cpu_util(0.0);
2439 	local_service_demand	= calc_service_demand(bytes_sent,
2440 						      0.0,
2441 						      0.0,
2442 						      0);
2443       }
2444       else {
2445 	local_cpu_utilization	= (float) -1.0;
2446 	local_service_demand	= (float) -1.0;
2447       }
2448 
2449       if (remote_cpu_usage) {
2450 
2451 	remote_cpu_utilization	= tcp_maerts_result->cpu_util;
2452 	remote_service_demand	= calc_service_demand(bytes_sent,
2453 						      0.0,
2454 						      remote_cpu_utilization,
2455 						      tcp_maerts_result->num_cpus);
2456       }
2457       else {
2458 	remote_cpu_utilization = (float) -1.0;
2459 	remote_service_demand  = (float) -1.0;
2460       }
2461     }
2462     else {
2463       /* we were not measuring cpu, for the confidence stuff, we */
2464       /* should make it -1.0 */
2465       local_cpu_utilization	= (float) -1.0;
2466       local_service_demand	= (float) -1.0;
2467       remote_cpu_utilization = (float) -1.0;
2468       remote_service_demand  = (float) -1.0;
2469     }
2470 
2471     /* at this point, we want to calculate the confidence information. */
2472     /* if debugging is on, calculate_confidence will print-out the */
2473     /* parameters we pass it */
2474 
2475     calculate_confidence(confidence_iteration,
2476 			 elapsed_time,
2477 			 thruput,
2478 			 local_cpu_utilization,
2479 			 remote_cpu_utilization,
2480 			 local_service_demand,
2481 			 remote_service_demand);
2482 
2483 
2484     confidence_iteration++;
2485   }
2486 
2487   /* at this point, we have finished making all the runs that we */
2488   /* will be making. so, we should extract what the calcuated values */
2489   /* are for all the confidence stuff. we could make the values */
2490   /* global, but that seemed a little messy, and it did not seem worth */
2491   /* all the mucking with header files. so, we create a routine much */
2492   /* like calcualte_confidence, which just returns the mean values. */
2493   /* raj 11/94 */
2494 
2495   retrieve_confident_values(&elapsed_time,
2496 			    &thruput,
2497 			    &local_cpu_utilization,
2498 			    &remote_cpu_utilization,
2499 			    &local_service_demand,
2500 			    &remote_service_demand);
2501 
2502   /* We are now ready to print all the information. If the user */
2503   /* has specified zero-level verbosity, we will just print the */
2504   /* local service demand, or the remote service demand. If the */
2505   /* user has requested verbosity level 1, he will get the basic */
2506   /* "streamperf" numbers. If the user has specified a verbosity */
2507   /* of greater than 1, we will display a veritable plethora of */
2508   /* background information from outside of this block as it it */
2509   /* not cpu_measurement specific...  */
2510 
2511   if (confidence < 0) {
2512     /* we did not hit confidence, but were we asked to look for it? */
2513     if (iteration_max > 1) {
2514       display_confidence();
2515     }
2516   }
2517 
2518   if (local_cpu_usage || remote_cpu_usage) {
2519     local_cpu_method = format_cpu_method(cpu_method);
2520     remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method);
2521 
2522     switch (verbosity) {
2523     case 0:
2524       if (local_cpu_usage) {
2525 	fprintf(where,
2526 		cpu_fmt_0,
2527 		local_service_demand,
2528 		local_cpu_method,
2529 		((print_headers) ||
2530 		 (result_brand == NULL)) ? "" : result_brand);
2531       }
2532       else {
2533 	fprintf(where,
2534 		cpu_fmt_0,
2535 		remote_service_demand,
2536 		remote_cpu_method,
2537 		((print_headers) ||
2538 		 (result_brand == NULL)) ? "" : result_brand);
2539       }
2540       break;
2541     case 1:
2542     case 2:
2543       if (print_headers) {
2544 	fprintf(where,
2545 		cpu_title,
2546 		format_units(),
2547 		local_cpu_method,
2548 		remote_cpu_method);
2549       }
2550 
2551       fprintf(where,
2552 	      cpu_fmt_1,		/* the format string */
2553 	      rsr_size,		        /* remote recvbuf size */
2554 	      lss_size,		        /* local sendbuf size */
2555 	      send_size,		/* how large were the recvs */
2556 	      elapsed_time,		/* how long was the test */
2557 	      thruput, 		        /* what was the xfer rate */
2558 	      local_cpu_utilization,	/* local cpu */
2559 	      remote_cpu_utilization,	/* remote cpu */
2560 	      local_service_demand,	/* local service demand */
2561 	      remote_service_demand,	/* remote service demand */
2562 	      ((print_headers) ||
2563 	       (result_brand == NULL)) ? "" : result_brand);
2564       break;
2565     }
2566   }
2567   else {
2568     /* The tester did not wish to measure service demand. */
2569 
2570     switch (verbosity) {
2571     case 0:
2572       fprintf(where,
2573 	      tput_fmt_0,
2574 	      thruput,
2575 	      ((print_headers) ||
2576 	       (result_brand == NULL)) ? "" : result_brand);
2577       break;
2578     case 1:
2579     case 2:
2580       if (print_headers) {
2581 	fprintf(where,tput_title,format_units());
2582       }
2583       fprintf(where,
2584 	      tput_fmt_1,		/* the format string */
2585 	      lsr_size, 		/* local recvbuf size */
2586 	      rss_size, 		/* remot sendbuf size */
2587 	      send_size,		/* how large were the recvs */
2588 	      elapsed_time, 		/* how long did it take */
2589 	      thruput,                  /* how fast did it go */
2590 	      ((print_headers) ||
2591 	       (result_brand == NULL)) ? "" : result_brand);
2592       break;
2593     }
2594   }
2595 
2596   /* it would be a good thing to include information about some of the */
2597   /* other parameters that may have been set for this test, but at the */
2598   /* moment, I do not wish to figure-out all the  formatting, so I will */
2599   /* just put this comment here to help remind me that it is something */
2600   /* that should be done at a later time. */
2601 
2602   if (verbosity > 1) {
2603     /* The user wanted to know it all, so we will give it to him. */
2604     /* This information will include as much as we can find about */
2605     /* TCP statistics, the alignments of the sends and receives */
2606     /* and all that sort of rot... */
2607 
2608     /* this stuff needs to be worked-out in the presence of confidence */
2609     /* intervals and multiple iterations of the test... raj 11/94 */
2610 
2611     fprintf(where,
2612 	    ksink_fmt,
2613 	    "Bytes",
2614 	    "Bytes",
2615 	    "Bytes",
2616 	    local_recv_align,
2617 	    remote_recv_align,
2618 	    local_recv_offset,
2619 	    remote_recv_offset,
2620 	    bytes_sent,
2621 	    bytes_sent / (double)nummessages,
2622 	    nummessages,
2623 	    bytes_sent / (double)tcp_maerts_result->send_calls,
2624 	    tcp_maerts_result->send_calls);
2625     fprintf(where,
2626 	    ksink_fmt2,
2627 	    tcp_mss);
2628     fflush(where);
2629 #ifdef WANT_HISTOGRAM
2630     fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
2631     fflush(where);
2632     HIST_report(time_hist);
2633 #endif /* WANT_HISTOGRAM */
2634   }
2635 
2636 }
2637 
2638 
2639 
2640 #ifdef HAVE_ICSC_EXS
2641 
2642 #include <sys/exs.h>
2643 
2644 
2645 /* This routine implements the TCP unidirectional data transfer test */
2646 /* (a.k.a. stream) for the sockets interface. It receives its */
2647 /* parameters via global variables from the shell and writes its */
2648 /* output to the standard output. */
2649 
2650 void
send_exs_tcp_stream(char remote_host[])2651 send_exs_tcp_stream(char remote_host[])
2652 {
2653 
2654     char *tput_title = "\
2655 Recv   Send    Send                          \n\
2656 Socket Socket  Message  Elapsed              \n\
2657 Size   Size    Size     Time     Throughput  \n\
2658 bytes  bytes   bytes    secs.    %s/sec  \n\n";
2659 
2660     char *tput_fmt_0 =
2661         "%7.2f\n";
2662 
2663     char *tput_fmt_1 =
2664         "%6d %6d %6d    %-6.2f   %7.2f   \n";
2665 
2666     char *cpu_title = "\
2667 Recv   Send    Send                          Utilization       Service Demand\n\
2668 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
2669 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
2670 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
2671 
2672     char *cpu_fmt_0 =
2673         "%6.3f %c\n";
2674 
2675     char *cpu_fmt_1 =
2676         "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
2677 
2678     char *ksink_fmt = "\n\
2679 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
2680 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
2681 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
2682 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
2683 
2684     char *ksink_fmt2 = "\n\
2685 Maximum\n\
2686 Segment\n\
2687 Size (bytes)\n\
2688 %6d\n";
2689 
2690 
2691     float         elapsed_time;
2692 
2693     /* what we want is to have a buffer space that is at least one */
2694     /* send-size greater than our send window. this will insure that we */
2695     /* are never trying to re-use a buffer that may still be in the hands */
2696     /* of the transport. This buffer will be malloc'd after we have found */
2697     /* the size of the local senc socket buffer. We will want to deal */
2698     /* with alignment and offset concerns as well. */
2699 
2700     struct ring_elt *send_ring;
2701 
2702     int len;
2703     unsigned int nummessages = 0;
2704     SOCKET send_socket;
2705     int bytes_remaining;
2706     int tcp_mss = -1;  /* possibly uninitialized on printf far below */
2707 
2708     exs_mhandle_t exs_mhandle;
2709     exs_qhandle_t exs_qhandle;
2710 #define NETPERF_EXS_PENDING  16
2711     int exs_aio_pending;
2712     int exs_aio_eagain;
2713     int exs_aio_dequeued;
2714     int exs_aio_dequeuecnt;
2715     int exs_evtcnt;
2716 #define NETPERF_EXS_QSIZE    128
2717     exs_event_t exs_evtvec[NETPERF_EXS_QSIZE];
2718 
2719     /* with links like fddi, one can send > 32 bits worth of bytes */
2720     /* during a test... ;-) at some point, this should probably become a */
2721     /* 64bit integral type, but those are not entirely common yet */
2722 
2723     double   bytes_sent = 0.0;
2724 
2725     float   local_cpu_utilization;
2726     float   local_service_demand;
2727     float   remote_cpu_utilization;
2728     float   remote_service_demand;
2729 
2730     double   thruput;
2731 
2732     struct addrinfo *remote_res;
2733     struct addrinfo *local_res;
2734 
2735     struct   tcp_stream_request_struct   *tcp_stream_request;
2736     struct   tcp_stream_response_struct   *tcp_stream_response;
2737     struct   tcp_stream_results_struct   *tcp_stream_result;
2738 
2739     tcp_stream_request  =
2740         (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
2741     tcp_stream_response =
2742         (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
2743     tcp_stream_result   =
2744         (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
2745 
2746 #if 0 /* def WANT_HISTOGRAM */
2747     time_hist = HIST_new();
2748 #endif /* WANT_HISTOGRAM */
2749     /* since we are now disconnected from the code that established the */
2750     /* control socket, and since we want to be able to use different */
2751     /* protocols and such, we are passed the name of the remote host and */
2752     /* must turn that into the test specific addressing information. */
2753 
2754     /* complete_addrinfos will either succede or exit the process */
2755     complete_addrinfos(&remote_res,
2756                        &local_res,
2757                        remote_host,
2758                        SOCK_STREAM,
2759                        IPPROTO_TCP,
2760                        0);
2761 
2762     if ( print_headers ) {
2763         print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res);
2764     }
2765 
2766     send_ring = NULL;
2767     confidence_iteration = 1;
2768     init_stat();
2769 
2770     /* initialize EXS API and create event queue */
2771     if (exs_init (EXS_VERSION) == -1) {
2772         perror ("netperf: send_exs_tcp_stream: exs_init failed");
2773         exit (1);
2774     }
2775 
2776     if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) {
2777         perror ("netperf: send_exs_tcp_stream: exs_qcreate failed");
2778         exit (1);
2779     }
2780     if (debug) {
2781         fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle);
2782     }
2783 
2784     /* we have a great-big while loop which controls the number of times */
2785     /* we run a particular test. this is for the calculation of a */
2786     /* confidence interval (I really should have stayed awake during */
2787     /* probstats :). If the user did not request confidence measurement */
2788     /* (no confidence is the default) then we will only go though the */
2789     /* loop once. the confidence stuff originates from the folks at IBM */
2790 
2791     while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2792            (confidence_iteration <= iteration_min)) {
2793 
2794         /* initialize a few counters. we have to remember that we might be */
2795         /* going through the loop more than once. */
2796 
2797         nummessages    =   0;
2798         bytes_sent     =   0.0;
2799         times_up       =    0;
2800 
2801         /*set up the data socket                        */
2802         send_socket = create_data_socket(local_res);
2803 
2804         if (send_socket == INVALID_SOCKET){
2805             perror("netperf: send_tcp_stream: tcp stream data socket");
2806             exit(1);
2807         }
2808 
2809         if (debug) {
2810             fprintf(where,"send_tcp_stream: send_socket obtained...\n");
2811         }
2812 
2813         /* at this point, we have either retrieved the socket buffer sizes, */
2814         /* or have tried to set them, so now, we may want to set the send */
2815         /* size based on that (because the user either did not use a -m */
2816         /* option, or used one with an argument of 0). If the socket buffer */
2817         /* size is not available, we will set the send size to 4KB - no */
2818         /* particular reason, just arbitrary... */
2819         if (send_size == 0) {
2820             if (lss_size > 0) {
2821                 send_size = lss_size;
2822             }
2823             else {
2824                 send_size = 4096;
2825             }
2826         }
2827 
2828         /* set-up the data buffer ring with the requested alignment and offset. */
2829         /* note also that we have allocated a quantity */
2830         /* of memory that is at least one send-size greater than our socket */
2831         /* buffer size. We want to be sure that there are at least two */
2832         /* buffers allocated - this can be a bit of a problem when the */
2833         /* send_size is bigger than the socket size, so we must check... the */
2834         /* user may have wanted to explicitly set the "width" of our send */
2835         /* buffers, we should respect that wish... */
2836         if (send_width == 0) {
2837             send_width = (lss_size/send_size) + 1;
2838             if (send_width == 1) send_width++;
2839         }
2840 
2841         if (send_ring == NULL) {
2842             /* only allocate the send ring once. this is a networking test, */
2843             /* not a memory allocation test. this way, we do not need a */
2844             /* deallocate_buffer_ring() routine, and I don't feel like */
2845             /* writing one anyway :) raj 11/94 */
2846             send_ring = allocate_exs_buffer_ring(send_width,
2847                                                  send_size,
2848                                                  local_send_align,
2849                                                  local_send_offset,
2850                                                  &exs_mhandle);
2851         }
2852 
2853         /* If the user has requested cpu utilization measurements, we must */
2854         /* calibrate the cpu(s). We will perform this task within the tests */
2855         /* themselves. If the user has specified the cpu rate, then */
2856         /* calibrate_local_cpu will return rather quickly as it will have */
2857         /* nothing to do. If local_cpu_rate is zero, then we will go through */
2858         /* all the "normal" calibration stuff and return the rate back. */
2859 
2860         if (local_cpu_usage) {
2861             local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2862         }
2863 
2864         /* Tell the remote end to do a listen. The server alters the socket */
2865         /* paramters on the other side at this point, hence the reason for */
2866         /* all the values being passed in the setup message. If the user did */
2867         /* not specify any of the parameters, they will be passed as 0, which */
2868         /* will indicate to the remote that no changes beyond the system's */
2869         /* default should be used. Alignment is the exception, it will */
2870         /* default to 1, which will be no alignment alterations. */
2871 
2872         netperf_request.content.request_type =   DO_TCP_STREAM;
2873         tcp_stream_request->send_buf_size   =   rss_size_req;
2874         tcp_stream_request->recv_buf_size   =   rsr_size_req;
2875         tcp_stream_request->receive_size   =   recv_size;
2876         tcp_stream_request->no_delay   =   rem_nodelay;
2877         tcp_stream_request->recv_alignment   =   remote_recv_align;
2878         tcp_stream_request->recv_offset   =   remote_recv_offset;
2879         tcp_stream_request->measure_cpu   =   remote_cpu_usage;
2880         tcp_stream_request->cpu_rate   =   remote_cpu_rate;
2881         if (test_time) {
2882             tcp_stream_request->test_length   =   test_time;
2883         }
2884         else {
2885             tcp_stream_request->test_length   =   test_bytes;
2886         }
2887         tcp_stream_request->so_rcvavoid   =   rem_rcvavoid;
2888         tcp_stream_request->so_sndavoid   =   rem_sndavoid;
2889 #ifdef DIRTY
2890         tcp_stream_request->dirty_count     =       rem_dirty_count;
2891         tcp_stream_request->clean_count     =       rem_clean_count;
2892 #endif /* DIRTY */
2893         tcp_stream_request->port            =    atoi(remote_data_port);
2894         tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
2895         if (debug > 1) {
2896             fprintf(where,
2897                     "netperf: send_tcp_stream: requesting TCP stream test\n");
2898         }
2899 
2900         send_request();
2901 
2902         /* The response from the remote will contain all of the relevant    */
2903         /* socket parameters for this test type. We will put them back into */
2904         /* the variables here so they can be displayed if desired.  The   */
2905         /* remote will have calibrated CPU if necessary, and will have done   */
2906         /* all the needed set-up we will have calibrated the cpu locally   */
2907         /* before sending the request, and will grab the counter value right*/
2908         /* after the connect returns. The remote will grab the counter right*/
2909         /* after the accept call. This saves the hassle of extra messages   */
2910         /* being sent for the TCP tests.               */
2911 
2912         recv_response();
2913 
2914         if (!netperf_response.content.serv_errno) {
2915             if (debug)
2916                 fprintf(where,"remote listen done.\n");
2917             rsr_size         =   tcp_stream_response->recv_buf_size;
2918             rss_size         =   tcp_stream_response->send_buf_size;
2919             rem_nodelay     =   tcp_stream_response->no_delay;
2920             remote_cpu_usage=   tcp_stream_response->measure_cpu;
2921             remote_cpu_rate = tcp_stream_response->cpu_rate;
2922 
2923             /* we have to make sure that the server port number is in */
2924             /* network order */
2925             set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
2926 
2927             rem_rcvavoid   = tcp_stream_response->so_rcvavoid;
2928             rem_sndavoid   = tcp_stream_response->so_sndavoid;
2929         }
2930         else {
2931             Set_errno(netperf_response.content.serv_errno);
2932             fprintf(where,
2933                     "netperf: remote error %d",
2934                     netperf_response.content.serv_errno);
2935             perror("");
2936             fflush(where);
2937 
2938             exit(1);
2939         }
2940 
2941 #if 0 /* def WANT_DEMO */
2942         DEMO_STREAM_SETUP(lss_size,rsr_size)
2943 #endif
2944 
2945             /*Connect up to the remote port on the data socket  */
2946             if (connect(send_socket,
2947                         remote_res->ai_addr,
2948                         remote_res->ai_addrlen) == INVALID_SOCKET){
2949                 perror("netperf: send_tcp_stream: data socket connect failed");
2950                 exit(1);
2951             }
2952 
2953         /* Data Socket set-up is finished. If there were problems, either */
2954         /* the connect would have failed, or the previous response would */
2955         /* have indicated a problem. I failed to see the value of the */
2956         /* extra  message after the accept on the remote. If it failed, */
2957         /* we'll see it here. If it didn't, we might as well start pumping */
2958         /* data. */
2959 
2960         /* Set-up the test end conditions. For a stream test, they can be */
2961         /* either time or byte-count based. */
2962 
2963         if (test_time) {
2964             /* The user wanted to end the test after a period of time. */
2965             times_up = 0;
2966             bytes_remaining = 0;
2967             /* in previous revisions, we had the same code repeated throught */
2968             /* all the test suites. this was unnecessary, and meant more */
2969             /* work for me when I wanted to switch to POSIX signals, so I */
2970             /* have abstracted this out into a routine in netlib.c. if you */
2971             /* are experiencing signal problems, you might want to look */
2972             /* there. raj 11/94 */
2973             start_timer(test_time);
2974         }
2975         else {
2976             /* The tester wanted to send a number of bytes. */
2977             bytes_remaining = test_bytes;
2978             times_up = 1;
2979         }
2980 
2981         /* The cpu_start routine will grab the current time and possibly */
2982         /* value of the idle counter for later use in measuring cpu */
2983         /* utilization and/or service demand and thruput. */
2984 
2985         cpu_start(local_cpu_usage);
2986 
2987 #if 0 /* def WANT_INTERVALS */
2988 	INTERVALS_INIT();
2989 #endif /* WANT_INTERVALS */
2990 
2991         /* before we start, initialize a few variables */
2992 
2993 #if 0 /* def WANT_DEMO */
2994         if (demo_mode) {
2995             HIST_timestamp(demo_one_ptr);
2996         }
2997 #endif
2998 
2999 
3000         /* We use an "OR" to control test execution. When the test is */
3001         /* controlled by time, the byte count check will always return false. */
3002         /* When the test is controlled by byte count, the time test will */
3003         /* always return false. When the test is finished, the whole */
3004         /* expression will go false and we will stop sending data. */
3005 
3006         exs_aio_pending = 0;
3007         exs_aio_eagain = 0;
3008         exs_aio_dequeuecnt = 0;
3009 
3010         while ((!times_up) || (bytes_remaining > 0)) {
3011 
3012 #ifdef DIRTY
3013 	  access_buffer(send_ring->buffer_ptr,
3014 			send_size,
3015 			loc_dirty_count,
3016 			loc_clean_count);
3017 #endif /* DIRTY */
3018 
3019 #if 0 /* def WANT_HISTOGRAM */
3020             /* timestamp just before we go into send and then again just after */
3021             /* we come out raj 8/94 */
3022             HIST_timestamp(&time_one);
3023 #endif /* WANT_HISTOGRAM */
3024 
3025 
3026             /* post up to NETPERF_EXS_PENDING I/Os  */
3027             while ((exs_aio_pending < NETPERF_EXS_PENDING) &&
3028                    (exs_send (send_socket, send_ring->buffer_ptr, send_size,
3029                               0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) {
3030                 exs_aio_pending++;
3031 
3032                 /* now we want to move our pointer to the next
3033 		   position in the data buffer...we may also want to
3034 		   wrap back to the "beginning" of the bufferspace, so
3035 		   we will mod the number of messages sent by the send
3036 		   width, and use that to calculate the offset to add
3037 		   to the base pointer. */
3038 
3039                 nummessages++;
3040                 send_ring = send_ring->next;
3041                 if (bytes_remaining) {
3042                     bytes_remaining -= send_size;
3043                 }
3044             }
3045 
3046             /* check exs_send result */
3047             if (exs_aio_pending < NETPERF_EXS_PENDING) {
3048                /* standard flow control case */
3049                 if (errno == EAGAIN)
3050                     exs_aio_eagain++;
3051                 /* case of times_up */
3052                 else if (errno == EINTR)
3053                     break;
3054                 /* strange, let's stop */
3055                 else {
3056                     perror ("netperf: exs_send error");
3057                     exit (1);
3058                 }
3059             }
3060 
3061             /* dequeue events with "threshold" on 1/2 posted */
3062             exs_aio_dequeued =
3063                 exs_qdequeue (exs_qhandle, exs_evtvec,
3064                               -(exs_aio_pending>>1), NULL);
3065             exs_aio_dequeuecnt++;
3066 
3067             /* check exs_dequeue result */
3068             if (exs_aio_dequeued < 0) {
3069                 /* case of times_up */
3070                 if (errno == EINTR)
3071                     break;
3072                 /* strange, let's stop */
3073                 else {
3074                     perror ("netperf: exs_send error");
3075                     exit (1);
3076                 }
3077             }
3078             /* update number of pending I/Os */
3079             else {
3080                 exs_aio_pending -= exs_aio_dequeued;
3081             }
3082 
3083 
3084 #if 0 /* def WANT_HISTOGRAM */
3085             /* timestamp the exit from the send call and update the histogram */
3086             HIST_timestamp(&time_two);
3087             HIST_add(time_hist,delta_micro(&time_one,&time_two));
3088 #endif /* WANT_HISTOGRAM */
3089 
3090 #if 0 /* def WANT_DEMO */
3091             DEMO_STREAM_INTERVAL(send_size);
3092 #endif
3093 
3094 #if 0 /* def WANT_INTERVALS */
3095 	    INTERVALS_WAIT();
3096 #endif /* WANT_INTERVALS */
3097 
3098         }
3099 
3100         /* Collect the last completion events */
3101         exs_aio_dequeued =
3102             exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL);
3103         exs_aio_dequeuecnt++;
3104         /* check exs_dequeue result and update number of pending I/Os */
3105         if (exs_aio_dequeued < 0) {
3106             perror ("netperf: exs_send error");
3107             exit (1);
3108         }
3109         exs_aio_pending -= exs_aio_dequeued;
3110 
3111         /* Display some async I/O debug info */
3112         if (debug) {
3113             fprintf (where, "send_exs_tcp_stream: "
3114                      "aio sent=%d eagain=%d dequeue=%d pending=%d\n",
3115                      nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending);
3116         }
3117 
3118         /* The test is over. Flush the buffers to the remote end. We do a */
3119         /* graceful release to insure that all data has been taken by the */
3120         /* remote. */
3121 
3122         /* but first, if the verbosity is greater than 1, find-out what */
3123         /* the TCP maximum segment_size was (if possible) */
3124         if (verbosity > 1) {
3125             tcp_mss = -1;
3126             get_tcp_info(send_socket,&tcp_mss);
3127         }
3128 
3129         if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
3130             perror("netperf: cannot shutdown tcp stream socket");
3131             exit(1);
3132         }
3133 
3134         /* hang a recv() off the socket to block until the remote has */
3135         /* brought all the data up into the application. it will do a */
3136         /* shutdown to cause a FIN to be sent our way. We will assume that */
3137         /* any exit from the recv() call is good... raj 4/93 */
3138 
3139         recv(send_socket, send_ring->buffer_ptr, send_size, 0);
3140 
3141         /* this call will always give us the elapsed time for the test, and */
3142         /* will also store-away the necessaries for cpu utilization */
3143 
3144         cpu_stop(local_cpu_usage,&elapsed_time);   /* was cpu being */
3145         /* measured and how */
3146         /* long did we really */
3147         /* run? */
3148 
3149         /* we are finished with the socket, so close it to prevent hitting */
3150         /* the limit on maximum open files. */
3151 
3152         close(send_socket);
3153 
3154         /* Get the statistics from the remote end. The remote will have */
3155         /* calculated service demand and all those interesting things. If it */
3156         /* wasn't supposed to care, it will return obvious values. */
3157 
3158         recv_response();
3159         if (!netperf_response.content.serv_errno) {
3160             if (debug)
3161                 fprintf(where,"remote results obtained\n");
3162         }
3163         else {
3164             Set_errno(netperf_response.content.serv_errno);
3165             fprintf(where,
3166                     "netperf: remote error %d",
3167                     netperf_response.content.serv_errno);
3168             perror("");
3169             fflush(where);
3170 
3171             exit(1);
3172         }
3173 
3174         /* We now calculate what our thruput was for the test. In the future, */
3175         /* we may want to include a calculation of the thruput measured by */
3176         /* the remote, but it should be the case that for a TCP stream test, */
3177         /* that the two numbers should be *very* close... We calculate */
3178         /* bytes_sent regardless of the way the test length was controlled. */
3179         /* If it was time, we needed to, and if it was by bytes, the user may */
3180         /* have specified a number of bytes that wasn't a multiple of the */
3181         /* send_size, so we really didn't send what he asked for ;-) */
3182 
3183         bytes_sent   = ntohd(tcp_stream_result->bytes_received);
3184 
3185         thruput   = calc_thruput(bytes_sent);
3186 
3187         if (local_cpu_usage || remote_cpu_usage) {
3188             /* We must now do a little math for service demand and cpu */
3189             /* utilization for the system(s) */
3190             /* Of course, some of the information might be bogus because */
3191             /* there was no idle counter in the kernel(s). We need to make */
3192             /* a note of this for the user's benefit...*/
3193             if (local_cpu_usage) {
3194 
3195                 local_cpu_utilization   = calc_cpu_util(0.0);
3196                 local_service_demand   = calc_service_demand(bytes_sent,
3197                                                              0.0,
3198                                                              0.0,
3199                                                              0);
3200             }
3201             else {
3202                 local_cpu_utilization   = (float) -1.0;
3203                 local_service_demand   = (float) -1.0;
3204             }
3205 
3206             if (remote_cpu_usage) {
3207 
3208                 remote_cpu_utilization   = tcp_stream_result->cpu_util;
3209                 remote_service_demand   = calc_service_demand(bytes_sent,
3210                                                               0.0,
3211                                                               remote_cpu_utilization,
3212                                                               tcp_stream_result->num_cpus);
3213             }
3214             else {
3215                 remote_cpu_utilization = (float) -1.0;
3216                 remote_service_demand  = (float) -1.0;
3217             }
3218         }
3219         else {
3220             /* we were not measuring cpu, for the confidence stuff, we */
3221             /* should make it -1.0 */
3222             local_cpu_utilization   = (float) -1.0;
3223             local_service_demand   = (float) -1.0;
3224             remote_cpu_utilization = (float) -1.0;
3225             remote_service_demand  = (float) -1.0;
3226         }
3227 
3228         /* at this point, we want to calculate the confidence information. */
3229         /* if debugging is on, calculate_confidence will print-out the */
3230         /* parameters we pass it */
3231 
3232         calculate_confidence(confidence_iteration,
3233                              elapsed_time,
3234                              thruput,
3235                              local_cpu_utilization,
3236                              remote_cpu_utilization,
3237                              local_service_demand,
3238                              remote_service_demand);
3239 
3240 
3241         confidence_iteration++;
3242     }
3243 
3244     /* at this point, we have finished making all the runs that we */
3245     /* will be making. so, we should extract what the calcuated values */
3246     /* are for all the confidence stuff. we could make the values */
3247     /* global, but that seemed a little messy, and it did not seem worth */
3248     /* all the mucking with header files. so, we create a routine much */
3249     /* like calcualte_confidence, which just returns the mean values. */
3250     /* raj 11/94 */
3251 
3252     retrieve_confident_values(&elapsed_time,
3253                               &thruput,
3254                               &local_cpu_utilization,
3255                               &remote_cpu_utilization,
3256                               &local_service_demand,
3257                               &remote_service_demand);
3258 
3259     /* We are now ready to print all the information. If the user */
3260     /* has specified zero-level verbosity, we will just print the */
3261     /* local service demand, or the remote service demand. If the */
3262     /* user has requested verbosity level 1, he will get the basic */
3263     /* "streamperf" numbers. If the user has specified a verbosity */
3264     /* of greater than 1, we will display a veritable plethora of */
3265     /* background information from outside of this block as it it */
3266     /* not cpu_measurement specific...  */
3267 
3268     if (confidence < 0) {
3269         /* we did not hit confidence, but were we asked to look for it? */
3270         if (iteration_max > 1) {
3271             display_confidence();
3272         }
3273     }
3274 
3275     if (local_cpu_usage || remote_cpu_usage) {
3276         local_cpu_method = format_cpu_method(cpu_method);
3277         remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
3278 
3279         switch (verbosity) {
3280             case 0:
3281                 if (local_cpu_usage) {
3282                     fprintf(where,
3283                             cpu_fmt_0,
3284                             local_service_demand,
3285                             local_cpu_method);
3286                 }
3287                 else {
3288                     fprintf(where,
3289                             cpu_fmt_0,
3290                             remote_service_demand,
3291                             remote_cpu_method);
3292                 }
3293                 break;
3294             case 1:
3295             case 2:
3296                 if (print_headers) {
3297                     fprintf(where,
3298                             cpu_title,
3299                             format_units(),
3300                             local_cpu_method,
3301                             remote_cpu_method);
3302                 }
3303 
3304                 fprintf(where,
3305                         cpu_fmt_1,      /* the format string */
3306                         rsr_size,              /* remote recvbuf size */
3307                         lss_size,              /* local sendbuf size */
3308                         send_size,      /* how large were the sends */
3309                         elapsed_time,      /* how long was the test */
3310                         thruput,               /* what was the xfer rate */
3311                         local_cpu_utilization,   /* local cpu */
3312                         remote_cpu_utilization,   /* remote cpu */
3313                         local_service_demand,   /* local service demand */
3314                         remote_service_demand);   /* remote service demand */
3315                 break;
3316         }
3317     }
3318     else {
3319         /* The tester did not wish to measure service demand. */
3320 
3321         switch (verbosity) {
3322             case 0:
3323                 fprintf(where,
3324                         tput_fmt_0,
3325                         thruput);
3326                 break;
3327             case 1:
3328             case 2:
3329                 if (print_headers) {
3330                     fprintf(where,tput_title,format_units());
3331                 }
3332                 fprintf(where,
3333                         tput_fmt_1,      /* the format string */
3334                         rsr_size,       /* remote recvbuf size */
3335                         lss_size,       /* local sendbuf size */
3336                         send_size,      /* how large were the sends */
3337                         elapsed_time,       /* how long did it take */
3338                         thruput);/* how fast did it go */
3339                 break;
3340         }
3341     }
3342 
3343     /* it would be a good thing to include information about some of the */
3344     /* other parameters that may have been set for this test, but at the */
3345     /* moment, I do not wish to figure-out all the  formatting, so I will */
3346     /* just put this comment here to help remind me that it is something */
3347     /* that should be done at a later time. */
3348 
3349     if (verbosity > 1) {
3350         /* The user wanted to know it all, so we will give it to him. */
3351         /* This information will include as much as we can find about */
3352         /* TCP statistics, the alignments of the sends and receives */
3353         /* and all that sort of rot... */
3354 
3355         /* this stuff needs to be worked-out in the presence of confidence */
3356         /* intervals and multiple iterations of the test... raj 11/94 */
3357 
3358         fprintf(where,
3359                 ksink_fmt,
3360                 "Bytes",
3361                 "Bytes",
3362                 "Bytes",
3363                 local_send_align,
3364                 remote_recv_align,
3365                 local_send_offset,
3366                 remote_recv_offset,
3367                 bytes_sent,
3368                 bytes_sent / (double)nummessages,
3369                 nummessages,
3370                 bytes_sent / (double)tcp_stream_result->recv_calls,
3371                 tcp_stream_result->recv_calls);
3372         fprintf(where,
3373                 ksink_fmt2,
3374                 tcp_mss);
3375         fflush(where);
3376 #if 0 /* def WANT_HISTOGRAM */
3377         fprintf(where,"\n\nHistogram of time spent in send() call.\n");
3378         fflush(where);
3379         HIST_report(time_hist);
3380 #endif /* WANT_HISTOGRAM */
3381     }
3382 
3383 }
3384 
3385 #endif /* HAVE_ICSC_EXS */
3386 
3387 
3388 
3389 #if defined(HAVE_SENDFILE)
3390 
3391 #if defined(QUICK_SENDPATH)
3392 
3393 /*
3394  * a temporary stub for the sendpath() system call
3395  * which is defined & implemented in the kernel
3396  * but which has no libc stub.
3397  */
3398 #include <sys/types.h>
3399 #include <sys/scall_define.h>
3400 #include <sys/uio.h>
3401 
3402 ssize_t
sendpath(int s,char * path,off_t offset,size_t nbytes,const struct iovec * hdtrl,int flags)3403 sendpath(int s, char *path, off_t offset, size_t nbytes,
3404 	 const struct iovec *hdtrl, int flags)
3405   {
3406     return syscall(SYS_sendpath, s, path, offset, nbytes, hdtrl, flags);
3407   }
3408 #endif /* QUICK_SENDPATH */
3409 
3410 /* This routine implements the TCP unidirectional data transfer test
3411    (a.k.a. stream) for the sockets interface using the sendfile()
3412    system call - TCP_SENDFILE.  It receives its  parameters via global
3413    variables from the shell and writes its  output to the standard
3414    output. Basically,  this is the same test as the send_tcp_stream()
3415    logic and we even tell the remote to do a TCP_STREAM test since for
3416    all it knows, nothig is different. */
3417 
3418 void
sendfile_tcp_stream(remote_host)3419 sendfile_tcp_stream(remote_host)
3420      char	remote_host[];
3421 {
3422 
3423   char *tput_title = "\
3424 Recv   Send    Send                          \n\
3425 Socket Socket  Message  Elapsed              \n\
3426 Size   Size    Size     Time     Throughput  \n\
3427 bytes  bytes   bytes    secs.    %s/sec  \n\n";
3428 
3429   char *tput_fmt_0 =
3430     "%7.2f\n";
3431 
3432   char *tput_fmt_1 =
3433     "%6d %6d %6d    %-6.2f   %7.2f   \n";
3434 
3435   char *cpu_title = "\
3436 Recv   Send    Send                          Utilization       Service Demand\n\
3437 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
3438 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
3439 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
3440 
3441   char *cpu_fmt_0 =
3442     "%6.3f %c\n";
3443   char *cpu_fmt_1 =
3444     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
3445 
3446   char *ksink_fmt = "\n\
3447 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
3448 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
3449 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
3450 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
3451 
3452 char *ksink_fmt2 = "\n\
3453 Maximum\n\
3454 Segment\n\
3455 Size (bytes)\n\
3456 %6d\n";
3457 
3458   float			elapsed_time;
3459 
3460   /* what we want is to have a buffer space that is at least one */
3461   /* send-size greater than our send window. this will insure that we */
3462   /* are never trying to re-use a buffer that may still be in the hands */
3463   /* of the transport. This buffer will be malloc'd after we have found */
3464   /* the size of the local senc socket buffer. We will want to deal */
3465   /* with alignment and offset concerns as well. */
3466 
3467   struct sendfile_ring_elt *send_ring;
3468 
3469   int len;
3470   unsigned int nummessages = 0;
3471   SOCKET send_socket;
3472   int bytes_remaining;
3473   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
3474 
3475   /* with links like fddi, one can send > 32 bits worth of bytes */
3476   /* during a test... ;-) at some point, this should probably become a */
3477   /* 64bit integral type, but those are not entirely common yet */
3478   double	bytes_sent = 0.0;
3479 
3480   float	local_cpu_utilization;
3481   float	local_service_demand;
3482   float	remote_cpu_utilization;
3483   float	remote_service_demand;
3484 
3485   double	thruput;
3486 
3487   struct  addrinfo *remote_res;
3488   struct  addrinfo *local_res;
3489   struct	sockaddr_in	server;
3490 
3491 #if defined(__linux) || defined(__sun__)
3492   off_t     scratch_offset;   /* the linux sendfile() call will update
3493 				 the offset variable, which is
3494 				 something we do _not_ want to happen
3495 				 to the value in the send_ring! so, we
3496 				 have to use a scratch variable. */
3497 #endif /* __linux  || defined(__sun__) */
3498 #if defined (USE_OSX)
3499    off_t    scratch_len;  /* Darwin 9.x need a value-result parameter  */
3500 #endif
3501 #if defined (__sun__)
3502    size_t  scratch_len;	/* the sun sendfilev() needs a place to
3503 			   tell us how many bytes were written,
3504 			   even though it also returns the value */
3505    sendfilevec_t sv;
3506 #endif /* __sun__ */
3507 
3508   struct	tcp_stream_request_struct	*tcp_stream_request;
3509   struct	tcp_stream_response_struct	*tcp_stream_response;
3510   struct	tcp_stream_results_struct	*tcp_stream_result;
3511 
3512   tcp_stream_request  =
3513     (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
3514   tcp_stream_response =
3515     (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
3516   tcp_stream_result   =
3517     (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
3518 
3519 #ifdef WANT_HISTOGRAM
3520   if (verbosity > 1) {
3521     time_hist = HIST_new();
3522   }
3523 #endif /* WANT_HISTOGRAM */
3524 
3525   /* since we are now disconnected from the code that established the */
3526   /* control socket, and since we want to be able to use different */
3527   /* protocols and such, we are passed the name of the remote host and */
3528   /* must turn that into the test specific addressing information. */
3529 
3530   bzero((char *)&server,
3531 	sizeof(server));
3532 
3533   complete_addrinfos(&remote_res,
3534 		     &local_res,
3535 		     remote_host,
3536 		     SOCK_STREAM,
3537 		     IPPROTO_TCP,
3538 		     0);
3539 
3540   if ( print_headers ) {
3541     /* we want to have some additional, interesting information in */
3542     /* the headers. we know some of it here, but not all, so we will */
3543     /* only print the test title here and will print the results */
3544     /* titles after the test is finished */
3545 #ifdef QUICK_SENDPATH
3546     print_top_test_header("TCP SENDPATH TEST",local_res,remote_res);
3547 #else
3548     print_top_test_header("TCP SENDFILE TEST",local_res,remote_res);
3549 #endif /* QUICK_SENDPATH */
3550   }
3551   send_ring = NULL;
3552   confidence_iteration = 1;
3553   init_stat();
3554 
3555   /* we have a great-big while loop which controls the number of times */
3556   /* we run a particular test. this is for the calculation of a */
3557   /* confidence interval (I really should have stayed awake during */
3558   /* probstats :). If the user did not request confidence measurement */
3559   /* (no confidence is the default) then we will only go though the */
3560   /* loop once. the confidence stuff originates from the folks at IBM */
3561 
3562   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
3563 	 (confidence_iteration <= iteration_min)) {
3564 
3565     /* initialize a few counters. we have to remember that we might be */
3566     /* going through the loop more than once. */
3567 
3568     nummessages    =	0;
3569     bytes_sent     =	0.0;
3570     times_up       = 	0;
3571 
3572     /* set up the data socket */
3573     send_socket = create_data_socket(local_res);
3574 
3575     if (send_socket == INVALID_SOCKET){
3576       perror("netperf: sendfile_tcp_stream: tcp stream data socket");
3577       exit(1);
3578     }
3579 
3580     if (debug) {
3581       fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n");
3582     }
3583 
3584 #if defined(TCP_CORK)
3585     /* should this even be here?!? */
3586     if (loc_tcpcork != 0) {
3587       /* the user wishes for us to set TCP_CORK on the socket */
3588       int one = 1;
3589       if (setsockopt(send_socket,
3590 		     getprotobyname("tcp")->p_proto,
3591 		     TCP_CORK,
3592 		     (char *)&one,
3593 		     sizeof(one)) == SOCKET_ERROR) {
3594 	perror("netperf: sendfile_tcp_stream: tcp_cork");
3595 	exit(1);
3596       }
3597       if (debug) {
3598 	fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
3599       }
3600     }
3601 
3602 #endif /* TCP_CORK */
3603 
3604     /* at this point, we have either retrieved the socket buffer sizes, */
3605     /* or have tried to set them, so now, we may want to set the send */
3606     /* size based on that (because the user either did not use a -m */
3607     /* option, or used one with an argument of 0). If the socket buffer */
3608     /* size is not available, we will set the send size to 4KB - no */
3609     /* particular reason, just arbitrary... */
3610 
3611     /*check for file size/ min file size here?  create file here/ back out???*/
3612 
3613     if (send_size == 0) {
3614       if (lss_size > 0) {
3615 	send_size = lss_size;
3616       }
3617       else {
3618 	send_size = 4096;
3619       }
3620     }
3621 
3622     /* set-up the data buffer ring with the requested alignment and
3623        offset. note also that we have allocated a quantity  of memory
3624        that is at least one send-size greater than our socket  buffer
3625        size. We want to be sure that there are at least two  buffers
3626        allocated - this can be a bit of a problem when the  send_size
3627        is bigger than the socket size, so we must check... the  user
3628        may have wanted to explicitly set the "width" of our send
3629        buffers, we should respect that wish... */
3630 
3631     /*sendring -> an offset index that will shift the starting point of the*/
3632     /*section of the file sent throughout the file*/
3633 
3634     if (send_width == 0) {
3635       send_width = (lss_size/send_size) + 1;
3636       if (send_width == 1) send_width++;
3637     }
3638 
3639     if (send_ring == NULL) {
3640 
3641       /* only allocate the send ring once. this is a networking test,
3642 	 not a memory allocation test. this way, we do not need a
3643 	 deallocate_buffer_ring() routine, and I don't feel like
3644 	 writing one anyway :) raj 11/94 */
3645 
3646       send_ring = alloc_sendfile_buf_ring(send_width,
3647 					  send_size,
3648 					  local_send_align,
3649 					  local_send_offset);
3650     }
3651 
3652     /* If the user has requested cpu utilization measurements, we must
3653        calibrate the cpu(s). We will perform this task within the
3654        tests  themselves. If the user has specified the cpu rate, then
3655        calibrate_local_cpu will return rather quickly as it will have
3656        nothing to do. If local_cpu_rate is zero, then we will go
3657        through  all the "normal" calibration stuff and return the rate
3658        back. */
3659 
3660     if (local_cpu_usage) {
3661       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3662     }
3663 
3664     /* Tell the remote end to do a listen. The server alters the
3665        socket  paramters on the other side at this point, hence the
3666        reason for  all the values being passed in the setup
3667        message. If the user did  not specify any of the parameters,
3668        they will be passed as 0, which  will indicate to the remote
3669        that no changes beyond the system's  default should be
3670        used. Alignment is the exception, it will  default to 1, which
3671        will be no alignment alterations. */
3672 
3673     netperf_request.content.request_type =	DO_TCP_STREAM;
3674     tcp_stream_request->send_buf_size	=	rss_size_req;
3675     tcp_stream_request->recv_buf_size	=	rsr_size_req;
3676     tcp_stream_request->receive_size	=	recv_size;
3677     tcp_stream_request->no_delay	=	rem_nodelay;
3678     tcp_stream_request->recv_alignment	=	remote_recv_align;
3679     tcp_stream_request->recv_offset	=	remote_recv_offset;
3680     tcp_stream_request->measure_cpu	=	remote_cpu_usage;
3681     tcp_stream_request->cpu_rate	=	remote_cpu_rate;
3682 
3683     if (test_time) {
3684       tcp_stream_request->test_length	=	test_time;
3685     }
3686     else {
3687       tcp_stream_request->test_length	=	test_bytes;
3688     }
3689 
3690     tcp_stream_request->so_rcvavoid	=	rem_rcvavoid;
3691     tcp_stream_request->so_sndavoid	=	rem_sndavoid;
3692 
3693 #ifdef DIRTY
3694     tcp_stream_request->dirty_count       =       rem_dirty_count;
3695     tcp_stream_request->clean_count       =       rem_clean_count;
3696 #endif /* DIRTY */
3697     tcp_stream_request->port     = atoi(remote_data_port);
3698     tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
3699 
3700     if (debug > 1) {
3701       fprintf(where,
3702 	      "netperf: send_tcp_stream: requesting TCP stream test\n");
3703     }
3704 
3705     send_request();
3706 
3707     /* The response from the remote will contain all of the relevant
3708        socket parameters for this test type. We will put them back
3709        into the variables here so they can be displayed if desired.
3710        The remote will have calibrated CPU if necessary, and will have
3711        done all the needed set-up we will have calibrated the cpu
3712        locally before sending the request, and will grab the counter
3713        value right after the connect returns. The remote will grab the
3714        counter right after the accept call. This saves the hassle of
3715        extra messages being sent for the TCP tests.  */
3716 
3717     recv_response();
3718 
3719     if (!netperf_response.content.serv_errno) {
3720       if (debug)
3721 	fprintf(where,"remote listen done.\n");
3722       rsr_size	      =	tcp_stream_response->recv_buf_size;
3723       rss_size	      =	tcp_stream_response->send_buf_size;
3724       rem_nodelay     =	tcp_stream_response->no_delay;
3725       remote_cpu_usage=	tcp_stream_response->measure_cpu;
3726       remote_cpu_rate = tcp_stream_response->cpu_rate;
3727 
3728       /* we have to make sure that the server port number is in */
3729       /* network order */
3730       set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
3731       rem_rcvavoid	= tcp_stream_response->so_rcvavoid;
3732       rem_sndavoid	= tcp_stream_response->so_sndavoid;
3733     }
3734     else {
3735       Set_errno(netperf_response.content.serv_errno);
3736       fprintf(where,
3737 	      "netperf: remote error %d",
3738 	      netperf_response.content.serv_errno);
3739       perror("");
3740       fflush(where);
3741 
3742       exit(1);
3743     }
3744 
3745 #ifdef WANT_DEMO
3746     DEMO_STREAM_SETUP(lss_size,rsr_size)
3747 #endif
3748 
3749     /*Connect up to the remote port on the data socket  */
3750     if (connect(send_socket,
3751 		remote_res->ai_addr,
3752 		remote_res->ai_addrlen) == INVALID_SOCKET){
3753       perror("netperf: send_tcp_stream: data socket connect failed");
3754       printf(" port: %d\n",ntohs(server.sin_port));
3755       exit(1);
3756     }
3757 
3758     /* Data Socket set-up is finished. If there were problems, either
3759        the connect would have failed, or the previous response would
3760        have indicated a problem. I failed to see the value of the
3761        extra message after the accept on the remote. If it failed,
3762        we'll see it here. If it didn't, we might as well start pumping
3763        data. */
3764 
3765     /* Set-up the test end conditions. For a stream test, they can be */
3766     /* either time or byte-count based. */
3767 
3768     if (test_time) {
3769       /* The user wanted to end the test after a period of time. */
3770       times_up = 0;
3771       bytes_remaining = 0;
3772 
3773       /* in previous revisions, we had the same code repeated throught
3774          all the test suites. this was unnecessary, and meant more
3775          work for me when I wanted to switch to POSIX signals, so I
3776          have abstracted this out into a routine in netlib.c. if you
3777          are experiencing signal problems, you might want to look
3778          there. raj 11/94 */
3779 
3780       start_timer(test_time);
3781     }
3782     else {
3783       /* The tester wanted to send a number of bytes. */
3784       bytes_remaining = test_bytes;
3785       times_up = 1;
3786     }
3787 
3788     /* The cpu_start routine will grab the current time and possibly */
3789     /* value of the idle counter for later use in measuring cpu */
3790     /* utilization and/or service demand and thruput. */
3791 
3792     cpu_start(local_cpu_usage);
3793 
3794 #ifdef WANT_INTERVALS
3795     INTERVALS_INIT();
3796 #endif /* WANT_INTERVALS */
3797 
3798 
3799     /* before we start, initialize a few variables */
3800 
3801 #ifdef WANT_DEMO
3802     if (demo_mode) {
3803       HIST_timestamp(demo_one_ptr);
3804     }
3805 #endif
3806 
3807     /* We use an "OR" to control test execution. When the test is
3808        controlled by time, the byte count check will always return
3809        false. When the test is controlled by byte count, the time test
3810        will always return false. When the test is finished, the whole
3811        expression will go false and we will stop sending data. */
3812 
3813     while ((!times_up) || (bytes_remaining > 0)) {
3814 
3815       /* the sendfile_tcp_stream test does not support making the buffers
3816 	 dirty. 08/2000 */
3817 
3818 #ifdef WANT_HISTOGRAM
3819       if (verbosity > 1) {
3820 	/* timestamp just before we go into sendfile() and then again
3821          just after we come out raj 08/2000 */
3822 	/* but only if we are actually going to display a histogram */
3823 	HIST_timestamp(&time_one);
3824       }
3825 #endif /* WANT_HISTOGRAM */
3826 
3827       /* you can look at netlib.h for a description of the fields we
3828 	 are passing to sendfile(). 08/2000 */
3829 #ifdef QUICK_SENDPATH
3830       if ((len=sendpath(send_socket,
3831 			fill_file,
3832 			send_ring->offset,
3833 			send_ring->length,
3834 			send_ring->hdtrl,
3835 			send_ring->flags)) != send_size)
3836 #elif defined(__linux)
3837 	scratch_offset = send_ring->offset;
3838       if ((len=sendfile(send_socket,
3839 			send_ring->fildes,
3840 			&scratch_offset,   /* modified after the call! */
3841 			send_ring->length)) != send_size)
3842 #elif defined (__sun__)
3843       /* We must call with SFV_NOWAIT and a large file size (>= 16MB) to
3844 	 get zero-copy, as well as compiling with  -D_LARGEFILE_SOURCE
3845 	  -D_FILE_OFFSET_BITS=64 */
3846       sv.sfv_fd = send_ring->fildes;
3847       sv.sfv_flag = SFV_NOWAIT;
3848       sv.sfv_off = send_ring->offset;
3849       sv.sfv_len =  send_ring->length;
3850       if ((len = sendfilev(send_socket, &sv, 1, &scratch_len)) != send_size)
3851 #elif defined(__FreeBSD__)
3852 	/* so close to HP-UX and yet so far away... :) */
3853 	if ((sendfile(send_ring->fildes,
3854 		      send_socket,
3855 		      send_ring->offset,
3856 		      send_ring->length,
3857 		      NULL,
3858 		      (off_t *)&len,
3859 		      send_ring->flags) != 0) ||
3860 	    (len != send_size))
3861 #elif defined(USE_OSX)
3862     scratch_len = send_ring->length;
3863     if ((sendfile(send_ring->fildes,
3864               send_socket,
3865               send_ring->offset,
3866               (off_t *)&scratch_len,
3867               NULL,
3868               send_ring->flags) != 0) ||
3869         (scratch_len != send_size))
3870 #else /* original sendile HP-UX */
3871 	  if ((len=sendfile(send_socket,
3872 			    send_ring->fildes,
3873 			    send_ring->offset,
3874 			    send_ring->length,
3875 			    send_ring->hdtrl,
3876 			    send_ring->flags)) != send_size)
3877 #endif /* QUICK_SENDPATH */
3878 	    {
3879 	      /* the test was interrupted, must be the end of test. the
3880 		 send_tcp_stream code has some WIN32 ifdefs that we do not
3881 		 need here. */
3882 	      if ((len >=0) || SOCKET_EINTR(len)) {
3883 		break;
3884 	      }
3885 	      perror("netperf: data send error: sendfile");
3886 	      fprintf(stderr,
3887 		      "len was %d send_size was %d\n",
3888 		      len,
3889 		      send_size);
3890 	      fflush(stderr);
3891 	      exit(1);
3892 	    }
3893 
3894       /*	offset += len;*/
3895 
3896 #ifdef WANT_HISTOGRAM
3897       if (verbosity > 1) {
3898 	/* timestamp the exit from the send call and update the
3899 	   histogram */
3900 
3901 	HIST_timestamp(&time_two);
3902 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
3903       }
3904 #endif /* WANT_HISTOGRAM */
3905 
3906 #ifdef WANT_DEMO
3907       DEMO_STREAM_INTERVAL(send_size);
3908 #endif
3909 
3910 #ifdef WANT_INTERVALS
3911       INTERVALS_WAIT();
3912 #endif /* WANT_INTERVALS */
3913 
3914       /* now we want to move our pointer to the next position in the */
3915       /* data buffer...we may also want to wrap back to the "beginning" */
3916       /* of the bufferspace, so we will mod the number of messages sent */
3917       /* by the send width, and use that to calculate the offset to add */
3918       /* to the base pointer. */
3919 
3920       nummessages++;
3921       send_ring = send_ring->next;
3922       if (bytes_remaining) {
3923 	bytes_remaining -= send_size;
3924       }
3925     }
3926 
3927     /* The test is over. Flush the buffers to the remote end. We do a
3928        graceful release to insure that all data has been taken by the
3929        remote. */
3930 
3931     /* but first, if the verbosity is greater than 1, find-out what */
3932     /* the TCP maximum segment_size was (if possible) */
3933     if (verbosity > 1) {
3934       tcp_mss = -1;
3935       get_tcp_info(send_socket,&tcp_mss);
3936     }
3937 
3938     if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
3939       perror("netperf: cannot shutdown tcp stream socket");
3940       exit(1);
3941     }
3942 
3943     /* hang a recv() off the socket to block until the remote has */
3944     /* brought all the data up into the application. it will do a */
3945     /* shutdown to cause a FIN to be sent our way. We will assume that */
3946     /* any exit from the recv() call is good... raj 4/93 */
3947 
3948     /* since we are using sendfile() instead of send, we have no
3949        scratch buffer from the send_ring to use for the
3950        receive. however, since we "know" that the recv should be
3951        returning zero bytes (not that we are making the checks we
3952        should) we can pass the address of the flags field. raj 08/2000
3953     */
3954 
3955     recv(send_socket,
3956 	 &(send_ring->flags),
3957 	 sizeof(send_ring->flags),
3958 	 0);
3959 
3960     /* this call will always give us the elapsed time for the test, and */
3961     /* will also store-away the necessaries for cpu utilization */
3962 
3963     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
3964 						/* measured and how */
3965 						/* long did we really */
3966 						/* run? */
3967 
3968     /* we are finished with the socket, so close it to prevent hitting */
3969     /* the limit on maximum open files. */
3970 
3971     close(send_socket);
3972 
3973     /* Get the statistics from the remote end. The remote will have */
3974     /* calculated service demand and all those interesting things. If it */
3975     /* wasn't supposed to care, it will return obvious values. */
3976 
3977     recv_response();
3978 
3979     if (!netperf_response.content.serv_errno) {
3980       if (debug)
3981 	fprintf(where,"remote results obtained\n");
3982     }
3983 
3984     else {
3985       Set_errno(netperf_response.content.serv_errno);
3986       fprintf(where,
3987 	      "netperf: remote error %d",
3988 	      netperf_response.content.serv_errno);
3989       perror("");
3990       fflush(where);
3991 
3992       exit(1);
3993     }
3994 
3995     /* We now calculate what our thruput was for the test. In the future, */
3996     /* we may want to include a calculation of the thruput measured by */
3997     /* the remote, but it should be the case that for a TCP stream test, */
3998     /* that the two numbers should be *very* close... We calculate */
3999     /* bytes_sent regardless of the way the test length was controlled. */
4000     /* If it was time, we needed to, and if it was by bytes, the user may */
4001     /* have specified a number of bytes that wasn't a multiple of the */
4002     /* send_size, so we really didn't send what he asked for ;-) */
4003 
4004     bytes_sent	= ntohd(tcp_stream_result->bytes_received);
4005 
4006     thruput	= calc_thruput(bytes_sent);
4007 
4008     if (local_cpu_usage || remote_cpu_usage) {
4009 
4010       /* We must now do a little math for service demand and cpu */
4011       /* utilization for the system(s) */
4012       /* Of course, some of the information might be bogus because */
4013       /* there was no idle counter in the kernel(s). We need to make */
4014       /* a note of this for the user's benefit...*/
4015       if (local_cpu_usage) {
4016 
4017 	local_cpu_utilization	= calc_cpu_util(0.0);
4018 	local_service_demand	= calc_service_demand(bytes_sent,
4019 						      0.0,
4020 						      0.0,
4021 						      0);
4022       }
4023       else {
4024 	local_cpu_utilization	= (float) -1.0;
4025 	local_service_demand	= (float) -1.0;
4026       }
4027 
4028       if (remote_cpu_usage) {
4029 
4030 	remote_cpu_utilization	= tcp_stream_result->cpu_util;
4031 	remote_service_demand	= calc_service_demand(bytes_sent,
4032 						      0.0,
4033 						      remote_cpu_utilization,
4034 						      tcp_stream_result->num_cpus);
4035       }
4036       else {
4037 	remote_cpu_utilization = (float) -1.0;
4038 	remote_service_demand  = (float) -1.0;
4039       }
4040     }
4041     else {
4042       /* we were not measuring cpu, for the confidence stuff, we */
4043       /* should make it -1.0 */
4044       local_cpu_utilization	= (float) -1.0;
4045       local_service_demand	= (float) -1.0;
4046       remote_cpu_utilization = (float) -1.0;
4047       remote_service_demand  = (float) -1.0;
4048     }
4049 
4050     /* at this point, we want to calculate the confidence information. */
4051     /* if debugging is on, calculate_confidence will print-out the */
4052     /* parameters we pass it */
4053 
4054     calculate_confidence(confidence_iteration,
4055 			 elapsed_time,
4056 			 thruput,
4057 			 local_cpu_utilization,
4058 			 remote_cpu_utilization,
4059 			 local_service_demand,
4060 			 remote_service_demand);
4061 
4062     confidence_iteration++;
4063   }
4064 
4065   /* at this point, we have finished making all the runs that we */
4066   /* will be making. so, we should extract what the calcuated values */
4067   /* are for all the confidence stuff. we could make the values */
4068   /* global, but that seemed a little messy, and it did not seem worth */
4069   /* all the mucking with header files. so, we create a routine much */
4070   /* like calcualte_confidence, which just returns the mean values. */
4071   /* raj 11/94 */
4072 
4073   retrieve_confident_values(&elapsed_time,
4074 			    &thruput,
4075 			    &local_cpu_utilization,
4076 			    &remote_cpu_utilization,
4077 			    &local_service_demand,
4078 			    &remote_service_demand);
4079 
4080   /* We are now ready to print all the information. If the user */
4081   /* has specified zero-level verbosity, we will just print the */
4082   /* local service demand, or the remote service demand. If the */
4083   /* user has requested verbosity level 1, he will get the basic */
4084   /* "streamperf" numbers. If the user has specified a verbosity */
4085   /* of greater than 1, we will display a veritable plethora of */
4086   /* background information from outside of this block as it it */
4087   /* not cpu_measurement specific...  */
4088 
4089   if (confidence < 0) {
4090     /* we did not hit confidence, but were we asked to look for it? */
4091     if (iteration_max > 1) {
4092       display_confidence();
4093     }
4094   }
4095 
4096   if (local_cpu_usage || remote_cpu_usage) {
4097     local_cpu_method = format_cpu_method(cpu_method);
4098     remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
4099 
4100     switch (verbosity) {
4101     case 0:
4102 
4103     if (local_cpu_usage) {
4104 	fprintf(where,
4105 		cpu_fmt_0,
4106 		local_service_demand,
4107 		local_cpu_method);
4108       }
4109 
4110       else {
4111 	fprintf(where,
4112 		cpu_fmt_0,
4113 		remote_service_demand,
4114 		remote_cpu_method);
4115       }
4116 
4117       break;
4118 
4119     case 1:
4120     case 2:
4121       if (print_headers) {
4122 	fprintf(where,
4123 		cpu_title,
4124 		format_units(),
4125 		local_cpu_method,
4126 		remote_cpu_method);
4127       }
4128 
4129       fprintf(where,
4130 	      cpu_fmt_1,		/* the format string */
4131 	      rsr_size,		        /* remote recvbuf size */
4132 	      lss_size,		        /* local sendbuf size */
4133 	      send_size,		/* how large were the sends */
4134 	      elapsed_time,		/* how long was the test */
4135 	      thruput, 		        /* what was the xfer rate */
4136 	      local_cpu_utilization,	/* local cpu */
4137 	      remote_cpu_utilization,	/* remote cpu */
4138 	      local_service_demand,	/* local service demand */
4139 	      remote_service_demand);	/* remote service demand */
4140       break;
4141     }
4142 
4143   }
4144 
4145   else {
4146     /* The tester did not wish to measure service demand. */
4147 
4148     switch (verbosity) {
4149 
4150     case 0:
4151 
4152       fprintf(where,
4153 	      tput_fmt_0,
4154 	      thruput);
4155       break;
4156 
4157     case 1:
4158     case 2:
4159 
4160       if (print_headers) {
4161 	fprintf(where,tput_title,format_units());
4162       }
4163 
4164       fprintf(where,
4165 	      tput_fmt_1,		/* the format string */
4166 	      rsr_size, 		/* remote recvbuf size */
4167 	      lss_size, 		/* local sendbuf size */
4168 	      send_size,		/* how large were the sends */
4169 	      elapsed_time, 		/* how long did it take */
4170 	      thruput);/* how fast did it go */
4171       break;
4172     }
4173   }
4174 
4175   /* it would be a good thing to include information about some of the */
4176   /* other parameters that may have been set for this test, but at the */
4177   /* moment, I do not wish to figure-out all the  formatting, so I will */
4178   /* just put this comment here to help remind me that it is something */
4179   /* that should be done at a later time. */
4180 
4181     if (verbosity > 1) {
4182 
4183     /* The user wanted to know it all, so we will give it to him. */
4184     /* This information will include as much as we can find about */
4185     /* TCP statistics, the alignments of the sends and receives */
4186     /* and all that sort of rot... */
4187 
4188     /* this stuff needs to be worked-out in the presence of confidence */
4189     /* intervals and multiple iterations of the test... raj 11/94 */
4190 
4191     fprintf(where,
4192 	    ksink_fmt,
4193 	    "Bytes",
4194 	    "Bytes",
4195 	    "Bytes",
4196 	    local_send_align,
4197 	    remote_recv_align,
4198 	    local_send_offset,
4199 	    remote_recv_offset,
4200 	    bytes_sent,
4201 	    bytes_sent / (double)nummessages,
4202 	    nummessages,
4203 	    bytes_sent / (double)tcp_stream_result->recv_calls,
4204 	    tcp_stream_result->recv_calls);
4205 
4206     fprintf(where,
4207 	    ksink_fmt2,
4208 	    tcp_mss);
4209 
4210     fflush(where);
4211 
4212 #ifdef WANT_HISTOGRAM
4213 
4214     fprintf(where,"\n\nHistogram of time spent in send() call.\n");
4215     fflush(where);
4216     HIST_report(time_hist);
4217 #endif /* WANT_HISTOGRAM */
4218   }
4219 }
4220 
4221 #endif /* HAVE_SENDFILE */
4222 
4223 /* This is the server-side routine for the tcp stream test. It is */
4224 /* implemented as one routine. I could break things-out somewhat, but */
4225 /* didn't feel it was necessary. */
4226 
4227 void
recv_tcp_stream()4228 recv_tcp_stream()
4229 {
4230 
4231   struct sockaddr_storage myaddr_in, peeraddr_in;
4232   SOCKET s_listen,s_data;
4233   netperf_socklen_t addrlen;
4234   int	len;
4235   unsigned int	receive_calls;
4236   float	elapsed_time;
4237   double   bytes_received;
4238 
4239   struct ring_elt *recv_ring;
4240 
4241   struct addrinfo *local_res;
4242   char local_name[BUFSIZ];
4243   char port_buffer[PORTBUFSIZE];
4244 
4245 #ifdef DO_SELECT
4246   fd_set readfds;
4247   struct timeval timeout;
4248 #endif /* DO_SELECT */
4249 
4250   struct	tcp_stream_request_struct	*tcp_stream_request;
4251   struct	tcp_stream_response_struct	*tcp_stream_response;
4252   struct	tcp_stream_results_struct	*tcp_stream_results;
4253 
4254 #ifdef DO_SELECT
4255   FD_ZERO(&readfds);
4256   timeout.tv_sec = 1;
4257   timeout.tv_usec = 0;
4258 #endif /* DO_SELECT */
4259 
4260   tcp_stream_request	=
4261     (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
4262   tcp_stream_response	=
4263     (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
4264   tcp_stream_results	=
4265     (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
4266 
4267   if (debug) {
4268     fprintf(where,"netserver: recv_tcp_stream: entered...\n");
4269     fflush(where);
4270   }
4271 
4272   /* We want to set-up the listen socket with all the desired */
4273   /* parameters and then let the initiator know that all is ready. If */
4274   /* socket size defaults are to be used, then the initiator will have */
4275   /* sent us 0's. If the socket sizes cannot be changed, then we will */
4276   /* send-back what they are. If that information cannot be determined, */
4277   /* then we send-back -1's for the sizes. If things go wrong for any */
4278   /* reason, we will drop back ten yards and punt. */
4279 
4280   /* If anything goes wrong, we want the remote to know about it. It */
4281   /* would be best if the error that the remote reports to the user is */
4282   /* the actual error we encountered, rather than some bogus unexpected */
4283   /* response type message. */
4284 
4285   if (debug) {
4286     fprintf(where,"recv_tcp_stream: setting the response type...\n");
4287     fflush(where);
4288   }
4289 
4290   netperf_response.content.response_type = TCP_STREAM_RESPONSE;
4291 
4292   if (debug) {
4293     fprintf(where,"recv_tcp_stream: the response type is set...\n");
4294     fflush(where);
4295   }
4296 
4297   /* We now alter the message_ptr variable to be at the desired */
4298   /* alignment with the desired offset. */
4299 
4300   if (debug) {
4301     fprintf(where,"recv_tcp_stream: requested alignment of %d\n",
4302 	    tcp_stream_request->recv_alignment);
4303     fflush(where);
4304   }
4305 
4306   /* create_data_socket expects to find some things in the global */
4307   /* variables, so set the globals based on the values in the request. */
4308   /* once the socket has been created, we will set the response values */
4309   /* based on the updated value of those globals. raj 7/94 */
4310   lss_size_req = tcp_stream_request->send_buf_size;
4311   lsr_size_req = tcp_stream_request->recv_buf_size;
4312   loc_nodelay  = tcp_stream_request->no_delay;
4313   loc_rcvavoid = tcp_stream_request->so_rcvavoid;
4314   loc_sndavoid = tcp_stream_request->so_sndavoid;
4315 
4316   set_hostname_and_port(local_name,
4317 			port_buffer,
4318 			nf_to_af(tcp_stream_request->ipfamily),
4319 			tcp_stream_request->port);
4320 
4321   local_res = complete_addrinfo(local_name,
4322 				local_name,
4323 				port_buffer,
4324 				nf_to_af(tcp_stream_request->ipfamily),
4325 				SOCK_STREAM,
4326 				IPPROTO_TCP,
4327 				0);
4328 
4329   s_listen = create_data_socket(local_res);
4330 
4331   if (s_listen == INVALID_SOCKET) {
4332     netperf_response.content.serv_errno = errno;
4333     send_response();
4334     exit(1);
4335   }
4336 
4337 #ifdef WIN32
4338   /* The test timer can fire during operations on the listening socket,
4339      so to make the start_timer below work we have to move
4340      it to close s_listen while we are blocked on accept. */
4341   win_kludge_socket2 = s_listen;
4342 #endif
4343 
4344   /* what sort of sizes did we end-up with? */
4345   if (tcp_stream_request->receive_size == 0) {
4346     if (lsr_size > 0) {
4347       recv_size = lsr_size;
4348     }
4349     else {
4350       recv_size = 4096;
4351     }
4352   }
4353   else {
4354     recv_size = tcp_stream_request->receive_size;
4355   }
4356 
4357   /* we want to set-up our recv_ring in a manner analagous to what we */
4358   /* do on the sending side. this is more for the sake of symmetry */
4359   /* than for the needs of say copy avoidance, but it might also be */
4360   /* more realistic - this way one could conceivably go with a */
4361   /* double-buffering scheme when taking the data an putting it into */
4362   /* the filesystem or something like that. raj 7/94 */
4363 
4364   if (recv_width == 0) {
4365     recv_width = (lsr_size/recv_size) + 1;
4366     if (recv_width == 1) recv_width++;
4367   }
4368 
4369   recv_ring = allocate_buffer_ring(recv_width,
4370 				   recv_size,
4371 				   tcp_stream_request->recv_alignment,
4372 				   tcp_stream_request->recv_offset);
4373 
4374   if (debug) {
4375     fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n");
4376     fflush(where);
4377   }
4378 
4379   /* Now, let's set-up the socket to listen for connections */
4380   if (listen(s_listen, 5) == SOCKET_ERROR) {
4381     netperf_response.content.serv_errno = errno;
4382     close(s_listen);
4383     send_response();
4384 
4385     exit(1);
4386   }
4387 
4388 
4389   /* now get the port number assigned by the system  */
4390   addrlen = sizeof(myaddr_in);
4391   if (getsockname(s_listen,
4392 		  (struct sockaddr *)&myaddr_in,
4393 		  &addrlen) == SOCKET_ERROR){
4394     netperf_response.content.serv_errno = errno;
4395     close(s_listen);
4396     send_response();
4397 
4398     exit(1);
4399   }
4400 
4401   /* Now myaddr_in contains the port and the internet address this is */
4402   /* returned to the sender also implicitly telling the sender that the */
4403   /* socket buffer sizing has been done. */
4404 
4405   tcp_stream_response->data_port_number =
4406     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
4407   netperf_response.content.serv_errno   = 0;
4408 
4409   /* But wait, there's more. If the initiator wanted cpu measurements, */
4410   /* then we must call the calibrate routine, which will return the max */
4411   /* rate back to the initiator. If the CPU was not to be measured, or */
4412   /* something went wrong with the calibration, we will return a -1 to */
4413   /* the initiator. */
4414 
4415   tcp_stream_response->cpu_rate = (float)0.0; 	/* assume no cpu */
4416   if (tcp_stream_request->measure_cpu) {
4417     tcp_stream_response->measure_cpu = 1;
4418     tcp_stream_response->cpu_rate =
4419       calibrate_local_cpu(tcp_stream_request->cpu_rate);
4420   }
4421   else {
4422     tcp_stream_response->measure_cpu = 0;
4423   }
4424 
4425   /* before we send the response back to the initiator, pull some of */
4426   /* the socket parms from the globals */
4427   tcp_stream_response->send_buf_size = lss_size;
4428   tcp_stream_response->recv_buf_size = lsr_size;
4429   tcp_stream_response->no_delay = loc_nodelay;
4430   tcp_stream_response->so_rcvavoid = loc_rcvavoid;
4431   tcp_stream_response->so_sndavoid = loc_sndavoid;
4432   tcp_stream_response->receive_size = recv_size;
4433 
4434   send_response();
4435 
4436   addrlen = sizeof(peeraddr_in);
4437 
4438   if ((s_data=accept(s_listen,
4439 		     (struct sockaddr *)&peeraddr_in,
4440 		     &addrlen)) == INVALID_SOCKET) {
4441     /* Let's just punt. The remote will be given some information */
4442     close(s_listen);
4443     exit(1);
4444   }
4445 
4446 #ifdef KLUDGE_SOCKET_OPTIONS
4447   /* this is for those systems which *INCORRECTLY* fail to pass */
4448   /* attributes across an accept() call. Including this goes against */
4449   /* my better judgement :( raj 11/95 */
4450 
4451   kludge_socket_options(s_data);
4452 
4453 #endif /* KLUDGE_SOCKET_OPTIONS */
4454 
4455   /* Now it's time to start receiving data on the connection. We will */
4456   /* first grab the apropriate counters and then start grabbing. */
4457 
4458   cpu_start(tcp_stream_request->measure_cpu);
4459 
4460   /* The loop will exit when the sender does a shutdown, which will */
4461   /* return a length of zero   */
4462 
4463   /* there used to be an #ifdef DIRTY call to access_buffer() here,
4464      but we have switched from accessing the buffer before the recv()
4465      call to accessing the buffer after the recv() call.  The
4466      accessing before was, IIRC, related to having dirty data when
4467      doing page-flipping copy avoidance. */
4468 
4469   bytes_received = 0;
4470   receive_calls  = 0;
4471 
4472   while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
4473     if (len == SOCKET_ERROR )
4474 	{
4475       netperf_response.content.serv_errno = errno;
4476       send_response();
4477       exit(1);
4478     }
4479     bytes_received += len;
4480     receive_calls++;
4481 
4482 #ifdef DIRTY
4483     /* we access the buffer after the recv() call now, rather than before */
4484     access_buffer(recv_ring->buffer_ptr,
4485 		  recv_size,
4486 		  tcp_stream_request->dirty_count,
4487 		  tcp_stream_request->clean_count);
4488 #endif /* DIRTY */
4489 
4490 
4491     /* move to the next buffer in the recv_ring */
4492     recv_ring = recv_ring->next;
4493 
4494 #ifdef PAUSE
4495     sleep(1);
4496 #endif /* PAUSE */
4497 
4498 #ifdef DO_SELECT
4499 	FD_SET(s_data,&readfds);
4500 	select(s_data+1,&readfds,NULL,NULL,&timeout);
4501 #endif /* DO_SELECT */
4502 
4503   }
4504 
4505   /* perform a shutdown to signal the sender that */
4506   /* we have received all the data sent. raj 4/93 */
4507 
4508   if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
4509       netperf_response.content.serv_errno = errno;
4510       send_response();
4511       exit(1);
4512     }
4513 
4514   cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time);
4515 
4516   /* send the results to the sender			*/
4517 
4518   if (debug) {
4519     fprintf(where,
4520 	    "recv_tcp_stream: got %g bytes\n",
4521 	    bytes_received);
4522     fprintf(where,
4523 	    "recv_tcp_stream: got %d recvs\n",
4524 	    receive_calls);
4525     fflush(where);
4526   }
4527 
4528   tcp_stream_results->bytes_received	= htond(bytes_received);
4529   tcp_stream_results->elapsed_time	= elapsed_time;
4530   tcp_stream_results->recv_calls	= receive_calls;
4531 
4532   tcp_stream_results->cpu_method = cpu_method;
4533   tcp_stream_results->num_cpus   = lib_num_loc_cpus;
4534 
4535   if (tcp_stream_request->measure_cpu) {
4536     tcp_stream_results->cpu_util	= calc_cpu_util(0.0);
4537   };
4538 
4539   if (debug) {
4540     fprintf(where,
4541 	    "recv_tcp_stream: test complete, sending results.\n");
4542     fprintf(where,
4543 	    "                 bytes_received %g receive_calls %d\n",
4544 	    bytes_received,
4545 	    receive_calls);
4546     fprintf(where,
4547 	    "                 len %d\n",
4548 	    len);
4549     fflush(where);
4550   }
4551 
4552   send_response();
4553 
4554   /* we are now done with the sockets */
4555   close(s_data);
4556   close(s_listen);
4557 
4558   }
4559 
4560 /* This is the server-side routine for the tcp maerts test. It is
4561    implemented as one routine. I could break things-out somewhat, but
4562    didn't feel it was necessary. */
4563 
4564 void
recv_tcp_maerts()4565 recv_tcp_maerts()
4566 {
4567 
4568   struct sockaddr_storage myaddr_in, peeraddr_in;
4569   struct addrinfo *local_res;
4570   char  local_name[BUFSIZ];
4571   char  port_buffer[PORTBUFSIZE];
4572 
4573   SOCKET	s_listen,s_data;
4574   netperf_socklen_t 	addrlen;
4575   int	len;
4576   unsigned int	send_calls;
4577   float	elapsed_time;
4578   double   bytes_sent = 0.0 ;
4579 
4580   struct ring_elt *send_ring;
4581 
4582   struct	tcp_maerts_request_struct	*tcp_maerts_request;
4583   struct	tcp_maerts_response_struct	*tcp_maerts_response;
4584   struct	tcp_maerts_results_struct	*tcp_maerts_results;
4585 
4586   tcp_maerts_request	=
4587     (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
4588   tcp_maerts_response	=
4589     (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
4590   tcp_maerts_results	=
4591     (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
4592 
4593   if (debug) {
4594     fprintf(where,"netserver: recv_tcp_maerts: entered...\n");
4595     fflush(where);
4596   }
4597 
4598   /* We want to set-up the listen socket with all the desired
4599      parameters and then let the initiator know that all is ready. If
4600      socket size defaults are to be used, then the initiator will have
4601      sent us 0's. If the socket sizes cannot be changed, then we will
4602      send-back what they are. If that information cannot be
4603      determined, then we send-back -1's for the sizes. If things go
4604      wrong for any reason, we will drop back ten yards and punt. */
4605 
4606   /* If anything goes wrong, we want the remote to know about it. It
4607      would be best if the error that the remote reports to the user is
4608      the actual error we encountered, rather than some bogus
4609      unexpected response type message. */
4610 
4611   if (debug) {
4612     fprintf(where,"recv_tcp_maerts: setting the response type...\n");
4613     fflush(where);
4614   }
4615 
4616   netperf_response.content.response_type = TCP_MAERTS_RESPONSE;
4617 
4618   if (debug) {
4619     fprintf(where,"recv_tcp_maerts: the response type is set...\n");
4620     fflush(where);
4621   }
4622 
4623   /* We now alter the message_ptr variable to be at the desired */
4624   /* alignment with the desired offset. */
4625 
4626   if (debug) {
4627     fprintf(where,"recv_tcp_maerts: requested alignment of %d\n",
4628 	    tcp_maerts_request->send_alignment);
4629     fflush(where);
4630   }
4631 
4632   /* Grab a socket to listen on, and then listen on it. */
4633 
4634   if (debug) {
4635     fprintf(where,"recv_tcp_maerts: grabbing a socket...\n");
4636     fflush(where);
4637   }
4638 
4639   /* create_data_socket expects to find some things in the global */
4640   /* variables, so set the globals based on the values in the request. */
4641   /* once the socket has been created, we will set the response values */
4642   /* based on the updated value of those globals. raj 7/94 */
4643   lss_size_req = tcp_maerts_request->send_buf_size;
4644   lsr_size_req = tcp_maerts_request->recv_buf_size;
4645   loc_nodelay = tcp_maerts_request->no_delay;
4646   loc_rcvavoid = tcp_maerts_request->so_rcvavoid;
4647   loc_sndavoid = tcp_maerts_request->so_sndavoid;
4648 
4649   set_hostname_and_port(local_name,
4650 			port_buffer,
4651 			nf_to_af(tcp_maerts_request->ipfamily),
4652 			tcp_maerts_request->port);
4653 
4654   local_res = complete_addrinfo(local_name,
4655 				local_name,
4656 				port_buffer,
4657 				nf_to_af(tcp_maerts_request->ipfamily),
4658 				SOCK_STREAM,
4659 				IPPROTO_TCP,
4660 				0);
4661 
4662   s_listen = create_data_socket(local_res);
4663 
4664   if (s_listen == INVALID_SOCKET) {
4665     netperf_response.content.serv_errno = errno;
4666     send_response();
4667     exit(1);
4668   }
4669 
4670 #ifdef WIN32
4671   /* The test timer can fire during operations on the listening socket,
4672      so to make the start_timer below work we have to move
4673      it to close s_listen while we are blocked on accept. */
4674   win_kludge_socket2 = s_listen;
4675 #endif
4676 
4677 
4678   /* what sort of sizes did we end-up with? */
4679   if (tcp_maerts_request->send_size == 0) {
4680     if (lss_size > 0) {
4681       send_size = lss_size;
4682     }
4683     else {
4684       send_size = 4096;
4685     }
4686   }
4687   else {
4688     send_size = tcp_maerts_request->send_size;
4689   }
4690 
4691   /* we want to set-up our recv_ring in a manner analagous to what we */
4692   /* do on the recving side. this is more for the sake of symmetry */
4693   /* than for the needs of say copy avoidance, but it might also be */
4694   /* more realistic - this way one could conceivably go with a */
4695   /* double-buffering scheme when taking the data an putting it into */
4696   /* the filesystem or something like that. raj 7/94 */
4697 
4698   if (send_width == 0) {
4699     send_width = (lsr_size/send_size) + 1;
4700     if (send_width == 1) send_width++;
4701   }
4702 
4703   send_ring = allocate_buffer_ring(send_width,
4704 				   send_size,
4705 				   tcp_maerts_request->send_alignment,
4706 				   tcp_maerts_request->send_offset);
4707 
4708   if (debug) {
4709     fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n");
4710     fflush(where);
4711   }
4712 
4713   /* Now, let's set-up the socket to listen for connections */
4714   if (listen(s_listen, 5) == SOCKET_ERROR) {
4715     netperf_response.content.serv_errno = errno;
4716     close(s_listen);
4717     send_response();
4718 
4719     exit(1);
4720   }
4721 
4722 
4723   /* now get the port number assigned by the system  */
4724   addrlen = sizeof(myaddr_in);
4725   if (getsockname(s_listen,
4726 		  (struct sockaddr *)&myaddr_in,
4727 		  &addrlen) == SOCKET_ERROR){
4728     netperf_response.content.serv_errno = errno;
4729     close(s_listen);
4730     send_response();
4731 
4732     exit(1);
4733   }
4734 
4735   /* Now myaddr_in contains the port and the internet address this is */
4736   /* returned to the sender also implicitly telling the sender that the */
4737   /* socket buffer sizing has been done. */
4738 
4739   tcp_maerts_response->data_port_number =
4740     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
4741   netperf_response.content.serv_errno   = 0;
4742 
4743   /* But wait, there's more. If the initiator wanted cpu measurements, */
4744   /* then we must call the calibrate routine, which will return the max */
4745   /* rate back to the initiator. If the CPU was not to be measured, or */
4746   /* something went wrong with the calibration, we will return a -1 to */
4747   /* the initiator. */
4748 
4749   tcp_maerts_response->cpu_rate = (float)0.0; 	/* assume no cpu */
4750   if (tcp_maerts_request->measure_cpu) {
4751     tcp_maerts_response->measure_cpu = 1;
4752     tcp_maerts_response->cpu_rate =
4753       calibrate_local_cpu(tcp_maerts_request->cpu_rate);
4754   }
4755   else {
4756     tcp_maerts_response->measure_cpu = 0;
4757   }
4758 
4759   /* before we send the response back to the initiator, pull some of */
4760   /* the socket parms from the globals */
4761   tcp_maerts_response->send_buf_size = lss_size;
4762   tcp_maerts_response->recv_buf_size = lsr_size;
4763   tcp_maerts_response->no_delay = loc_nodelay;
4764   tcp_maerts_response->so_rcvavoid = loc_rcvavoid;
4765   tcp_maerts_response->so_sndavoid = loc_sndavoid;
4766   tcp_maerts_response->send_size = send_size;
4767 
4768   send_response();
4769 
4770   addrlen = sizeof(peeraddr_in);
4771 
4772   /* we will start the timer before the accept() to be somewhat
4773      analagous to the starting of the timer before the connect() call
4774      in the TCP_STREAM test. raj 2002-06-21 */
4775 
4776   start_timer(tcp_maerts_request->test_length);
4777 
4778   /* Now it's time to start receiving data on the connection. We will
4779      first grab the apropriate counters and then start grabbing. */
4780 
4781   cpu_start(tcp_maerts_request->measure_cpu);
4782 
4783 
4784   if ((s_data=accept(s_listen,
4785 		     (struct sockaddr *)&peeraddr_in,
4786 		     &addrlen)) == INVALID_SOCKET) {
4787     /* Let's just punt. The remote will be given some information */
4788     close(s_listen);
4789     exit(1);
4790   }
4791 
4792 #ifdef KLUDGE_SOCKET_OPTIONS
4793 
4794   /* this is for those systems which *INCORRECTLY* fail to pass
4795      attributes across an accept() call. Including this goes against
4796      my better judgement :( raj 11/95 */
4797 
4798   kludge_socket_options(s_data);
4799 
4800 #endif /* KLUDGE_SOCKET_OPTIONS */
4801 
4802   /* The loop will exit when the sender does a shutdown, which will */
4803   /* return a length of zero   */
4804 
4805   bytes_sent = 0.0;
4806   send_calls  = 0;
4807 
4808   len = 0;   /* nt-lint; len is not initialized (printf far below) if
4809 		times_up initially true.*/
4810   times_up = 0; /* must remember to initialize this little beauty */
4811   while (!times_up) {
4812 
4813 #ifdef DIRTY
4814     /* we want to dirty some number of consecutive integers in the buffer */
4815     /* we are about to send. we may also want to bring some number of */
4816     /* them cleanly into the cache. The clean ones will follow any dirty */
4817     /* ones into the cache. */
4818 
4819   access_buffer(send_ring->buffer_ptr,
4820 		send_size,
4821 		tcp_maerts_request->dirty_count,
4822 		tcp_maerts_request->clean_count);
4823 
4824 #endif /* DIRTY */
4825 
4826     if((len=send(s_data,
4827 		 send_ring->buffer_ptr,
4828 		 send_size,
4829 		 0)) != send_size) {
4830 		if ((len >=0) || SOCKET_EINTR(len)) {
4831 	      /* the test was interrupted, must be the end of test */
4832 	      break;
4833 		}
4834       netperf_response.content.serv_errno = errno;
4835       send_response();
4836       exit(1);
4837     }
4838 
4839     bytes_sent += len;
4840     send_calls++;
4841 
4842     /* more to the next buffer in the send_ring */
4843     send_ring = send_ring->next;
4844 
4845   }
4846 
4847   /* perform a shutdown to signal the sender that */
4848   /* we have received all the data sent. raj 4/93 */
4849 
4850   if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
4851       netperf_response.content.serv_errno = errno;
4852       send_response();
4853       exit(1);
4854     }
4855 
4856   /* hang a recv() off the socket to block until the remote has
4857      brought all the data up into the application. it will do a
4858      shutdown to cause a FIN to be sent our way. We will assume that
4859      any exit from the recv() call is good... raj 4/93 */
4860 
4861   recv(s_data, send_ring->buffer_ptr, send_size, 0);
4862 
4863 
4864   cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time);
4865 
4866   /* send the results to the sender			*/
4867 
4868   if (debug) {
4869     fprintf(where,
4870 	    "recv_tcp_maerts: got %g bytes\n",
4871 	    bytes_sent);
4872     fprintf(where,
4873 	    "recv_tcp_maerts: got %d sends\n",
4874 	    send_calls);
4875     fflush(where);
4876   }
4877 
4878   tcp_maerts_results->bytes_sent	= htond(bytes_sent);
4879   tcp_maerts_results->elapsed_time	= elapsed_time;
4880   tcp_maerts_results->send_calls	= send_calls;
4881 
4882   if (tcp_maerts_request->measure_cpu) {
4883     tcp_maerts_results->cpu_util	= calc_cpu_util(0.0);
4884   };
4885 
4886   if (debug) {
4887     fprintf(where,
4888 	    "recv_tcp_maerts: test complete, sending results.\n");
4889     fprintf(where,
4890 	    "                 bytes_sent %g send_calls %d\n",
4891 	    bytes_sent,
4892 	    send_calls);
4893     fprintf(where,
4894 	    "                 len %d\n",
4895 	    len);
4896     fflush(where);
4897   }
4898 
4899   tcp_maerts_results->cpu_method = cpu_method;
4900   tcp_maerts_results->num_cpus   = lib_num_loc_cpus;
4901   send_response();
4902 
4903   /* we are now done with the sockets */
4904   close(s_data);
4905   close(s_listen);
4906 
4907   }
4908 
4909 
4910  /* this routine implements the sending (netperf) side of the TCP_RR */
4911  /* test. */
4912 
4913 void
send_tcp_rr(char remote_host[])4914 send_tcp_rr(char remote_host[])
4915 {
4916 
4917   char *tput_title = "\
4918 Local /Remote\n\
4919 Socket Size   Request  Resp.   Elapsed  Trans.\n\
4920 Send   Recv   Size     Size    Time     Rate         \n\
4921 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
4922 
4923   char *tput_title_band = "\
4924 Local /Remote\n\
4925 Socket Size   Request  Resp.   Elapsed  \n\
4926 Send   Recv   Size     Size    Time     Throughput \n\
4927 bytes  Bytes  bytes    bytes   secs.    %s/sec   \n\n";
4928 
4929   char *tput_fmt_0 =
4930     "%7.2f %s\n";
4931 
4932   char *tput_fmt_1_line_1 = "\
4933 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   %s\n";
4934   char *tput_fmt_1_line_2 = "\
4935 %-6d %-6d\n";
4936 
4937   char *cpu_title = "\
4938 Local /Remote\n\
4939 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
4940 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
4941 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
4942 
4943   char *cpu_title_tput = "\
4944 Local /Remote\n\
4945 Socket Size   Request Resp.  Elapsed Tput     CPU    CPU    S.dem   S.dem\n\
4946 Send   Recv   Size    Size   Time    %-8.8s local  remote local   remote\n\
4947 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
4948 
4949   char *cpu_fmt_0 =
4950     "%6.3f %c %s\n";
4951 
4952   char *cpu_fmt_1_line_1 = "\
4953 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f %s\n";
4954 
4955   char *cpu_fmt_1_line_2 = "\
4956 %-6d %-6d\n";
4957 
4958   char *ksink_fmt = "\
4959 Alignment      Offset         RoundTrip  Trans    Throughput\n\
4960 Local  Remote  Local  Remote  Latency    Rate     %-8.8s/s\n\
4961 Send   Recv    Send   Recv    usec/Tran  per sec  Outbound   Inbound\n\
4962 %5d  %5d   %5d  %5d   %-6.3f   %-6.3f %-6.3f    %-6.3f\n";
4963 
4964 
4965   int			timed_out = 0;
4966   float			elapsed_time;
4967 
4968   int	len;
4969   char	*temp_message_ptr;
4970   int	nummessages;
4971   SOCKET	send_socket;
4972   int	trans_remaining;
4973   double	bytes_xferd;
4974 
4975   struct ring_elt *send_ring;
4976   struct ring_elt *recv_ring;
4977 
4978   int	rsp_bytes_left;
4979   int	rsp_bytes_recvd;
4980 
4981   float	local_cpu_utilization;
4982   float	local_service_demand;
4983   float	remote_cpu_utilization;
4984   float	remote_service_demand;
4985   double	thruput;
4986 
4987   struct addrinfo *local_res;
4988   struct addrinfo *remote_res;
4989 
4990   struct	tcp_rr_request_struct	*tcp_rr_request;
4991   struct	tcp_rr_response_struct	*tcp_rr_response;
4992   struct	tcp_rr_results_struct	*tcp_rr_result;
4993 
4994 #ifdef WANT_FIRST_BURST
4995 #define REQUEST_CWND_INITIAL 2
4996   /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
4997      Unix and the state of New Jersey - both were simple an unspoiled.
4998      then it was realized that some stacks are quite picky about
4999      initial congestion windows and a non-trivial initial burst of
5000      requests would not be individual segments even with TCP_NODELAY
5001      set. so, we have to start tracking a poor-man's congestion window
5002      up here in window space because we want to try to make something
5003      happen that frankly, we cannot guarantee with the specification
5004      of TCP.  ain't that grand?-)  raj 2006-01-30 */
5005   int requests_outstanding = 0;
5006   int request_cwnd = REQUEST_CWND_INITIAL;  /* we ass-u-me that having
5007 					       three requests
5008 					       outstanding at the
5009 					       beginning of the test
5010 					       is ok with TCP stacks
5011 					       of interest. the first
5012 					       two will come from our
5013 					       first_burst loop, and
5014 					       the third from our
5015 					       regularly scheduled
5016 					       send */
5017 #endif
5018 
5019   tcp_rr_request =
5020     (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
5021   tcp_rr_response=
5022     (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
5023   tcp_rr_result	=
5024     (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
5025 
5026 #ifdef WANT_HISTOGRAM
5027   if (verbosity > 1) {
5028     time_hist = HIST_new();
5029   }
5030 #endif /* WANT_HISTOGRAM */
5031 
5032   /* since we are now disconnected from the code that established the */
5033   /* control socket, and since we want to be able to use different */
5034   /* protocols and such, we are passed the name of the remote host and */
5035   /* must turn that into the test specific addressing information. */
5036 
5037   complete_addrinfos(&remote_res,
5038 		     &local_res,
5039 		     remote_host,
5040 		     SOCK_STREAM,
5041 		     IPPROTO_TCP,
5042 		     0);
5043 
5044   if ( print_headers ) {
5045     print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res);
5046   }
5047 
5048   /* initialize a few counters */
5049 
5050   send_ring = NULL;
5051   recv_ring = NULL;
5052   confidence_iteration = 1;
5053   init_stat();
5054 
5055   /* we have a great-big while loop which controls the number of times */
5056   /* we run a particular test. this is for the calculation of a */
5057   /* confidence interval (I really should have stayed awake during */
5058   /* probstats :). If the user did not request confidence measurement */
5059   /* (no confidence is the default) then we will only go though the */
5060   /* loop once. the confidence stuff originates from the folks at IBM */
5061 
5062   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
5063 	 (confidence_iteration <= iteration_min)) {
5064 
5065     /* initialize a few counters. we have to remember that we might be */
5066     /* going through the loop more than once. */
5067 
5068     nummessages     = 0;
5069     bytes_xferd     = 0.0;
5070     times_up        = 0;
5071     timed_out       = 0;
5072     trans_remaining = 0;
5073 
5074 #ifdef WANT_FIRST_BURST
5075     /* we have to remember to reset the number of transactions
5076        outstanding and the "congestion window for each new
5077        iteration. raj 2006-01-31 */
5078     requests_outstanding = 0;
5079     request_cwnd = REQUEST_CWND_INITIAL;
5080 #endif
5081 
5082 
5083     /* set-up the data buffers with the requested alignment and offset. */
5084     /* since this is a request/response test, default the send_width and */
5085     /* recv_width to 1 and not two raj 7/94 */
5086 
5087     if (send_width == 0) send_width = 1;
5088     if (recv_width == 0) recv_width = 1;
5089 
5090     if (send_ring == NULL) {
5091       send_ring = allocate_buffer_ring(send_width,
5092 				       req_size,
5093 				       local_send_align,
5094 				       local_send_offset);
5095     }
5096 
5097     if (recv_ring == NULL) {
5098       recv_ring = allocate_buffer_ring(recv_width,
5099 				       rsp_size,
5100 				       local_recv_align,
5101 				       local_recv_offset);
5102     }
5103 
5104     /*set up the data socket                        */
5105     send_socket = create_data_socket(local_res);
5106 
5107     if (send_socket == INVALID_SOCKET){
5108       perror("netperf: send_tcp_rr: tcp stream data socket");
5109       exit(1);
5110     }
5111 
5112     if (debug) {
5113       fprintf(where,"send_tcp_rr: send_socket obtained...\n");
5114     }
5115 
5116     /* If the user has requested cpu utilization measurements, we must */
5117     /* calibrate the cpu(s). We will perform this task within the tests */
5118     /* themselves. If the user has specified the cpu rate, then */
5119     /* calibrate_local_cpu will return rather quickly as it will have */
5120     /* nothing to do. If local_cpu_rate is zero, then we will go through */
5121     /* all the "normal" calibration stuff and return the rate back.*/
5122 
5123     if (local_cpu_usage) {
5124       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
5125     }
5126 
5127     if (!no_control) {
5128       /* Tell the remote end to do a listen. The server alters the
5129 	 socket paramters on the other side at this point, hence the
5130 	 reason for all the values being passed in the setup
5131 	 message. If the user did not specify any of the parameters,
5132 	 they will be passed as 0, which will indicate to the remote
5133 	 that no changes beyond the system's default should be
5134 	 used. Alignment is the exception, it will default to 8, which
5135 	 will be no alignment alterations. */
5136 
5137       netperf_request.content.request_type	=	DO_TCP_RR;
5138       tcp_rr_request->recv_buf_size	=	rsr_size_req;
5139       tcp_rr_request->send_buf_size	=	rss_size_req;
5140       tcp_rr_request->recv_alignment    =	remote_recv_align;
5141       tcp_rr_request->recv_offset	=	remote_recv_offset;
5142       tcp_rr_request->send_alignment    =	remote_send_align;
5143       tcp_rr_request->send_offset	=	remote_send_offset;
5144       tcp_rr_request->request_size	=	req_size;
5145       tcp_rr_request->response_size	=	rsp_size;
5146       tcp_rr_request->no_delay	        =	rem_nodelay;
5147       tcp_rr_request->measure_cpu	=	remote_cpu_usage;
5148       tcp_rr_request->cpu_rate	        =	remote_cpu_rate;
5149       tcp_rr_request->so_rcvavoid	=	rem_rcvavoid;
5150       tcp_rr_request->so_sndavoid	=	rem_sndavoid;
5151       if (test_time) {
5152 	tcp_rr_request->test_length	=	test_time;
5153       }
5154       else {
5155 	tcp_rr_request->test_length	=	test_trans * -1;
5156       }
5157       tcp_rr_request->port              =      atoi(remote_data_port);
5158       tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
5159 
5160       if (debug > 1) {
5161 	fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n");
5162       }
5163 
5164       send_request();
5165 
5166       /* The response from the remote will contain all of the relevant
5167 	 socket parameters for this test type. We will put them back
5168 	 into the variables here so they can be displayed if desired.
5169 	 The remote will have calibrated CPU if necessary, and will
5170 	 have done all the needed set-up we will have calibrated the
5171 	 cpu locally before sending the request, and will grab the
5172 	 counter value right after the connect returns. The remote
5173 	 will grab the counter right after the accept call. This saves
5174 	 the hassle of extra messages being sent for the TCP
5175 	 tests.  */
5176 
5177       recv_response();
5178 
5179       if (!netperf_response.content.serv_errno) {
5180 	if (debug)
5181 	  fprintf(where,"remote listen done.\n");
5182 	rsr_size          = tcp_rr_response->recv_buf_size;
5183 	rss_size          = tcp_rr_response->send_buf_size;
5184 	rem_nodelay       = tcp_rr_response->no_delay;
5185 	remote_cpu_usage  = tcp_rr_response->measure_cpu;
5186 	remote_cpu_rate   = tcp_rr_response->cpu_rate;
5187 	/* make sure that port numbers are in network order */
5188 	set_port_number(remote_res,(short)tcp_rr_response->data_port_number);
5189       }
5190       else {
5191 	Set_errno(netperf_response.content.serv_errno);
5192 	fprintf(where,
5193 		"netperf: remote error %d",
5194 		netperf_response.content.serv_errno);
5195 	perror("");
5196 	fflush(where);
5197 
5198 	exit(1);
5199       }
5200     }
5201 
5202 #ifdef WANT_DEMO
5203     DEMO_RR_SETUP(1000)
5204 #endif
5205 
5206     /*Connect up to the remote port on the data socket  */
5207     if (connect(send_socket,
5208 		remote_res->ai_addr,
5209 		remote_res->ai_addrlen) == INVALID_SOCKET){
5210       perror("netperf: data socket connect failed");
5211 
5212       exit(1);
5213     }
5214 
5215     /* Data Socket set-up is finished. If there were problems, either the */
5216     /* connect would have failed, or the previous response would have */
5217     /* indicated a problem. I failed to see the value of the extra */
5218     /* message after the accept on the remote. If it failed, we'll see it */
5219     /* here. If it didn't, we might as well start pumping data. */
5220 
5221     /* Set-up the test end conditions. For a request/response test, they */
5222     /* can be either time or transaction based. */
5223 
5224     if (test_time) {
5225       /* The user wanted to end the test after a period of time. */
5226       times_up = 0;
5227       trans_remaining = 0;
5228       start_timer(test_time);
5229     }
5230     else {
5231       /* The tester wanted to send a number of bytes. */
5232       trans_remaining = test_bytes;
5233       times_up = 1;
5234     }
5235 
5236     /* The cpu_start routine will grab the current time and possibly */
5237     /* value of the idle counter for later use in measuring cpu */
5238     /* utilization and/or service demand and thruput. */
5239 
5240     cpu_start(local_cpu_usage);
5241 
5242 #ifdef WANT_INTERVALS
5243     INTERVALS_INIT();
5244 #endif /* WANT_INTERVALS */
5245 
5246     /* We use an "OR" to control test execution. When the test is */
5247     /* controlled by time, the byte count check will always return false. */
5248     /* When the test is controlled by byte count, the time test will */
5249     /* always return false. When the test is finished, the whole */
5250     /* expression will go false and we will stop sending data. I think I */
5251     /* just arbitrarily decrement trans_remaining for the timed test, but */
5252     /* will not do that just yet... One other question is whether or not */
5253     /* the send buffer and the receive buffer should be the same buffer. */
5254 
5255 #ifdef WANT_DEMO
5256       if (demo_mode) {
5257 	HIST_timestamp(demo_one_ptr);
5258       }
5259 #endif
5260 
5261     while ((!times_up) || (trans_remaining > 0)) {
5262       /* send the request. we assume that if we use a blocking socket, */
5263       /* the request will be sent at one shot. */
5264 
5265 #ifdef WANT_FIRST_BURST
5266       /* we can inject no more than request_cwnd, which will grow with
5267 	 time, and no more than first_burst_size.  we don't use <= to
5268 	 account for the "regularly scheduled" send call.  of course
5269 	 that makes it more a "max_outstanding_ than a
5270 	 "first_burst_size" but for now we won't fix the names. also,
5271 	 I suspect the extra check against < first_burst_size is
5272 	 redundant since later I expect to make sure that request_cwnd
5273 	 can never get larger than first_burst_size, but just at the
5274 	 moment I'm feeling like a belt and suspenders kind of
5275 	 programmer. raj 2006-01-30 */
5276       while ((first_burst_size > 0) &&
5277 	     (requests_outstanding < request_cwnd) &&
5278 	     (requests_outstanding < first_burst_size)) {
5279 	if (debug) {
5280 	  fprintf(where,
5281 		  "injecting, req_outstndng %d req_cwnd %d burst %d\n",
5282 		  requests_outstanding,
5283 		  request_cwnd,
5284 		  first_burst_size);
5285 	}
5286 	if ((len = send(send_socket,
5287 			send_ring->buffer_ptr,
5288 			req_size,
5289 			0)) != req_size) {
5290 	  /* we should never hit the end of the test in the first burst */
5291 	  perror("send_tcp_rr: initial burst data send error");
5292 	  exit(-1);
5293 	}
5294 	requests_outstanding += 1;
5295       }
5296 
5297 #endif /* WANT_FIRST_BURST */
5298 
5299 #ifdef WANT_HISTOGRAM
5300       if (verbosity > 1) {
5301 	/* timestamp just before our call to send, and then again just
5302 	   after the receive raj 8/94 */
5303 	/* but only if we are actually going to display one. raj
5304 	   2007-02-07 */
5305 
5306 	HIST_timestamp(&time_one);
5307       }
5308 #endif /* WANT_HISTOGRAM */
5309 
5310       if ((len = send(send_socket,
5311 		      send_ring->buffer_ptr,
5312 		      req_size,
5313 		      0)) != req_size) {
5314 	if (SOCKET_EINTR(len) || (errno == 0)) {
5315 	  /* we hit the end of a */
5316 	  /* timed test. */
5317 	  timed_out = 1;
5318 	  break;
5319 	}
5320 	perror("send_tcp_rr: data send error");
5321 	exit(1);
5322       }
5323       send_ring = send_ring->next;
5324 
5325 #ifdef WANT_FIRST_BURST
5326       requests_outstanding += 1;
5327 #endif
5328 
5329       /* receive the response */
5330       rsp_bytes_left = rsp_size;
5331       temp_message_ptr  = recv_ring->buffer_ptr;
5332       while(rsp_bytes_left > 0) {
5333 	if((rsp_bytes_recvd=recv(send_socket,
5334 				 temp_message_ptr,
5335 				 rsp_bytes_left,
5336 				 0)) == SOCKET_ERROR) {
5337 		if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
5338 		    /* We hit the end of a timed test. */
5339 			timed_out = 1;
5340 			break;
5341 		}
5342 	  perror("send_tcp_rr: data recv error");
5343 	  exit(1);
5344 	}
5345 	rsp_bytes_left -= rsp_bytes_recvd;
5346 	temp_message_ptr  += rsp_bytes_recvd;
5347       }
5348       recv_ring = recv_ring->next;
5349 
5350 #ifdef WANT_FIRST_BURST
5351       /* so, since we've gotten a response back, update the
5352 	 bookkeeping accordingly.  there is one less request
5353 	 outstanding and we can put one more out there than before. */
5354       requests_outstanding -= 1;
5355       if (request_cwnd < first_burst_size) {
5356 	request_cwnd += 1;
5357 	if (debug) {
5358 	  fprintf(where,
5359 		  "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
5360 		  request_cwnd,
5361 		  first_burst_size,
5362 		  requests_outstanding);
5363 	}
5364       }
5365 #endif
5366       if (timed_out) {
5367 	/* we may have been in a nested while loop - we need */
5368 	/* another call to break. */
5369 	break;
5370       }
5371 
5372 #ifdef WANT_HISTOGRAM
5373       if (verbosity > 1) {
5374 	HIST_timestamp(&time_two);
5375 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
5376       }
5377 #endif /* WANT_HISTOGRAM */
5378 
5379 #ifdef WANT_DEMO
5380       DEMO_RR_INTERVAL(1);
5381 #endif
5382 
5383 #ifdef WANT_INTERVALS
5384       INTERVALS_WAIT();
5385 #endif /* WANT_INTERVALS */
5386 
5387       nummessages++;
5388       if (trans_remaining) {
5389 	trans_remaining--;
5390       }
5391 
5392       if (debug > 3) {
5393 	if ((nummessages % 100) == 0) {
5394 	  fprintf(where,
5395 		  "Transaction %d completed\n",
5396 		  nummessages);
5397 	  fflush(where);
5398 	}
5399       }
5400     }
5401 
5402     /* At this point we used to call shutdown on the data socket to be
5403        sure all the data was delivered, but this was not germane in a
5404        request/response test, and it was causing the tests to "hang"
5405        when they were being controlled by time. So, I have replaced
5406        this shutdown call with a call to close that can be found later
5407        in the procedure. */
5408 
5409     /* this call will always give us the elapsed time for the test,
5410        and will also store-away the necessaries for cpu utilization */
5411 
5412     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
5413 						/* measured? how long */
5414 						/* did we really run? */
5415 
5416     if (!no_control) {
5417       /* Get the statistics from the remote end. The remote will have
5418 	 calculated CPU utilization. If it wasn't supposed to care, it
5419 	 will return obvious values. */
5420 
5421       recv_response();
5422       if (!netperf_response.content.serv_errno) {
5423 	if (debug)
5424 	  fprintf(where,"remote results obtained\n");
5425       }
5426       else {
5427 	Set_errno(netperf_response.content.serv_errno);
5428 	fprintf(where,"netperf: remote error %d",
5429 		netperf_response.content.serv_errno);
5430 	perror("");
5431 	fflush(where);
5432 	exit(1);
5433       }
5434     }
5435 
5436     /* We now calculate what our "throughput" was for the test. */
5437 
5438     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
5439     thruput	= nummessages/elapsed_time;
5440 
5441     if (local_cpu_usage || remote_cpu_usage) {
5442       /* We must now do a little math for service demand and cpu
5443        utilization for the system(s) Of course, some of the
5444        information might be bogus because there was no idle counter in
5445        the kernel(s). We need to make a note of this for the user's
5446        benefit... */
5447       if (local_cpu_usage) {
5448 	local_cpu_utilization = calc_cpu_util(0.0);
5449  	/* since calc_service demand is doing ms/Kunit we will
5450 	   multiply the number of transaction by 1024 to get "good"
5451 	   numbers */
5452 	local_service_demand  = calc_service_demand((double) nummessages*1024,
5453 						    0.0,
5454 						    0.0,
5455 						    0);
5456       }
5457       else {
5458 	local_cpu_utilization	= (float) -1.0;
5459 	local_service_demand	= (float) -1.0;
5460       }
5461 
5462       if (remote_cpu_usage) {
5463 	remote_cpu_utilization = tcp_rr_result->cpu_util;
5464 	/* since calc_service demand is doing ms/Kunit we will
5465 	   multiply the number of transaction by 1024 to get "good"
5466 	   numbers */
5467 	remote_service_demand = calc_service_demand((double) nummessages*1024,
5468 						    0.0,
5469 						    remote_cpu_utilization,
5470 						    tcp_rr_result->num_cpus);
5471       }
5472       else {
5473 	remote_cpu_utilization = (float) -1.0;
5474 	remote_service_demand  = (float) -1.0;
5475       }
5476 
5477     }
5478     else {
5479       /* we were not measuring cpu, for the confidence stuff, we */
5480       /* should make it -1.0 */
5481       local_cpu_utilization	= (float) -1.0;
5482       local_service_demand	= (float) -1.0;
5483       remote_cpu_utilization = (float) -1.0;
5484       remote_service_demand  = (float) -1.0;
5485     }
5486 
5487     /* at this point, we want to calculate the confidence information.
5488        if debugging is on, calculate_confidence will print-out the
5489        parameters we pass it */
5490 
5491     calculate_confidence(confidence_iteration,
5492 			 elapsed_time,
5493 			 thruput,
5494 			 local_cpu_utilization,
5495 			 remote_cpu_utilization,
5496 			 local_service_demand,
5497 			 remote_service_demand);
5498 
5499 
5500     confidence_iteration++;
5501 
5502     /* we are now done with the socket, so close it */
5503     close(send_socket);
5504 
5505   }
5506 
5507   retrieve_confident_values(&elapsed_time,
5508 			    &thruput,
5509 			    &local_cpu_utilization,
5510 			    &remote_cpu_utilization,
5511 			    &local_service_demand,
5512 			    &remote_service_demand);
5513 
5514   /* We are now ready to print all the information. If the user has
5515      specified zero-level verbosity, we will just print the local
5516      service demand, or the remote service demand. If the user has
5517      requested verbosity level 1, he will get the basic "streamperf"
5518      numbers. If the user has specified a verbosity of greater than 1,
5519      we will display a veritable plethora of background information
5520      from outside of this block as it it not cpu_measurement
5521      specific...  */
5522 
5523   if (confidence < 0) {
5524     /* we did not hit confidence, but were we asked to look for it? */
5525     if (iteration_max > 1) {
5526       display_confidence();
5527     }
5528   }
5529 
5530   if (local_cpu_usage || remote_cpu_usage) {
5531     local_cpu_method = format_cpu_method(cpu_method);
5532     remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
5533 
5534     switch (verbosity) {
5535     case 0:
5536       if (local_cpu_usage) {
5537 	fprintf(where,
5538 		cpu_fmt_0,
5539 		local_service_demand,
5540 		local_cpu_method,
5541 		((print_headers) ||
5542 		 (result_brand == NULL)) ? "" : result_brand);
5543       }
5544       else {
5545 	fprintf(where,
5546 		cpu_fmt_0,
5547 		remote_service_demand,
5548 		remote_cpu_method,
5549 		((print_headers) ||
5550 		 (result_brand == NULL)) ? "" : result_brand);
5551       }
5552       break;
5553     case 1:
5554     case 2:
5555       if (print_headers) {
5556 	if ('x' == libfmt) {
5557 	  fprintf(where,
5558 		  cpu_title,
5559 		  local_cpu_method,
5560 		  remote_cpu_method);
5561 	}
5562 	else {
5563 	  fprintf(where,
5564 		  cpu_title_tput,
5565 		  format_units(),
5566 		  local_cpu_method,
5567 		  remote_cpu_method);
5568 	}
5569       }
5570 
5571       fprintf(where,
5572 	      cpu_fmt_1_line_1,		/* the format string */
5573 	      lss_size,		/* local sendbuf size */
5574 	      lsr_size,
5575 	      req_size,		/* how large were the requests */
5576 	      rsp_size,		/* guess */
5577 	      elapsed_time,		/* how long was the test */
5578 	      ('x' == libfmt) ? thruput :
5579 	      calc_thruput_interval_omni(thruput * (req_size+rsp_size),
5580 					 1.0),
5581 	      local_cpu_utilization,	/* local cpu */
5582 	      remote_cpu_utilization,	/* remote cpu */
5583 	      local_service_demand,	/* local service demand */
5584 	      remote_service_demand,	/* remote service demand */
5585 	      ((print_headers) ||
5586 	       (result_brand == NULL)) ? "" : result_brand);
5587       fprintf(where,
5588 	      cpu_fmt_1_line_2,
5589 	      rss_size,
5590 	      rsr_size);
5591       break;
5592     }
5593   }
5594   else {
5595     /* The tester did not wish to measure service demand. */
5596 
5597     switch (verbosity) {
5598     case 0:
5599       fprintf(where,
5600 	      tput_fmt_0,
5601 	      ('x' == libfmt) ? thruput :
5602 	      calc_thruput_interval_omni(thruput * (req_size+rsp_size),
5603 					 1.0),
5604 	      ((print_headers) ||
5605 	       (result_brand == NULL)) ? "" : result_brand);
5606       break;
5607     case 1:
5608     case 2:
5609       if (print_headers) {
5610 	fprintf(where,
5611 		('x' == libfmt) ? tput_title : tput_title_band,
5612 		format_units());
5613       }
5614 
5615       fprintf(where,
5616 	      tput_fmt_1_line_1,	/* the format string */
5617 	      lss_size,
5618 	      lsr_size,
5619 	      req_size,		/* how large were the requests */
5620 	      rsp_size,		/* how large were the responses */
5621 	      elapsed_time, 		/* how long did it take */
5622 	      /* are we trans or do we need to convert to bytes then
5623 		 bits? at this point, thruput is in our "confident"
5624 		 transactions per second. we can convert to a
5625 		 bidirectional bitrate by multiplying that by the sum
5626 		 of the req_size and rsp_size.  we pass that to
5627 		 calc_thruput_interval_omni with an elapsed time of
5628 		 1.0 s to get it converted to [kmg]bits/s or
5629 		 [KMG]Bytes/s */
5630 	      ('x' == libfmt) ?  thruput :
5631 	      calc_thruput_interval_omni(thruput * (req_size+rsp_size),
5632 					 1.0),
5633 	      ((print_headers) ||
5634 	       (result_brand == NULL)) ? "" : result_brand);
5635       fprintf(where,
5636 	      tput_fmt_1_line_2,
5637 	      rss_size, 		/* remote recvbuf size */
5638 	      rsr_size);
5639 
5640       break;
5641     }
5642   }
5643 
5644   /* it would be a good thing to include information about some of the */
5645   /* other parameters that may have been set for this test, but at the */
5646   /* moment, I do not wish to figure-out all the  formatting, so I will */
5647   /* just put this comment here to help remind me that it is something */
5648   /* that should be done at a later time. */
5649 
5650   /* how to handle the verbose information in the presence of */
5651   /* confidence intervals is yet to be determined... raj 11/94 */
5652   if (verbosity > 1) {
5653     /* The user wanted to know it all, so we will give it to him. */
5654     /* This information will include as much as we can find about */
5655     /* TCP statistics, the alignments of the sends and receives */
5656     /* and all that sort of rot... */
5657 
5658     /* normally, you might think that if we were messing about with
5659        the value of libfmt we would need to put it back again, but
5660        since this is basically the last thing we are going to do with
5661        it, it does not matter.  so there :) raj 2007-06-08 */
5662     /* if the user was asking for transactions, then we report
5663        megabits per sedcond for the unidirectional throughput,
5664        otherwise we use the desired units. */
5665     if ('x' == libfmt) {
5666       libfmt = 'm';
5667     }
5668 
5669     fprintf(where,
5670 	    ksink_fmt,
5671 	    format_units(),
5672 	    local_send_align,
5673 	    remote_recv_offset,
5674 	    local_send_offset,
5675 	    remote_recv_offset,
5676 	    /* if the user has enable burst mode, we have to remember
5677 	       to account for that in the number of transactions
5678 	       outstanding at any one time. otherwise we will
5679 	       underreport the latency of individual
5680 	       transactions. learned from saf by raj 2007-06-08  */
5681 	    (((double)1.0/thruput)*(double)1000000.0) *
5682 	    (double) (1+first_burst_size),
5683 	    thruput,
5684 	    calc_thruput_interval_omni(thruput * (double)req_size,1.0),
5685 	    calc_thruput_interval_omni(thruput * (double)rsp_size,1.0));
5686 
5687 #ifdef WANT_HISTOGRAM
5688     fprintf(where,"\nHistogram of request/response times\n");
5689     fflush(where);
5690     HIST_report(time_hist);
5691 #endif /* WANT_HISTOGRAM */
5692 
5693   }
5694 
5695 }
5696 
5697 void
send_udp_stream(char remote_host[])5698 send_udp_stream(char remote_host[])
5699 {
5700   /**********************************************************************/
5701   /*									*/
5702   /*               	UDP Unidirectional Send Test                    */
5703   /*									*/
5704   /**********************************************************************/
5705 
5706 #define UDP_LENGTH_MAX 0XFFFF - 28
5707 
5708   char *tput_title = "\
5709 Socket  Message  Elapsed      Messages                \n\
5710 Size    Size     Time         Okay Errors   Throughput\n\
5711 bytes   bytes    secs            #      #   %s/sec\n\n";
5712 
5713   char *tput_fmt_0 =
5714     "%7.2f\n";
5715 
5716   char *tput_fmt_1 = "\
5717 %6d  %6d   %-7.2f   %7d %6d    %7.2f\n\
5718 %6d           %-7.2f   %7d           %7.2f\n\n";
5719 
5720 
5721   char *cpu_title = "\
5722 Socket  Message  Elapsed      Messages                   CPU      Service\n\
5723 Size    Size     Time         Okay Errors   Throughput   Util     Demand\n\
5724 bytes   bytes    secs            #      #   %s/sec %% %c%c     us/KB\n\n";
5725 
5726   char *cpu_fmt_0 =
5727     "%6.2f %c\n";
5728 
5729   char *cpu_fmt_1 = "\
5730 %6d  %6d   %-7.2f   %7d %6d    %7.1f     %-6.2f   %-6.3f\n\
5731 %6d           %-7.2f   %7d           %7.1f     %-6.2f   %-6.3f\n\n";
5732 
5733   unsigned int	messages_recvd;
5734   unsigned int 	messages_sent;
5735   unsigned int	failed_sends;
5736 
5737   float	elapsed_time,
5738         local_cpu_utilization,
5739         remote_cpu_utilization;
5740 
5741   float	 local_service_demand, remote_service_demand;
5742   double local_thruput, remote_thruput;
5743   double bytes_sent;
5744   double bytes_recvd;
5745 
5746 
5747   int	len;
5748   struct ring_elt *send_ring;
5749   SOCKET 	data_socket;
5750 
5751   unsigned int sum_messages_sent;
5752   unsigned int sum_messages_recvd;
5753   unsigned int sum_failed_sends;
5754   double sum_local_thruput;
5755 
5756   struct addrinfo *local_res;
5757   struct addrinfo *remote_res;
5758 
5759   struct	udp_stream_request_struct	*udp_stream_request;
5760   struct	udp_stream_response_struct	*udp_stream_response;
5761   struct	udp_stream_results_struct	*udp_stream_results;
5762 
5763   udp_stream_request	=
5764     (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
5765   udp_stream_response	=
5766     (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
5767   udp_stream_results	=
5768     (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
5769 
5770 #ifdef WANT_HISTOGRAM
5771   if (verbosity > 1) {
5772     time_hist = HIST_new();
5773   }
5774 #endif /* WANT_HISTOGRAM */
5775 
5776   /* since we are now disconnected from the code that established the */
5777   /* control socket, and since we want to be able to use different */
5778   /* protocols and such, we are passed the name of the remote host and */
5779   /* must turn that into the test specific addressing information. */
5780 
5781   complete_addrinfos(&remote_res,
5782 		     &local_res,
5783 		     remote_host,
5784 		     SOCK_DGRAM,
5785 		     IPPROTO_UDP,
5786 		     0);
5787 
5788   if ( print_headers ) {
5789     print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res);
5790   }
5791 
5792   send_ring            = NULL;
5793   confidence_iteration = 1;
5794   init_stat();
5795   sum_messages_sent    = 0;
5796   sum_messages_recvd   = 0;
5797   sum_failed_sends     = 0;
5798   sum_local_thruput    = 0.0;
5799 
5800   /* we have a great-big while loop which controls the number of times */
5801   /* we run a particular test. this is for the calculation of a */
5802   /* confidence interval (I really should have stayed awake during */
5803   /* probstats :). If the user did not request confidence measurement */
5804   /* (no confidence is the default) then we will only go though the */
5805   /* loop once. the confidence stuff originates from the folks at IBM */
5806 
5807   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
5808 	 (confidence_iteration <= iteration_min)) {
5809 
5810     /* initialize a few counters. we have to remember that we might be */
5811     /* going through the loop more than once. */
5812     messages_sent  = 0;
5813     messages_recvd = 0;
5814     failed_sends   = 0;
5815     times_up       = 0;
5816 
5817     /*set up the data socket			*/
5818     data_socket = create_data_socket(local_res);
5819 
5820     if (data_socket == INVALID_SOCKET){
5821       perror("udp_send: data socket");
5822       exit(1);
5823     }
5824 
5825     /* now, we want to see if we need to set the send_size */
5826     if (send_size == 0) {
5827       if (lss_size > 0) {
5828 	send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX);
5829       }
5830       else {
5831 	send_size = 4096;
5832       }
5833     }
5834 
5835 
5836     /* set-up the data buffer with the requested alignment and offset, */
5837     /* most of the numbers here are just a hack to pick something nice */
5838     /* and big in an attempt to never try to send a buffer a second time */
5839     /* before it leaves the node...unless the user set the width */
5840     /* explicitly. */
5841     if (send_width == 0) send_width = 32;
5842 
5843     if (send_ring == NULL ) {
5844       send_ring = allocate_buffer_ring(send_width,
5845 				       send_size,
5846 				       local_send_align,
5847 				       local_send_offset);
5848     }
5849 
5850 
5851     /* if the user supplied a cpu rate, this call will complete rather */
5852     /* quickly, otherwise, the cpu rate will be retured to us for */
5853     /* possible display. The Library will keep it's own copy of this data */
5854     /* for use elsewhere. We will only display it. (Does that make it */
5855     /* "opaque" to us?) */
5856 
5857     if (local_cpu_usage)
5858       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
5859 
5860     if (!no_control) {
5861       /* Tell the remote end to set up the data connection. The server
5862          sends back the port number and alters the socket parameters
5863          there.  Of course this is a datagram service so no connection
5864          is actually set up, the server just sets up the socket and
5865          binds it. */
5866 
5867       netperf_request.content.request_type      = DO_UDP_STREAM;
5868       udp_stream_request->recv_buf_size  = rsr_size_req;
5869       udp_stream_request->message_size   = send_size;
5870       udp_stream_request->recv_connected = remote_connected;
5871       udp_stream_request->recv_alignment = remote_recv_align;
5872       udp_stream_request->recv_offset    = remote_recv_offset;
5873       udp_stream_request->measure_cpu    = remote_cpu_usage;
5874       udp_stream_request->cpu_rate       = remote_cpu_rate;
5875       udp_stream_request->test_length    = test_time;
5876       udp_stream_request->so_rcvavoid    = rem_rcvavoid;
5877       udp_stream_request->so_sndavoid    = rem_sndavoid;
5878       udp_stream_request->port           = atoi(remote_data_port);
5879       udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
5880 
5881       send_request();
5882 
5883       recv_response();
5884 
5885       if (!netperf_response.content.serv_errno) {
5886 	if (debug)
5887 	  fprintf(where,"send_udp_stream: remote data connection done.\n");
5888       }
5889       else {
5890 	Set_errno(netperf_response.content.serv_errno);
5891 	perror("send_udp_stream: error on remote");
5892 	exit(1);
5893       }
5894 
5895       /* Place the port number returned by the remote into the sockaddr */
5896       /* structure so our sends can be sent to the correct place. Also get */
5897       /* some of the returned socket buffer information for user display. */
5898 
5899       /* make sure that port numbers are in the proper order */
5900       set_port_number(remote_res,(short)udp_stream_response->data_port_number);
5901 
5902       rsr_size        = udp_stream_response->recv_buf_size;
5903       rss_size        = udp_stream_response->send_buf_size;
5904       remote_cpu_rate = udp_stream_response->cpu_rate;
5905     }
5906 
5907 #ifdef WANT_DEMO
5908     DEMO_STREAM_SETUP(lss_size,rsr_size)
5909 #endif
5910 
5911     /* We "connect" up to the remote post to allow is to use the send */
5912     /* call instead of the sendto call. Presumeably, this is a little */
5913     /* simpler, and a little more efficient. I think that it also means */
5914     /* that we can be informed of certain things, but am not sure */
5915     /* yet...also, this is the way I would expect a client to behave */
5916     /* when talking to a server */
5917     if (local_connected) {
5918        if (connect(data_socket,
5919       		   remote_res->ai_addr,
5920 		   remote_res->ai_addrlen) == INVALID_SOCKET){
5921           perror("send_udp_stream: data socket connect failed");
5922           exit(1);
5923        } else if (debug) {
5924           fprintf(where,"send_udp_stream: connected data socket.\n");
5925           fflush(where);
5926        }
5927     }
5928 
5929     /* set up the timer to call us after test_time. one of these days, */
5930     /* it might be nice to figure-out a nice reliable way to have the */
5931     /* test controlled by a byte count as well, but since UDP is not */
5932     /* reliable, that could prove difficult. so, in the meantime, we */
5933     /* only allow a UDP_STREAM test to be a timed test. */
5934 
5935     if (test_time) {
5936       times_up = 0;
5937       start_timer(test_time);
5938     }
5939     else {
5940       fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n");
5941       fflush(where);
5942     }
5943 
5944     /* Get the start count for the idle counter and the start time */
5945 
5946     cpu_start(local_cpu_usage);
5947 
5948 #ifdef WANT_INTERVALS
5949     INTERVALS_INIT();
5950 #endif /* WANT_INTERVALS */
5951 
5952 #ifdef WANT_DEMO
5953     if (demo_mode) {
5954       HIST_timestamp(demo_one_ptr);
5955     }
5956 #endif
5957 
5958     /* Send datagrams like there was no tomorrow. at somepoint it might */
5959     /* be nice to set this up so that a quantity of bytes could be sent, */
5960     /* but we still need some sort of end of test trigger on the receive */
5961     /* side. that could be a select with a one second timeout, but then */
5962     /* if there is a test where none of the data arrives for awile and */
5963     /* then starts again, we would end the test too soon. something to */
5964     /* think about... */
5965     while (!times_up) {
5966 
5967 #ifdef DIRTY
5968       /* we want to dirty some number of consecutive integers in the buffer */
5969       /* we are about to send. we may also want to bring some number of */
5970       /* them cleanly into the cache. The clean ones will follow any dirty */
5971       /* ones into the cache. */
5972 
5973       access_buffer(send_ring->buffer_ptr,
5974 		    send_size,
5975 		    loc_dirty_count,
5976 		    loc_clean_count);
5977 #endif /* DIRTY */
5978 
5979 #ifdef WANT_HISTOGRAM
5980       if (verbosity > 1) {
5981 	HIST_timestamp(&time_one);
5982       }
5983 #endif /* WANT_HISTOGRAM */
5984 
5985       if (local_connected) {
5986          len = send(data_socket,
5987 	  	    send_ring->buffer_ptr,
5988 		    send_size,
5989 		    0);
5990       } else {
5991          len = sendto(data_socket,
5992 		      send_ring->buffer_ptr,
5993 		      send_size,
5994 		      0,
5995 		      remote_res->ai_addr,
5996 		      remote_res->ai_addrlen);
5997       }
5998 
5999       if (len != send_size) {
6000 	if ((len >= 0) ||
6001 	    SOCKET_EINTR(len))
6002 	  break;
6003 	if (errno == ENOBUFS) {
6004 	  failed_sends++;
6005 	  continue;
6006 	}
6007 	perror("udp_send: data send error");
6008 	exit(1);
6009       }
6010       messages_sent++;
6011 
6012       /* now we want to move our pointer to the next position in the */
6013       /* data buffer... */
6014 
6015       send_ring = send_ring->next;
6016 
6017 
6018 #ifdef WANT_HISTOGRAM
6019       if (verbosity > 1) {
6020 	/* get the second timestamp */
6021 	HIST_timestamp(&time_two);
6022 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
6023       }
6024 #endif /* WANT_HISTOGRAM */
6025 
6026 #ifdef WANT_DEMO
6027       DEMO_STREAM_INTERVAL(send_size)
6028 #endif
6029 
6030 #ifdef WANT_INTERVALS
6031       INTERVALS_WAIT();
6032 #endif /* WANT_INTERVALS */
6033 
6034     }
6035 
6036     /* This is a timed test, so the remote will be returning to us after */
6037     /* a time. We should not need to send any "strange" messages to tell */
6038     /* the remote that the test is completed, unless we decide to add a */
6039     /* number of messages to the test. */
6040 
6041     /* the test is over, so get stats and stuff */
6042     cpu_stop(local_cpu_usage,
6043 	     &elapsed_time);
6044 
6045     if (!no_control) {
6046       /* Get the statistics from the remote end	*/
6047       recv_response();
6048       if (!netperf_response.content.serv_errno) {
6049 	if (debug)
6050 	  fprintf(where,"send_udp_stream: remote results obtained\n");
6051       }
6052       else {
6053 	Set_errno(netperf_response.content.serv_errno);
6054 	perror("send_udp_stream: error on remote");
6055 	exit(1);
6056       }
6057       messages_recvd = udp_stream_results->messages_recvd;
6058       bytes_recvd    = (double) send_size * (double) messages_recvd;
6059     }
6060     else {
6061       /* since there was no control connection, we've no idea what was
6062 	 actually received. raj 2007-02-08 */
6063       messages_recvd = -1;
6064       bytes_recvd = -1.0;
6065     }
6066 
6067     bytes_sent    = (double) send_size * (double) messages_sent;
6068     local_thruput = calc_thruput(bytes_sent);
6069 
6070 
6071     /* we asume that the remote ran for as long as we did */
6072 
6073     remote_thruput = calc_thruput(bytes_recvd);
6074 
6075     /* print the results for this socket and message size */
6076 
6077     if (local_cpu_usage || remote_cpu_usage) {
6078       /* We must now do a little math for service demand and cpu */
6079       /* utilization for the system(s) We pass zeros for the local */
6080       /* cpu utilization and elapsed time to tell the routine to use */
6081       /* the libraries own values for those. */
6082       if (local_cpu_usage) {
6083 	local_cpu_utilization	= calc_cpu_util(0.0);
6084 	/* shouldn't this really be based on bytes_recvd, since that is */
6085 	/* the effective throughput of the test? I think that it should, */
6086 	/* so will make the change raj 11/94 */
6087 	local_service_demand	= calc_service_demand(bytes_recvd,
6088 						      0.0,
6089 						      0.0,
6090 						      0);
6091       }
6092       else {
6093 	local_cpu_utilization	= (float) -1.0;
6094 	local_service_demand	= (float) -1.0;
6095       }
6096 
6097       /* The local calculations could use variables being kept by */
6098       /* the local netlib routines. The remote calcuations need to */
6099       /* have a few things passed to them. */
6100       if (remote_cpu_usage) {
6101 	remote_cpu_utilization	= udp_stream_results->cpu_util;
6102 	remote_service_demand	= calc_service_demand(bytes_recvd,
6103 						      0.0,
6104 						      remote_cpu_utilization,
6105 						      udp_stream_results->num_cpus);
6106       }
6107       else {
6108 	remote_cpu_utilization	= (float) -1.0;
6109 	remote_service_demand	= (float) -1.0;
6110       }
6111     }
6112     else {
6113       /* we were not measuring cpu, for the confidence stuff, we */
6114       /* should make it -1.0 */
6115       local_cpu_utilization  = (float) -1.0;
6116       local_service_demand   = (float) -1.0;
6117       remote_cpu_utilization = (float) -1.0;
6118       remote_service_demand  = (float) -1.0;
6119     }
6120 
6121     /* at this point, we want to calculate the confidence information. */
6122     /* if debugging is on, calculate_confidence will print-out the */
6123     /* parameters we pass it */
6124 
6125     calculate_confidence(confidence_iteration,
6126 			 elapsed_time,
6127 			 remote_thruput,
6128 			 local_cpu_utilization,
6129 			 remote_cpu_utilization,
6130 			 local_service_demand,
6131 			 remote_service_demand);
6132 
6133     /* since the routine calculate_confidence is rather generic, and */
6134     /* we have a few other parms of interest, we will do a little work */
6135     /* here to caclulate their average. */
6136     sum_messages_sent  += messages_sent;
6137     sum_messages_recvd += messages_recvd;
6138     sum_failed_sends   += failed_sends;
6139     sum_local_thruput  += local_thruput;
6140 
6141     confidence_iteration++;
6142 
6143     /* this datapoint is done, so we don't need the socket any longer */
6144     close(data_socket);
6145 
6146   }
6147 
6148   /* we should reach this point once the test is finished */
6149 
6150   retrieve_confident_values(&elapsed_time,
6151 			    &remote_thruput,
6152 			    &local_cpu_utilization,
6153 			    &remote_cpu_utilization,
6154 			    &local_service_demand,
6155 			    &remote_service_demand);
6156 
6157   /* some of the interesting values aren't covered by the generic */
6158   /* confidence routine */
6159   messages_sent    = sum_messages_sent / (confidence_iteration -1);
6160   messages_recvd   = sum_messages_recvd / (confidence_iteration -1);
6161   failed_sends     = sum_failed_sends / (confidence_iteration -1);
6162   local_thruput    = sum_local_thruput / (confidence_iteration -1);
6163 
6164   /* We are now ready to print all the information. If the user */
6165   /* has specified zero-level verbosity, we will just print the */
6166   /* local service demand, or the remote service demand. If the */
6167   /* user has requested verbosity level 1, he will get the basic */
6168   /* "streamperf" numbers. If the user has specified a verbosity */
6169   /* of greater than 1, we will display a veritable plethora of */
6170   /* background information from outside of this block as it it */
6171   /* not cpu_measurement specific...  */
6172 
6173 
6174   if (confidence < 0) {
6175     /* we did not hit confidence, but were we asked to look for it? */
6176     if (iteration_max > 1) {
6177       display_confidence();
6178     }
6179   }
6180 
6181   if (local_cpu_usage || remote_cpu_usage) {
6182     local_cpu_method = format_cpu_method(cpu_method);
6183     remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method);
6184 
6185     switch (verbosity) {
6186     case 0:
6187       if (local_cpu_usage) {
6188 	fprintf(where,
6189 		cpu_fmt_0,
6190 		local_service_demand,
6191 		local_cpu_method);
6192       }
6193       else {
6194 	fprintf(where,
6195 		cpu_fmt_0,
6196 		remote_service_demand,
6197 		local_cpu_method);
6198       }
6199       break;
6200     case 1:
6201     case 2:
6202       if (print_headers) {
6203 	fprintf(where,
6204 		cpu_title,
6205 		format_units(),
6206 		local_cpu_method,
6207 		remote_cpu_method);
6208       }
6209 
6210       fprintf(where,
6211 	      cpu_fmt_1,		/* the format string */
6212 	      lss_size,		        /* local sendbuf size */
6213 	      send_size,		/* how large were the sends */
6214 	      elapsed_time,		/* how long was the test */
6215 	      messages_sent,
6216 	      failed_sends,
6217 	      local_thruput, 		/* what was the xfer rate */
6218 	      local_cpu_utilization,	/* local cpu */
6219 	      local_service_demand,	/* local service demand */
6220 	      rsr_size,
6221 	      elapsed_time,
6222 	      messages_recvd,
6223 	      remote_thruput,
6224 	      remote_cpu_utilization,	/* remote cpu */
6225 	      remote_service_demand);	/* remote service demand */
6226       break;
6227     }
6228   }
6229   else {
6230     /* The tester did not wish to measure service demand. */
6231     switch (verbosity) {
6232     case 0:
6233       fprintf(where,
6234 	      tput_fmt_0,
6235 	      local_thruput);
6236       break;
6237     case 1:
6238     case 2:
6239       if (print_headers) {
6240 	fprintf(where,tput_title,format_units());
6241       }
6242       fprintf(where,
6243 	      tput_fmt_1,		/* the format string */
6244 	      lss_size, 		/* local sendbuf size */
6245 	      send_size,		/* how large were the sends */
6246 	      elapsed_time, 		/* how long did it take */
6247 	      messages_sent,
6248 	      failed_sends,
6249 	      local_thruput,
6250 	      rsr_size, 		/* remote recvbuf size */
6251 	      elapsed_time,
6252 	      messages_recvd,
6253 	      remote_thruput);
6254       break;
6255     }
6256   }
6257 
6258   fflush(where);
6259 #ifdef WANT_HISTOGRAM
6260   if (verbosity > 1) {
6261     fprintf(where,"\nHistogram of time spent in send() call\n");
6262     fflush(where);
6263     HIST_report(time_hist);
6264   }
6265 #endif /* WANT_HISTOGRAM */
6266 
6267 }
6268 
6269 
6270  /* this routine implements the receive side (netserver) of the */
6271  /* UDP_STREAM performance test. */
6272 
6273 void
recv_udp_stream()6274 recv_udp_stream()
6275 {
6276   struct ring_elt *recv_ring;
6277   struct addrinfo *local_res;
6278   char local_name[BUFSIZ];
6279   char port_buffer[PORTBUFSIZE];
6280 
6281   struct sockaddr_storage myaddr_in;
6282   SOCKET	s_data;
6283   netperf_socklen_t 	addrlen;
6284   struct sockaddr_storage remote_addr;
6285   netperf_socklen_t remote_addrlen;
6286 
6287   int	len = 0;
6288   unsigned int	bytes_received = 0;
6289   float	elapsed_time;
6290 
6291   int	message_size;
6292   unsigned int	messages_recvd = 0;
6293 
6294   struct	udp_stream_request_struct	*udp_stream_request;
6295   struct	udp_stream_response_struct	*udp_stream_response;
6296   struct	udp_stream_results_struct	*udp_stream_results;
6297 
6298   udp_stream_request  =
6299     (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
6300   udp_stream_response =
6301     (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
6302   udp_stream_results  =
6303     (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
6304 
6305   if (debug) {
6306     fprintf(where,"netserver: recv_udp_stream: entered...\n");
6307     fflush(where);
6308   }
6309 
6310   /* We want to set-up the listen socket with all the desired */
6311   /* parameters and then let the initiator know that all is ready. If */
6312   /* socket size defaults are to be used, then the initiator will have */
6313   /* sent us 0's. If the socket sizes cannot be changed, then we will */
6314   /* send-back what they are. If that information cannot be determined, */
6315   /* then we send-back -1's for the sizes. If things go wrong for any */
6316   /* reason, we will drop back ten yards and punt. */
6317 
6318   /* If anything goes wrong, we want the remote to know about it. It */
6319   /* would be best if the error that the remote reports to the user is */
6320   /* the actual error we encountered, rather than some bogus unexpected */
6321   /* response type message. */
6322 
6323   if (debug > 1) {
6324     fprintf(where,"recv_udp_stream: setting the response type...\n");
6325     fflush(where);
6326   }
6327 
6328   netperf_response.content.response_type = UDP_STREAM_RESPONSE;
6329 
6330   if (debug > 2) {
6331     fprintf(where,"recv_udp_stream: the response type is set...\n");
6332     fflush(where);
6333   }
6334 
6335   /* We now alter the message_ptr variable to be at the desired */
6336   /* alignment with the desired offset. */
6337 
6338   if (debug > 1) {
6339     fprintf(where,"recv_udp_stream: requested alignment of %d\n",
6340 	    udp_stream_request->recv_alignment);
6341     fflush(where);
6342   }
6343 
6344   if (recv_width == 0) recv_width = 1;
6345 
6346   recv_ring = allocate_buffer_ring(recv_width,
6347 				   udp_stream_request->message_size,
6348 				   udp_stream_request->recv_alignment,
6349 				   udp_stream_request->recv_offset);
6350 
6351   if (debug > 1) {
6352     fprintf(where,"recv_udp_stream: receive alignment and offset set...\n");
6353     fflush(where);
6354   }
6355 
6356   /* Grab a socket to listen on, and then listen on it. */
6357 
6358   if (debug > 1) {
6359     fprintf(where,"recv_udp_stream: grabbing a socket...\n");
6360     fflush(where);
6361   }
6362 
6363   /* create_data_socket expects to find some things in the global */
6364   /* variables, so set the globals based on the values in the request. */
6365   /* once the socket has been created, we will set the response values */
6366   /* based on the updated value of those globals. raj 7/94 */
6367   lsr_size_req = udp_stream_request->recv_buf_size;
6368   loc_rcvavoid = udp_stream_request->so_rcvavoid;
6369   loc_sndavoid = udp_stream_request->so_sndavoid;
6370   local_connected = udp_stream_request->recv_connected;
6371 
6372   set_hostname_and_port(local_name,
6373 			port_buffer,
6374 			nf_to_af(udp_stream_request->ipfamily),
6375 			udp_stream_request->port);
6376 
6377   local_res = complete_addrinfo(local_name,
6378 				local_name,
6379 				port_buffer,
6380 				nf_to_af(udp_stream_request->ipfamily),
6381 				SOCK_DGRAM,
6382 				IPPROTO_UDP,
6383 				0);
6384 
6385   s_data = create_data_socket(local_res);
6386 
6387   if (s_data == INVALID_SOCKET) {
6388     netperf_response.content.serv_errno = errno;
6389     send_response();
6390     exit(1);
6391   }
6392 
6393   udp_stream_response->test_length = udp_stream_request->test_length;
6394 
6395   /* now get the port number assigned by the system  */
6396   addrlen = sizeof(myaddr_in);
6397   if (getsockname(s_data,
6398 		  (struct sockaddr *)&myaddr_in,
6399 		  &addrlen) == SOCKET_ERROR){
6400     netperf_response.content.serv_errno = errno;
6401     close(s_data);
6402     send_response();
6403 
6404     exit(1);
6405   }
6406 
6407   /* Now myaddr_in contains the port and the internet address this is */
6408   /* returned to the sender also implicitly telling the sender that the */
6409   /* socket buffer sizing has been done. */
6410 
6411   udp_stream_response->data_port_number =
6412     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
6413   netperf_response.content.serv_errno   = 0;
6414 
6415   /* But wait, there's more. If the initiator wanted cpu measurements, */
6416   /* then we must call the calibrate routine, which will return the max */
6417   /* rate back to the initiator. If the CPU was not to be measured, or */
6418   /* something went wrong with the calibration, we will return a -1 to */
6419   /* the initiator. */
6420 
6421   udp_stream_response->cpu_rate    = (float)0.0; /* assume no cpu */
6422   udp_stream_response->measure_cpu = 0;
6423   if (udp_stream_request->measure_cpu) {
6424     /* We will pass the rate into the calibration routine. If the */
6425     /* user did not specify one, it will be 0.0, and we will do a */
6426     /* "real" calibration. Otherwise, all it will really do is */
6427     /* store it away... */
6428     udp_stream_response->measure_cpu = 1;
6429     udp_stream_response->cpu_rate =
6430       calibrate_local_cpu(udp_stream_request->cpu_rate);
6431   }
6432 
6433   message_size	= udp_stream_request->message_size;
6434   test_time	= udp_stream_request->test_length;
6435 
6436   /* before we send the response back to the initiator, pull some of */
6437   /* the socket parms from the globals */
6438   udp_stream_response->send_buf_size = lss_size;
6439   udp_stream_response->recv_buf_size = lsr_size;
6440   udp_stream_response->so_rcvavoid = loc_rcvavoid;
6441   udp_stream_response->so_sndavoid = loc_sndavoid;
6442 
6443   send_response();
6444 
6445   /* Now it's time to start receiving data on the connection. We will */
6446   /* first grab the apropriate counters and then start grabbing. */
6447 
6448   cpu_start(udp_stream_request->measure_cpu);
6449 
6450 #ifdef WIN32
6451   /* this is used so the timer thread can close the socket out from */
6452   /* under us, which to date is the easiest/cleanest/least */
6453   /* Windows-specific way I can find to force the winsock calls to */
6454   /* return WSAEINTR with the test is over. anything that will run on */
6455   /* 95 and NT and is closer to what netperf expects from Unix signals */
6456   /* and such would be appreciated raj 1/96 */
6457   win_kludge_socket = s_data;
6458 #endif /* WIN32 */
6459 
6460   /* The loop will exit when the timer pops, or if we happen to recv a */
6461   /* message of less than send_size bytes... */
6462 
6463   times_up = 0;
6464 
6465   start_timer(test_time + PAD_TIME);
6466 
6467   if (debug) {
6468     fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n");
6469     fflush(where);
6470   }
6471 
6472   /* We "connect" up to the remote post to allow us to use the recv */
6473   /* call instead of the recvfrom call. Presumeably, this is a little */
6474   /* simpler, and a little more efficient. */
6475 
6476   if (local_connected) {
6477 
6478     /* Receive the first message using recvfrom to find the remote address */
6479     remote_addrlen = sizeof(remote_addr);
6480     len = recvfrom(s_data, recv_ring->buffer_ptr,
6481                    message_size, 0,
6482                    (struct sockaddr*)&remote_addr, &remote_addrlen);
6483     if (len != message_size) {
6484       if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
6485             netperf_response.content.serv_errno = errno;
6486             send_response();
6487             exit(1);
6488       }
6489     }
6490     messages_recvd++;
6491     recv_ring = recv_ring->next;
6492 
6493 
6494     /* Now connect with the remote socket address */
6495     if (connect(s_data,
6496                 (struct sockaddr*)&remote_addr,
6497                 remote_addrlen )== INVALID_SOCKET) {
6498         netperf_response.content.serv_errno = errno;
6499         close(s_data);
6500         send_response();
6501         exit(1);
6502     }
6503 
6504     if (debug) {
6505         fprintf(where,"recv_udp_stream: connected data socket\n");
6506         fflush(where);
6507      }
6508   }
6509 
6510   while (!times_up) {
6511     if(local_connected) {
6512        len = recv(s_data,
6513                   recv_ring->buffer_ptr,
6514                   message_size,
6515                   0);
6516     } else {
6517        len = recvfrom(s_data,
6518                       recv_ring->buffer_ptr,
6519     	              message_size,
6520 		      0,0,0);
6521     }
6522 
6523     if (len != message_size) {
6524       if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
6525             netperf_response.content.serv_errno = errno;
6526 	    send_response();
6527 	    exit(1);
6528       }
6529       break;
6530     }
6531     messages_recvd++;
6532     recv_ring = recv_ring->next;
6533   }
6534 
6535   if (debug) {
6536     fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd);
6537     fflush(where);
6538   }
6539 
6540 
6541   /* The loop now exits due timer or < send_size bytes received. in */
6542   /* reality, we only really support a timed UDP_STREAM test. raj */
6543   /* 12/95 */
6544 
6545   cpu_stop(udp_stream_request->measure_cpu,&elapsed_time);
6546 
6547   if (times_up) {
6548     /* we ended on a timer, subtract the PAD_TIME */
6549     elapsed_time -= (float)PAD_TIME;
6550   }
6551   else {
6552     stop_timer();
6553   }
6554 
6555   if (debug) {
6556     fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time);
6557     fflush(where);
6558   }
6559 
6560 
6561   /* We will count the "off" message that got us out of the loop */
6562   bytes_received = (messages_recvd * message_size) + len;
6563 
6564   /* send the results to the sender			*/
6565 
6566   if (debug) {
6567     fprintf(where,
6568 	    "recv_udp_stream: got %d bytes\n",
6569 	    bytes_received);
6570     fflush(where);
6571   }
6572 
6573   netperf_response.content.response_type	= UDP_STREAM_RESULTS;
6574   udp_stream_results->bytes_received	= htonl(bytes_received);
6575   udp_stream_results->messages_recvd	= messages_recvd;
6576   udp_stream_results->elapsed_time	= elapsed_time;
6577   udp_stream_results->cpu_method        = cpu_method;
6578   udp_stream_results->num_cpus          = lib_num_loc_cpus;
6579   if (udp_stream_request->measure_cpu) {
6580     udp_stream_results->cpu_util	= calc_cpu_util(elapsed_time);
6581   }
6582   else {
6583     udp_stream_results->cpu_util	= (float) -1.0;
6584   }
6585 
6586   if (debug > 1) {
6587     fprintf(where,
6588 	    "recv_udp_stream: test complete, sending results.\n");
6589     fflush(where);
6590   }
6591 
6592   send_response();
6593 
6594   close(s_data);
6595 
6596 }
6597 
6598 void
send_udp_rr(char remote_host[])6599 send_udp_rr(char remote_host[])
6600 {
6601 
6602   char *tput_title = "\
6603 Local /Remote\n\
6604 Socket Size   Request  Resp.   Elapsed  Trans.\n\
6605 Send   Recv   Size     Size    Time     Rate         \n\
6606 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
6607 
6608   char *tput_fmt_0 =
6609     "%7.2f\n";
6610 
6611   char *tput_fmt_1_line_1 = "\
6612 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
6613   char *tput_fmt_1_line_2 = "\
6614 %-6d %-6d\n";
6615 
6616   char *cpu_title = "\
6617 Local /Remote\n\
6618 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
6619 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
6620 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
6621 
6622   char *cpu_fmt_0 =
6623     "%6.3f %c\n";
6624 
6625   char *cpu_fmt_1_line_1 = "\
6626 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
6627 
6628   char *cpu_fmt_1_line_2 = "\
6629 %-6d %-6d\n";
6630 
6631   float			elapsed_time;
6632 
6633   struct ring_elt *send_ring;
6634   struct ring_elt *recv_ring;
6635 
6636   int	len;
6637   int	nummessages;
6638   SOCKET	send_socket;
6639   int	trans_remaining;
6640   int	bytes_xferd;
6641 
6642   int	rsp_bytes_recvd;
6643 
6644   float	local_cpu_utilization;
6645   float	local_service_demand;
6646   float	remote_cpu_utilization;
6647   float	remote_service_demand;
6648   double	thruput;
6649 
6650   struct addrinfo *local_res;
6651   struct addrinfo *remote_res;
6652 
6653   struct	udp_rr_request_struct	*udp_rr_request;
6654   struct	udp_rr_response_struct	*udp_rr_response;
6655   struct	udp_rr_results_struct	*udp_rr_result;
6656 
6657   udp_rr_request  =
6658     (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
6659   udp_rr_response =
6660     (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
6661   udp_rr_result	 =
6662     (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
6663 
6664 #ifdef WANT_HISTOGRAM
6665   if (verbosity > 1) {
6666     time_hist = HIST_new();
6667   }
6668 #endif
6669 
6670   /* since we are now disconnected from the code that established the */
6671   /* control socket, and since we want to be able to use different */
6672   /* protocols and such, we are passed the name of the remote host and */
6673   /* must turn that into the test specific addressing information. */
6674 
6675   complete_addrinfos(&remote_res,
6676 		     &local_res,
6677 		     remote_host,
6678 		     SOCK_DGRAM,
6679 		     IPPROTO_UDP,
6680 		     0);
6681 
6682   if ( print_headers ) {
6683     print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res);
6684   }
6685 
6686   /* initialize a few counters */
6687 
6688   send_ring     = NULL;
6689   recv_ring     = NULL;
6690   nummessages	= 0;
6691   bytes_xferd	= 0;
6692   times_up 	= 0;
6693   confidence_iteration = 1;
6694   init_stat();
6695 
6696   /* we have a great-big while loop which controls the number of times */
6697   /* we run a particular test. this is for the calculation of a */
6698   /* confidence interval (I really should have stayed awake during */
6699   /* probstats :). If the user did not request confidence measurement */
6700   /* (no confidence is the default) then we will only go though the */
6701   /* loop once. the confidence stuff originates from the folks at IBM */
6702 
6703   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
6704 	 (confidence_iteration <= iteration_min)) {
6705 
6706     nummessages     = 0;
6707     bytes_xferd     = 0;
6708     times_up        = 0;
6709     trans_remaining = 0;
6710 
6711     /* set-up the data buffers with the requested alignment and offset */
6712 
6713     if (send_width == 0) send_width = 1;
6714     if (recv_width == 0) recv_width = 1;
6715 
6716     if (send_ring == NULL) {
6717       send_ring = allocate_buffer_ring(send_width,
6718 				       req_size,
6719 				       local_send_align,
6720 				       local_send_offset);
6721     }
6722 
6723     if (recv_ring == NULL) {
6724       recv_ring = allocate_buffer_ring(recv_width,
6725 				       rsp_size,
6726 				       local_recv_align,
6727 				       local_recv_offset);
6728     }
6729 
6730     /*set up the data socket                        */
6731     send_socket = create_data_socket(local_res);
6732 
6733     if (send_socket == INVALID_SOCKET){
6734       perror("netperf: send_udp_rr: udp rr data socket");
6735       exit(1);
6736     }
6737 
6738     if (debug) {
6739       fprintf(where,"send_udp_rr: send_socket obtained...\n");
6740     }
6741 
6742     /* If the user has requested cpu utilization measurements, we must */
6743     /* calibrate the cpu(s). We will perform this task within the tests */
6744     /* themselves. If the user has specified the cpu rate, then */
6745     /* calibrate_local_cpu will return rather quickly as it will have */
6746     /* nothing to do. If local_cpu_rate is zero, then we will go through */
6747     /* all the "normal" calibration stuff and return the rate back. If */
6748     /* there is no idle counter in the kernel idle loop, the */
6749     /* local_cpu_rate will be set to -1. */
6750 
6751     if (local_cpu_usage) {
6752       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
6753     }
6754 
6755     if (!no_control) {
6756       /* Tell the remote end to do a listen. The server alters the
6757 	 socket paramters on the other side at this point, hence the
6758 	 reason for all the values being passed in the setup
6759 	 message. If the user did not specify any of the parameters,
6760 	 they will be passed as 0, which will indicate to the remote
6761 	 that no changes beyond the system's default should be
6762 	 used. Alignment is the exception, it will default to 8, which
6763 	 will be no alignment alterations. */
6764 
6765       netperf_request.content.request_type	= DO_UDP_RR;
6766       udp_rr_request->recv_buf_size	= rsr_size_req;
6767       udp_rr_request->send_buf_size	= rss_size_req;
6768       udp_rr_request->recv_alignment      = remote_recv_align;
6769       udp_rr_request->recv_offset	        = remote_recv_offset;
6770       udp_rr_request->send_alignment      = remote_send_align;
6771       udp_rr_request->send_offset	        = remote_send_offset;
6772       udp_rr_request->request_size	= req_size;
6773       udp_rr_request->response_size	= rsp_size;
6774       udp_rr_request->measure_cpu	        = remote_cpu_usage;
6775       udp_rr_request->cpu_rate	        = remote_cpu_rate;
6776       udp_rr_request->so_rcvavoid	        = rem_rcvavoid;
6777       udp_rr_request->so_sndavoid	        = rem_sndavoid;
6778       if (test_time) {
6779 	udp_rr_request->test_length	= test_time;
6780       }
6781       else {
6782 	udp_rr_request->test_length	= test_trans * -1;
6783       }
6784       udp_rr_request->port                = atoi(remote_data_port);
6785       udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
6786 
6787       if (debug > 1) {
6788 	fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n");
6789       }
6790 
6791       send_request();
6792 
6793       /* The response from the remote will contain all of the relevant
6794 	 socket parameters for this test type. We will put them back
6795 	 into the variables here so they can be displayed if desired.
6796 	 The remote will have calibrated CPU if necessary, and will
6797 	 have done all the needed set-up we will have calibrated the
6798 	 cpu locally before sending the request, and will grab the
6799 	 counter value right after the connect returns. The remote
6800 	 will grab the counter right after the accept call. This saves
6801 	 the hassle of extra messages being sent for the UDP
6802 	 tests.  */
6803 
6804       recv_response();
6805 
6806       if (!netperf_response.content.serv_errno) {
6807 	if (debug)
6808 	  fprintf(where,"remote listen done.\n");
6809 	rsr_size	       =	udp_rr_response->recv_buf_size;
6810 	rss_size	       =	udp_rr_response->send_buf_size;
6811 	remote_cpu_usage =	udp_rr_response->measure_cpu;
6812 	remote_cpu_rate  = 	udp_rr_response->cpu_rate;
6813 	/* port numbers in proper order */
6814 	set_port_number(remote_res,(short)udp_rr_response->data_port_number);
6815       }
6816       else {
6817 	Set_errno(netperf_response.content.serv_errno);
6818 	fprintf(where,
6819 		"netperf: remote error %d",
6820 		netperf_response.content.serv_errno);
6821 	perror("");
6822 	fflush(where);
6823 	exit(1);
6824       }
6825     }
6826 
6827 #ifdef WANT_DEMO
6828     DEMO_RR_SETUP(100)
6829 #endif
6830 
6831     /* Connect up to the remote port on the data socket. This will set */
6832     /* the default destination address on this socket. With UDP, this */
6833     /* does make a performance difference as we may not have to do as */
6834     /* many routing lookups, however, I expect that a client would */
6835     /* behave this way. raj 1/94 */
6836 
6837     if ( connect(send_socket,
6838 		 remote_res->ai_addr,
6839 		 remote_res->ai_addrlen) == INVALID_SOCKET ) {
6840       perror("netperf: data socket connect failed");
6841       exit(1);
6842     }
6843 
6844     /* Data Socket set-up is finished. If there were problems, either the */
6845     /* connect would have failed, or the previous response would have */
6846     /* indicated a problem. I failed to see the value of the extra */
6847     /* message after the accept on the remote. If it failed, we'll see it */
6848     /* here. If it didn't, we might as well start pumping data. */
6849 
6850     /* Set-up the test end conditions. For a request/response test, they */
6851     /* can be either time or transaction based. */
6852 
6853     if (test_time) {
6854       /* The user wanted to end the test after a period of time. */
6855       times_up = 0;
6856       trans_remaining = 0;
6857       start_timer(test_time);
6858     }
6859     else {
6860       /* The tester wanted to send a number of bytes. */
6861       trans_remaining = test_bytes;
6862       times_up = 1;
6863     }
6864 
6865     /* The cpu_start routine will grab the current time and possibly */
6866     /* value of the idle counter for later use in measuring cpu */
6867     /* utilization and/or service demand and thruput. */
6868 
6869     cpu_start(local_cpu_usage);
6870 
6871 #ifdef WANT_DEMO
6872     if (demo_mode) {
6873       HIST_timestamp(demo_one_ptr);
6874     }
6875 #endif
6876 
6877 #ifdef WANT_INTERVALS
6878     INTERVALS_INIT();
6879 #endif /* WANT_INTERVALS */
6880 
6881     /* We use an "OR" to control test execution. When the test is */
6882     /* controlled by time, the byte count check will always return */
6883     /* false. When the test is controlled by byte count, the time test */
6884     /* will always return false. When the test is finished, the whole */
6885     /* expression will go false and we will stop sending data. I think */
6886     /* I just arbitrarily decrement trans_remaining for the timed */
6887     /* test, but will not do that just yet... One other question is */
6888     /* whether or not the send buffer and the receive buffer should be */
6889     /* the same buffer. */
6890 
6891 #ifdef WANT_FIRST_BURST
6892     {
6893       int i;
6894       for (i = 0; i < first_burst_size; i++) {
6895 	if((len=send(send_socket,
6896 		     send_ring->buffer_ptr,
6897 		     req_size,
6898 		     0)) != req_size) {
6899 	  /* we should never hit the end of the test in the first burst */
6900 	  perror("send_udp_rr: initial burst data send error");
6901 	  exit(-1);
6902 	}
6903       }
6904     }
6905 #endif /* WANT_FIRST_BURST */
6906 
6907     while ((!times_up) || (trans_remaining > 0)) {
6908       /* send the request */
6909 #ifdef WANT_HISTOGRAM
6910       if (verbosity > 1) {
6911 	HIST_timestamp(&time_one);
6912       }
6913 #endif
6914       if((len=send(send_socket,
6915 		   send_ring->buffer_ptr,
6916 		   req_size,
6917 		   0)) != req_size) {
6918         if (SOCKET_EINTR(len)) {
6919 	      /* We likely hit */
6920 	      /* test-end time. */
6921 	      break;
6922 		}
6923 	    perror("send_udp_rr: data send error");
6924 	    exit(1);
6925 	  }
6926       send_ring = send_ring->next;
6927 
6928       /* receive the response. with UDP we will get it all, or nothing */
6929 
6930       if((rsp_bytes_recvd=recv(send_socket,
6931 			       recv_ring->buffer_ptr,
6932 			       rsp_size,
6933 			       0)) != rsp_size) {
6934 	    if (SOCKET_EINTR(rsp_bytes_recvd))
6935 		{
6936     	  /* Again, we have likely hit test-end time */
6937 	      break;
6938 		}
6939 	    perror("send_udp_rr: data recv error");
6940 	    exit(1);
6941       }
6942       recv_ring = recv_ring->next;
6943 
6944 #ifdef WANT_HISTOGRAM
6945       if (verbosity > 1) {
6946 	HIST_timestamp(&time_two);
6947 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
6948       }
6949 
6950 #endif
6951 
6952       /* at this point, we may wish to sleep for some period of */
6953       /* time, so we see how long that last transaction just took, */
6954       /* and sleep for the difference of that and the interval. We */
6955       /* will not sleep if the time would be less than a */
6956       /* millisecond.  */
6957 
6958 #ifdef WANT_DEMO
6959       DEMO_RR_INTERVAL(1);
6960 #endif
6961 
6962 #ifdef WANT_INTERVALS
6963       INTERVALS_WAIT();
6964 #endif /* WANT_INTERVALS */
6965 
6966       nummessages++;
6967       if (trans_remaining) {
6968 	trans_remaining--;
6969       }
6970 
6971       if (debug > 3) {
6972 	if ((nummessages % 100) == 0) {
6973 	  fprintf(where,"Transaction %d completed\n",nummessages);
6974 	  fflush(where);
6975 	}
6976       }
6977 
6978     }
6979 
6980     /* for some strange reason, I used to call shutdown on the UDP */
6981     /* data socket here. I'm not sure why, because it would not have */
6982     /* any effect... raj 11/94 */
6983 
6984     /* this call will always give us the elapsed time for the test, and */
6985     /* will also store-away the necessaries for cpu utilization */
6986 
6987     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
6988 						/* measured? how long */
6989 						/* did we really run? */
6990 
6991     if (!no_control) {
6992       /* Get the statistics from the remote end. The remote will have
6993 	 calculated service demand and all those interesting
6994 	 things. If it wasn't supposed to care, it will return obvious
6995 	 values. */
6996 
6997       recv_response();
6998       if (!netperf_response.content.serv_errno) {
6999 	if (debug)
7000 	  fprintf(where,"remote results obtained\n");
7001       }
7002       else {
7003 	Set_errno(netperf_response.content.serv_errno);
7004 	fprintf(where,
7005 		"netperf: remote error %d",
7006 		netperf_response.content.serv_errno);
7007 	perror("");
7008 	fflush(where);
7009 	exit(1);
7010       }
7011     }
7012 
7013     /* We now calculate what our thruput was for the test. In the */
7014     /* future, we may want to include a calculation of the thruput */
7015     /* measured by the remote, but it should be the case that for a */
7016     /* UDP rr test, that the two numbers should be *very* close... */
7017     /* We calculate bytes_sent regardless of the way the test length */
7018     /* was controlled.  */
7019 
7020     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
7021     thruput	= nummessages / elapsed_time;
7022 
7023     if (local_cpu_usage || remote_cpu_usage) {
7024 
7025       /* We must now do a little math for service demand and cpu */
7026       /* utilization for the system(s) Of course, some of the */
7027       /* information might be bogus because there was no idle counter */
7028       /* in the kernel(s). We need to make a note of this for the */
7029       /* user's benefit by placing a code for the metod used in the */
7030       /* test banner */
7031 
7032       if (local_cpu_usage) {
7033 	local_cpu_utilization = calc_cpu_util(0.0);
7034 
7035 	/* since calc_service demand is doing ms/Kunit we will */
7036 	/* multiply the number of transaction by 1024 to get */
7037 	/* "good" numbers */
7038 
7039 	local_service_demand  = calc_service_demand((double) nummessages*1024,
7040 						    0.0,
7041 						    0.0,
7042 						    0);
7043       }
7044       else {
7045 	local_cpu_utilization	= (float) -1.0;
7046 	local_service_demand	= (float) -1.0;
7047       }
7048 
7049       if (remote_cpu_usage) {
7050 	remote_cpu_utilization = udp_rr_result->cpu_util;
7051 
7052 	/* since calc_service demand is doing ms/Kunit we will */
7053 	/* multiply the number of transaction by 1024 to get */
7054 	/* "good" numbers */
7055 
7056 	remote_service_demand  = calc_service_demand((double) nummessages*1024,
7057 						     0.0,
7058 						     remote_cpu_utilization,
7059 						     udp_rr_result->num_cpus);
7060       }
7061       else {
7062 	remote_cpu_utilization = (float) -1.0;
7063 	remote_service_demand  = (float) -1.0;
7064       }
7065     }
7066     else {
7067       /* we were not measuring cpu, for the confidence stuff, we */
7068       /* should make it -1.0 */
7069       local_cpu_utilization	= (float) -1.0;
7070       local_service_demand	= (float) -1.0;
7071       remote_cpu_utilization = (float) -1.0;
7072       remote_service_demand  = (float) -1.0;
7073     }
7074 
7075     /* at this point, we want to calculate the confidence information. */
7076     /* if debugging is on, calculate_confidence will print-out the */
7077     /* parameters we pass it */
7078 
7079     calculate_confidence(confidence_iteration,
7080 			 elapsed_time,
7081 			 thruput,
7082 			 local_cpu_utilization,
7083 			 remote_cpu_utilization,
7084 			 local_service_demand,
7085 			 remote_service_demand);
7086 
7087 
7088     confidence_iteration++;
7089 
7090     /* we are done with the socket */
7091     close(send_socket);
7092   }
7093 
7094   /* at this point, we have made all the iterations we are going to */
7095   /* make. */
7096   retrieve_confident_values(&elapsed_time,
7097 			    &thruput,
7098 			    &local_cpu_utilization,
7099 			    &remote_cpu_utilization,
7100 			    &local_service_demand,
7101 			    &remote_service_demand);
7102 
7103   /* We are now ready to print all the information. If the user */
7104   /* has specified zero-level verbosity, we will just print the */
7105   /* local service demand, or the remote service demand. If the */
7106   /* user has requested verbosity level 1, he will get the basic */
7107   /* "streamperf" numbers. If the user has specified a verbosity */
7108   /* of greater than 1, we will display a veritable plethora of */
7109   /* background information from outside of this block as it it */
7110   /* not cpu_measurement specific...  */
7111 
7112   if (confidence < 0) {
7113     /* we did not hit confidence, but were we asked to look for it? */
7114     if (iteration_max > 1) {
7115       display_confidence();
7116     }
7117   }
7118 
7119   if (local_cpu_usage || remote_cpu_usage) {
7120     local_cpu_method = format_cpu_method(cpu_method);
7121     remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method);
7122 
7123     switch (verbosity) {
7124     case 0:
7125       if (local_cpu_usage) {
7126 	fprintf(where,
7127 		cpu_fmt_0,
7128 		local_service_demand,
7129 		local_cpu_method);
7130       }
7131       else {
7132 	fprintf(where,
7133 		cpu_fmt_0,
7134 		remote_service_demand,
7135 		remote_cpu_method);
7136       }
7137       break;
7138     case 1:
7139     case 2:
7140       if (print_headers) {
7141 	fprintf(where,
7142 		cpu_title,
7143 		local_cpu_method,
7144 		remote_cpu_method);
7145       }
7146 
7147       fprintf(where,
7148 	      cpu_fmt_1_line_1,		/* the format string */
7149 	      lss_size,		/* local sendbuf size */
7150 	      lsr_size,
7151 	      req_size,		/* how large were the requests */
7152 	      rsp_size,		/* guess */
7153 	      elapsed_time,		/* how long was the test */
7154 	      nummessages/elapsed_time,
7155 	      local_cpu_utilization,	/* local cpu */
7156 	      remote_cpu_utilization,	/* remote cpu */
7157 	      local_service_demand,	/* local service demand */
7158 	      remote_service_demand);	/* remote service demand */
7159       fprintf(where,
7160 	      cpu_fmt_1_line_2,
7161 	      rss_size,
7162 	      rsr_size);
7163       break;
7164     }
7165   }
7166   else {
7167     /* The tester did not wish to measure service demand. */
7168     switch (verbosity) {
7169     case 0:
7170       fprintf(where,
7171 	      tput_fmt_0,
7172 	      nummessages/elapsed_time);
7173       break;
7174     case 1:
7175     case 2:
7176       if (print_headers) {
7177 	fprintf(where,tput_title,format_units());
7178       }
7179 
7180       fprintf(where,
7181 	      tput_fmt_1_line_1,	/* the format string */
7182 	      lss_size,
7183 	      lsr_size,
7184 	      req_size,		/* how large were the requests */
7185 	      rsp_size,		/* how large were the responses */
7186 	      elapsed_time, 		/* how long did it take */
7187 	      nummessages/elapsed_time);
7188       fprintf(where,
7189 	      tput_fmt_1_line_2,
7190 	      rss_size, 		/* remote recvbuf size */
7191 	      rsr_size);
7192 
7193       break;
7194     }
7195   }
7196   fflush(where);
7197 
7198   /* it would be a good thing to include information about some of the */
7199   /* other parameters that may have been set for this test, but at the */
7200   /* moment, I do not wish to figure-out all the  formatting, so I will */
7201   /* just put this comment here to help remind me that it is something */
7202   /* that should be done at a later time. */
7203 
7204   /* how to handle the verbose information in the presence of */
7205   /* confidence intervals is yet to be determined... raj 11/94 */
7206 
7207   if (verbosity > 1) {
7208     /* The user wanted to know it all, so we will give it to him. */
7209     /* This information will include as much as we can find about */
7210     /* UDP statistics, the alignments of the sends and receives */
7211     /* and all that sort of rot... */
7212 
7213 #ifdef WANT_HISTOGRAM
7214     fprintf(where,"\nHistogram of request/reponse times.\n");
7215     fflush(where);
7216     HIST_report(time_hist);
7217 #endif /* WANT_HISTOGRAM */
7218   }
7219 }
7220 
7221  /* this routine implements the receive side (netserver) of a UDP_RR */
7222  /* test. */
7223 void
recv_udp_rr()7224 recv_udp_rr()
7225 {
7226 
7227   struct ring_elt *recv_ring;
7228   struct ring_elt *send_ring;
7229 
7230   struct addrinfo *local_res;
7231   char local_name[BUFSIZ];
7232   char port_buffer[PORTBUFSIZE];
7233 
7234   struct sockaddr_storage        myaddr_in;
7235   struct sockaddr_storage    peeraddr;
7236   SOCKET	s_data;
7237   netperf_socklen_t 	addrlen;
7238   int	trans_received;
7239   int	trans_remaining;
7240   int   request_bytes_recvd;
7241   int   response_bytes_sent;
7242   float	elapsed_time;
7243 
7244   struct	udp_rr_request_struct	*udp_rr_request;
7245   struct	udp_rr_response_struct	*udp_rr_response;
7246   struct	udp_rr_results_struct	*udp_rr_results;
7247 
7248   udp_rr_request  =
7249     (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
7250   udp_rr_response =
7251     (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
7252   udp_rr_results  =
7253     (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
7254 
7255   if (debug) {
7256     fprintf(where,"netserver: recv_udp_rr: entered...\n");
7257     fflush(where);
7258   }
7259 
7260   /* We want to set-up the listen socket with all the desired */
7261   /* parameters and then let the initiator know that all is ready. If */
7262   /* socket size defaults are to be used, then the initiator will have */
7263   /* sent us 0's. If the socket sizes cannot be changed, then we will */
7264   /* send-back what they are. If that information cannot be determined, */
7265   /* then we send-back -1's for the sizes. If things go wrong for any */
7266   /* reason, we will drop back ten yards and punt. */
7267 
7268   /* If anything goes wrong, we want the remote to know about it. It */
7269   /* would be best if the error that the remote reports to the user is */
7270   /* the actual error we encountered, rather than some bogus unexpected */
7271   /* response type message. */
7272 
7273   if (debug) {
7274     fprintf(where,"recv_udp_rr: setting the response type...\n");
7275     fflush(where);
7276   }
7277 
7278   netperf_response.content.response_type = UDP_RR_RESPONSE;
7279 
7280   if (debug) {
7281     fprintf(where,"recv_udp_rr: the response type is set...\n");
7282     fflush(where);
7283   }
7284 
7285   /* We now alter the message_ptr variables to be at the desired */
7286   /* alignments with the desired offsets. */
7287 
7288   if (debug) {
7289     fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n",
7290 	    udp_rr_request->recv_alignment,
7291 	    udp_rr_request->recv_offset);
7292     fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n",
7293 	    udp_rr_request->send_alignment,
7294 	    udp_rr_request->send_offset);
7295     fflush(where);
7296   }
7297 
7298   if (send_width == 0) send_width = 1;
7299   if (recv_width == 0) recv_width = 1;
7300 
7301   recv_ring = allocate_buffer_ring(recv_width,
7302 				   udp_rr_request->request_size,
7303 				   udp_rr_request->recv_alignment,
7304 				   udp_rr_request->recv_offset);
7305 
7306   send_ring = allocate_buffer_ring(send_width,
7307 				   udp_rr_request->response_size,
7308 				   udp_rr_request->send_alignment,
7309 				   udp_rr_request->send_offset);
7310 
7311   if (debug) {
7312     fprintf(where,"recv_udp_rr: receive alignment and offset set...\n");
7313     fflush(where);
7314   }
7315 
7316   /* Grab a socket to listen on, and then listen on it. */
7317 
7318   if (debug) {
7319     fprintf(where,"recv_udp_rr: grabbing a socket...\n");
7320     fflush(where);
7321   }
7322 
7323 
7324   /* create_data_socket expects to find some things in the global */
7325   /* variables, so set the globals based on the values in the request. */
7326   /* once the socket has been created, we will set the response values */
7327   /* based on the updated value of those globals. raj 7/94 */
7328   lss_size_req = udp_rr_request->send_buf_size;
7329   lsr_size_req = udp_rr_request->recv_buf_size;
7330   loc_rcvavoid = udp_rr_request->so_rcvavoid;
7331   loc_sndavoid = udp_rr_request->so_sndavoid;
7332 
7333   set_hostname_and_port(local_name,
7334 			port_buffer,
7335 			nf_to_af(udp_rr_request->ipfamily),
7336 			udp_rr_request->port);
7337 
7338   local_res = complete_addrinfo(local_name,
7339 				local_name,
7340 				port_buffer,
7341 				nf_to_af(udp_rr_request->ipfamily),
7342 				SOCK_DGRAM,
7343 				IPPROTO_UDP,
7344 				0);
7345 
7346   s_data = create_data_socket(local_res);
7347 
7348   if (s_data == INVALID_SOCKET) {
7349     netperf_response.content.serv_errno = errno;
7350     send_response();
7351 
7352     exit(1);
7353   }
7354 
7355   /* now get the port number assigned by the system  */
7356   addrlen = sizeof(myaddr_in);
7357   if (getsockname(s_data,
7358 		  (struct sockaddr *)&myaddr_in,
7359 		  &addrlen) == SOCKET_ERROR){
7360     netperf_response.content.serv_errno = errno;
7361     close(s_data);
7362     send_response();
7363 
7364     exit(1);
7365   }
7366 
7367   /* Now myaddr_in contains the port and the internet address this is */
7368   /* returned to the sender also implicitly telling the sender that the */
7369   /* socket buffer sizing has been done. */
7370 
7371   udp_rr_response->data_port_number =
7372     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
7373   netperf_response.content.serv_errno   = 0;
7374 
7375   if (debug) {
7376     fprintf(where,
7377 	    "recv port number %d\n",
7378 	    ((struct sockaddr_in *)&myaddr_in)->sin_port);
7379     fflush(where);
7380   }
7381 
7382   /* But wait, there's more. If the initiator wanted cpu measurements, */
7383   /* then we must call the calibrate routine, which will return the max */
7384   /* rate back to the initiator. If the CPU was not to be measured, or */
7385   /* something went wrong with the calibration, we will return a 0.0 to */
7386   /* the initiator. */
7387 
7388   udp_rr_response->cpu_rate    = (float)0.0; 	/* assume no cpu */
7389   udp_rr_response->measure_cpu = 0;
7390   if (udp_rr_request->measure_cpu) {
7391     udp_rr_response->measure_cpu = 1;
7392     udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate);
7393   }
7394 
7395   /* before we send the response back to the initiator, pull some of */
7396   /* the socket parms from the globals */
7397   udp_rr_response->send_buf_size = lss_size;
7398   udp_rr_response->recv_buf_size = lsr_size;
7399   udp_rr_response->so_rcvavoid   = loc_rcvavoid;
7400   udp_rr_response->so_sndavoid   = loc_sndavoid;
7401 
7402   send_response();
7403 
7404 
7405   /* Now it's time to start receiving data on the connection. We will */
7406   /* first grab the apropriate counters and then start grabbing. */
7407 
7408   cpu_start(udp_rr_request->measure_cpu);
7409 
7410 #ifdef WIN32
7411   /* this is used so the timer thread can close the socket out from */
7412   /* under us, which to date is the easiest/cleanest/least */
7413   /* Windows-specific way I can find to force the winsock calls to */
7414   /* return WSAEINTR with the test is over. anything that will run on */
7415   /* 95 and NT and is closer to what netperf expects from Unix signals */
7416   /* and such would be appreciated raj 1/96 */
7417   win_kludge_socket = s_data;
7418 #endif /* WIN32 */
7419 
7420   if (udp_rr_request->test_length > 0) {
7421     times_up = 0;
7422     trans_remaining = 0;
7423     start_timer(udp_rr_request->test_length + PAD_TIME);
7424   }
7425   else {
7426     times_up = 1;
7427     trans_remaining = udp_rr_request->test_length * -1;
7428   }
7429 
7430   addrlen = sizeof(peeraddr);
7431   bzero((char *)&peeraddr, addrlen);
7432 
7433   trans_received = 0;
7434 
7435   while ((!times_up) || (trans_remaining > 0)) {
7436 
7437     /* receive the request from the other side */
7438     if ((request_bytes_recvd = recvfrom(s_data,
7439 		 recv_ring->buffer_ptr,
7440 		 udp_rr_request->request_size,
7441 		 0,
7442 		 (struct sockaddr *)&peeraddr,
7443 		 &addrlen)) != udp_rr_request->request_size) {
7444 	  if ( SOCKET_EINTR(request_bytes_recvd) )
7445 	  {
7446 	    /* we must have hit the end of test time. */
7447 	    break;
7448       }
7449       netperf_response.content.serv_errno = errno;
7450       send_response();
7451       exit(1);
7452     }
7453     recv_ring = recv_ring->next;
7454 
7455     /* Now, send the response to the remote */
7456     if ((response_bytes_sent = sendto(s_data,
7457 				      send_ring->buffer_ptr,
7458 				      udp_rr_request->response_size,
7459 				      0,
7460 				      (struct sockaddr *)&peeraddr,
7461 				      addrlen)) !=
7462 	udp_rr_request->response_size) {
7463       if ( SOCKET_EINTR(response_bytes_sent) )
7464 	  {
7465 	    /* we have hit end of test time. */
7466 	    break;
7467       }
7468       netperf_response.content.serv_errno = errno;
7469       send_response();
7470       exit(1);
7471     }
7472     send_ring = send_ring->next;
7473 
7474     trans_received++;
7475     if (trans_remaining) {
7476       trans_remaining--;
7477     }
7478 
7479     if (debug) {
7480       fprintf(where,
7481 	      "recv_udp_rr: Transaction %d complete.\n",
7482 	      trans_received);
7483       fflush(where);
7484     }
7485 
7486   }
7487 
7488 
7489   /* The loop now exits due to timeout or transaction count being */
7490   /* reached */
7491 
7492   cpu_stop(udp_rr_request->measure_cpu,&elapsed_time);
7493 
7494   if (times_up) {
7495     /* we ended the test by time, which was at least 2 seconds */
7496     /* longer than we wanted to run. so, we want to subtract */
7497     /* PAD_TIME from the elapsed_time. */
7498     elapsed_time -= PAD_TIME;
7499   }
7500   /* send the results to the sender			*/
7501 
7502   if (debug) {
7503     fprintf(where,
7504 	    "recv_udp_rr: got %d transactions\n",
7505 	    trans_received);
7506     fflush(where);
7507   }
7508 
7509   udp_rr_results->bytes_received = (trans_received *
7510 				    (udp_rr_request->request_size +
7511 				     udp_rr_request->response_size));
7512   udp_rr_results->trans_received = trans_received;
7513   udp_rr_results->elapsed_time	 = elapsed_time;
7514   udp_rr_results->cpu_method     = cpu_method;
7515   udp_rr_results->num_cpus       = lib_num_loc_cpus;
7516   if (udp_rr_request->measure_cpu) {
7517     udp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
7518   }
7519 
7520   if (debug) {
7521     fprintf(where,
7522 	    "recv_udp_rr: test complete, sending results.\n");
7523     fflush(where);
7524   }
7525 
7526   send_response();
7527 
7528   /* we are done with the socket now */
7529   close(s_data);
7530 
7531       }
7532 
7533 
7534  /* this routine implements the receive (netserver) side of a TCP_RR */
7535  /* test */
7536 void
recv_tcp_rr()7537 recv_tcp_rr()
7538 {
7539 
7540   struct ring_elt *send_ring;
7541   struct ring_elt *recv_ring;
7542 
7543   struct addrinfo *local_res;
7544   char local_name[BUFSIZ];
7545   char port_buffer[PORTBUFSIZE];
7546 
7547   struct	sockaddr_storage        myaddr_in,
7548   peeraddr_in;
7549   SOCKET	s_listen,s_data;
7550   netperf_socklen_t 	addrlen;
7551   char	*temp_message_ptr;
7552   int	trans_received;
7553   int	trans_remaining;
7554   int	bytes_sent;
7555   int	request_bytes_recvd;
7556   int	request_bytes_remaining;
7557   int	timed_out = 0;
7558   int   sock_closed = 0;
7559   float	elapsed_time;
7560 
7561   struct	tcp_rr_request_struct	*tcp_rr_request;
7562   struct	tcp_rr_response_struct	*tcp_rr_response;
7563   struct	tcp_rr_results_struct	*tcp_rr_results;
7564 
7565   tcp_rr_request =
7566     (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
7567   tcp_rr_response =
7568     (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
7569   tcp_rr_results =
7570     (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
7571 
7572   if (debug) {
7573     fprintf(where,"netserver: recv_tcp_rr: entered...\n");
7574     fflush(where);
7575   }
7576 
7577   /* We want to set-up the listen socket with all the desired */
7578   /* parameters and then let the initiator know that all is ready. If */
7579   /* socket size defaults are to be used, then the initiator will have */
7580   /* sent us 0's. If the socket sizes cannot be changed, then we will */
7581   /* send-back what they are. If that information cannot be determined, */
7582   /* then we send-back -1's for the sizes. If things go wrong for any */
7583   /* reason, we will drop back ten yards and punt. */
7584 
7585   /* If anything goes wrong, we want the remote to know about it. It */
7586   /* would be best if the error that the remote reports to the user is */
7587   /* the actual error we encountered, rather than some bogus unexpected */
7588   /* response type message. */
7589 
7590   if (debug) {
7591     fprintf(where,"recv_tcp_rr: setting the response type...\n");
7592     fflush(where);
7593   }
7594 
7595   netperf_response.content.response_type = TCP_RR_RESPONSE;
7596 
7597   if (debug) {
7598     fprintf(where,"recv_tcp_rr: the response type is set...\n");
7599     fflush(where);
7600   }
7601 
7602   /* allocate the recv and send rings with the requested alignments */
7603   /* and offsets. raj 7/94 */
7604   if (debug) {
7605     fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n",
7606 	    tcp_rr_request->recv_alignment,
7607 	    tcp_rr_request->recv_offset);
7608     fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n",
7609 	    tcp_rr_request->send_alignment,
7610 	    tcp_rr_request->send_offset);
7611     fflush(where);
7612   }
7613 
7614   /* at some point, these need to come to us from the remote system */
7615   if (send_width == 0) send_width = 1;
7616   if (recv_width == 0) recv_width = 1;
7617 
7618   send_ring = allocate_buffer_ring(send_width,
7619 				   tcp_rr_request->response_size,
7620 				   tcp_rr_request->send_alignment,
7621 				   tcp_rr_request->send_offset);
7622 
7623   recv_ring = allocate_buffer_ring(recv_width,
7624 				   tcp_rr_request->request_size,
7625 				   tcp_rr_request->recv_alignment,
7626 				   tcp_rr_request->recv_offset);
7627 
7628 
7629   /* Grab a socket to listen on, and then listen on it. */
7630 
7631   if (debug) {
7632     fprintf(where,"recv_tcp_rr: grabbing a socket...\n");
7633     fflush(where);
7634   }
7635 
7636   /* create_data_socket expects to find some things in the global */
7637   /* variables, so set the globals based on the values in the request. */
7638   /* once the socket has been created, we will set the response values */
7639   /* based on the updated value of those globals. raj 7/94 */
7640   lss_size_req = tcp_rr_request->send_buf_size;
7641   lsr_size_req = tcp_rr_request->recv_buf_size;
7642   loc_nodelay = tcp_rr_request->no_delay;
7643   loc_rcvavoid = tcp_rr_request->so_rcvavoid;
7644   loc_sndavoid = tcp_rr_request->so_sndavoid;
7645 
7646   set_hostname_and_port(local_name,
7647 			port_buffer,
7648 			nf_to_af(tcp_rr_request->ipfamily),
7649 			tcp_rr_request->port);
7650 
7651   local_res = complete_addrinfo(local_name,
7652 				local_name,
7653 				port_buffer,
7654 				nf_to_af(tcp_rr_request->ipfamily),
7655 				SOCK_STREAM,
7656 				IPPROTO_TCP,
7657 				0);
7658 
7659   s_listen = create_data_socket(local_res);
7660 
7661   if (s_listen == INVALID_SOCKET) {
7662     netperf_response.content.serv_errno = errno;
7663     send_response();
7664 
7665     exit(1);
7666   }
7667 
7668 
7669 #ifdef WIN32
7670   /* The test timer can fire during operations on the listening socket,
7671      so to make the start_timer below work we have to move
7672      it to close s_listen while we are blocked on accept. */
7673   win_kludge_socket2 = s_listen;
7674 #endif
7675 
7676 
7677   /* Now, let's set-up the socket to listen for connections */
7678   if (listen(s_listen, 5) == SOCKET_ERROR) {
7679     netperf_response.content.serv_errno = errno;
7680     close(s_listen);
7681     send_response();
7682 
7683     exit(1);
7684   }
7685 
7686 
7687   /* now get the port number assigned by the system  */
7688   addrlen = sizeof(myaddr_in);
7689   if (getsockname(s_listen,
7690 		  (struct sockaddr *)&myaddr_in,
7691 		  &addrlen) == SOCKET_ERROR) {
7692     netperf_response.content.serv_errno = errno;
7693     close(s_listen);
7694     send_response();
7695 
7696     exit(1);
7697   }
7698 
7699   /* Now myaddr_in contains the port and the internet address this is */
7700   /* returned to the sender also implicitly telling the sender that the */
7701   /* socket buffer sizing has been done. */
7702 
7703   tcp_rr_response->data_port_number =
7704     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
7705   netperf_response.content.serv_errno   = 0;
7706 
7707   /* But wait, there's more. If the initiator wanted cpu measurements, */
7708   /* then we must call the calibrate routine, which will return the max */
7709   /* rate back to the initiator. If the CPU was not to be measured, or */
7710   /* something went wrong with the calibration, we will return a 0.0 to */
7711   /* the initiator. */
7712 
7713   tcp_rr_response->cpu_rate = (float)0.0; 	/* assume no cpu */
7714   tcp_rr_response->measure_cpu = 0;
7715 
7716   if (tcp_rr_request->measure_cpu) {
7717     tcp_rr_response->measure_cpu = 1;
7718     tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
7719   }
7720 
7721 
7722   /* before we send the response back to the initiator, pull some of */
7723   /* the socket parms from the globals */
7724   tcp_rr_response->send_buf_size = lss_size;
7725   tcp_rr_response->recv_buf_size = lsr_size;
7726   tcp_rr_response->no_delay = loc_nodelay;
7727   tcp_rr_response->so_rcvavoid = loc_rcvavoid;
7728   tcp_rr_response->so_sndavoid = loc_sndavoid;
7729   tcp_rr_response->test_length = tcp_rr_request->test_length;
7730   send_response();
7731 
7732   addrlen = sizeof(peeraddr_in);
7733 
7734   if ((s_data = accept(s_listen,
7735 		       (struct sockaddr *)&peeraddr_in,
7736 		       &addrlen)) == INVALID_SOCKET) {
7737     /* Let's just punt. The remote will be given some information */
7738     close(s_listen);
7739 
7740     exit(1);
7741   }
7742 
7743 #ifdef KLUDGE_SOCKET_OPTIONS
7744   /* this is for those systems which *INCORRECTLY* fail to pass */
7745   /* attributes across an accept() call. Including this goes against */
7746   /* my better judgement :( raj 11/95 */
7747 
7748   kludge_socket_options(s_data);
7749 
7750 #endif /* KLUDGE_SOCKET_OPTIONS */
7751 
7752 #ifdef WIN32
7753   /* this is used so the timer thread can close the socket out from */
7754   /* under us, which to date is the easiest/cleanest/least */
7755   /* Windows-specific way I can find to force the winsock calls to */
7756   /* return WSAEINTR with the test is over. anything that will run on */
7757   /* 95 and NT and is closer to what netperf expects from Unix signals */
7758   /* and such would be appreciated raj 1/96 */
7759   win_kludge_socket = s_data;
7760 #endif /* WIN32 */
7761 
7762   if (debug) {
7763     fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n");
7764     fflush(where);
7765   }
7766 
7767   /* Now it's time to start receiving data on the connection. We will */
7768   /* first grab the apropriate counters and then start grabbing. */
7769 
7770   cpu_start(tcp_rr_request->measure_cpu);
7771 
7772   /* The loop will exit when we hit the end of the test time, or when */
7773   /* we have exchanged the requested number of transactions. */
7774 
7775   if (tcp_rr_request->test_length > 0) {
7776     times_up = 0;
7777     trans_remaining = 0;
7778     start_timer(tcp_rr_request->test_length + PAD_TIME);
7779   }
7780   else {
7781     times_up = 1;
7782     trans_remaining = tcp_rr_request->test_length * -1;
7783   }
7784 
7785   trans_received = 0;
7786 
7787   while ((!times_up) || (trans_remaining > 0)) {
7788     temp_message_ptr = recv_ring->buffer_ptr;
7789     request_bytes_remaining	= tcp_rr_request->request_size;
7790     while(request_bytes_remaining > 0) {
7791       if((request_bytes_recvd=recv(s_data,
7792 				   temp_message_ptr,
7793 				   request_bytes_remaining,
7794 				   0)) == SOCKET_ERROR) {
7795 	if (SOCKET_EINTR(request_bytes_recvd))
7796 	{
7797 	  timed_out = 1;
7798 	  break;
7799 	}
7800 
7801 	netperf_response.content.serv_errno = errno;
7802 	send_response();
7803 	exit(1);
7804       }
7805       else if( request_bytes_recvd == 0 ) {
7806 	if (debug) {
7807 	  fprintf(where,"zero is my hero\n");
7808 	  fflush(where);
7809 	}
7810 	sock_closed = 1;
7811 	break;
7812       }
7813       else {
7814 	request_bytes_remaining -= request_bytes_recvd;
7815 	temp_message_ptr  += request_bytes_recvd;
7816       }
7817     }
7818 
7819     recv_ring = recv_ring->next;
7820 
7821     if ((timed_out) || (sock_closed)) {
7822       /* we hit the end of the test based on time - or the socket
7823 	 closed on us along the way.  bail out of here now... */
7824       if (debug) {
7825 	fprintf(where,"yo5\n");
7826 	fflush(where);
7827       }
7828       break;
7829     }
7830 
7831     /* Now, send the response to the remote */
7832     if((bytes_sent=send(s_data,
7833 			send_ring->buffer_ptr,
7834 			tcp_rr_request->response_size,
7835 			0)) == SOCKET_ERROR) {
7836       if (SOCKET_EINTR(bytes_sent)) {
7837 	/* the test timer has popped */
7838 	timed_out = 1;
7839 	fprintf(where,"yo6\n");
7840 	fflush(where);
7841 	break;
7842       }
7843       netperf_response.content.serv_errno = 992;
7844       send_response();
7845       exit(1);
7846     }
7847 
7848     send_ring = send_ring->next;
7849 
7850     trans_received++;
7851     if (trans_remaining) {
7852       trans_remaining--;
7853     }
7854   }
7855 
7856 
7857   /* The loop now exits due to timeout or transaction count being */
7858   /* reached */
7859 
7860   cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
7861 
7862   stop_timer();
7863 
7864   if (timed_out) {
7865     /* we ended the test by time, which was at least 2 seconds */
7866     /* longer than we wanted to run. so, we want to subtract */
7867     /* PAD_TIME from the elapsed_time. */
7868     elapsed_time -= PAD_TIME;
7869   }
7870 
7871   /* send the results to the sender			*/
7872 
7873   if (debug) {
7874     fprintf(where,
7875 	    "recv_tcp_rr: got %d transactions\n",
7876 	    trans_received);
7877     fflush(where);
7878   }
7879 
7880   tcp_rr_results->bytes_received = (trans_received *
7881 				    (tcp_rr_request->request_size +
7882 				     tcp_rr_request->response_size));
7883   tcp_rr_results->trans_received = trans_received;
7884   tcp_rr_results->elapsed_time   = elapsed_time;
7885   tcp_rr_results->cpu_method     = cpu_method;
7886   tcp_rr_results->num_cpus       = lib_num_loc_cpus;
7887   if (tcp_rr_request->measure_cpu) {
7888     tcp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
7889   }
7890 
7891   if (debug) {
7892     fprintf(where,
7893 	    "recv_tcp_rr: test complete, sending results.\n");
7894     fflush(where);
7895   }
7896 
7897   /* we are now done with the sockets */
7898   close(s_data);
7899   close(s_listen);
7900 
7901   send_response();
7902 
7903 }
7904 
7905 
7906 void
loc_cpu_rate()7907 loc_cpu_rate()
7908 {
7909 #if defined(USE_LOOPER)
7910   float dummy;
7911 #endif
7912 
7913   /* a rather simple little test - it merely calibrates the local cpu */
7914   /* and prints the results. There are no headers to allow someone to */
7915   /* find a rate and use it in other tests automagically by setting a */
7916   /* variable equal to the output of this test. We ignore any rates */
7917   /* that may have been specified. In fact, we ignore all of the */
7918   /* command line args! */
7919 
7920   fprintf(where,
7921 	  "%g",
7922 	  calibrate_local_cpu(0.0));
7923 
7924   if (verbosity > 1)
7925     fprintf(where,
7926 	    "\nThere %s %d local %s\n",
7927 	    (lib_num_loc_cpus > 1) ? "are" : "is",
7928 	    lib_num_loc_cpus,
7929 	    (lib_num_loc_cpus > 1) ? "cpus" : "cpu");
7930 
7931   /* we need the cpu_start, cpu_stop in the looper case to kill the */
7932   /* child proceses raj 4/95 */
7933 
7934 #ifdef USE_LOOPER
7935   cpu_start(1);
7936   cpu_stop(1,&dummy);
7937 #endif /* USE_LOOPER */
7938 
7939 }
7940 
7941 void
rem_cpu_rate()7942 rem_cpu_rate()
7943 {
7944   /* this test is much like the local variant, except that it works for */
7945   /* the remote system, so in this case, we do pay attention to the */
7946   /* value of the '-H' command line argument. */
7947 
7948   fprintf(where,
7949 	  "%g",
7950 	  calibrate_remote_cpu());
7951 
7952   if (verbosity > 1)
7953     fprintf(where,
7954 	    "\nThere %s %d remote %s\n",
7955 	    (lib_num_rem_cpus > 1) ? "are" : "is",
7956 	    lib_num_rem_cpus,
7957 	    (lib_num_rem_cpus > 1) ? "cpus" : "cpu");
7958 
7959 }
7960 
7961 
7962  /* this test is intended to test the performance of establishing a
7963     connection, exchanging a request/response pair, and repeating. it
7964     is expected that this would be a good starting-point for
7965     comparision of T/TCP with classic TCP for transactional workloads.
7966     it will also look (can look) much like the communication pattern
7967     of http for www access. */
7968 
7969 void
send_tcp_conn_rr(char remote_host[])7970 send_tcp_conn_rr(char remote_host[])
7971 {
7972 
7973   char *tput_title = "\
7974 Local /Remote\n\
7975 Socket Size   Request  Resp.   Elapsed  Trans.\n\
7976 Send   Recv   Size     Size    Time     Rate         \n\
7977 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
7978 
7979   char *tput_fmt_0 =
7980     "%7.2f\n";
7981 
7982   char *tput_fmt_1_line_1 = "\
7983 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
7984   char *tput_fmt_1_line_2 = "\
7985 %-6d %-6d\n";
7986 
7987   char *cpu_title = "\
7988 Local /Remote\n\
7989 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
7990 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
7991 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
7992 
7993   char *cpu_fmt_0 =
7994     "%6.3f\n";
7995 
7996   char *cpu_fmt_1_line_1 = "\
7997 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
7998 
7999   char *cpu_fmt_1_line_2 = "\
8000 %-6d %-6d\n";
8001 
8002   char *ksink_fmt = "\n\
8003 Alignment      Offset\n\
8004 Local  Remote  Local  Remote\n\
8005 Send   Recv    Send   Recv\n\
8006 %5d  %5d   %5d  %5d\n";
8007 
8008 
8009   int			timed_out = 0;
8010   float			elapsed_time;
8011 
8012   int	len;
8013   struct ring_elt *send_ring;
8014   struct ring_elt *recv_ring;
8015   char	*temp_message_ptr;
8016   int	nummessages;
8017   SOCKET	send_socket;
8018   int	trans_remaining;
8019   double	bytes_xferd;
8020   int	rsp_bytes_left;
8021   int	rsp_bytes_recvd;
8022 
8023   float	local_cpu_utilization;
8024   float	local_service_demand;
8025   float	remote_cpu_utilization;
8026   float	remote_service_demand;
8027   double	thruput;
8028 
8029   struct addrinfo *local_res;
8030   struct addrinfo *remote_res;
8031 
8032   int                           myport;
8033   int                           ret;
8034 
8035   struct	tcp_conn_rr_request_struct	*tcp_conn_rr_request;
8036   struct	tcp_conn_rr_response_struct	*tcp_conn_rr_response;
8037   struct	tcp_conn_rr_results_struct	*tcp_conn_rr_result;
8038 
8039   tcp_conn_rr_request =
8040     (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
8041   tcp_conn_rr_response =
8042     (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
8043   tcp_conn_rr_result =
8044     (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
8045 
8046 
8047 #ifdef WANT_HISTOGRAM
8048   if (verbosity > 1) {
8049     time_hist = HIST_new();
8050   }
8051 #endif /* WANT_HISTOGRAM */
8052 
8053   /* since we are now disconnected from the code that established the */
8054   /* control socket, and since we want to be able to use different */
8055   /* protocols and such, we are passed the name of the remote host and */
8056   /* must turn that into the test specific addressing information. */
8057 
8058   complete_addrinfos(&remote_res,
8059 		     &local_res,
8060 		     remote_host,
8061 		     SOCK_STREAM,
8062 		     IPPROTO_TCP,
8063 		     0);
8064 
8065   if ( print_headers ) {
8066     print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res);
8067   }
8068 
8069   /* initialize a few counters */
8070 
8071   nummessages	=	0;
8072   bytes_xferd	=	0.0;
8073   times_up 	= 	0;
8074 
8075   /* set-up the data buffers with the requested alignment and offset */
8076   if (send_width == 0) send_width = 1;
8077   if (recv_width == 0) recv_width = 1;
8078 
8079   send_ring = allocate_buffer_ring(send_width,
8080 				   req_size,
8081 				   local_send_align,
8082 				   local_send_offset);
8083 
8084   recv_ring = allocate_buffer_ring(recv_width,
8085 				   rsp_size,
8086 				   local_recv_align,
8087 				   local_recv_offset);
8088 
8089 
8090   if (debug) {
8091     fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n");
8092   }
8093 
8094   /* If the user has requested cpu utilization measurements, we must */
8095   /* calibrate the cpu(s). We will perform this task within the tests */
8096   /* themselves. If the user has specified the cpu rate, then */
8097   /* calibrate_local_cpu will return rather quickly as it will have */
8098   /* nothing to do. If local_cpu_rate is zero, then we will go through */
8099   /* all the "normal" calibration stuff and return the rate back.*/
8100 
8101   if (local_cpu_usage) {
8102     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
8103   }
8104 
8105   if (!no_control) {
8106 
8107     /* Tell the remote end to do a listen. The server alters the
8108        socket paramters on the other side at this point, hence the
8109        reason for all the values being passed in the setup message. If
8110        the user did not specify any of the parameters, they will be
8111        passed as 0, which will indicate to the remote that no changes
8112        beyond the system's default should be used. Alignment is the
8113        exception, it will default to 8, which will be no alignment
8114        alterations. */
8115 
8116     netperf_request.content.request_type =	DO_TCP_CRR;
8117     tcp_conn_rr_request->recv_buf_size	=	rsr_size_req;
8118     tcp_conn_rr_request->send_buf_size	=	rss_size_req;
8119     tcp_conn_rr_request->recv_alignment	=	remote_recv_align;
8120     tcp_conn_rr_request->recv_offset	=	remote_recv_offset;
8121     tcp_conn_rr_request->send_alignment	=	remote_send_align;
8122     tcp_conn_rr_request->send_offset	=	remote_send_offset;
8123     tcp_conn_rr_request->request_size	=	req_size;
8124     tcp_conn_rr_request->response_size	=	rsp_size;
8125     tcp_conn_rr_request->no_delay	=	rem_nodelay;
8126     tcp_conn_rr_request->measure_cpu	=	remote_cpu_usage;
8127     tcp_conn_rr_request->cpu_rate	=	remote_cpu_rate;
8128     tcp_conn_rr_request->so_rcvavoid	=	rem_rcvavoid;
8129     tcp_conn_rr_request->so_sndavoid	=	rem_sndavoid;
8130     if (test_time) {
8131       tcp_conn_rr_request->test_length	=	test_time;
8132     }
8133     else {
8134       tcp_conn_rr_request->test_length	=	test_trans * -1;
8135     }
8136     tcp_conn_rr_request->port           = atoi(remote_data_port);
8137     tcp_conn_rr_request->ipfamily       = af_to_nf(remote_res->ai_family);
8138 
8139     if (debug > 1) {
8140       fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n");
8141     }
8142 
8143     send_request();
8144 
8145     /* The response from the remote will contain all of the relevant
8146        socket parameters for this test type. We will put them back
8147        into the variables here so they can be displayed if desired.
8148        The remote will have calibrated CPU if necessary, and will have
8149        done all the needed set-up we will have calibrated the cpu
8150        locally before sending the request, and will grab the counter
8151        value right after the connect returns. The remote will grab the
8152        counter right after the accept call. This saves the hassle of
8153        extra messages being sent for the TCP tests.  */
8154 
8155     recv_response();
8156 
8157     if (!netperf_response.content.serv_errno) {
8158       rsr_size	       =	tcp_conn_rr_response->recv_buf_size;
8159       rss_size	       =	tcp_conn_rr_response->send_buf_size;
8160       rem_nodelay      =	tcp_conn_rr_response->no_delay;
8161       remote_cpu_usage =	tcp_conn_rr_response->measure_cpu;
8162       remote_cpu_rate  = 	tcp_conn_rr_response->cpu_rate;
8163       /* make sure that port numbers are in network order */
8164       set_port_number(remote_res,
8165 		      (unsigned short)tcp_conn_rr_response->data_port_number);
8166 
8167       if (debug) {
8168 	fprintf(where,"remote listen done.\n");
8169 	fprintf(where,"remote port is %u\n",get_port_number(remote_res));
8170 	fflush(where);
8171       }
8172     }
8173     else {
8174       Set_errno(netperf_response.content.serv_errno);
8175       fprintf(where,
8176 	      "netperf: remote error %d",
8177 	      netperf_response.content.serv_errno);
8178       perror("");
8179       fflush(where);
8180       exit(1);
8181     }
8182   }
8183 #ifdef WANT_DEMO
8184   DEMO_RR_SETUP(100)
8185 #endif
8186 
8187   /* pick a nice random spot between client_port_min and */
8188   /* client_port_max for our initial port number */
8189   srand(getpid());
8190   if (client_port_max - client_port_min) {
8191     myport = client_port_min +
8192       (rand() % (client_port_max - client_port_min));
8193   }
8194   else {
8195     myport = client_port_min;
8196   }
8197   /* there will be a ++ before the first call to bind, so subtract one */
8198   myport--;
8199   /* Set-up the test end conditions. For a request/response test, they */
8200   /* can be either time or transaction based. */
8201 
8202   if (test_time) {
8203     /* The user wanted to end the test after a period of time. */
8204     times_up = 0;
8205     trans_remaining = 0;
8206     start_timer(test_time);
8207   }
8208   else {
8209     /* The tester wanted to send a number of bytes. */
8210     trans_remaining = test_bytes;
8211     times_up = 1;
8212   }
8213 
8214   /* The cpu_start routine will grab the current time and possibly */
8215   /* value of the idle counter for later use in measuring cpu */
8216   /* utilization and/or service demand and thruput. */
8217 
8218 
8219   cpu_start(local_cpu_usage);
8220 
8221 #ifdef WANT_DEMO
8222       if (demo_mode) {
8223 	HIST_timestamp(demo_one_ptr);
8224       }
8225 #endif
8226 
8227   /* We use an "OR" to control test execution. When the test is */
8228   /* controlled by time, the byte count check will always return false. */
8229   /* When the test is controlled by byte count, the time test will */
8230   /* always return false. When the test is finished, the whole */
8231   /* expression will go false and we will stop sending data. I think I */
8232   /* just arbitrarily decrement trans_remaining for the timed test, but */
8233   /* will not do that just yet... One other question is whether or not */
8234   /* the send buffer and the receive buffer should be the same buffer. */
8235 
8236   while ((!times_up) || (trans_remaining > 0)) {
8237 
8238 #ifdef WANT_HISTOGRAM
8239     if (verbosity > 1) {
8240       /* timestamp just before our call to create the socket, and then */
8241       /* again just after the receive raj 3/95 */
8242       HIST_timestamp(&time_one);
8243     }
8244 #endif /* WANT_HISTOGRAM */
8245 
8246 newport:
8247     /* pick a new port number */
8248     myport++;
8249 
8250     /* wrap the port number when we get to client_port_max. NOTE, some */
8251     /* broken TCP's might treat the port number as a signed 16 bit */
8252     /* quantity.  we aren't interested in testing such broken */
8253     /* implementations :) so we won't make sure that it is below 32767 */
8254     /* raj 8/94  */
8255     if (myport >= client_port_max) {
8256       myport = client_port_min;
8257     }
8258 
8259     /* we do not want to use the port number that the server is */
8260     /* sitting at - this would cause us to fail in a loopback test. we */
8261     /* could just rely on the failure of the bind to get us past this, */
8262     /* but I'm guessing that in this one case at least, it is much */
8263     /* faster, given that we *know* that port number is already in use */
8264     /* (or rather would be in a loopback test) */
8265 
8266     if (myport == get_port_number(remote_res)) myport++;
8267 
8268     if (debug) {
8269       if ((nummessages % 100) == 0) {
8270 	printf("port %d\n",myport);
8271       }
8272     }
8273 
8274     /* set up the data socket */
8275     set_port_number(local_res, (unsigned short)myport);
8276     send_socket = create_data_socket(local_res);
8277 
8278     if (send_socket == INVALID_SOCKET) {
8279       perror("netperf: send_tcp_conn_rr: tcp stream data socket");
8280       exit(1);
8281     }
8282 
8283 
8284     /* we used to call bind here, but that is now taken-care-of by the
8285        create_data_socket routine. */
8286 
8287     /* Connect up to the remote port on the data socket  */
8288     if ((ret = connect(send_socket,
8289 		       remote_res->ai_addr,
8290 		       remote_res->ai_addrlen)) == INVALID_SOCKET){
8291       if (SOCKET_EINTR(ret))
8292 	  {
8293 	    /* we hit the end of a */
8294 	    /* timed test. */
8295 	    timed_out = 1;
8296 	    break;
8297       }
8298       if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) {
8299 	/* likely something our explicit bind() would have caught in
8300            the past, so go get another port, via create_data_socket.
8301            yes, this is a bit more overhead than before, but the
8302            condition should be rather rare.  raj 2005-02-08 */
8303 	close(send_socket);
8304 	goto newport;
8305       }
8306       perror("netperf: data socket connect failed");
8307       printf("\tattempted to connect on socket %d to port %d",
8308 	     send_socket,
8309 	     get_port_number(remote_res));
8310       printf(" from port %d \n",get_port_number(local_res));
8311       exit(1);
8312     }
8313 
8314 
8315     /* send the request */
8316     if((len=send(send_socket,
8317 		 send_ring->buffer_ptr,
8318 		 req_size,
8319 		 0)) != req_size) {
8320       if (SOCKET_EINTR(len))
8321 	  {
8322 	    /* we hit the end of a */
8323 	    /* timed test. */
8324 	    timed_out = 1;
8325 	    break;
8326       }
8327       perror("send_tcp_conn_rr: data send error");
8328       exit(1);
8329     }
8330     send_ring = send_ring->next;
8331 
8332     /* receive the response */
8333     rsp_bytes_left = rsp_size;
8334     temp_message_ptr  = recv_ring->buffer_ptr;
8335 
8336 
8337     do {
8338       rsp_bytes_recvd = recv(send_socket,
8339 			     temp_message_ptr,
8340 			     rsp_bytes_left,
8341 			     0);
8342       if (rsp_bytes_recvd > 0) {
8343 	rsp_bytes_left -= rsp_bytes_recvd;
8344 	temp_message_ptr += rsp_bytes_recvd;
8345       }
8346       else {
8347 	break;
8348       }
8349     } while (rsp_bytes_left);
8350 
8351 
8352     /* OK, we are out of the loop - now what? */
8353     if (rsp_bytes_recvd < 0) {
8354       /* did the timer hit, or was there an error? */
8355       if (SOCKET_EINTR(rsp_bytes_recvd))
8356 	  {
8357 	    /* We hit the end of a timed test. */
8358 	    timed_out = 1;
8359 	    break;
8360 	  }
8361 	  perror("send_tcp_conn_rr: data recv error");
8362 	  exit(1);
8363     }
8364 
8365     /* if this is a no_control test, we initiate connection close,
8366        otherwise the remote netserver does it to remain just like
8367        previous behaviour. raj 2007-27-08 */
8368     if (!no_control) {
8369       shutdown(send_socket,SHUT_WR);
8370     }
8371 
8372     /* we are expecting to get either a return of zero indicating
8373        connection close, or an error.  */
8374     rsp_bytes_recvd = recv(send_socket,
8375 			   temp_message_ptr,
8376 			   1,
8377 			   0);
8378 
8379     /* our exit from the while loop should generally be when */
8380     /* tmp_bytes_recvd is equal to zero, which implies the connection */
8381     /* has been closed by the server side. By waiting until we get the */
8382     /* zero return we can avoid race conditions that stick us with the */
8383     /* TIME_WAIT connection and not the server. raj 8/96 */
8384 
8385     if (rsp_bytes_recvd == 0) {
8386       /* connection close, call close. we assume that the requisite */
8387       /* number of bytes have been received */
8388       recv_ring = recv_ring->next;
8389 
8390 #ifdef WANT_HISTOGRAM
8391       if (verbosity > 1) {
8392 	HIST_timestamp(&time_two);
8393 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
8394       }
8395 #endif /* WANT_HISTOGRAM */
8396 
8397 #ifdef WANT_DEMO
8398       DEMO_RR_INTERVAL(1)
8399 #endif
8400 
8401       nummessages++;
8402       if (trans_remaining) {
8403 	trans_remaining--;
8404       }
8405 
8406       if (debug > 3) {
8407 	fprintf(where,
8408 		"Transaction %d completed on local port %d\n",
8409 		nummessages,
8410 		get_port_number(local_res));
8411 	fflush(where);
8412       }
8413 
8414       close(send_socket);
8415 
8416     }
8417     else {
8418       /* it was less than zero - an error occured */
8419       if (SOCKET_EINTR(rsp_bytes_recvd))
8420 	  {
8421 	    /* We hit the end of a timed test. */
8422 	    timed_out = 1;
8423 	    break;
8424 	  }
8425 	  perror("send_tcp_conn_rr: data recv error");
8426 	  exit(1);
8427     }
8428 
8429   }
8430 
8431 
8432   /* this call will always give us the elapsed time for the test, and */
8433   /* will also store-away the necessaries for cpu utilization */
8434 
8435   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being measured? */
8436   /* how long did we really run? */
8437 
8438   if (!no_control) {
8439     /* Get the statistics from the remote end. The remote will have
8440        calculated service demand and all those interesting things. If
8441        it wasn't supposed to care, it will return obvious values. */
8442 
8443     recv_response();
8444     if (!netperf_response.content.serv_errno) {
8445       if (debug)
8446 	fprintf(where,"remote results obtained\n");
8447     }
8448     else {
8449       Set_errno(netperf_response.content.serv_errno);
8450       fprintf(where,
8451 	      "netperf: remote error %d",
8452 	      netperf_response.content.serv_errno);
8453       perror("");
8454       fflush(where);
8455 
8456       exit(1);
8457     }
8458   }
8459 
8460   /* We now calculate what our thruput was for the test. In the future, */
8461   /* we may want to include a calculation of the thruput measured by */
8462   /* the remote, but it should be the case that for a TCP stream test, */
8463   /* that the two numbers should be *very* close... We calculate */
8464   /* bytes_sent regardless of the way the test length was controlled. */
8465   /* If it was time, we needed to, and if it was by bytes, the user may */
8466   /* have specified a number of bytes that wasn't a multiple of the */
8467   /* send_size, so we really didn't send what he asked for ;-) We use */
8468   /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
8469   /* 1024. A future enhancement *might* be to choose from a couple of */
8470   /* unit selections. */
8471 
8472   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
8473   thruput	= calc_thruput(bytes_xferd);
8474 
8475   if (local_cpu_usage || remote_cpu_usage) {
8476     /* We must now do a little math for service demand and cpu */
8477     /* utilization for the system(s) */
8478     /* Of course, some of the information might be bogus because */
8479     /* there was no idle counter in the kernel(s). We need to make */
8480     /* a note of this for the user's benefit...*/
8481     if (local_cpu_usage) {
8482       if (local_cpu_rate == 0.0) {
8483 	fprintf(where,
8484 		"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
8485 	fprintf(where,
8486 		"Local CPU usage numbers based on process information only!\n");
8487 	fflush(where);
8488       }
8489       local_cpu_utilization = calc_cpu_util(0.0);
8490       /* since calc_service demand is doing ms/Kunit we will */
8491       /* multiply the number of transaction by 1024 to get */
8492       /* "good" numbers */
8493       local_service_demand  = calc_service_demand((double) nummessages*1024,
8494 						  0.0,
8495 						  0.0,
8496 						  0);
8497     }
8498     else {
8499       local_cpu_utilization	= (float) -1.0;
8500       local_service_demand	= (float) -1.0;
8501     }
8502 
8503     if (remote_cpu_usage) {
8504       if (remote_cpu_rate == 0.0) {
8505 	fprintf(where,
8506 		"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
8507 	fprintf(where,
8508 		"Remote CPU usage numbers based on process information only!\n");
8509 	fflush(where);
8510       }
8511       remote_cpu_utilization = tcp_conn_rr_result->cpu_util;
8512       /* since calc_service demand is doing ms/Kunit we will */
8513       /* multiply the number of transaction by 1024 to get */
8514       /* "good" numbers */
8515       remote_service_demand = calc_service_demand((double) nummessages*1024,
8516 						  0.0,
8517 						  remote_cpu_utilization,
8518 						  tcp_conn_rr_result->num_cpus);
8519     }
8520     else {
8521       remote_cpu_utilization = (float) -1.0;
8522       remote_service_demand  = (float) -1.0;
8523     }
8524 
8525     /* We are now ready to print all the information. If the user */
8526     /* has specified zero-level verbosity, we will just print the */
8527     /* local service demand, or the remote service demand. If the */
8528     /* user has requested verbosity level 1, he will get the basic */
8529     /* "streamperf" numbers. If the user has specified a verbosity */
8530     /* of greater than 1, we will display a veritable plethora of */
8531     /* background information from outside of this block as it it */
8532     /* not cpu_measurement specific...  */
8533 
8534     switch (verbosity) {
8535     case 0:
8536       if (local_cpu_usage) {
8537 	fprintf(where,
8538 		cpu_fmt_0,
8539 		local_service_demand);
8540       }
8541       else {
8542 	fprintf(where,
8543 		cpu_fmt_0,
8544 		remote_service_demand);
8545       }
8546       break;
8547     case 1:
8548     case 2:
8549 
8550       if (print_headers) {
8551 	fprintf(where,
8552 		cpu_title,
8553 		local_cpu_method,
8554 		remote_cpu_method);
8555       }
8556 
8557       fprintf(where,
8558 	      cpu_fmt_1_line_1,		/* the format string */
8559 	      lss_size,		/* local sendbuf size */
8560 	      lsr_size,
8561 	      req_size,		/* how large were the requests */
8562 	      rsp_size,		/* guess */
8563 	      elapsed_time,		/* how long was the test */
8564 	      nummessages/elapsed_time,
8565 	      local_cpu_utilization,	/* local cpu */
8566 	      remote_cpu_utilization,	/* remote cpu */
8567 	      local_service_demand,	/* local service demand */
8568 	      remote_service_demand);	/* remote service demand */
8569       fprintf(where,
8570 	      cpu_fmt_1_line_2,
8571 	      rss_size,
8572 	      rsr_size);
8573       break;
8574     }
8575   }
8576   else {
8577     /* The tester did not wish to measure service demand. */
8578     switch (verbosity) {
8579     case 0:
8580       fprintf(where,
8581 	      tput_fmt_0,
8582 	      nummessages/elapsed_time);
8583       break;
8584     case 1:
8585     case 2:
8586       if (print_headers) {
8587 	fprintf(where,tput_title,format_units());
8588       }
8589 
8590       fprintf(where,
8591 	      tput_fmt_1_line_1,	/* the format string */
8592 	      lss_size,
8593 	      lsr_size,
8594 	      req_size,		/* how large were the requests */
8595 	      rsp_size,		/* how large were the responses */
8596 	      elapsed_time, 		/* how long did it take */
8597 	      nummessages/elapsed_time);
8598       fprintf(where,
8599 	      tput_fmt_1_line_2,
8600 	      rss_size, 		/* remote recvbuf size */
8601 	      rsr_size);
8602 
8603       break;
8604     }
8605   }
8606 
8607   /* it would be a good thing to include information about some of the */
8608   /* other parameters that may have been set for this test, but at the */
8609   /* moment, I do not wish to figure-out all the  formatting, so I will */
8610   /* just put this comment here to help remind me that it is something */
8611   /* that should be done at a later time. */
8612 
8613   if (verbosity > 1) {
8614     /* The user wanted to know it all, so we will give it to him. */
8615     /* This information will include as much as we can find about */
8616     /* TCP statistics, the alignments of the sends and receives */
8617     /* and all that sort of rot... */
8618 
8619     fprintf(where,
8620 	    ksink_fmt,
8621 	    local_send_align,
8622 	    remote_recv_offset,
8623 	    local_send_offset,
8624 	    remote_recv_offset);
8625 
8626 #ifdef WANT_HISTOGRAM
8627     fprintf(where,"\nHistogram of request/response times\n");
8628     fflush(where);
8629     HIST_report(time_hist);
8630 #endif /* WANT_HISTOGRAM */
8631 
8632   }
8633 
8634 }
8635 
8636 
8637 void
recv_tcp_conn_rr()8638 recv_tcp_conn_rr()
8639 {
8640 
8641   char  *message;
8642   struct addrinfo *local_res;
8643   char local_name[BUFSIZ];
8644   char port_buffer[PORTBUFSIZE];
8645 
8646   struct	sockaddr_storage        myaddr_in, peeraddr_in;
8647   SOCKET	s_listen,s_data;
8648   netperf_socklen_t 	addrlen;
8649   char	*recv_message_ptr;
8650   char	*send_message_ptr;
8651   char	*temp_message_ptr;
8652   int	trans_received;
8653   int	trans_remaining;
8654   int	bytes_sent;
8655   int	request_bytes_recvd;
8656   int	request_bytes_remaining;
8657   int	timed_out = 0;
8658   float	elapsed_time;
8659 
8660   struct	tcp_conn_rr_request_struct	*tcp_conn_rr_request;
8661   struct	tcp_conn_rr_response_struct	*tcp_conn_rr_response;
8662   struct	tcp_conn_rr_results_struct	*tcp_conn_rr_results;
8663 
8664   tcp_conn_rr_request =
8665     (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
8666   tcp_conn_rr_response =
8667     (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
8668   tcp_conn_rr_results =
8669     (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
8670 
8671   if (debug) {
8672     fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n");
8673     fflush(where);
8674   }
8675 
8676   /* We want to set-up the listen socket with all the desired */
8677   /* parameters and then let the initiator know that all is ready. If */
8678   /* socket size defaults are to be used, then the initiator will have */
8679   /* sent us 0's. If the socket sizes cannot be changed, then we will */
8680   /* send-back what they are. If that information cannot be determined, */
8681   /* then we send-back -1's for the sizes. If things go wrong for any */
8682   /* reason, we will drop back ten yards and punt. */
8683 
8684   /* If anything goes wrong, we want the remote to know about it. It */
8685   /* would be best if the error that the remote reports to the user is */
8686   /* the actual error we encountered, rather than some bogus unexpected */
8687   /* response type message. */
8688 
8689   if (debug) {
8690     fprintf(where,"recv_tcp_conn_rr: setting the response type...\n");
8691     fflush(where);
8692   }
8693 
8694   netperf_response.content.response_type = TCP_CRR_RESPONSE;
8695 
8696   if (debug) {
8697     fprintf(where,"recv_tcp_conn_rr: the response type is set...\n");
8698     fflush(where);
8699   }
8700 
8701   /* set-up the data buffer with the requested alignment and offset */
8702   message = (char *)malloc(DATABUFFERLEN);
8703   if (message == NULL) {
8704     printf("malloc(%d) failed!\n", DATABUFFERLEN);
8705     exit(1);
8706   }
8707 
8708   /* We now alter the message_ptr variables to be at the desired */
8709   /* alignments with the desired offsets. */
8710 
8711   if (debug) {
8712     fprintf(where,
8713 	    "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n",
8714 	    tcp_conn_rr_request->recv_alignment,
8715 	    tcp_conn_rr_request->recv_offset);
8716     fprintf(where,
8717 	    "recv_tcp_conn_rr: requested send alignment of %d offset %d\n",
8718 	    tcp_conn_rr_request->send_alignment,
8719 	    tcp_conn_rr_request->send_offset);
8720     fflush(where);
8721   }
8722 
8723   recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset);
8724 
8725   send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset);
8726 
8727   if (debug) {
8728     fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n");
8729     fflush(where);
8730   }
8731 
8732   /* Grab a socket to listen on, and then listen on it. */
8733 
8734   if (debug) {
8735     fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n");
8736     fflush(where);
8737   }
8738 
8739   /* create_data_socket expects to find some things in the global */
8740   /* variables, so set the globals based on the values in the request. */
8741   /* once the socket has been created, we will set the response values */
8742   /* based on the updated value of those globals. raj 7/94 */
8743   lss_size_req = tcp_conn_rr_request->send_buf_size;
8744   lsr_size_req = tcp_conn_rr_request->recv_buf_size;
8745   loc_nodelay = tcp_conn_rr_request->no_delay;
8746   loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid;
8747   loc_sndavoid = tcp_conn_rr_request->so_sndavoid;
8748 
8749   set_hostname_and_port(local_name,
8750 			port_buffer,
8751 			nf_to_af(tcp_conn_rr_request->ipfamily),
8752 			tcp_conn_rr_request->port);
8753 
8754   local_res = complete_addrinfo(local_name,
8755 				local_name,
8756 				port_buffer,
8757 				nf_to_af(tcp_conn_rr_request->ipfamily),
8758 				SOCK_STREAM,
8759 				IPPROTO_TCP,
8760 				0);
8761 
8762   s_listen = create_data_socket(local_res);
8763 
8764   if (s_listen == INVALID_SOCKET) {
8765     netperf_response.content.serv_errno = errno;
8766     send_response();
8767     if (debug) {
8768       fprintf(where,"could not create data socket\n");
8769       fflush(where);
8770     }
8771     exit(1);
8772   }
8773 
8774 #ifdef WIN32
8775     /* The test timer can fire during operations on the listening socket,
8776        so to make the start_timer below work we have to move
8777        it to close s_listen while we are blocked on accept. */
8778     win_kludge_socket2 = s_listen;
8779 #endif
8780 
8781 
8782   /* Now, let's set-up the socket to listen for connections */
8783   if (listen(s_listen, 5) == SOCKET_ERROR) {
8784     netperf_response.content.serv_errno = errno;
8785     close(s_listen);
8786     send_response();
8787     if (debug) {
8788       fprintf(where,"could not listen\n");
8789       fflush(where);
8790     }
8791     exit(1);
8792   }
8793 
8794   /* now get the port number assigned by the system  */
8795   addrlen = sizeof(myaddr_in);
8796   if (getsockname(s_listen,
8797 		  (struct sockaddr *)&myaddr_in,
8798 		  &addrlen) == SOCKET_ERROR){
8799     netperf_response.content.serv_errno = errno;
8800     close(s_listen);
8801     send_response();
8802     if (debug) {
8803       fprintf(where,"could not getsockname\n");
8804       fflush(where);
8805     }
8806     exit(1);
8807   }
8808 
8809   /* Now myaddr_in contains the port and the internet address this is */
8810   /* returned to the sender also implicitly telling the sender that the */
8811   /* socket buffer sizing has been done. */
8812 
8813   tcp_conn_rr_response->data_port_number =
8814     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
8815   if (debug) {
8816     fprintf(where,"telling the remote to call me at %d\n",
8817 	    tcp_conn_rr_response->data_port_number);
8818     fflush(where);
8819   }
8820   netperf_response.content.serv_errno   = 0;
8821 
8822   /* But wait, there's more. If the initiator wanted cpu measurements, */
8823   /* then we must call the calibrate routine, which will return the max */
8824   /* rate back to the initiator. If the CPU was not to be measured, or */
8825   /* something went wrong with the calibration, we will return a 0.0 to */
8826   /* the initiator. */
8827 
8828   tcp_conn_rr_response->cpu_rate = (float)0.0; 	/* assume no cpu */
8829   if (tcp_conn_rr_request->measure_cpu) {
8830     tcp_conn_rr_response->measure_cpu = 1;
8831     tcp_conn_rr_response->cpu_rate =
8832       calibrate_local_cpu(tcp_conn_rr_request->cpu_rate);
8833   }
8834 
8835 
8836 
8837   /* before we send the response back to the initiator, pull some of */
8838   /* the socket parms from the globals */
8839   tcp_conn_rr_response->send_buf_size = lss_size;
8840   tcp_conn_rr_response->recv_buf_size = lsr_size;
8841   tcp_conn_rr_response->no_delay = loc_nodelay;
8842   tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
8843   tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
8844 
8845   send_response();
8846 
8847   addrlen = sizeof(peeraddr_in);
8848 
8849   /* Now it's time to start receiving data on the connection. We will */
8850   /* first grab the apropriate counters and then start grabbing. */
8851 
8852   cpu_start(tcp_conn_rr_request->measure_cpu);
8853 
8854   /* The loop will exit when the sender does a shutdown, which will */
8855   /* return a length of zero   */
8856 
8857   if (tcp_conn_rr_request->test_length > 0) {
8858     times_up = 0;
8859     trans_remaining = 0;
8860     start_timer(tcp_conn_rr_request->test_length + PAD_TIME);
8861   }
8862   else {
8863     times_up = 1;
8864     trans_remaining = tcp_conn_rr_request->test_length * -1;
8865   }
8866 
8867   trans_received = 0;
8868 
8869   while ((!times_up) || (trans_remaining > 0)) {
8870 
8871     /* accept a connection from the remote */
8872 #ifdef WIN32
8873     /* The test timer will probably fire during this accept,
8874        so to make the start_timer above work we have to move
8875        it to close s_listen while we are blocked on accept. */
8876     win_kludge_socket = s_listen;
8877 #endif
8878     if ((s_data=accept(s_listen,
8879 		       (struct sockaddr *)&peeraddr_in,
8880 		       &addrlen)) == INVALID_SOCKET) {
8881       if (errno == EINTR) {
8882 	/* the timer popped */
8883 	timed_out = 1;
8884 	break;
8885       }
8886       fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno);
8887       fflush(where);
8888       close(s_listen);
8889 
8890       exit(1);
8891     }
8892 
8893     if (debug) {
8894       fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n");
8895       fflush(where);
8896     }
8897 
8898 #ifdef WIN32
8899   /* this is used so the timer thread can close the socket out from */
8900   /* under us, which to date is the easiest/cleanest/least */
8901   /* Windows-specific way I can find to force the winsock calls to */
8902   /* return WSAEINTR with the test is over. anything that will run on */
8903   /* 95 and NT and is closer to what netperf expects from Unix signals */
8904   /* and such would be appreciated raj 1/96 */
8905   win_kludge_socket = s_data;
8906 #endif /* WIN32 */
8907 
8908 #ifdef KLUDGE_SOCKET_OPTIONS
8909     /* this is for those systems which *INCORRECTLY* fail to pass */
8910     /* attributes across an accept() call. Including this goes against */
8911     /* my better judgement :( raj 11/95 */
8912 
8913     kludge_socket_options(s_data);
8914 
8915 #endif /* KLUDGE_SOCKET_OPTIONS */
8916 
8917     temp_message_ptr	= recv_message_ptr;
8918     request_bytes_remaining	= tcp_conn_rr_request->request_size;
8919 
8920     /* receive the request from the other side */
8921     while (!times_up && (request_bytes_remaining > 0)) {
8922       if((request_bytes_recvd=recv(s_data,
8923 				   temp_message_ptr,
8924 				   request_bytes_remaining,
8925 				   0)) == SOCKET_ERROR) {
8926 	if (SOCKET_EINTR(request_bytes_recvd))
8927 	{
8928 	  /* the timer popped */
8929 	  timed_out = 1;
8930 	  break;
8931 	}
8932 	netperf_response.content.serv_errno = errno;
8933 	send_response();
8934 	exit(1);
8935       }
8936       else {
8937 	request_bytes_remaining -= request_bytes_recvd;
8938 	temp_message_ptr  += request_bytes_recvd;
8939       }
8940     }
8941 
8942     if (timed_out) {
8943       /* we hit the end of the test based on time - lets */
8944       /* bail out of here now... */
8945       fprintf(where,"yo5\n");
8946       fflush(where);
8947       break;
8948     }
8949 
8950     /* Now, send the response to the remote */
8951     if((bytes_sent=send(s_data,
8952 			send_message_ptr,
8953 			tcp_conn_rr_request->response_size,
8954 			0)) == SOCKET_ERROR) {
8955       if (errno == EINTR) {
8956 	/* the test timer has popped */
8957 	timed_out = 1;
8958 	fprintf(where,"yo6\n");
8959 	fflush(where);
8960 	break;
8961       }
8962       netperf_response.content.serv_errno = 99;
8963       send_response();
8964       exit(1);
8965     }
8966 
8967     trans_received++;
8968     if (trans_remaining) {
8969       trans_remaining--;
8970     }
8971 
8972     if (debug) {
8973       fprintf(where,
8974 	      "recv_tcp_conn_rr: Transaction %d complete\n",
8975 	      trans_received);
8976       fflush(where);
8977     }
8978 
8979     /* close the connection. the server will likely do a graceful */
8980     /* close of the connection, insuring that all data has arrived at */
8981     /* the client. for this it will call shutdown(), and then recv() and */
8982     /* then close(). I'm reasonably confident that this is the */
8983     /* appropriate sequence of calls - I would like to hear of */
8984     /* examples in web servers to the contrary. raj 10/95*/
8985 #ifdef TCP_CRR_SHUTDOWN
8986     shutdown(s_data,SHUT_WR);
8987     recv(s_data,
8988 	 recv_message_ptr,
8989 	 1,
8990 	 0);
8991     close(s_data);
8992 #else
8993     close(s_data);
8994 #endif /* TCP_CRR_SHUTDOWN */
8995 
8996   }
8997 
8998 
8999   /* The loop now exits due to timeout or transaction count being */
9000   /* reached */
9001 
9002   cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time);
9003 
9004   if (timed_out) {
9005     /* we ended the test by time, which was at least 2 seconds */
9006     /* longer than we wanted to run. so, we want to subtract */
9007     /* PAD_TIME from the elapsed_time. */
9008     elapsed_time -= PAD_TIME;
9009   }
9010   /* send the results to the sender			*/
9011 
9012   if (debug) {
9013     fprintf(where,
9014 	    "recv_tcp_conn_rr: got %d transactions\n",
9015 	    trans_received);
9016     fflush(where);
9017   }
9018 
9019   tcp_conn_rr_results->bytes_received	= (trans_received *
9020 					   (tcp_conn_rr_request->request_size +
9021 					    tcp_conn_rr_request->response_size));
9022   tcp_conn_rr_results->trans_received	= trans_received;
9023   tcp_conn_rr_results->elapsed_time	= elapsed_time;
9024   if (tcp_conn_rr_request->measure_cpu) {
9025     tcp_conn_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
9026   }
9027 
9028   if (debug) {
9029     fprintf(where,
9030 	    "recv_tcp_conn_rr: test complete, sending results.\n");
9031     fflush(where);
9032   }
9033 
9034   send_response();
9035 
9036 }
9037 
9038 
9039 #ifdef DO_1644
9040 
9041  /* this test is intended to test the performance of establishing a */
9042  /* connection, exchanging a request/response pair, and repeating. it */
9043  /* is expected that this would be a good starting-point for */
9044  /* comparision of T/TCP with classic TCP for transactional workloads. */
9045  /* it will also look (can look) much like the communication pattern */
9046  /* of http for www access. */
9047 
9048 int
send_tcp_tran_rr(char remote_host[])9049 send_tcp_tran_rr(char remote_host[])
9050 {
9051 
9052   char *tput_title = "\
9053 Local /Remote\n\
9054 Socket Size   Request  Resp.   Elapsed  Trans.\n\
9055 Send   Recv   Size     Size    Time     Rate         \n\
9056 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
9057 
9058   char *tput_fmt_0 =
9059     "%7.2f\n";
9060 
9061   char *tput_fmt_1_line_1 = "\
9062 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
9063   char *tput_fmt_1_line_2 = "\
9064 %-6d %-6d\n";
9065 
9066   char *cpu_title = "\
9067 Local /Remote\n\
9068 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
9069 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
9070 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
9071 
9072   char *cpu_fmt_0 =
9073     "%6.3f\n";
9074 
9075   char *cpu_fmt_1_line_1 = "\
9076 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
9077 
9078   char *cpu_fmt_1_line_2 = "\
9079 %-6d %-6d\n";
9080 
9081   char *ksink_fmt = "\n\
9082 Alignment      Offset\n\
9083 Local  Remote  Local  Remote\n\
9084 Send   Recv    Send   Recv\n\
9085 %5d  %5d   %5d  %5d\n";
9086 
9087 
9088   int 			one = 1;
9089   int			timed_out = 0;
9090   float			elapsed_time;
9091 
9092   int	len;
9093   struct ring_elt *send_ring;
9094   struct ring_elt *recv_ring;
9095   char	*temp_message_ptr;
9096   int	nummessages;
9097   SOCKET	send_socket;
9098   int	trans_remaining;
9099   double	bytes_xferd;
9100   int	sock_opt_len = sizeof(int);
9101   int	rsp_bytes_left;
9102   int	rsp_bytes_recvd;
9103 
9104   float	local_cpu_utilization;
9105   float	local_service_demand;
9106   float	remote_cpu_utilization;
9107   float	remote_service_demand;
9108   double	thruput;
9109 
9110   struct	hostent	        *hp;
9111   struct	sockaddr_in	server;
9112   struct        sockaddr_in     *myaddr;
9113   unsigned      int             addr;
9114   int                           myport;
9115 
9116   struct	tcp_tran_rr_request_struct	*tcp_tran_rr_request;
9117   struct	tcp_tran_rr_response_struct	*tcp_tran_rr_response;
9118   struct	tcp_tran_rr_results_struct	*tcp_tran_rr_result;
9119 
9120   tcp_tran_rr_request =
9121     (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
9122   tcp_tran_rr_response =
9123     (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
9124   tcp_tran_rr_result =
9125     (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
9126 
9127 
9128 #ifdef WANT_HISTOGRAM
9129   if (verbosity > 1) {
9130     time_hist = HIST_new();
9131   }
9132 #endif /* WANT_HISTOGRAM */
9133 
9134   /* since we are now disconnected from the code that established the */
9135   /* control socket, and since we want to be able to use different */
9136   /* protocols and such, we are passed the name of the remote host and */
9137   /* must turn that into the test specific addressing information. */
9138 
9139   myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
9140   if (myaddr == NULL) {
9141     printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage));
9142     exit(1);
9143   }
9144 
9145   bzero((char *)&server,
9146 	sizeof(server));
9147   bzero((char *)myaddr,
9148 	sizeof(struct sockaddr_storage));
9149   myaddr->sin_family = AF_INET;
9150 
9151   complete_addrinfos(&remote_res,
9152 		     &local_res,
9153 		     remote_host,
9154 		     SOCK_STREAM,
9155 		     IPPROTO_TCP,
9156 		     0);
9157 
9158   if ( print_headers ) {
9159     print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res);
9160   }
9161 
9162   /* initialize a few counters */
9163 
9164   nummessages	=	0;
9165   bytes_xferd	=	0.0;
9166   times_up 	= 	0;
9167 
9168   /* set-up the data buffers with the requested alignment and offset */
9169   if (send_width == 0) send_width = 1;
9170   if (recv_width == 0) recv_width = 1;
9171 
9172   send_ring = allocate_buffer_ring(send_width,
9173 				   req_size,
9174 				   local_send_align,
9175 				   local_send_offset);
9176 
9177   recv_ring = allocate_buffer_ring(recv_width,
9178 				   rsp_size,
9179 				   local_recv_align,
9180 				   local_recv_offset);
9181 
9182 
9183   if (debug) {
9184     fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n");
9185   }
9186 
9187   /* If the user has requested cpu utilization measurements, we must */
9188   /* calibrate the cpu(s). We will perform this task within the tests */
9189   /* themselves. If the user has specified the cpu rate, then */
9190   /* calibrate_local_cpu will return rather quickly as it will have */
9191   /* nothing to do. If local_cpu_rate is zero, then we will go through */
9192   /* all the "normal" calibration stuff and return the rate back.*/
9193 
9194   if (local_cpu_usage) {
9195     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
9196   }
9197 
9198   /* Tell the remote end to do a listen. The server alters the socket */
9199   /* paramters on the other side at this point, hence the reason for */
9200   /* all the values being passed in the setup message. If the user did */
9201   /* not specify any of the parameters, they will be passed as 0, which */
9202   /* will indicate to the remote that no changes beyond the system's */
9203   /* default should be used. Alignment is the exception, it will */
9204   /* default to 8, which will be no alignment alterations. */
9205 
9206   netperf_request.content.request_type	        =	DO_TCP_TRR;
9207   tcp_tran_rr_request->recv_buf_size	=	rsr_size_req;
9208   tcp_tran_rr_request->send_buf_size	=	rss_size_req;
9209   tcp_tran_rr_request->recv_alignment	=	remote_recv_align;
9210   tcp_tran_rr_request->recv_offset	=	remote_recv_offset;
9211   tcp_tran_rr_request->send_alignment	=	remote_send_align;
9212   tcp_tran_rr_request->send_offset	=	remote_send_offset;
9213   tcp_tran_rr_request->request_size	=	req_size;
9214   tcp_tran_rr_request->response_size	=	rsp_size;
9215   tcp_tran_rr_request->no_delay	        =	rem_nodelay;
9216   tcp_tran_rr_request->measure_cpu	=	remote_cpu_usage;
9217   tcp_tran_rr_request->cpu_rate	        =	remote_cpu_rate;
9218   tcp_tran_rr_request->so_rcvavoid	=	rem_rcvavoid;
9219   tcp_tran_rr_request->so_sndavoid	=	rem_sndavoid;
9220   if (test_time) {
9221     tcp_tran_rr_request->test_length	=	test_time;
9222   }
9223   else {
9224     tcp_tran_rr_request->test_length	=	test_trans * -1;
9225   }
9226   tcp_tran_rr_request->port             =       atoi(remote_data_port);
9227   tcp_tran_rr_request->ipfamily        =       af_to_nf(remote_res->ai_family);
9228 
9229   if (debug > 1) {
9230     fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n");
9231   }
9232 
9233   send_request();
9234 
9235   /* The response from the remote will contain all of the relevant 	*/
9236   /* socket parameters for this test type. We will put them back into 	*/
9237   /* the variables here so they can be displayed if desired.  The	*/
9238   /* remote will have calibrated CPU if necessary, and will have done	*/
9239   /* all the needed set-up we will have calibrated the cpu locally	*/
9240   /* before sending the request, and will grab the counter value right	*/
9241   /* after the connect returns. The remote will grab the counter right	*/
9242   /* after the accept call. This saves the hassle of extra messages	*/
9243   /* being sent for the TCP tests.					*/
9244 
9245   recv_response();
9246 
9247   if (!netperf_response.content.serv_errno) {
9248     rsr_size	=	tcp_tran_rr_response->recv_buf_size;
9249     rss_size	=	tcp_tran_rr_response->send_buf_size;
9250     rem_nodelay	=	tcp_tran_rr_response->no_delay;
9251     remote_cpu_usage=	tcp_tran_rr_response->measure_cpu;
9252     remote_cpu_rate = 	tcp_tran_rr_response->cpu_rate;
9253     /* make sure that port numbers are in network order */
9254     server.sin_port	=	tcp_tran_rr_response->data_port_number;
9255     server.sin_port =	htons(server.sin_port);
9256     if (debug) {
9257       fprintf(where,"remote listen done.\n");
9258       fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
9259       fflush(where);
9260     }
9261   }
9262   else {
9263     Set_errno(netperf_response.content.serv_errno);
9264     fprintf(where,
9265 	    "netperf: remote error %d",
9266 	    netperf_response.content.serv_errno);
9267     perror("");
9268     fflush(where);
9269     exit(1);
9270   }
9271 
9272   /* pick a nice random spot between client_port_min and */
9273   /* client_port_max for our initial port number. if they are the */
9274   /* same, then just set to _min */
9275   if (client_port_max - client_port_min) {
9276     srand(getpid());
9277     myport = client_port_min +
9278       (rand() % (client_port_max - client_port_min));
9279   }
9280   else {
9281     myport = client_port_min;
9282   }
9283 
9284   /* there will be a ++ before the first call to bind, so subtract one */
9285   myport--;
9286   myaddr->sin_port = htons((unsigned short)myport);
9287 
9288   /* Set-up the test end conditions. For a request/response test, they */
9289   /* can be either time or transaction based. */
9290 
9291   if (test_time) {
9292     /* The user wanted to end the test after a period of time. */
9293     times_up = 0;
9294     trans_remaining = 0;
9295     start_timer(test_time);
9296   }
9297   else {
9298     /* The tester wanted to send a number of bytes. */
9299     trans_remaining = test_bytes;
9300     times_up = 1;
9301   }
9302 
9303   /* The cpu_start routine will grab the current time and possibly */
9304   /* value of the idle counter for later use in measuring cpu */
9305   /* utilization and/or service demand and thruput. */
9306 
9307   cpu_start(local_cpu_usage);
9308 
9309   /* We use an "OR" to control test execution. When the test is */
9310   /* controlled by time, the byte count check will always return false. */
9311   /* When the test is controlled by byte count, the time test will */
9312   /* always return false. When the test is finished, the whole */
9313   /* expression will go false and we will stop sending data. I think I */
9314   /* just arbitrarily decrement trans_remaining for the timed test, but */
9315   /* will not do that just yet... One other question is whether or not */
9316   /* the send buffer and the receive buffer should be the same buffer. */
9317 
9318   while ((!times_up) || (trans_remaining > 0)) {
9319 
9320 #ifdef WANT_HISTOGRAM
9321     if (verbosity > 1) {
9322       /* timestamp just before our call to create the socket, and then */
9323       /* again just after the receive raj 3/95 */
9324       HIST_timestamp(&time_one);
9325     }
9326 #endif /* WANT_HISTOGRAM */
9327 
9328     /* set up the data socket - is this really necessary or can I just */
9329     /* re-use the same socket and move this cal out of the while loop. */
9330     /* it does introcudea *boatload* of system calls. I guess that it */
9331     /* all depends on "reality of programming." keeping it this way is */
9332     /* a bit more conservative I imagine - raj 3/95 */
9333     send_socket = create_data_socket(local_res);
9334 
9335     if (send_socket == INVALID_SOCKET) {
9336       perror("netperf: send_tcp_tran_rr: tcp stream data socket");
9337       exit(1);
9338     }
9339 
9340     /* we set SO_REUSEADDR on the premis that no unreserved port */
9341     /* number on the local system is going to be already connected to */
9342     /* the remote netserver's port number. One thing that I might */
9343     /* try later is to have the remote actually allocate a couple of */
9344     /* port numbers and cycle through those as well. depends on if we */
9345     /* can get through all the unreserved port numbers in less than */
9346     /* the length of the TIME_WAIT state raj 8/94 */
9347     one = 1;
9348     if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
9349 		  (char *)&one, sock_opt_len) == SOCKET_ERROR) {
9350       perror("netperf: send_tcp_tran_rr: so_reuseaddr");
9351       exit(1);
9352     }
9353 
9354 newport:
9355     /* pick a new port number */
9356     myport = ntohs(myaddr->sin_port);
9357     myport++;
9358 
9359     /* we do not want to use the port number that the server is */
9360     /* sitting at - this would cause us to fail in a loopback test. we */
9361     /* could just rely on the failure of the bind to get us past this, */
9362     /* but I'm guessing that in this one case at least, it is much */
9363     /* faster, given that we *know* that port number is already in use */
9364     /* (or rather would be in a loopback test) */
9365 
9366     if (myport == ntohs(server.sin_port)) myport++;
9367 
9368     /* wrap the port number when we get to 65535. NOTE, some broken */
9369     /* TCP's might treat the port number as a signed 16 bit quantity. */
9370     /* we aren't interested in testing such broken implementations :) */
9371     /* raj 8/94  */
9372     if (myport >= client_port_max) {
9373       myport = client_port_min;
9374     }
9375     myaddr->sin_port = htons((unsigned short)myport);
9376 
9377     if (debug) {
9378       if ((nummessages % 100) == 0) {
9379 	printf("port %d\n",myport);
9380       }
9381     }
9382 
9383     /* we want to bind our socket to a particular port number. */
9384     if (bind(send_socket,
9385 	     (struct sockaddr *)myaddr,
9386 	     sizeof(struct sockaddr_storage)) == SOCKET_ERROR) {
9387       /* if the bind failed, someone else must have that port number */
9388       /* - perhaps in the listen state. since we can't use it, skip to */
9389       /* the next port number. we may have to do this again later, but */
9390       /* that's just too bad :) */
9391       if (debug > 1) {
9392 	fprintf(where,
9393 		"send_tcp_tran_rr: tried to bind to port %d errno %d\n",
9394 		ntohs(myaddr->sin_port),
9395 		errno);
9396 	fflush(where);
9397       }
9398 	/* yes, goto's are supposed to be evil, but they do have their */
9399 	/* uses from time to time. the real world doesn't always have */
9400 	/* to code to ge tthe A in CS 101 :) raj 3/95 */
9401 	goto newport;
9402     }
9403 
9404     /* Connect up to the remote port on the data socket. Since this is */
9405     /* a test for RFC_1644-style transactional TCP, we can use the */
9406     /* sendto() call instead of calling connect and then send() */
9407 
9408     /* send the request */
9409     if((len=sendto(send_socket,
9410 		   send_ring->buffer_ptr,
9411 		   req_size,
9412 		   MSG_EOF,
9413 		   (struct sockaddr *)&server,
9414 		   sizeof(server))) != req_size) {
9415       if (SOCKET_EINTR(len))
9416 	  {
9417 	    /* we hit the end of a */
9418 	    /* timed test. */
9419 	    timed_out = 1;
9420 	    break;
9421       }
9422       perror("send_tcp_tran_rr: data send error");
9423       exit(1);
9424     }
9425     send_ring = send_ring->next;
9426 
9427     /* receive the response */
9428     rsp_bytes_left = rsp_size;
9429     temp_message_ptr  = recv_ring->buffer_ptr;
9430     while(rsp_bytes_left > 0) {
9431       if((rsp_bytes_recvd=recv(send_socket,
9432 			       temp_message_ptr,
9433 			       rsp_bytes_left,
9434 			       0)) == SOCKET_ERROR) {
9435 	    if (SOCKET_EINTR(rsp_bytes_recvd))
9436 		{
9437 	      /* We hit the end of a timed test. */
9438 	      timed_out = 1;
9439 	      break;
9440 		}
9441 	    perror("send_tcp_tran_rr: data recv error");
9442 	    exit(1);
9443       }
9444       rsp_bytes_left -= rsp_bytes_recvd;
9445       temp_message_ptr  += rsp_bytes_recvd;
9446     }
9447     recv_ring = recv_ring->next;
9448 
9449     if (timed_out) {
9450       /* we may have been in a nested while loop - we need */
9451       /* another call to break. */
9452       break;
9453     }
9454 
9455     close(send_socket);
9456 
9457 #ifdef WANT_HISTOGRAM
9458     if (verbosity > 1) {
9459       HIST_timestamp(&time_two);
9460       HIST_add(time_hist,delta_micro(&time_one,&time_two));
9461     }
9462 #endif /* WANT_HISTOGRAM */
9463 
9464     nummessages++;
9465     if (trans_remaining) {
9466       trans_remaining--;
9467     }
9468 
9469     if (debug > 3) {
9470       fprintf(where,
9471 	      "Transaction %d completed on local port %d\n",
9472 	      nummessages,
9473 	      ntohs(myaddr->sin_port));
9474       fflush(where);
9475     }
9476 
9477 
9478   }
9479 
9480   /* this call will always give us the elapsed time for the test, and */
9481   /* will also store-away the necessaries for cpu utilization */
9482 
9483   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being measured? */
9484   /* how long did we really run? */
9485 
9486   /* Get the statistics from the remote end. The remote will have */
9487   /* calculated service demand and all those interesting things. If it */
9488   /* wasn't supposed to care, it will return obvious values. */
9489 
9490   recv_response();
9491   if (!netperf_response.content.serv_errno) {
9492     if (debug)
9493       fprintf(where,"remote results obtained\n");
9494   }
9495   else {
9496     Set_errno(netperf_response.content.serv_errno);
9497     fprintf(where,
9498 	    "netperf: remote error %d",
9499 	    netperf_response.content.serv_errno);
9500     perror("");
9501     fflush(where);
9502     exit(1);
9503   }
9504 
9505   /* We now calculate what our thruput was for the test. In the future, */
9506   /* we may want to include a calculation of the thruput measured by */
9507   /* the remote, but it should be the case that for a TCP stream test, */
9508   /* that the two numbers should be *very* close... We calculate */
9509   /* bytes_sent regardless of the way the test length was controlled. */
9510   /* If it was time, we needed to, and if it was by bytes, the user may */
9511   /* have specified a number of bytes that wasn't a multiple of the */
9512   /* send_size, so we really didn't send what he asked for ;-) We use */
9513   /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
9514   /* 1024. A future enhancement *might* be to choose from a couple of */
9515   /* unit selections. */
9516 
9517   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
9518   thruput	= calc_thruput(bytes_xferd);
9519 
9520   if (local_cpu_usage || remote_cpu_usage) {
9521     /* We must now do a little math for service demand and cpu */
9522     /* utilization for the system(s) */
9523     /* Of course, some of the information might be bogus because */
9524     /* there was no idle counter in the kernel(s). We need to make */
9525     /* a note of this for the user's benefit...*/
9526     if (local_cpu_usage) {
9527       if (local_cpu_rate == 0.0) {
9528 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
9529 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
9530 	fflush(where);
9531       }
9532       local_cpu_utilization = calc_cpu_util(0.0);
9533       /* since calc_service demand is doing ms/Kunit we will */
9534       /* multiply the number of transaction by 1024 to get */
9535       /* "good" numbers */
9536       local_service_demand  = calc_service_demand((double) nummessages*1024,
9537 						  0.0,
9538 						  0.0,
9539 						  0);
9540     }
9541     else {
9542       local_cpu_utilization	= (float) -1.0;
9543       local_service_demand	= (float) -1.0;
9544     }
9545 
9546     if (remote_cpu_usage) {
9547       if (remote_cpu_rate == 0.0) {
9548 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
9549 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
9550 	fflush(where);
9551       }
9552       remote_cpu_utilization = tcp_tran_rr_result->cpu_util;
9553       /* since calc_service demand is doing ms/Kunit we will */
9554       /* multiply the number of transaction by 1024 to get */
9555       /* "good" numbers */
9556       remote_service_demand = calc_service_demand((double) nummessages*1024,
9557 						  0.0,
9558 						  remote_cpu_utilization,
9559 						  tcp_tran_rr_result->num_cpus);
9560     }
9561     else {
9562       remote_cpu_utilization = (float) -1.0;
9563       remote_service_demand  = (float) -1.0;
9564     }
9565 
9566     /* We are now ready to print all the information. If the user */
9567     /* has specified zero-level verbosity, we will just print the */
9568     /* local service demand, or the remote service demand. If the */
9569     /* user has requested verbosity level 1, he will get the basic */
9570     /* "streamperf" numbers. If the user has specified a verbosity */
9571     /* of greater than 1, we will display a veritable plethora of */
9572     /* background information from outside of this block as it it */
9573     /* not cpu_measurement specific...  */
9574 
9575     switch (verbosity) {
9576     case 0:
9577       if (local_cpu_usage) {
9578 	fprintf(where,
9579 		cpu_fmt_0,
9580 		local_service_demand);
9581       }
9582       else {
9583 	fprintf(where,
9584 		cpu_fmt_0,
9585 		remote_service_demand);
9586       }
9587       break;
9588     case 1:
9589     case 2:
9590 
9591       if (print_headers) {
9592 	fprintf(where,
9593 		cpu_title,
9594 		local_cpu_method,
9595 		remote_cpu_method);
9596       }
9597 
9598       fprintf(where,
9599 	      cpu_fmt_1_line_1,		/* the format string */
9600 	      lss_size,		/* local sendbuf size */
9601 	      lsr_size,
9602 	      req_size,		/* how large were the requests */
9603 	      rsp_size,		/* guess */
9604 	      elapsed_time,		/* how long was the test */
9605 	      nummessages/elapsed_time,
9606 	      local_cpu_utilization,	/* local cpu */
9607 	      remote_cpu_utilization,	/* remote cpu */
9608 	      local_service_demand,	/* local service demand */
9609 	      remote_service_demand);	/* remote service demand */
9610       fprintf(where,
9611 	      cpu_fmt_1_line_2,
9612 	      rss_size,
9613 	      rsr_size);
9614       break;
9615     }
9616   }
9617   else {
9618     /* The tester did not wish to measure service demand. */
9619     switch (verbosity) {
9620     case 0:
9621       fprintf(where,
9622 	      tput_fmt_0,
9623 	      nummessages/elapsed_time);
9624       break;
9625     case 1:
9626     case 2:
9627       if (print_headers) {
9628 	fprintf(where,tput_title,format_units());
9629       }
9630 
9631       fprintf(where,
9632 	      tput_fmt_1_line_1,	/* the format string */
9633 	      lss_size,
9634 	      lsr_size,
9635 	      req_size,		/* how large were the requests */
9636 	      rsp_size,		/* how large were the responses */
9637 	      elapsed_time, 		/* how long did it take */
9638 	      nummessages/elapsed_time);
9639       fprintf(where,
9640 	      tput_fmt_1_line_2,
9641 	      rss_size, 		/* remote recvbuf size */
9642 	      rsr_size);
9643 
9644       break;
9645     }
9646   }
9647 
9648   /* it would be a good thing to include information about some of the */
9649   /* other parameters that may have been set for this test, but at the */
9650   /* moment, I do not wish to figure-out all the  formatting, so I will */
9651   /* just put this comment here to help remind me that it is something */
9652   /* that should be done at a later time. */
9653 
9654   if (verbosity > 1) {
9655     /* The user wanted to know it all, so we will give it to him. */
9656     /* This information will include as much as we can find about */
9657     /* TCP statistics, the alignments of the sends and receives */
9658     /* and all that sort of rot... */
9659 
9660     fprintf(where,
9661 	    ksink_fmt,
9662 	    local_send_align,
9663 	    remote_recv_offset,
9664 	    local_send_offset,
9665 	    remote_recv_offset);
9666 
9667 #ifdef WANT_HISTOGRAM
9668     fprintf(where,"\nHistogram of request/response times\n");
9669     fflush(where);
9670     HIST_report(time_hist);
9671 #endif /* WANT_HISTOGRAM */
9672 
9673   }
9674 
9675 }
9676 
9677 
9678 int
recv_tcp_tran_rr()9679 recv_tcp_tran_rr()
9680 {
9681 
9682   char  *message;
9683   struct	sockaddr_in        myaddr_in,
9684   peeraddr_in;
9685   SOCKET	s_listen,s_data;
9686   netperf_socklen_t 	addrlen;
9687   int   NoPush = 1;
9688 
9689   char	*recv_message_ptr;
9690   char	*send_message_ptr;
9691   char	*temp_message_ptr;
9692   int	trans_received;
9693   int	trans_remaining;
9694   int	bytes_sent;
9695   int	request_bytes_recvd;
9696   int	request_bytes_remaining;
9697   int	timed_out = 0;
9698   float	elapsed_time;
9699 
9700   struct	tcp_tran_rr_request_struct	*tcp_tran_rr_request;
9701   struct	tcp_tran_rr_response_struct	*tcp_tran_rr_response;
9702   struct	tcp_tran_rr_results_struct	*tcp_tran_rr_results;
9703 
9704   tcp_tran_rr_request =
9705     (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
9706   tcp_tran_rr_response =
9707     (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
9708   tcp_tran_rr_results =
9709     (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
9710 
9711   if (debug) {
9712     fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n");
9713     fflush(where);
9714   }
9715 
9716   /* We want to set-up the listen socket with all the desired */
9717   /* parameters and then let the initiator know that all is ready. If */
9718   /* socket size defaults are to be used, then the initiator will have */
9719   /* sent us 0's. If the socket sizes cannot be changed, then we will */
9720   /* send-back what they are. If that information cannot be determined, */
9721   /* then we send-back -1's for the sizes. If things go wrong for any */
9722   /* reason, we will drop back ten yards and punt. */
9723 
9724   /* If anything goes wrong, we want the remote to know about it. It */
9725   /* would be best if the error that the remote reports to the user is */
9726   /* the actual error we encountered, rather than some bogus unexpected */
9727   /* response type message. */
9728 
9729   if (debug) {
9730     fprintf(where,"recv_tcp_tran_rr: setting the response type...\n");
9731     fflush(where);
9732   }
9733 
9734   netperf_response.content.response_type = TCP_TRR_RESPONSE;
9735 
9736   if (debug) {
9737     fprintf(where,"recv_tcp_tran_rr: the response type is set...\n");
9738     fflush(where);
9739   }
9740 
9741   /* set-up the data buffer with the requested alignment and offset */
9742   message = (char *)malloc(DATABUFFERLEN);
9743   if (message == NULL) {
9744     printf("malloc(%d) failed!\n", DATABUFFERLEN);
9745     exit(1);
9746   }
9747 
9748   /* We now alter the message_ptr variables to be at the desired */
9749   /* alignments with the desired offsets. */
9750 
9751   if (debug) {
9752     fprintf(where,
9753 	    "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n",
9754 	    tcp_tran_rr_request->recv_alignment,
9755 	    tcp_tran_rr_request->recv_offset);
9756     fprintf(where,
9757 	    "recv_tcp_tran_rr: requested send alignment of %d offset %d\n",
9758 	    tcp_tran_rr_request->send_alignment,
9759 	    tcp_tran_rr_request->send_offset);
9760     fflush(where);
9761   }
9762 
9763   recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset);
9764 
9765   send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset);
9766 
9767   if (debug) {
9768     fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n");
9769     fflush(where);
9770   }
9771 
9772   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
9773   /* can put in OUR values !-) At some point, we may want to nail this */
9774   /* socket to a particular network-level address, but for now, */
9775   /* INADDR_ANY should be just fine. */
9776 
9777   bzero((char *)&myaddr_in,
9778 	sizeof(myaddr_in));
9779   myaddr_in.sin_family      = AF_INET;
9780   myaddr_in.sin_addr.s_addr = INADDR_ANY;
9781   myaddr_in.sin_port        = htons((unsigned short)tcp_tran_rr_request->port);
9782 
9783   /* Grab a socket to listen on, and then listen on it. */
9784 
9785   if (debug) {
9786     fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n");
9787     fflush(where);
9788   }
9789 
9790   /* create_data_socket expects to find some things in the global */
9791   /* variables, so set the globals based on the values in the request. */
9792   /* once the socket has been created, we will set the response values */
9793   /* based on the updated value of those globals. raj 7/94 */
9794   lss_size_req = tcp_tran_rr_request->send_buf_size;
9795   lsr_size_req = tcp_tran_rr_request->recv_buf_size;
9796   loc_nodelay = tcp_tran_rr_request->no_delay;
9797   loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid;
9798   loc_sndavoid = tcp_tran_rr_request->so_sndavoid;
9799 
9800   set_hostname_and_port(local_name,
9801 			port_buffer,
9802 			nf_to_af(tcp_tran_rr_request->ipfamily),
9803 			tcp_tran_rr_request->port);
9804 
9805   local_res = complete_addrinfo(local_name,
9806 				local_name,
9807 				port_buffer,
9808 				nf_to_af(tcp_tran_rr_request->ipfamily),
9809 				SOCK_STREAM,
9810 				IPPROTO_TCP,
9811 				0);
9812 
9813   s_listen = create_data_socket(local_res);
9814 
9815   if (s_listen == INVALID_SOCKET) {
9816     netperf_response.content.serv_errno = errno;
9817     send_response();
9818     if (debug) {
9819       fprintf(where,"could not create data socket\n");
9820       fflush(where);
9821     }
9822     exit(1);
9823   }
9824 
9825 #ifdef WIN32
9826   /* The test timer can fire during operations on the listening socket,
9827      so to make the start_timer below work we have to move
9828      it to close s_listen while we are blocked on accept. */
9829   win_kludge_socket2 = s_listen;
9830 #endif
9831 
9832 
9833   /* Let's get an address assigned to this socket so we can tell the */
9834   /* initiator how to reach the data socket. There may be a desire to */
9835   /* nail this socket to a specific IP address in a multi-homed, */
9836   /* multi-connection situation, but for now, we'll ignore the issue */
9837   /* and concentrate on single connection testing. */
9838 
9839   if (bind(s_listen,
9840 	   (struct sockaddr *)&myaddr_in,
9841 	   sizeof(myaddr_in)) == SOCKET_ERROR) {
9842     netperf_response.content.serv_errno = errno;
9843     close(s_listen);
9844     send_response();
9845     if (debug) {
9846       fprintf(where,"could not bind\n");
9847       fflush(where);
9848     }
9849     exit(1);
9850   }
9851 
9852   /* we want to disable the implicit PUSH on all sends. at some point, */
9853   /* this might want to be a parm to the test raj 3/95 */
9854   if (setsockopt(s_listen,
9855 		 IPPROTO_TCP,
9856 		 TCP_NOPUSH,
9857 		 (const char *)&NoPush,
9858 		 sizeof(int)) == SOCKET_ERROR) {
9859     fprintf(where,
9860 	    "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n",
9861 	    errno);
9862     fflush(where);
9863     netperf_response.content.serv_errno = errno;
9864     close(s_listen);
9865     send_response();
9866   }
9867 
9868   /* Now, let's set-up the socket to listen for connections */
9869   if (listen(s_listen, 5) == SOCKET_ERROR) {
9870     netperf_response.content.serv_errno = errno;
9871     close(s_listen);
9872     send_response();
9873     if (debug) {
9874       fprintf(where,"could not listen\n");
9875       fflush(where);
9876     }
9877     exit(1);
9878   }
9879 
9880   /* now get the port number assigned by the system  */
9881   addrlen = sizeof(myaddr_in);
9882   if (getsockname(s_listen,
9883 		  (struct sockaddr *)&myaddr_in,
9884 		  &addrlen) == SOCKET_ERROR){
9885     netperf_response.content.serv_errno = errno;
9886     close(s_listen);
9887     send_response();
9888     if (debug) {
9889       fprintf(where,"could not geetsockname\n");
9890       fflush(where);
9891     }
9892     exit(1);
9893   }
9894 
9895   /* Now myaddr_in contains the port and the internet address this is */
9896   /* returned to the sender also implicitly telling the sender that the */
9897   /* socket buffer sizing has been done. */
9898 
9899   tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
9900   if (debug) {
9901     fprintf(where,"telling the remote to call me at %d\n",
9902 	    tcp_tran_rr_response->data_port_number);
9903     fflush(where);
9904   }
9905   netperf_response.content.serv_errno   = 0;
9906 
9907   /* But wait, there's more. If the initiator wanted cpu measurements, */
9908   /* then we must call the calibrate routine, which will return the max */
9909   /* rate back to the initiator. If the CPU was not to be measured, or */
9910   /* something went wrong with the calibration, we will return a 0.0 to */
9911   /* the initiator. */
9912 
9913   tcp_tran_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
9914   if (tcp_tran_rr_request->measure_cpu) {
9915     tcp_tran_rr_response->measure_cpu = 1;
9916     tcp_tran_rr_response->cpu_rate =
9917       calibrate_local_cpu(tcp_tran_rr_request->cpu_rate);
9918   }
9919 
9920 
9921 
9922   /* before we send the response back to the initiator, pull some of */
9923   /* the socket parms from the globals */
9924   tcp_tran_rr_response->send_buf_size = lss_size;
9925   tcp_tran_rr_response->recv_buf_size = lsr_size;
9926   tcp_tran_rr_response->no_delay = loc_nodelay;
9927   tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid;
9928   tcp_tran_rr_response->so_sndavoid = loc_sndavoid;
9929 
9930   send_response();
9931 
9932   addrlen = sizeof(peeraddr_in);
9933 
9934   /* Now it's time to start receiving data on the connection. We will */
9935   /* first grab the apropriate counters and then start grabbing. */
9936 
9937   cpu_start(tcp_tran_rr_request->measure_cpu);
9938 
9939   /* The loop will exit when the sender does a shutdown, which will */
9940   /* return a length of zero   */
9941 
9942   if (tcp_tran_rr_request->test_length > 0) {
9943     times_up = 0;
9944     trans_remaining = 0;
9945     start_timer(tcp_tran_rr_request->test_length + PAD_TIME);
9946   }
9947   else {
9948     times_up = 1;
9949     trans_remaining = tcp_tran_rr_request->test_length * -1;
9950   }
9951 
9952   trans_received = 0;
9953 
9954   while ((!times_up) || (trans_remaining > 0)) {
9955 
9956     /* accept a connection from the remote */
9957     if ((s_data=accept(s_listen,
9958 		       (struct sockaddr *)&peeraddr_in,
9959 		       &addrlen)) == INVALID_SOCKET) {
9960       if (errno == EINTR) {
9961 	/* the timer popped */
9962 	timed_out = 1;
9963 	break;
9964       }
9965       fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno);
9966       fflush(where);
9967       close(s_listen);
9968 
9969       exit(1);
9970     }
9971 
9972     if (debug) {
9973       fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n");
9974       fflush(where);
9975     }
9976 
9977 #ifdef WIN32
9978   /* this is used so the timer thread can close the socket out from */
9979   /* under us, which to date is the easiest/cleanest/least */
9980   /* Windows-specific way I can find to force the winsock calls to */
9981   /* return WSAEINTR with the test is over. anything that will run on */
9982   /* 95 and NT and is closer to what netperf expects from Unix signals */
9983   /* and such would be appreciated raj 1/96 */
9984   win_kludge_socket = s_data;
9985 #endif /* WIN32 */
9986 
9987 #ifdef KLUDGE_SOCKET_OPTIONS
9988   /* this is for those systems which *INCORRECTLY* fail to pass */
9989   /* attributes across an accept() call. Including this goes against */
9990   /* my better judgement :( raj 11/95 */
9991 
9992   kludge_socket_options(s_data);
9993 
9994 #endif /* KLUDGE_SOCKET_OPTIONS */
9995 
9996     temp_message_ptr	= recv_message_ptr;
9997     request_bytes_remaining	= tcp_tran_rr_request->request_size;
9998 
9999     /* receive the request from the other side. we can just receive */
10000     /* until we get zero bytes, but that would be a slight structure */
10001     /* change in the code, with minimal perfomance effects. If */
10002     /* however, I has variable-length messages, I would want to do */
10003     /* this to avoid needing "double reads" - one for the message */
10004     /* length, and one for the rest of the message raj 3/95 */
10005     while(request_bytes_remaining > 0) {
10006       if((request_bytes_recvd=recv(s_data,
10007 				   temp_message_ptr,
10008 				   request_bytes_remaining,
10009 				   0)) == SOCKET_ERROR) {
10010 	    if ( SOCKET_EINTR(request_bytes_recvd) )
10011 		{
10012 	      /* the timer popped */
10013 	      timed_out = 1;
10014 	      break;
10015 		}
10016 	    netperf_response.content.serv_errno = errno;
10017 	    send_response();
10018 	    exit(1);
10019       }
10020       else {
10021 	request_bytes_remaining -= request_bytes_recvd;
10022 	temp_message_ptr  += request_bytes_recvd;
10023       }
10024     }
10025 
10026     if (timed_out) {
10027       /* we hit the end of the test based on time - lets */
10028       /* bail out of here now... */
10029       fprintf(where,"yo5\n");
10030       fflush(where);
10031       break;
10032     }
10033 
10034     /* Now, send the response to the remote we can use sendto here to */
10035     /* help remind people that this is an rfc 1644 style of test */
10036     if((bytes_sent=sendto(s_data,
10037 			  send_message_ptr,
10038 			  tcp_tran_rr_request->response_size,
10039 			  MSG_EOF,
10040 			  (struct sockaddr *)&peeraddr_in,
10041 			  sizeof(struct sockaddr_storage))) == SOCKET_ERROR) {
10042       if (SOCKET_EINTR(bytes_sent)) {
10043 	/* the test timer has popped */
10044 	timed_out = 1;
10045 	fprintf(where,"yo6\n");
10046 	fflush(where);
10047 	break;
10048       }
10049       netperf_response.content.serv_errno = 99;
10050       send_response();
10051       exit(1);
10052     }
10053 
10054     trans_received++;
10055     if (trans_remaining) {
10056       trans_remaining--;
10057     }
10058 
10059     if (debug) {
10060       fprintf(where,
10061 	      "recv_tcp_tran_rr: Transaction %d complete\n",
10062 	      trans_received);
10063       fflush(where);
10064     }
10065 
10066     /* close the connection. since we have disable PUSH on sends, the */
10067     /* FIN should be tacked-onto our last send instead of being */
10068     /* standalone */
10069     close(s_data);
10070 
10071   }
10072 
10073 
10074   /* The loop now exits due to timeout or transaction count being */
10075   /* reached */
10076 
10077   cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time);
10078 
10079   if (timed_out) {
10080     /* we ended the test by time, which was at least 2 seconds */
10081     /* longer than we wanted to run. so, we want to subtract */
10082     /* PAD_TIME from the elapsed_time. */
10083     elapsed_time -= PAD_TIME;
10084   }
10085   /* send the results to the sender			*/
10086 
10087   if (debug) {
10088     fprintf(where,
10089 	    "recv_tcp_tran_rr: got %d transactions\n",
10090 	    trans_received);
10091     fflush(where);
10092   }
10093 
10094   tcp_tran_rr_results->bytes_received	= (trans_received *
10095 					   (tcp_tran_rr_request->request_size +
10096 					    tcp_tran_rr_request->response_size));
10097   tcp_tran_rr_results->trans_received	= trans_received;
10098   tcp_tran_rr_results->elapsed_time	= elapsed_time;
10099   if (tcp_tran_rr_request->measure_cpu) {
10100     tcp_tran_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
10101   }
10102 
10103   if (debug) {
10104     fprintf(where,
10105 	    "recv_tcp_tran_rr: test complete, sending results.\n");
10106     fflush(where);
10107   }
10108 
10109   send_response();
10110 
10111 }
10112 #endif /* DO_1644 */
10113 
10114 #ifdef DO_NBRR
10115  /* this routine implements the sending (netperf) side of the TCP_RR */
10116  /* test using POSIX-style non-blocking sockets. */
10117 
10118 void
send_tcp_nbrr(char remote_host[])10119 send_tcp_nbrr(char remote_host[])
10120 {
10121 
10122   char *tput_title = "\
10123 Local /Remote\n\
10124 Socket Size   Request  Resp.   Elapsed  Trans.\n\
10125 Send   Recv   Size     Size    Time     Rate         \n\
10126 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
10127 
10128   char *tput_fmt_0 =
10129     "%7.2f\n";
10130 
10131   char *tput_fmt_1_line_1 = "\
10132 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
10133   char *tput_fmt_1_line_2 = "\
10134 %-6d %-6d\n";
10135 
10136   char *cpu_title = "\
10137 Local /Remote\n\
10138 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
10139 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
10140 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
10141 
10142   char *cpu_fmt_0 =
10143     "%6.3f %c\n";
10144 
10145   char *cpu_fmt_1_line_1 = "\
10146 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f\n";
10147 
10148   char *cpu_fmt_1_line_2 = "\
10149 %-6d %-6d\n";
10150 
10151   char *ksink_fmt = "\
10152 Alignment      Offset\n\
10153 Local  Remote  Local  Remote\n\
10154 Send   Recv    Send   Recv\n\
10155 %5d  %5d   %5d  %5d\n";
10156 
10157 
10158   int			timed_out = 0;
10159   float			elapsed_time;
10160 
10161   int	len;
10162   char	*temp_message_ptr;
10163   int	nummessages;
10164   SOCKET	send_socket;
10165   int	trans_remaining;
10166   double	bytes_xferd;
10167 
10168   struct ring_elt *send_ring;
10169   struct ring_elt *recv_ring;
10170 
10171   int	rsp_bytes_left;
10172   int	rsp_bytes_recvd;
10173 
10174   float	local_cpu_utilization;
10175   float	local_service_demand;
10176   float	remote_cpu_utilization;
10177   float	remote_service_demand;
10178   double	thruput;
10179 
10180   struct	hostent	        *hp;
10181   struct	sockaddr_storage	server;
10182   unsigned      int             addr;
10183 
10184   struct	tcp_rr_request_struct	*tcp_rr_request;
10185   struct	tcp_rr_response_struct	*tcp_rr_response;
10186   struct	tcp_rr_results_struct	*tcp_rr_result;
10187 
10188   struct addrinfo *remote_res;
10189   struct addrinfo *local_res;
10190 
10191   tcp_rr_request =
10192     (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
10193   tcp_rr_response=
10194     (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
10195   tcp_rr_result	=
10196     (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
10197 
10198 #ifdef WANT_HISTOGRAM
10199   if (verbosity > 1) {
10200     time_hist = HIST_new();
10201   }
10202 #endif /* WANT_HISTOGRAM */
10203 
10204   /* since we are now disconnected from the code that established the */
10205   /* control socket, and since we want to be able to use different */
10206   /* protocols and such, we are passed the name of the remote host and */
10207   /* must turn that into the test specific addressing information. */
10208 
10209   bzero((char *)&server,
10210 	sizeof(server));
10211 
10212   complete_addrinfos(&remote_res,
10213 		     &local_res,
10214 		     remote_host,
10215 		     SOCK_STREAM,
10216 		     IPPROTO_TCP,
10217 		     0);
10218 
10219   if ( print_headers ) {
10220     print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res);
10221   }
10222 
10223   /* initialize a few counters */
10224 
10225   send_ring = NULL;
10226   recv_ring = NULL;
10227   confidence_iteration = 1;
10228   init_stat();
10229 
10230   /* we have a great-big while loop which controls the number of times */
10231   /* we run a particular test. this is for the calculation of a */
10232   /* confidence interval (I really should have stayed awake during */
10233   /* probstats :). If the user did not request confidence measurement */
10234   /* (no confidence is the default) then we will only go though the */
10235   /* loop once. the confidence stuff originates from the folks at IBM */
10236 
10237   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
10238 	 (confidence_iteration <= iteration_min)) {
10239 
10240     /* initialize a few counters. we have to remember that we might be */
10241     /* going through the loop more than once. */
10242 
10243     nummessages     = 0;
10244     bytes_xferd     = 0.0;
10245     times_up        = 0;
10246     timed_out       = 0;
10247     trans_remaining = 0;
10248 
10249     /* set-up the data buffers with the requested alignment and offset. */
10250     /* since this is a request/response test, default the send_width and */
10251     /* recv_width to 1 and not two raj 7/94 */
10252 
10253     if (send_width == 0) send_width = 1;
10254     if (recv_width == 0) recv_width = 1;
10255 
10256     if (send_ring == NULL) {
10257       send_ring = allocate_buffer_ring(send_width,
10258 				       req_size,
10259 				       local_send_align,
10260 				       local_send_offset);
10261     }
10262 
10263     if (recv_ring == NULL) {
10264       recv_ring = allocate_buffer_ring(recv_width,
10265 				       rsp_size,
10266 				       local_recv_align,
10267 				       local_recv_offset);
10268     }
10269 
10270     /*set up the data socket                        */
10271     send_socket = create_data_socket(local_res);
10272 
10273     if (send_socket == INVALID_SOCKET){
10274       perror("netperf: send_tcp_nbrr: tcp stream data socket");
10275       exit(1);
10276     }
10277 
10278     if (debug) {
10279       fprintf(where,"send_tcp_nbrr: send_socket obtained...\n");
10280     }
10281 
10282     /* If the user has requested cpu utilization measurements, we must */
10283     /* calibrate the cpu(s). We will perform this task within the tests */
10284     /* themselves. If the user has specified the cpu rate, then */
10285     /* calibrate_local_cpu will return rather quickly as it will have */
10286     /* nothing to do. If local_cpu_rate is zero, then we will go through */
10287     /* all the "normal" calibration stuff and return the rate back.*/
10288 
10289     if (local_cpu_usage) {
10290       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
10291     }
10292 
10293     /* Tell the remote end to do a listen. The server alters the socket */
10294     /* paramters on the other side at this point, hence the reason for */
10295     /* all the values being passed in the setup message. If the user did */
10296     /* not specify any of the parameters, they will be passed as 0, which */
10297     /* will indicate to the remote that no changes beyond the system's */
10298     /* default should be used. Alignment is the exception, it will */
10299     /* default to 8, which will be no alignment alterations. */
10300 
10301     netperf_request.content.request_type	=	DO_TCP_NBRR;
10302     tcp_rr_request->recv_buf_size	=	rsr_size_req;
10303     tcp_rr_request->send_buf_size	=	rss_size_req;
10304     tcp_rr_request->recv_alignment      =	remote_recv_align;
10305     tcp_rr_request->recv_offset	        =	remote_recv_offset;
10306     tcp_rr_request->send_alignment      =	remote_send_align;
10307     tcp_rr_request->send_offset	        =	remote_send_offset;
10308     tcp_rr_request->request_size	=	req_size;
10309     tcp_rr_request->response_size	=	rsp_size;
10310     tcp_rr_request->no_delay	        =	rem_nodelay;
10311     tcp_rr_request->measure_cpu	        =	remote_cpu_usage;
10312     tcp_rr_request->cpu_rate	        =	remote_cpu_rate;
10313     tcp_rr_request->so_rcvavoid	        =	rem_rcvavoid;
10314     tcp_rr_request->so_sndavoid	        =	rem_sndavoid;
10315     if (test_time) {
10316       tcp_rr_request->test_length	=	test_time;
10317     }
10318     else {
10319       tcp_rr_request->test_length	=	test_trans * -1;
10320     }
10321 
10322     if (debug > 1) {
10323       fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n");
10324     }
10325 
10326     send_request();
10327 
10328     /* The response from the remote will contain all of the relevant 	*/
10329     /* socket parameters for this test type. We will put them back into */
10330     /* the variables here so they can be displayed if desired.  The	*/
10331     /* remote will have calibrated CPU if necessary, and will have done	*/
10332     /* all the needed set-up we will have calibrated the cpu locally	*/
10333     /* before sending the request, and will grab the counter value right*/
10334     /* after the connect returns. The remote will grab the counter right*/
10335     /* after the accept call. This saves the hassle of extra messages	*/
10336     /* being sent for the TCP tests.					*/
10337 
10338     recv_response();
10339 
10340     if (!netperf_response.content.serv_errno) {
10341       if (debug)
10342 	fprintf(where,"remote listen done.\n");
10343       rsr_size          = tcp_rr_response->recv_buf_size;
10344       rss_size          = tcp_rr_response->send_buf_size;
10345       rem_nodelay       = tcp_rr_response->no_delay;
10346       remote_cpu_usage  = tcp_rr_response->measure_cpu;
10347       remote_cpu_rate   = tcp_rr_response->cpu_rate;
10348       /* make sure that port numbers are in network order */
10349       server.sin_port   = (unsigned short)tcp_rr_response->data_port_number;
10350       server.sin_port   = htons(server.sin_port);
10351     }
10352     else {
10353       Set_errno(netperf_response.content.serv_errno);
10354       fprintf(where,
10355 	      "netperf: remote error %d",
10356 	      netperf_response.content.serv_errno);
10357       perror("");
10358       fflush(where);
10359       exit(1);
10360     }
10361 
10362     /*Connect up to the remote port on the data socket  */
10363     if (connect(send_socket,
10364 		remote_res->ai_addr,
10365 		remote_res->ai_addrlen) == INVALID_SOCKET){
10366       perror("netperf: data socket connect failed");
10367 
10368       exit(1);
10369     }
10370 
10371     /* now that we are connected, mark the socket as non-blocking */
10372     if (!set_nonblock(send_socket)) {
10373       perror("netperf: set_nonblock");
10374       exit(1);
10375     }
10376 
10377     /* Data Socket set-up is finished. If there were problems, either the */
10378     /* connect would have failed, or the previous response would have */
10379     /* indicated a problem. I failed to see the value of the extra */
10380     /* message after the accept on the remote. If it failed, we'll see it */
10381     /* here. If it didn't, we might as well start pumping data. */
10382 
10383     /* Set-up the test end conditions. For a request/response test, they */
10384     /* can be either time or transaction based. */
10385 
10386     if (test_time) {
10387       /* The user wanted to end the test after a period of time. */
10388       times_up = 0;
10389       trans_remaining = 0;
10390       start_timer(test_time);
10391     }
10392     else {
10393       /* The tester wanted to send a number of bytes. */
10394       trans_remaining = test_bytes;
10395       times_up = 1;
10396     }
10397 
10398     /* The cpu_start routine will grab the current time and possibly */
10399     /* value of the idle counter for later use in measuring cpu */
10400     /* utilization and/or service demand and thruput. */
10401 
10402     cpu_start(local_cpu_usage);
10403 
10404 #ifdef WANT_INTERVALS
10405     INTERVALS_INIT();
10406 #endif /* WANT_INTERVALS */
10407 
10408     /* We use an "OR" to control test execution. When the test is */
10409     /* controlled by time, the byte count check will always return false. */
10410     /* When the test is controlled by byte count, the time test will */
10411     /* always return false. When the test is finished, the whole */
10412     /* expression will go false and we will stop sending data. I think I */
10413     /* just arbitrarily decrement trans_remaining for the timed test, but */
10414     /* will not do that just yet... One other question is whether or not */
10415     /* the send buffer and the receive buffer should be the same buffer. */
10416 
10417     while ((!times_up) || (trans_remaining > 0)) {
10418       /* send the request. we assume that if we use a blocking socket, */
10419       /* the request will be sent at one shot. */
10420 
10421 #ifdef WANT_HISTOGRAM
10422       if (verbosity > 1) {
10423 	/* timestamp just before our call to send, and then again just */
10424 	/* after the receive raj 8/94 */
10425 	HIST_timestamp(&time_one);
10426       }
10427 #endif /* WANT_HISTOGRAM */
10428 
10429       /* even though this is a non-blocking socket, we will assume for */
10430       /* the time being that we will be able to send an entire request */
10431       /* without getting an EAGAIN */
10432       if((len=send(send_socket,
10433 		   send_ring->buffer_ptr,
10434 		   req_size,
10435 		   0)) != req_size) {
10436 	if (SOCKET_EINTR(len)) {
10437 	  /* we hit the end of a */
10438 	  /* timed test. */
10439 	  timed_out = 1;
10440 	  break;
10441 	}
10442 	perror("send_tcp_nbrr: data send error");
10443 	exit(1);
10444       }
10445       send_ring = send_ring->next;
10446 
10447       /* receive the response. since we are using non-blocking I/O, we */
10448       /* will "spin" on the recvs */
10449       rsp_bytes_left = rsp_size;
10450       temp_message_ptr  = recv_ring->buffer_ptr;
10451       while(rsp_bytes_left > 0) {
10452 	if((rsp_bytes_recvd=recv(send_socket,
10453 				 temp_message_ptr,
10454 				 rsp_bytes_left,
10455 				 0)) == SOCKET_ERROR) {
10456 	  if (SOCKET_EINTR(rsp_bytes_recvd))
10457 	  {
10458 	    /* We hit the end of a timed test. */
10459 	    timed_out = 1;
10460 	    break;
10461 	  }
10462 #ifndef WIN32  // But what does WinNT indicate in this situation...
10463 	  else if (errno == EAGAIN) {
10464 	    Set_errno(0);
10465 	    continue;
10466 	  }
10467 #endif
10468 	  else {
10469 	    perror("send_tcp_nbrr: data recv error");
10470 	    exit(1);
10471 	  }
10472 	}
10473 	rsp_bytes_left -= rsp_bytes_recvd;
10474 	temp_message_ptr  += rsp_bytes_recvd;
10475       }
10476       recv_ring = recv_ring->next;
10477 
10478       if (timed_out) {
10479 	/* we may have been in a nested while loop - we need */
10480 	/* another call to break. */
10481 	break;
10482       }
10483 
10484 #ifdef WANT_HISTOGRAM
10485       if (verbosity > 1) {
10486 	HIST_timestamp(&time_two);
10487 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
10488       }
10489 #endif /* WANT_HISTOGRAM */
10490 #ifdef WANT_INTERVALS
10491       INTERVALS_WAIT();
10492 #endif /* WANT_INTERVALS */
10493 
10494       nummessages++;
10495       if (trans_remaining) {
10496 	trans_remaining--;
10497       }
10498 
10499       if (debug > 3) {
10500 	if ((nummessages % 100) == 0) {
10501 	  fprintf(where,
10502 		  "Transaction %d completed\n",
10503 		  nummessages);
10504 	  fflush(where);
10505 	}
10506       }
10507     }
10508 
10509     /* At this point we used to call shutdown on the data socket to be */
10510     /* sure all the data was delivered, but this was not germane in a */
10511     /* request/response test, and it was causing the tests to "hang" when */
10512     /* they were being controlled by time. So, I have replaced this */
10513     /* shutdown call with a call to close that can be found later in the */
10514     /* procedure. */
10515 
10516     /* this call will always give us the elapsed time for the test, and */
10517     /* will also store-away the necessaries for cpu utilization */
10518 
10519     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
10520 						/* measured? how long */
10521 						/* did we really run? */
10522 
10523     /* Get the statistics from the remote end. The remote will have */
10524     /* calculated service demand and all those interesting things. If it */
10525     /* wasn't supposed to care, it will return obvious values. */
10526 
10527     recv_response();
10528     if (!netperf_response.content.serv_errno) {
10529       if (debug)
10530 	fprintf(where,"remote results obtained\n");
10531     }
10532     else {
10533       Set_errno(netperf_response.content.serv_errno);
10534       fprintf(where,
10535 	      "netperf: remote error %d",
10536 	      netperf_response.content.serv_errno);
10537       perror("");
10538       fflush(where);
10539 
10540       exit(1);
10541     }
10542 
10543     /* We now calculate what our thruput was for the test. */
10544 
10545     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
10546     thruput	= nummessages/elapsed_time;
10547 
10548     if (local_cpu_usage || remote_cpu_usage) {
10549       /* We must now do a little math for service demand and cpu */
10550       /* utilization for the system(s) */
10551       /* Of course, some of the information might be bogus because */
10552       /* there was no idle counter in the kernel(s). We need to make */
10553       /* a note of this for the user's benefit...*/
10554       if (local_cpu_usage) {
10555 	local_cpu_utilization = calc_cpu_util(0.0);
10556 	/* since calc_service demand is doing ms/Kunit we will */
10557 	/* multiply the number of transaction by 1024 to get */
10558 	/* "good" numbers */
10559 	local_service_demand  = calc_service_demand((double) nummessages*1024,
10560 						    0.0,
10561 						    0.0,
10562 						    0);
10563       }
10564       else {
10565 	local_cpu_utilization	= (float) -1.0;
10566 	local_service_demand	= (float) -1.0;
10567       }
10568 
10569       if (remote_cpu_usage) {
10570 	remote_cpu_utilization = tcp_rr_result->cpu_util;
10571 	/* since calc_service demand is doing ms/Kunit we will */
10572 	/* multiply the number of transaction by 1024 to get */
10573 	/* "good" numbers */
10574 	remote_service_demand = calc_service_demand((double) nummessages*1024,
10575 						    0.0,
10576 						    remote_cpu_utilization,
10577 						    tcp_rr_result->num_cpus);
10578       }
10579       else {
10580 	remote_cpu_utilization = (float) -1.0;
10581 	remote_service_demand  = (float) -1.0;
10582       }
10583 
10584     }
10585     else {
10586       /* we were not measuring cpu, for the confidence stuff, we */
10587       /* should make it -1.0 */
10588       local_cpu_utilization	= (float) -1.0;
10589       local_service_demand	= (float) -1.0;
10590       remote_cpu_utilization = (float) -1.0;
10591       remote_service_demand  = (float) -1.0;
10592     }
10593 
10594     /* at this point, we want to calculate the confidence information. */
10595     /* if debugging is on, calculate_confidence will print-out the */
10596     /* parameters we pass it */
10597 
10598     calculate_confidence(confidence_iteration,
10599 			 elapsed_time,
10600 			 thruput,
10601 			 local_cpu_utilization,
10602 			 remote_cpu_utilization,
10603 			 local_service_demand,
10604 			 remote_service_demand);
10605 
10606 
10607     confidence_iteration++;
10608 
10609     /* we are now done with the socket, so close it */
10610     close(send_socket);
10611 
10612   }
10613 
10614   retrieve_confident_values(&elapsed_time,
10615 			    &thruput,
10616 			    &local_cpu_utilization,
10617 			    &remote_cpu_utilization,
10618 			    &local_service_demand,
10619 			    &remote_service_demand);
10620 
10621   /* We are now ready to print all the information. If the user */
10622   /* has specified zero-level verbosity, we will just print the */
10623   /* local service demand, or the remote service demand. If the */
10624   /* user has requested verbosity level 1, he will get the basic */
10625   /* "streamperf" numbers. If the user has specified a verbosity */
10626   /* of greater than 1, we will display a veritable plethora of */
10627   /* background information from outside of this block as it it */
10628   /* not cpu_measurement specific...  */
10629 
10630   if (confidence < 0) {
10631     /* we did not hit confidence, but were we asked to look for it? */
10632     if (iteration_max > 1) {
10633       display_confidence();
10634     }
10635   }
10636 
10637   if (local_cpu_usage || remote_cpu_usage) {
10638     local_cpu_method = format_cpu_method(cpu_method);
10639     remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
10640 
10641     switch (verbosity) {
10642     case 0:
10643       if (local_cpu_usage) {
10644 	fprintf(where,
10645 		cpu_fmt_0,
10646 		local_service_demand,
10647 		local_cpu_method);
10648       }
10649       else {
10650 	fprintf(where,
10651 		cpu_fmt_0,
10652 		remote_service_demand,
10653 		remote_cpu_method);
10654       }
10655       break;
10656     case 1:
10657     case 2:
10658       if (print_headers) {
10659 	fprintf(where,
10660 		cpu_title,
10661 		local_cpu_method,
10662 		remote_cpu_method);
10663       }
10664 
10665       fprintf(where,
10666 	      cpu_fmt_1_line_1,		/* the format string */
10667 	      lss_size,		/* local sendbuf size */
10668 	      lsr_size,
10669 	      req_size,		/* how large were the requests */
10670 	      rsp_size,		/* guess */
10671 	      elapsed_time,		/* how long was the test */
10672 	      thruput,
10673 	      local_cpu_utilization,	/* local cpu */
10674 	      remote_cpu_utilization,	/* remote cpu */
10675 	      local_service_demand,	/* local service demand */
10676 	      remote_service_demand);	/* remote service demand */
10677       fprintf(where,
10678 	      cpu_fmt_1_line_2,
10679 	      rss_size,
10680 	      rsr_size);
10681       break;
10682     }
10683   }
10684   else {
10685     /* The tester did not wish to measure service demand. */
10686 
10687     switch (verbosity) {
10688     case 0:
10689       fprintf(where,
10690 	      tput_fmt_0,
10691 	      thruput);
10692       break;
10693     case 1:
10694     case 2:
10695       if (print_headers) {
10696 	fprintf(where,tput_title,format_units());
10697       }
10698 
10699       fprintf(where,
10700 	      tput_fmt_1_line_1,	/* the format string */
10701 	      lss_size,
10702 	      lsr_size,
10703 	      req_size,		/* how large were the requests */
10704 	      rsp_size,		/* how large were the responses */
10705 	      elapsed_time, 		/* how long did it take */
10706 	      thruput);
10707       fprintf(where,
10708 	      tput_fmt_1_line_2,
10709 	      rss_size, 		/* remote recvbuf size */
10710 	      rsr_size);
10711 
10712       break;
10713     }
10714   }
10715 
10716   /* it would be a good thing to include information about some of the */
10717   /* other parameters that may have been set for this test, but at the */
10718   /* moment, I do not wish to figure-out all the  formatting, so I will */
10719   /* just put this comment here to help remind me that it is something */
10720   /* that should be done at a later time. */
10721 
10722   /* how to handle the verbose information in the presence of */
10723   /* confidence intervals is yet to be determined... raj 11/94 */
10724   if (verbosity > 1) {
10725     /* The user wanted to know it all, so we will give it to him. */
10726     /* This information will include as much as we can find about */
10727     /* TCP statistics, the alignments of the sends and receives */
10728     /* and all that sort of rot... */
10729 
10730     fprintf(where,
10731 	    ksink_fmt,
10732 	    local_send_align,
10733 	    remote_recv_offset,
10734 	    local_send_offset,
10735 	    remote_recv_offset);
10736 
10737 #ifdef WANT_HISTOGRAM
10738     fprintf(where,"\nHistogram of request/response times\n");
10739     fflush(where);
10740     HIST_report(time_hist);
10741 #endif /* WANT_HISTOGRAM */
10742 
10743   }
10744 
10745 }
10746 
10747  /* this routine implements the receive (netserver) side of a TCP_RR */
10748  /* test */
10749 void
recv_tcp_nbrr()10750 recv_tcp_nbrr()
10751 {
10752 
10753   struct ring_elt *send_ring;
10754   struct ring_elt *recv_ring;
10755 
10756   struct	sockaddr_in        myaddr_in,
10757   peeraddr_in;
10758   SOCKET	s_listen,s_data;
10759   netperf_socklen_t 	addrlen;
10760   char	*temp_message_ptr;
10761   int	trans_received;
10762   int	trans_remaining;
10763   int	bytes_sent;
10764   int	request_bytes_recvd;
10765   int	request_bytes_remaining;
10766   int	timed_out = 0;
10767   float	elapsed_time;
10768 
10769   struct addrinfo *local_res;
10770   char local_name[BUFSIZ];
10771   char port_buffer[PORTBUFSIZE];
10772 
10773   struct	tcp_rr_request_struct	*tcp_rr_request;
10774   struct	tcp_rr_response_struct	*tcp_rr_response;
10775   struct	tcp_rr_results_struct	*tcp_rr_results;
10776 
10777   tcp_rr_request =
10778     (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
10779   tcp_rr_response =
10780     (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
10781   tcp_rr_results =
10782     (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
10783 
10784   if (debug) {
10785     fprintf(where,"netserver: recv_tcp_nbrr: entered...\n");
10786     fflush(where);
10787   }
10788 
10789   /* We want to set-up the listen socket with all the desired */
10790   /* parameters and then let the initiator know that all is ready. If */
10791   /* socket size defaults are to be used, then the initiator will have */
10792   /* sent us 0's. If the socket sizes cannot be changed, then we will */
10793   /* send-back what they are. If that information cannot be determined, */
10794   /* then we send-back -1's for the sizes. If things go wrong for any */
10795   /* reason, we will drop back ten yards and punt. */
10796 
10797   /* If anything goes wrong, we want the remote to know about it. It */
10798   /* would be best if the error that the remote reports to the user is */
10799   /* the actual error we encountered, rather than some bogus unexpected */
10800   /* response type message. */
10801 
10802   if (debug) {
10803     fprintf(where,"recv_tcp_nbrr: setting the response type...\n");
10804     fflush(where);
10805   }
10806 
10807   netperf_response.content.response_type = TCP_RR_RESPONSE;
10808 
10809   if (debug) {
10810     fprintf(where,"recv_tcp_nbrr: the response type is set...\n");
10811     fflush(where);
10812   }
10813 
10814   /* allocate the recv and send rings with the requested alignments */
10815   /* and offsets. raj 7/94 */
10816   if (debug) {
10817     fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n",
10818 	    tcp_rr_request->recv_alignment,
10819 	    tcp_rr_request->recv_offset);
10820     fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n",
10821 	    tcp_rr_request->send_alignment,
10822 	    tcp_rr_request->send_offset);
10823     fflush(where);
10824   }
10825 
10826   /* at some point, these need to come to us from the remote system */
10827   if (send_width == 0) send_width = 1;
10828   if (recv_width == 0) recv_width = 1;
10829 
10830   send_ring = allocate_buffer_ring(send_width,
10831 				   tcp_rr_request->response_size,
10832 				   tcp_rr_request->send_alignment,
10833 				   tcp_rr_request->send_offset);
10834 
10835   recv_ring = allocate_buffer_ring(recv_width,
10836 				   tcp_rr_request->request_size,
10837 				   tcp_rr_request->recv_alignment,
10838 				   tcp_rr_request->recv_offset);
10839 
10840 
10841   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
10842   /* can put in OUR values !-) At some point, we may want to nail this */
10843   /* socket to a particular network-level address, but for now, */
10844   /* INADDR_ANY should be just fine. */
10845 
10846   bzero((char *)&myaddr_in,
10847 	sizeof(myaddr_in));
10848   myaddr_in.sin_family      = AF_INET;
10849   myaddr_in.sin_addr.s_addr = INADDR_ANY;
10850   myaddr_in.sin_port        = htons((unsigned short)tcp_rr_request->port);
10851 
10852   /* Grab a socket to listen on, and then listen on it. */
10853 
10854   if (debug) {
10855     fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n");
10856     fflush(where);
10857   }
10858 
10859   /* create_data_socket expects to find some things in the global */
10860   /* variables, so set the globals based on the values in the request. */
10861   /* once the socket has been created, we will set the response values */
10862   /* based on the updated value of those globals. raj 7/94 */
10863   lss_size_req = tcp_rr_request->send_buf_size;
10864   lsr_size_req = tcp_rr_request->recv_buf_size;
10865   loc_nodelay = tcp_rr_request->no_delay;
10866   loc_rcvavoid = tcp_rr_request->so_rcvavoid;
10867   loc_sndavoid = tcp_rr_request->so_sndavoid;
10868 
10869   set_hostname_and_port(local_name,
10870 			port_buffer,
10871 			nf_to_af(tcp_rr_request->ipfamily),
10872 			tcp_rr_request->port);
10873 
10874   local_res = complete_addrinfo(local_name,
10875 				local_name,
10876 				port_buffer,
10877 				nf_to_af(tcp_rr_request->ipfamily),
10878 				SOCK_STREAM,
10879 				IPPROTO_TCP,
10880 				0);
10881 
10882   s_listen = create_data_socket(local_res);
10883 
10884   if (s_listen == INVALID_SOCKET) {
10885     netperf_response.content.serv_errno = errno;
10886     send_response();
10887 
10888     exit(1);
10889   }
10890 
10891   /* Let's get an address assigned to this socket so we can tell the */
10892   /* initiator how to reach the data socket. There may be a desire to */
10893   /* nail this socket to a specific IP address in a multi-homed, */
10894   /* multi-connection situation, but for now, we'll ignore the issue */
10895   /* and concentrate on single connection testing. */
10896 
10897   if (bind(s_listen,
10898 	   (struct sockaddr *)&myaddr_in,
10899 	   sizeof(myaddr_in)) == SOCKET_ERROR) {
10900     netperf_response.content.serv_errno = errno;
10901     close(s_listen);
10902     send_response();
10903 
10904     exit(1);
10905   }
10906 
10907   /* Now, let's set-up the socket to listen for connections */
10908   if (listen(s_listen, 5) == SOCKET_ERROR) {
10909     netperf_response.content.serv_errno = errno;
10910     close(s_listen);
10911     send_response();
10912 
10913     exit(1);
10914   }
10915 
10916 
10917   /* now get the port number assigned by the system  */
10918   addrlen = sizeof(myaddr_in);
10919   if (getsockname(s_listen,
10920 		  (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){
10921     netperf_response.content.serv_errno = errno;
10922     close(s_listen);
10923     send_response();
10924 
10925     exit(1);
10926   }
10927 
10928   /* Now myaddr_in contains the port and the internet address this is */
10929   /* returned to the sender also implicitly telling the sender that the */
10930   /* socket buffer sizing has been done. */
10931 
10932   tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
10933   netperf_response.content.serv_errno   = 0;
10934 
10935   /* But wait, there's more. If the initiator wanted cpu measurements, */
10936   /* then we must call the calibrate routine, which will return the max */
10937   /* rate back to the initiator. If the CPU was not to be measured, or */
10938   /* something went wrong with the calibration, we will return a 0.0 to */
10939   /* the initiator. */
10940 
10941   tcp_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
10942   tcp_rr_response->measure_cpu = 0;
10943 
10944   if (tcp_rr_request->measure_cpu) {
10945     tcp_rr_response->measure_cpu = 1;
10946     tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
10947   }
10948 
10949 
10950   /* before we send the response back to the initiator, pull some of */
10951   /* the socket parms from the globals */
10952   tcp_rr_response->send_buf_size = lss_size;
10953   tcp_rr_response->recv_buf_size = lsr_size;
10954   tcp_rr_response->no_delay = loc_nodelay;
10955   tcp_rr_response->so_rcvavoid = loc_rcvavoid;
10956   tcp_rr_response->so_sndavoid = loc_sndavoid;
10957   tcp_rr_response->test_length = tcp_rr_request->test_length;
10958   send_response();
10959 
10960   addrlen = sizeof(peeraddr_in);
10961 
10962   if ((s_data = accept(s_listen,
10963 		       (struct sockaddr *)&peeraddr_in,
10964 		       &addrlen)) == INVALID_SOCKET) {
10965     /* Let's just punt. The remote will be given some information */
10966     close(s_listen);
10967     exit(1);
10968   }
10969 
10970   if (debug) {
10971     fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n");
10972     fflush(where);
10973   }
10974 
10975 #ifdef KLUDGE_SOCKET_OPTIONS
10976   /* this is for those systems which *INCORRECTLY* fail to pass */
10977   /* attributes across an accept() call. Including this goes against */
10978   /* my better judgement :( raj 11/95 */
10979 
10980   kludge_socket_options(s_data);
10981 
10982 #endif /* KLUDGE_SOCKET_OPTIONS */
10983 
10984   /* now that we are connected, mark the socket as non-blocking */
10985   if (!set_nonblock(s_data)) {
10986     close(s_data);
10987     exit(1);
10988   }
10989 
10990 
10991   /* Now it's time to start receiving data on the connection. We will */
10992   /* first grab the apropriate counters and then start grabbing. */
10993 
10994   cpu_start(tcp_rr_request->measure_cpu);
10995 
10996 #ifdef WIN32
10997   /* this is used so the timer thread can close the socket out from */
10998   /* under us, which to date is the easiest/cleanest/least */
10999   /* Windows-specific way I can find to force the winsock calls to */
11000   /* return WSAEINTR with the test is over. anything that will run on */
11001   /* 95 and NT and is closer to what netperf expects from Unix signals */
11002   /* and such would be appreciated raj 1/96 */
11003   win_kludge_socket = s_data;
11004 #endif /* WIN32 */
11005 
11006   /* The loop will exit when the sender does a shutdown, which will */
11007   /* return a length of zero   */
11008 
11009   if (tcp_rr_request->test_length > 0) {
11010     times_up = 0;
11011     trans_remaining = 0;
11012     start_timer(tcp_rr_request->test_length + PAD_TIME);
11013   }
11014   else {
11015     times_up = 1;
11016     trans_remaining = tcp_rr_request->test_length * -1;
11017   }
11018 
11019   trans_received = 0;
11020 
11021   while ((!times_up) || (trans_remaining > 0)) {
11022     temp_message_ptr = recv_ring->buffer_ptr;
11023     request_bytes_remaining	= tcp_rr_request->request_size;
11024     while(request_bytes_remaining > 0) {
11025       if((request_bytes_recvd=recv(s_data,
11026 				   temp_message_ptr,
11027 				   request_bytes_remaining,
11028 				   0)) == SOCKET_ERROR) {
11029 	    if ( SOCKET_EINTR(request_bytes_recvd))
11030 		{
11031 	      /* the timer popped */
11032 	      timed_out = 1;
11033 	      break;
11034 		}
11035 #ifndef WIN32  // But what does WinNT indicate in this situation...
11036 	    else if (errno == EAGAIN) {
11037 	      Set_errno(0);
11038 	      if (times_up) {
11039 	        timed_out = 1;
11040 	        break;
11041 		  }
11042 	      continue;
11043 		}
11044 #endif
11045 	    else {
11046 	      netperf_response.content.serv_errno = errno;
11047 	      send_response();
11048 	      exit(1);
11049 		}
11050       }
11051       else {
11052 	request_bytes_remaining -= request_bytes_recvd;
11053 	temp_message_ptr  += request_bytes_recvd;
11054       }
11055     }
11056 
11057     recv_ring = recv_ring->next;
11058 
11059     if (timed_out) {
11060       /* we hit the end of the test based on time - lets */
11061       /* bail out of here now... */
11062       fprintf(where,"yo5\n");
11063       fflush(where);
11064       break;
11065     }
11066 
11067     /* Now, send the response to the remote */
11068     if((bytes_sent=send(s_data,
11069 			send_ring->buffer_ptr,
11070 			tcp_rr_request->response_size,
11071 			0)) == SOCKET_ERROR) {
11072       if (SOCKET_EINTR(bytes_sent)) {
11073 	/* the test timer has popped */
11074 	timed_out = 1;
11075 	fprintf(where,"yo6\n");
11076 	fflush(where);
11077 	break;
11078       }
11079       netperf_response.content.serv_errno = 992;
11080       send_response();
11081       exit(1);
11082     }
11083 
11084     send_ring = send_ring->next;
11085 
11086     trans_received++;
11087     if (trans_remaining) {
11088       trans_remaining--;
11089     }
11090   }
11091 
11092 
11093   /* The loop now exits due to timeout or transaction count being */
11094   /* reached */
11095 
11096   cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
11097 
11098   stop_timer();
11099 
11100   if (timed_out) {
11101     /* we ended the test by time, which was at least 2 seconds */
11102     /* longer than we wanted to run. so, we want to subtract */
11103     /* PAD_TIME from the elapsed_time. */
11104     elapsed_time -= PAD_TIME;
11105   }
11106 
11107   /* send the results to the sender			*/
11108 
11109   if (debug) {
11110     fprintf(where,
11111 	    "recv_tcp_nbrr: got %d transactions\n",
11112 	    trans_received);
11113     fflush(where);
11114   }
11115 
11116   tcp_rr_results->bytes_received = (trans_received *
11117 				    (tcp_rr_request->request_size +
11118 				     tcp_rr_request->response_size));
11119   tcp_rr_results->trans_received = trans_received;
11120   tcp_rr_results->elapsed_time   = elapsed_time;
11121   tcp_rr_results->cpu_method     = cpu_method;
11122   tcp_rr_results->num_cpus       = lib_num_loc_cpus;
11123   if (tcp_rr_request->measure_cpu) {
11124     tcp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
11125   }
11126 
11127   if (debug) {
11128     fprintf(where,
11129 	    "recv_tcp_nbrr: test complete, sending results.\n");
11130     fflush(where);
11131   }
11132 
11133   /* we are done with the socket, free it */
11134   close(s_data);
11135 
11136   send_response();
11137 
11138 }
11139 
11140 #endif /* DO_NBRR */
11141 
11142 
11143  /* this test is intended to test the performance of establishing a */
11144  /* connection, and then closing it again. this test is of somewhat */
11145  /* arcane interest since no packets are exchanged between the */
11146  /* user-space processes, but it will show the raw overhead of */
11147  /* establishing a TCP connection. that service demand could then be */
11148  /* compared with the sum of the service demands of a TCP_CRR and */
11149  /* TCP_RR test - presumeably, they would all relate */
11150 
11151 void
send_tcp_cc(char remote_host[])11152 send_tcp_cc(char remote_host[])
11153 {
11154 
11155   char *tput_title = "\
11156 Local /Remote\n\
11157 Socket Size   Request  Resp.   Elapsed  Trans.\n\
11158 Send   Recv   Size     Size    Time     Rate         \n\
11159 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
11160 
11161   char *tput_fmt_0 =
11162     "%7.2f\n";
11163 
11164   char *tput_fmt_1_line_1 = "\
11165 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
11166   char *tput_fmt_1_line_2 = "\
11167 %-6d %-6d\n";
11168 
11169   char *cpu_title = "\
11170 Local /Remote\n\
11171 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
11172 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
11173 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
11174 
11175   char *cpu_fmt_0 =
11176     "%6.3f\n";
11177 
11178   char *cpu_fmt_1_line_1 = "\
11179 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
11180 
11181   char *cpu_fmt_1_line_2 = "\
11182 %-6d %-6d\n";
11183 
11184   char *ksink_fmt = "\n\
11185 Alignment      Offset\n\
11186 Local  Remote  Local  Remote\n\
11187 Send   Recv    Send   Recv\n\
11188 %5d  %5d   %5d  %5d\n";
11189 
11190 
11191   int			timed_out = 0;
11192   float			elapsed_time;
11193 
11194   char	temp_message_ptr[1];
11195   int	nummessages;
11196   SOCKET	send_socket;
11197   int	trans_remaining;
11198   double	bytes_xferd;
11199   int	rsp_bytes_left = 1;
11200   int	rsp_bytes_recvd;
11201 
11202   float	local_cpu_utilization;
11203   float	local_service_demand;
11204   float	remote_cpu_utilization;
11205   float	remote_service_demand;
11206   double	thruput;
11207 
11208   struct addrinfo *local_res;
11209   struct addrinfo *remote_res;
11210 
11211   int                           myport;
11212   int                           ret;
11213 
11214   struct	tcp_cc_request_struct	*tcp_cc_request;
11215   struct	tcp_cc_response_struct	*tcp_cc_response;
11216   struct	tcp_cc_results_struct	*tcp_cc_result;
11217 
11218   tcp_cc_request =
11219     (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
11220   tcp_cc_response =
11221     (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
11222   tcp_cc_result =
11223     (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
11224 
11225 
11226 #ifdef WANT_HISTOGRAM
11227   if (verbosity > 1) {
11228     time_hist = HIST_new();
11229   }
11230 #endif /* WANT_HISTOGRAM */
11231 
11232   /* since we are now disconnected from the code that established the */
11233   /* control socket, and since we want to be able to use different */
11234   /* protocols and such, we are passed the name of the remote host and */
11235   /* must turn that into the test specific addressing information. */
11236 
11237   complete_addrinfos(&remote_res,
11238 		     &local_res,
11239 		     remote_host,
11240 		     SOCK_STREAM,
11241 		     IPPROTO_TCP,
11242 		     0);
11243 
11244   if ( print_headers ) {
11245     print_top_test_header("TCP Connect/Close TEST",local_res,remote_res);
11246   }
11247 
11248   /* initialize a few counters */
11249 
11250   nummessages	=	0;
11251   bytes_xferd	=	0.0;
11252   times_up 	= 	0;
11253 
11254   /* since there are no data buffers in this test, we need no send or */
11255   /* recv rings */
11256 
11257   if (debug) {
11258     fprintf(where,"send_tcp_cc: send_socket obtained...\n");
11259   }
11260 
11261   /* If the user has requested cpu utilization measurements, we must */
11262   /* calibrate the cpu(s). We will perform this task within the tests */
11263   /* themselves. If the user has specified the cpu rate, then */
11264   /* calibrate_local_cpu will return rather quickly as it will have */
11265   /* nothing to do. If local_cpu_rate is zero, then we will go through */
11266   /* all the "normal" calibration stuff and return the rate back.*/
11267 
11268   if (local_cpu_usage) {
11269     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
11270   }
11271 
11272   /* Tell the remote end to do a listen. The server alters the socket */
11273   /* paramters on the other side at this point, hence the reason for */
11274   /* all the values being passed in the setup message. If the user did */
11275   /* not specify any of the parameters, they will be passed as 0, which */
11276   /* will indicate to the remote that no changes beyond the system's */
11277   /* default should be used. Alignment is the exception, it will */
11278   /* default to 8, which will be no alignment alterations. */
11279 
11280   netperf_request.content.request_type	=	DO_TCP_CC;
11281   tcp_cc_request->recv_buf_size	        =	rsr_size_req;
11282   tcp_cc_request->send_buf_size	        =	rss_size_req;
11283   tcp_cc_request->recv_alignment	=	remote_recv_align;
11284   tcp_cc_request->recv_offset	        =	remote_recv_offset;
11285   tcp_cc_request->send_alignment	=	remote_send_align;
11286   tcp_cc_request->send_offset	        =	remote_send_offset;
11287   tcp_cc_request->request_size	        =	req_size;
11288   tcp_cc_request->response_size	        =	rsp_size;
11289   tcp_cc_request->no_delay	        =	rem_nodelay;
11290   tcp_cc_request->measure_cpu	        =	remote_cpu_usage;
11291   tcp_cc_request->cpu_rate	        =	remote_cpu_rate;
11292   tcp_cc_request->so_rcvavoid	=	rem_rcvavoid;
11293   tcp_cc_request->so_sndavoid	=	rem_sndavoid;
11294   if (test_time) {
11295     tcp_cc_request->test_length	=	test_time;
11296   }
11297   else {
11298     tcp_cc_request->test_length	=	test_trans * -1;
11299   }
11300   tcp_cc_request->port          = atoi(remote_data_port);
11301   tcp_cc_request->ipfamily  = af_to_nf(remote_res->ai_family);
11302 
11303   if (debug > 1) {
11304     fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n");
11305   }
11306 
11307   send_request();
11308 
11309   /* The response from the remote will contain all of the relevant 	*/
11310   /* socket parameters for this test type. We will put them back into 	*/
11311   /* the variables here so they can be displayed if desired.  The	*/
11312   /* remote will have calibrated CPU if necessary, and will have done	*/
11313   /* all the needed set-up we will have calibrated the cpu locally	*/
11314   /* before sending the request, and will grab the counter value right	*/
11315   /* after the connect returns. The remote will grab the counter right	*/
11316   /* after the accept call. This saves the hassle of extra messages	*/
11317   /* being sent for the TCP tests.					*/
11318 
11319   recv_response();
11320 
11321   if (!netperf_response.content.serv_errno) {
11322     rsr_size	=	tcp_cc_response->recv_buf_size;
11323     rss_size	=	tcp_cc_response->send_buf_size;
11324     rem_nodelay	=	tcp_cc_response->no_delay;
11325     remote_cpu_usage=	tcp_cc_response->measure_cpu;
11326     remote_cpu_rate = 	tcp_cc_response->cpu_rate;
11327     /* make sure that port numbers are in network order */
11328     set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number);
11329 
11330     if (debug) {
11331       fprintf(where,"remote listen done.\n");
11332       fprintf(where,"remote port is %d\n",get_port_number(remote_res));
11333       fflush(where);
11334     }
11335   }
11336   else {
11337     Set_errno(netperf_response.content.serv_errno);
11338     fprintf(where,
11339 	    "netperf: remote error %d",
11340 	    netperf_response.content.serv_errno);
11341     perror("");
11342     fflush(where);
11343     exit(1);
11344   }
11345 
11346 #ifdef WANT_DEMO
11347   DEMO_RR_SETUP(100)
11348 #endif
11349 
11350   /* pick a nice random spot between client_port_min and */
11351   /* client_port_max for our initial port number */
11352   srand(getpid());
11353   if (client_port_max - client_port_min) {
11354     myport = client_port_min +
11355       (rand() % (client_port_max - client_port_min));
11356   }
11357   else {
11358     myport = client_port_min;
11359   }
11360   /* there will be a ++ before the first call to bind, so subtract one */
11361   myport--;
11362 
11363   /* Set-up the test end conditions. For a request/response test, they */
11364   /* can be either time or transaction based. */
11365 
11366   if (test_time) {
11367     /* The user wanted to end the test after a period of time. */
11368     times_up = 0;
11369     trans_remaining = 0;
11370     start_timer(test_time);
11371   }
11372   else {
11373     /* The tester wanted to send a number of bytes. */
11374     trans_remaining = test_bytes;
11375     times_up = 1;
11376   }
11377 
11378   /* The cpu_start routine will grab the current time and possibly */
11379   /* value of the idle counter for later use in measuring cpu */
11380   /* utilization and/or service demand and thruput. */
11381 
11382   cpu_start(local_cpu_usage);
11383 
11384 #ifdef WANT_DEMO
11385   if (demo_mode) {
11386     HIST_timestamp(demo_one_ptr);
11387   }
11388 #endif
11389 
11390   /* We use an "OR" to control test execution. When the test is */
11391   /* controlled by time, the byte count check will always return false. */
11392   /* When the test is controlled by byte count, the time test will */
11393   /* always return false. When the test is finished, the whole */
11394   /* expression will go false and we will stop sending data. I think I */
11395   /* just arbitrarily decrement trans_remaining for the timed test, but */
11396   /* will not do that just yet... One other question is whether or not */
11397   /* the send buffer and the receive buffer should be the same buffer. */
11398 
11399   while ((!times_up) || (trans_remaining > 0)) {
11400 
11401 #ifdef WANT_HISTOGRAM
11402     if (verbosity > 1) {
11403       /* timestamp just before our call to create the socket, and then */
11404       /* again just after the receive raj 3/95 */
11405       HIST_timestamp(&time_one);
11406     }
11407 #endif /* WANT_HISTOGRAM */
11408 
11409     /* set up the data socket */
11410     /* newport: is this label really required any longer? */
11411     /* pick a new port number */
11412     myport++;
11413 
11414     /* wrap the port number when we get to client_port_max. NOTE, some */
11415     /* broken TCP's might treat the port number as a signed 16 bit */
11416     /* quantity.  we aren't interested in testing such broken */
11417     /* implementations :) so we won't make sure that it is below 32767 */
11418     /* raj 8/94  */
11419     if (myport >= client_port_max) {
11420       myport = client_port_min;
11421     }
11422 
11423     /* we do not want to use the port number that the server is */
11424     /* sitting at - this would cause us to fail in a loopback test. we */
11425     /* could just rely on the failure of the bind to get us past this, */
11426     /* but I'm guessing that in this one case at least, it is much */
11427     /* faster, given that we *know* that port number is already in use */
11428     /* (or rather would be in a loopback test) */
11429 
11430     if (myport == get_port_number(remote_res)) myport++;
11431 
11432     if (debug) {
11433       if ((nummessages % 100) == 0) {
11434 	printf("port %d\n",myport);
11435       }
11436     }
11437     set_port_number(local_res, (unsigned short)myport);
11438     send_socket = create_data_socket(local_res);
11439 
11440     if (send_socket == INVALID_SOCKET) {
11441       perror("netperf: send_tcp_cc: tcp stream data socket");
11442       exit(1);
11443     }
11444 
11445     /* we used to have a call to bind() here, but that is being
11446        taken care of by create_data_socket(). raj 2005-02-08 */
11447 
11448     /* Connect up to the remote port on the data socket  */
11449     if ((ret = connect(send_socket,
11450 		       remote_res->ai_addr,
11451 		       remote_res->ai_addrlen)) == INVALID_SOCKET){
11452       if (SOCKET_EINTR(ret))
11453 	  {
11454 	    /* we hit the end of a */
11455 	    /* timed test. */
11456 	    timed_out = 1;
11457 	    break;
11458       }
11459       perror("netperf: data socket connect failed");
11460       printf("\tattempted to connect on socket %d to port %d",
11461 	     send_socket,
11462 	     get_port_number(remote_res));
11463       printf(" from port %u \n",get_port_number(local_res));
11464       exit(1);
11465     }
11466 
11467     /* we hang in a recv() to get the remote's close indication */
11468 
11469     rsp_bytes_recvd=recv(send_socket,
11470 			 temp_message_ptr,
11471 			 rsp_bytes_left,
11472 			 0);
11473 
11474 
11475     if (rsp_bytes_recvd == 0) {
11476       /* connection close, call close. we assume that the requisite */
11477       /* number of bytes have been received */
11478 
11479 #ifdef WANT_HISTOGRAM
11480       if (verbosity > 1) {
11481 	HIST_timestamp(&time_two);
11482 	HIST_add(time_hist,delta_micro(&time_one,&time_two));
11483       }
11484 #endif /* WANT_HISTOGRAM */
11485 
11486 #ifdef WANT_DEMO
11487       DEMO_RR_INTERVAL(1)
11488 #endif
11489 
11490       nummessages++;
11491       if (trans_remaining) {
11492 	trans_remaining--;
11493       }
11494 
11495       if (debug > 3) {
11496 	fprintf(where,
11497 		"Transaction %d completed on local port %u\n",
11498 		nummessages,
11499 		get_port_number(local_res));
11500 	fflush(where);
11501       }
11502 
11503       close(send_socket);
11504 
11505     }
11506     else {
11507       /* it was less than zero - an error occured */
11508       if (SOCKET_EINTR(rsp_bytes_recvd))
11509 	  {
11510 	    /* We hit the end of a timed test. */
11511 	    timed_out = 1;
11512 	    break;
11513 	  }
11514 	  perror("send_tcp_cc: data recv error");
11515 	  exit(1);
11516     }
11517 
11518   }
11519 
11520 
11521   /* this call will always give us the elapsed time for the test, and */
11522   /* will also store-away the necessaries for cpu utilization */
11523 
11524   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being measured? */
11525   /* how long did we really run? */
11526 
11527   /* Get the statistics from the remote end. The remote will have */
11528   /* calculated service demand and all those interesting things. If it */
11529   /* wasn't supposed to care, it will return obvious values. */
11530 
11531   recv_response();
11532   if (!netperf_response.content.serv_errno) {
11533     if (debug)
11534       fprintf(where,"remote results obtained\n");
11535   }
11536   else {
11537     Set_errno(netperf_response.content.serv_errno);
11538     fprintf(where,
11539 	    "netperf: remote error %d",
11540 	     netperf_response.content.serv_errno);
11541     perror("");
11542     fflush(where);
11543 
11544     exit(1);
11545   }
11546 
11547   /* We now calculate what our thruput was for the test. In the future, */
11548   /* we may want to include a calculation of the thruput measured by */
11549   /* the remote, but it should be the case that for a TCP stream test, */
11550   /* that the two numbers should be *very* close... We calculate */
11551   /* bytes_sent regardless of the way the test length was controlled. */
11552   /* If it was time, we needed to, and if it was by bytes, the user may */
11553   /* have specified a number of bytes that wasn't a multiple of the */
11554   /* send_size, so we really didn't send what he asked for ;-) We use */
11555   /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
11556   /* 1024. A future enhancement *might* be to choose from a couple of */
11557   /* unit selections. */
11558 
11559   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
11560   thruput	= calc_thruput(bytes_xferd);
11561 
11562   if (local_cpu_usage || remote_cpu_usage) {
11563     /* We must now do a little math for service demand and cpu */
11564     /* utilization for the system(s) */
11565     /* Of course, some of the information might be bogus because */
11566     /* there was no idle counter in the kernel(s). We need to make */
11567     /* a note of this for the user's benefit...*/
11568     if (local_cpu_usage) {
11569       if (local_cpu_rate == 0.0) {
11570 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
11571 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
11572 	fflush(where);
11573       }
11574       local_cpu_utilization = calc_cpu_util(0.0);
11575       /* since calc_service demand is doing ms/Kunit we will */
11576       /* multiply the number of transaction by 1024 to get */
11577       /* "good" numbers */
11578       local_service_demand  = calc_service_demand((double) nummessages*1024,
11579 						  0.0,
11580 						  0.0,
11581 						  0);
11582     }
11583     else {
11584       local_cpu_utilization	= (float) -1.0;
11585       local_service_demand	= (float) -1.0;
11586     }
11587 
11588     if (remote_cpu_usage) {
11589       if (remote_cpu_rate == 0.0) {
11590 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
11591 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
11592 	fflush(where);
11593       }
11594       remote_cpu_utilization = tcp_cc_result->cpu_util;
11595       /* since calc_service demand is doing ms/Kunit we will */
11596       /* multiply the number of transaction by 1024 to get */
11597       /* "good" numbers */
11598       remote_service_demand = calc_service_demand((double) nummessages*1024,
11599 						  0.0,
11600 						  remote_cpu_utilization,
11601 						  tcp_cc_result->num_cpus);
11602     }
11603     else {
11604       remote_cpu_utilization = (float) -1.0;
11605       remote_service_demand  = (float) -1.0;
11606     }
11607 
11608     /* We are now ready to print all the information. If the user */
11609     /* has specified zero-level verbosity, we will just print the */
11610     /* local service demand, or the remote service demand. If the */
11611     /* user has requested verbosity level 1, he will get the basic */
11612     /* "streamperf" numbers. If the user has specified a verbosity */
11613     /* of greater than 1, we will display a veritable plethora of */
11614     /* background information from outside of this block as it it */
11615     /* not cpu_measurement specific...  */
11616 
11617     switch (verbosity) {
11618     case 0:
11619       if (local_cpu_usage) {
11620 	fprintf(where,
11621 		cpu_fmt_0,
11622 		local_service_demand);
11623       }
11624       else {
11625 	fprintf(where,
11626 		cpu_fmt_0,
11627 		remote_service_demand);
11628       }
11629       break;
11630     case 1:
11631     case 2:
11632 
11633       if (print_headers) {
11634 	fprintf(where,
11635 		cpu_title,
11636 		local_cpu_method,
11637 		remote_cpu_method);
11638       }
11639 
11640       fprintf(where,
11641 	      cpu_fmt_1_line_1,		/* the format string */
11642 	      lss_size,		/* local sendbuf size */
11643 	      lsr_size,
11644 	      req_size,		/* how large were the requests */
11645 	      rsp_size,		/* guess */
11646 	      elapsed_time,		/* how long was the test */
11647 	      nummessages/elapsed_time,
11648 	      local_cpu_utilization,	/* local cpu */
11649 	      remote_cpu_utilization,	/* remote cpu */
11650 	      local_service_demand,	/* local service demand */
11651 	      remote_service_demand);	/* remote service demand */
11652       fprintf(where,
11653 	      cpu_fmt_1_line_2,
11654 	      rss_size,
11655 	      rsr_size);
11656       break;
11657     }
11658   }
11659   else {
11660     /* The tester did not wish to measure service demand. */
11661     switch (verbosity) {
11662     case 0:
11663       fprintf(where,
11664 	      tput_fmt_0,
11665 	      nummessages/elapsed_time);
11666       break;
11667     case 1:
11668     case 2:
11669       if (print_headers) {
11670 	fprintf(where,tput_title,format_units());
11671       }
11672 
11673       fprintf(where,
11674 	      tput_fmt_1_line_1,	/* the format string */
11675 	      lss_size,
11676 	      lsr_size,
11677 	      req_size,		/* how large were the requests */
11678 	      rsp_size,		/* how large were the responses */
11679 	      elapsed_time, 		/* how long did it take */
11680 	      nummessages/elapsed_time);
11681       fprintf(where,
11682 	      tput_fmt_1_line_2,
11683 	      rss_size, 		/* remote recvbuf size */
11684 	      rsr_size);
11685 
11686       break;
11687     }
11688   }
11689 
11690   /* it would be a good thing to include information about some of the */
11691   /* other parameters that may have been set for this test, but at the */
11692   /* moment, I do not wish to figure-out all the  formatting, so I will */
11693   /* just put this comment here to help remind me that it is something */
11694   /* that should be done at a later time. */
11695 
11696   if (verbosity > 1) {
11697     /* The user wanted to know it all, so we will give it to him. */
11698     /* This information will include as much as we can find about */
11699     /* TCP statistics, the alignments of the sends and receives */
11700     /* and all that sort of rot... */
11701 
11702     fprintf(where,
11703 	    ksink_fmt,
11704 	    local_send_align,
11705 	    remote_recv_offset,
11706 	    local_send_offset,
11707 	    remote_recv_offset);
11708 
11709 #ifdef WANT_HISTOGRAM
11710     fprintf(where,"\nHistogram of request/response times\n");
11711     fflush(where);
11712     HIST_report(time_hist);
11713 #endif /* WANT_HISTOGRAM */
11714 
11715   }
11716 
11717 }
11718 
11719 
11720 void
recv_tcp_cc()11721 recv_tcp_cc()
11722 {
11723 
11724   char  *message;
11725 
11726   struct addrinfo *local_res;
11727   char local_name[BUFSIZ];
11728   char port_buffer[PORTBUFSIZE];
11729 
11730   struct	sockaddr_storage        myaddr_in,  peeraddr_in;
11731   SOCKET	s_listen,s_data;
11732   netperf_socklen_t 	addrlen;
11733   char	*recv_message_ptr;
11734   char	*send_message_ptr;
11735   int	trans_received;
11736   int	trans_remaining;
11737   int	timed_out = 0;
11738   float	elapsed_time;
11739 
11740   struct	tcp_cc_request_struct	*tcp_cc_request;
11741   struct	tcp_cc_response_struct	*tcp_cc_response;
11742   struct	tcp_cc_results_struct	*tcp_cc_results;
11743 
11744   tcp_cc_request =
11745     (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
11746   tcp_cc_response =
11747     (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
11748   tcp_cc_results =
11749     (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
11750 
11751   if (debug) {
11752     fprintf(where,"netserver: recv_tcp_cc: entered...\n");
11753     fflush(where);
11754   }
11755 
11756   /* We want to set-up the listen socket with all the desired */
11757   /* parameters and then let the initiator know that all is ready. If */
11758   /* socket size defaults are to be used, then the initiator will have */
11759   /* sent us 0's. If the socket sizes cannot be changed, then we will */
11760   /* send-back what they are. If that information cannot be determined, */
11761   /* then we send-back -1's for the sizes. If things go wrong for any */
11762   /* reason, we will drop back ten yards and punt. */
11763 
11764   /* If anything goes wrong, we want the remote to know about it. It */
11765   /* would be best if the error that the remote reports to the user is */
11766   /* the actual error we encountered, rather than some bogus unexpected */
11767   /* response type message. */
11768 
11769   if (debug) {
11770     fprintf(where,"recv_tcp_cc: setting the response type...\n");
11771     fflush(where);
11772   }
11773 
11774   netperf_response.content.response_type = TCP_CC_RESPONSE;
11775 
11776   if (debug) {
11777     fprintf(where,"recv_tcp_cc: the response type is set...\n");
11778     fflush(where);
11779   }
11780 
11781   /* set-up the data buffer with the requested alignment and offset */
11782   message = (char *)malloc(DATABUFFERLEN);
11783   if (message == NULL) {
11784     printf("malloc(%d) failed!\n", DATABUFFERLEN);
11785     exit(1);
11786   }
11787 
11788   /* We now alter the message_ptr variables to be at the desired */
11789   /* alignments with the desired offsets. */
11790 
11791   if (debug) {
11792     fprintf(where,
11793 	    "recv_tcp_cc: requested recv alignment of %d offset %d\n",
11794 	    tcp_cc_request->recv_alignment,
11795 	    tcp_cc_request->recv_offset);
11796     fprintf(where,
11797 	    "recv_tcp_cc: requested send alignment of %d offset %d\n",
11798 	    tcp_cc_request->send_alignment,
11799 	    tcp_cc_request->send_offset);
11800     fflush(where);
11801   }
11802 
11803   recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset);
11804 
11805   send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset);
11806 
11807   if (debug) {
11808     fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n");
11809     fflush(where);
11810   }
11811 
11812   /* Grab a socket to listen on, and then listen on it. */
11813 
11814   if (debug) {
11815     fprintf(where,"recv_tcp_cc: grabbing a socket...\n");
11816     fflush(where);
11817   }
11818 
11819   /* create_data_socket expects to find some things in the global */
11820   /* variables, so set the globals based on the values in the request. */
11821   /* once the socket has been created, we will set the response values */
11822   /* based on the updated value of those globals. raj 7/94 */
11823   lss_size_req = tcp_cc_request->send_buf_size;
11824   lsr_size_req = tcp_cc_request->recv_buf_size;
11825   loc_nodelay = tcp_cc_request->no_delay;
11826   loc_rcvavoid = tcp_cc_request->so_rcvavoid;
11827   loc_sndavoid = tcp_cc_request->so_sndavoid;
11828 
11829   set_hostname_and_port(local_name,
11830 			port_buffer,
11831 			nf_to_af(tcp_cc_request->ipfamily),
11832 			tcp_cc_request->port);
11833 
11834   local_res = complete_addrinfo(local_name,
11835 				local_name,
11836 				port_buffer,
11837 				nf_to_af(tcp_cc_request->ipfamily),
11838 				SOCK_STREAM,
11839 				IPPROTO_TCP,
11840 				0);
11841 
11842   s_listen = create_data_socket(local_res);
11843 
11844   if (s_listen == INVALID_SOCKET) {
11845     netperf_response.content.serv_errno = errno;
11846     send_response();
11847     if (debug) {
11848       fprintf(where,"could not create data socket\n");
11849       fflush(where);
11850     }
11851     exit(1);
11852   }
11853 
11854 #ifdef WIN32
11855   /* The test timer can fire during operations on the listening socket,
11856      so to make the start_timer below work we have to move
11857      it to close s_listen while we are blocked on accept. */
11858   win_kludge_socket2 = s_listen;
11859 #endif
11860 
11861 
11862   /* Now, let's set-up the socket to listen for connections */
11863   if (listen(s_listen, 5) == SOCKET_ERROR) {
11864     netperf_response.content.serv_errno = errno;
11865     close(s_listen);
11866     send_response();
11867     if (debug) {
11868       fprintf(where,"could not listen\n");
11869       fflush(where);
11870     }
11871     exit(1);
11872   }
11873 
11874   /* now get the port number assigned by the system  */
11875   addrlen = sizeof(myaddr_in);
11876   if (getsockname(s_listen,
11877 		  (struct sockaddr *)&myaddr_in,
11878 		  &addrlen) == SOCKET_ERROR){
11879     netperf_response.content.serv_errno = errno;
11880     close(s_listen);
11881     send_response();
11882     if (debug) {
11883       fprintf(where,"could not geetsockname\n");
11884       fflush(where);
11885     }
11886     exit(1);
11887   }
11888 
11889   /* Now myaddr_in contains the port and the internet address this is */
11890   /* returned to the sender also implicitly telling the sender that the */
11891   /* socket buffer sizing has been done. */
11892 
11893   tcp_cc_response->data_port_number =
11894     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
11895   if (debug) {
11896     fprintf(where,"telling the remote to call me at %d\n",
11897 	    tcp_cc_response->data_port_number);
11898     fflush(where);
11899   }
11900   netperf_response.content.serv_errno   = 0;
11901 
11902   /* But wait, there's more. If the initiator wanted cpu measurements, */
11903   /* then we must call the calibrate routine, which will return the max */
11904   /* rate back to the initiator. If the CPU was not to be measured, or */
11905   /* something went wrong with the calibration, we will return a 0.0 to */
11906   /* the initiator. */
11907 
11908   tcp_cc_response->cpu_rate = (float)0.0; 	/* assume no cpu */
11909   if (tcp_cc_request->measure_cpu) {
11910     tcp_cc_response->measure_cpu = 1;
11911     tcp_cc_response->cpu_rate =
11912       calibrate_local_cpu(tcp_cc_request->cpu_rate);
11913   }
11914 
11915 
11916 
11917   /* before we send the response back to the initiator, pull some of */
11918   /* the socket parms from the globals */
11919   tcp_cc_response->send_buf_size = lss_size;
11920   tcp_cc_response->recv_buf_size = lsr_size;
11921   tcp_cc_response->no_delay = loc_nodelay;
11922   tcp_cc_response->so_rcvavoid = loc_rcvavoid;
11923   tcp_cc_response->so_sndavoid = loc_sndavoid;
11924 
11925   send_response();
11926 
11927   addrlen = sizeof(peeraddr_in);
11928 
11929   /* Now it's time to start receiving data on the connection. We will */
11930   /* first grab the apropriate counters and then start grabbing. */
11931 
11932   cpu_start(tcp_cc_request->measure_cpu);
11933 
11934   /* The loop will exit when the sender does a shutdown, which will */
11935   /* return a length of zero   */
11936 
11937   if (tcp_cc_request->test_length > 0) {
11938     times_up = 0;
11939     trans_remaining = 0;
11940     start_timer(tcp_cc_request->test_length + PAD_TIME);
11941   }
11942   else {
11943     times_up = 1;
11944     trans_remaining = tcp_cc_request->test_length * -1;
11945   }
11946 
11947   trans_received = 0;
11948 
11949   while ((!times_up) || (trans_remaining > 0)) {
11950 #ifdef WIN32
11951     /* The test timer will probably fire during this accept,
11952        so to make the start_timer above work we have to move
11953        it to close s_listen while we are blocked on accept. */
11954     win_kludge_socket = s_listen;
11955 #endif
11956     /* accept a connection from the remote */
11957     if ((s_data=accept(s_listen,
11958 		       (struct sockaddr *)&peeraddr_in,
11959 		       &addrlen)) == INVALID_SOCKET) {
11960       if (errno == EINTR) {
11961 	/* the timer popped */
11962 	timed_out = 1;
11963 	break;
11964       }
11965       fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno);
11966       fflush(where);
11967       close(s_listen);
11968 
11969       exit(1);
11970     }
11971 
11972 #ifdef KLUDGE_SOCKET_OPTIONS
11973     /* this is for those systems which *INCORRECTLY* fail to pass */
11974     /* attributes across an accept() call. Including this goes against */
11975     /* my better judgement :( raj 11/95 */
11976 
11977     kludge_socket_options(s_data);
11978 
11979 #endif /* KLUDGE_SOCKET_OPTIONS */
11980 
11981 #ifdef WIN32
11982   /* this is used so the timer thread can close the socket out from */
11983   /* under us, which to date is the easiest/cleanest/least */
11984   /* Windows-specific way I can find to force the winsock calls to */
11985   /* return WSAEINTR with the test is over. anything that will run on */
11986   /* 95 and NT and is closer to what netperf expects from Unix signals */
11987   /* and such would be appreciated raj 1/96 */
11988   win_kludge_socket = s_data;
11989 #endif /* WIN32 */
11990 
11991     if (debug) {
11992       fprintf(where,"recv_tcp_cc: accepted data connection.\n");
11993       fflush(where);
11994     }
11995 
11996 
11997     /* close the connection. the server will likely do a graceful */
11998     /* close of the connection, insuring that all data has arrived at */
11999     /* the client. for this it will call shutdown(), and then recv() and */
12000     /* then close(). I'm reasonably confident that this is the */
12001     /* appropriate sequence of calls - I would like to hear of */
12002     /* examples in web servers to the contrary. raj 10/95*/
12003     close(s_data);
12004 
12005     trans_received++;
12006     if (trans_remaining) {
12007       trans_remaining--;
12008     }
12009 
12010     if (debug) {
12011       fprintf(where,
12012 	      "recv_tcp_cc: Transaction %d complete\n",
12013 	      trans_received);
12014       fflush(where);
12015     }
12016 
12017   }
12018 
12019 
12020   /* The loop now exits due to timeout or transaction count being */
12021   /* reached */
12022 
12023   cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time);
12024 
12025   if (timed_out) {
12026     /* we ended the test by time, which was at least 2 seconds */
12027     /* longer than we wanted to run. so, we want to subtract */
12028     /* PAD_TIME from the elapsed_time. */
12029     elapsed_time -= PAD_TIME;
12030   }
12031   /* send the results to the sender			*/
12032 
12033   if (debug) {
12034     fprintf(where,
12035 	    "recv_tcp_cc: got %d transactions\n",
12036 	    trans_received);
12037     fflush(where);
12038   }
12039 
12040   tcp_cc_results->bytes_received	= (trans_received *
12041 					   (tcp_cc_request->request_size +
12042 					    tcp_cc_request->response_size));
12043   tcp_cc_results->trans_received	= trans_received;
12044   tcp_cc_results->elapsed_time	= elapsed_time;
12045   if (tcp_cc_request->measure_cpu) {
12046     tcp_cc_results->cpu_util	= calc_cpu_util(elapsed_time);
12047   }
12048 
12049   if (debug) {
12050     fprintf(where,
12051 	    "recv_tcp_cc: test complete, sending results.\n");
12052     fflush(where);
12053   }
12054 
12055   send_response();
12056 
12057 }
12058 
12059 void
print_sockets_usage()12060 print_sockets_usage()
12061 {
12062 
12063   fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout);
12064   exit(1);
12065 
12066 }
12067 
12068 void
scan_sockets_args(int argc,char * argv[])12069 scan_sockets_args(int argc, char *argv[])
12070 
12071 {
12072 
12073 #define SOCKETS_ARGS "b:CDnNhH:L:m:M:p:P:r:s:S:T:Vw:W:z46"
12074 
12075   extern char	*optarg;	  /* pointer to option string	*/
12076 
12077   int		c;
12078 
12079   char
12080     arg1[BUFSIZ],  /* argument holders		*/
12081     arg2[BUFSIZ];
12082 
12083   if (debug) {
12084     int i;
12085     printf("%s called with the following argument vector\n",
12086 	   __func__);
12087     for (i = 0; i< argc; i++) {
12088       printf("%s ",argv[i]);
12089     }
12090     printf("\n");
12091   }
12092 
12093   strncpy(local_data_port,"0",sizeof(local_data_port));
12094   strncpy(remote_data_port,"0",sizeof(remote_data_port));
12095 
12096   /* Go through all the command line arguments and break them */
12097   /* out. For those options that take two parms, specifying only */
12098   /* the first will set both to that value. Specifying only the */
12099   /* second will leave the first untouched. To change only the */
12100   /* first, use the form "first," (see the routine break_args.. */
12101 
12102   while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
12103     switch (c) {
12104     case '?':
12105     case '4':
12106       remote_data_family = AF_INET;
12107       local_data_family = AF_INET;
12108       break;
12109     case '6':
12110 #if defined(AF_INET6)
12111       remote_data_family = AF_INET6;
12112       local_data_family = AF_INET6;
12113 #else
12114       fprintf(stderr,
12115 	      "This netperf was not compiled on an IPv6 capable host!\n");
12116       fflush(stderr);
12117       exit(-1);
12118 #endif
12119       break;
12120     case 'h':
12121       print_sockets_usage();
12122       exit(1);
12123     case 'b':
12124 #ifdef WANT_FIRST_BURST
12125       first_burst_size = atoi(optarg);
12126 #else /* WANT_FIRST_BURST */
12127       printf("Initial request burst functionality not compiled-in!\n");
12128 #endif /* WANT_FIRST_BURST */
12129       break;
12130     case 'C':
12131 #ifdef TCP_CORK
12132       /* set TCP_CORK */
12133       loc_tcpcork = 1;
12134       rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */
12135 #else
12136       printf("WARNING: TCP_CORK not available on this platform!\n");
12137 #endif /* TCP_CORK */
12138       break;
12139     case 'D':
12140       /* set the TCP nodelay flag */
12141       loc_nodelay = 1;
12142       rem_nodelay = 1;
12143       break;
12144     case 'H':
12145       break_args_explicit(optarg,arg1,arg2);
12146       if (arg1[0]) {
12147 	/* make sure we leave room for the NULL termination boys and
12148 	   girls. raj 2005-02-82 */
12149 	remote_data_address = malloc(strlen(arg1)+1);
12150 	strncpy(remote_data_address,arg1,strlen(arg1));
12151       }
12152       if (arg2[0])
12153 	remote_data_family = parse_address_family(arg2);
12154       break;
12155     case 'L':
12156       break_args_explicit(optarg,arg1,arg2);
12157       if (arg1[0]) {
12158 	/* make sure we leave room for the NULL termination boys and
12159 	   girls. raj 2005-02-82 */
12160 	local_data_address = malloc(strlen(arg1)+1);
12161 	strncpy(local_data_address,arg1,strlen(arg1));
12162       }
12163       if (arg2[0])
12164 	local_data_family = parse_address_family(arg2);
12165       break;
12166     case 's':
12167       /* set local socket sizes */
12168       break_args(optarg,arg1,arg2);
12169       if (arg1[0])
12170 	lss_size_req = convert(arg1);
12171       if (arg2[0])
12172 	lsr_size_req = convert(arg2);
12173       break;
12174     case 'S':
12175       /* set remote socket sizes */
12176       break_args(optarg,arg1,arg2);
12177       if (arg1[0])
12178 	rss_size_req = convert(arg1);
12179       if (arg2[0])
12180 	rsr_size_req = convert(arg2);
12181       break;
12182     case 'r':
12183       /* set the request/response sizes */
12184       break_args(optarg,arg1,arg2);
12185       if (arg1[0])
12186 	req_size = convert(arg1);
12187       if (arg2[0])
12188 	rsp_size = convert(arg2);
12189       break;
12190     case 'm':
12191       /* set the send size */
12192       send_size = convert(optarg);
12193       break;
12194     case 'M':
12195       /* set the recv size */
12196       recv_size = convert(optarg);
12197       break;
12198     case 'n':
12199       /* set the local socket type*/
12200       local_connected = 1;
12201       break;
12202     case 'N':
12203       /* set the remote socket type*/
12204       remote_connected = 1;
12205       break;
12206     case 'p':
12207       /* set the min and max port numbers for the TCP_CRR and TCP_TRR */
12208       /* tests. */
12209       break_args(optarg,arg1,arg2);
12210       if (arg1[0])
12211 	client_port_min = atoi(arg1);
12212       if (arg2[0])
12213 	client_port_max = atoi(arg2);
12214       break;
12215     case 'P':
12216       /* set the local and remote data port numbers for the tests to
12217 	 allow them to run through those blankety blank end-to-end
12218 	 breaking firewalls. raj 2004-06-15 */
12219       break_args(optarg,arg1,arg2);
12220       if (arg1[0])
12221 	strncpy(local_data_port,arg1,sizeof(local_data_port));
12222       if (arg2[0])
12223 	strncpy(remote_data_port,arg2,sizeof(remote_data_port));
12224       break;
12225     case 't':
12226       /* set the test name */
12227       strcpy(test_name,optarg);
12228       break;
12229     case 'W':
12230       /* set the "width" of the user space data */
12231       /* buffer. This will be the number of */
12232       /* send_size buffers malloc'd in the */
12233       /* *_STREAM test. It may be enhanced to set */
12234       /* both send and receive "widths" but for now */
12235       /* it is just the sending *_STREAM. */
12236       send_width = convert(optarg);
12237       break;
12238     case 'V' :
12239       /* we want to do copy avoidance and will set */
12240       /* it for everything, everywhere, if we really */
12241       /* can. of course, we don't know anything */
12242       /* about the remote... */
12243 #ifdef SO_SND_COPYAVOID
12244       loc_sndavoid = 1;
12245 #else
12246       loc_sndavoid = 0;
12247       printf("Local send copy avoidance not available.\n");
12248 #endif
12249 #ifdef SO_RCV_COPYAVOID
12250       loc_rcvavoid = 1;
12251 #else
12252       loc_rcvavoid = 0;
12253       printf("Local recv copy avoidance not available.\n");
12254 #endif
12255       rem_sndavoid = 1;
12256       rem_rcvavoid = 1;
12257       break;
12258     };
12259   }
12260 
12261 #if defined(WANT_FIRST_BURST)
12262 #if defined(WANT_HISTOGRAM)
12263   /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user
12264      indeed wants a non-zero first burst size, and we would emit a
12265      histogram, then we should emit a warning that the two are not
12266      compatible. raj 2006-01-31 */
12267   if ((first_burst_size > 0) && (verbosity >= 2)) {
12268     fprintf(stderr,
12269 	    "WARNING! Histograms and first bursts are incompatible!\n");
12270     fflush(stderr);
12271   }
12272 #endif
12273 #endif
12274 
12275   /* we do not want to make remote_data_address non-NULL because if
12276      the user has not specified a remote adata address, we want to
12277      take it from the hostname in the -H global option. raj
12278      2005-02-08 */
12279 
12280   /* so, if there is to be no control connection, we want to have some
12281      different settings for a few things */
12282 
12283   if (no_control) {
12284 
12285     if (strcmp(remote_data_port,"0") == 0) {
12286       /* we need to select either the discard port, echo port or
12287 	 chargen port dedepending on the test name. raj 2007-02-08 */
12288       if (strstr(test_name,"STREAM") ||
12289 	  strstr(test_name,"SENDFILE")) {
12290 	strncpy(remote_data_port,"discard",sizeof(remote_data_port));
12291       }
12292       else if (strstr(test_name,"RR")) {
12293 	strncpy(remote_data_port,"echo",sizeof(remote_data_port));
12294       }
12295       else if (strstr(test_name,"MAERTS")) {
12296 	strncpy(remote_data_port,"chargen",sizeof(remote_data_port));
12297       }
12298       else {
12299 	printf("No default port known for the %s test, please set one yourself\n",test_name);
12300 	exit(-1);
12301       }
12302     }
12303     remote_data_port[sizeof(remote_data_port) - 1] = '\0';
12304 
12305     /* I go back and forth on whether these should become -1 or if
12306        they should become 0 for a no_control test. what do you think?
12307        raj 2006-02-08 */
12308 
12309     rem_rcvavoid = -1;
12310     rem_sndavoid = -1;
12311     rss_size_req = -1;
12312     rsr_size_req = -1;
12313     rem_nodelay = -1;
12314 
12315     if (strstr(test_name,"STREAM") ||
12316 	strstr(test_name,"SENDFILE")) {
12317       recv_size = -1;
12318     }
12319     else if (strstr(test_name,"RR")) {
12320       /* I am however _certain_ that for a no control RR test the
12321 	 response size must equal the request size since 99 times out
12322 	 of ten we will be speaking to the echo service somewhere */
12323       rsp_size = req_size;
12324     }
12325     else if (strstr(test_name,"MAERTS")) {
12326       send_size = -1;
12327     }
12328     else {
12329       printf("No default port known for the %s test, please set one yourself\n",test_name);
12330       exit(-1);
12331     }
12332   }
12333 }
12334