1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #ifdef WANT_XTI
6 #ifndef lint
7 char	nettest_xti_id[]="\
8 @(#)nettest_xti.c (c) Copyright 1995-2012 Hewlett-Packard Co. Version 2.6.0";
9 #else
10 #define DIRTY
11 #define WANT_HISTOGRAM
12 #define WANT_INTERVALS
13 #endif /* lint */
14 
15 #ifdef WIN32
16 #error XTI Interface tests are not available under Windows
17 #endif
18 
19 /****************************************************************/
20 /*								*/
21 /*	nettest_xti.c						*/
22 /*								*/
23 /*      the XTI args parsing routine...                         */
24 /*                                                              */
25 /*      scan_xti_args()                                         */
26 /*                                                              */
27 /*	the actual test routines...				*/
28 /*								*/
29 /*	send_xti_tcp_stream()	perform a tcp stream test	*/
30 /*	recv_xti_tcp_stream()					*/
31 /*	send_xti_tcp_rr()	perform a tcp request/response	*/
32 /*	recv_xti_tcp_rr()					*/
33 /*      send_xti_tcp_conn_rr()  an RR test including connect    */
34 /*      recv_xti_tcp_conn_rr()                                  */
35 /*	send_xti_udp_stream()	perform a udp stream test	*/
36 /*	recv_xti_udp_stream()					*/
37 /*	send_xti_udp_rr()	perform a udp request/response	*/
38 /*	recv_xti_udp_rr()					*/
39 /*								*/
40 /****************************************************************/
41 
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45 
46 #include <sys/types.h>
47 #include <fcntl.h>
48 #if defined(HAVE_SYS_IPC_H)
49 #include <sys/ipc.h>
50 #endif
51 #include <sys/socket.h>
52 #include <netinet/in.h>
53 #include <netdb.h>
54 #include <errno.h>
55 #include <signal.h>
56 #include <stdio.h>
57 #include <time.h>
58 #include <malloc.h>
59  /* xti.h should be included *after* in.h because there are name */
60  /* conflicts!( Silly standards people... raj 2/95 fortuenately, the */
61  /* confilcts are on IP_TOP and IP_TTL, whcih netperf does not yet use */
62 #include <xti.h>
63 
64 #include "netlib.h"
65 #include "netsh.h"
66 #include "nettest_xti.h"
67 
68 #ifdef WANT_HISTOGRAM
69 #ifdef __sgi
70 #include <sys/time.h>
71 #endif /* __sgi */
72 #include "hist.h"
73 #endif /* WANT_HISTOGRAM */
74 
75 
76 
77  /* these variables are specific to the XTI sockets tests. declare */
78  /* them static to make them global only to this file. */
79 
80 static int
81   rss_size,		/* remote socket send buffer size	*/
82   rsr_size,		/* remote socket recv buffer size	*/
83   lss_size,		/* local  socket send buffer size 	*/
84   lsr_size,		/* local  socket recv buffer size 	*/
85   req_size = 1,		/* request size                   	*/
86   rsp_size = 1,		/* response size			*/
87   send_size,		/* how big are individual sends		*/
88   recv_size;		/* how big are individual receives	*/
89 
90 static  int   confidence_iteration;
91 static  char  local_cpu_method;
92 static  char  remote_cpu_method;
93 
94  /* different options for the xti				*/
95 
96 static int
97   loc_nodelay,		/* don't/do use NODELAY	locally		*/
98   rem_nodelay,		/* don't/do use NODELAY remotely	*/
99   loc_sndavoid,		/* avoid send copies locally		*/
100   loc_rcvavoid,		/* avoid recv copies locally		*/
101   rem_sndavoid,		/* avoid send copies remotely		*/
102   rem_rcvavoid;		/* avoid recv_copies remotely		*/
103 
104 static struct t_info info_struct;
105 
106 #ifdef WANT_HISTOGRAM
107 #ifdef HAVE_GETHRTIME
108 hrtime_t time_one;
109 hrtime_t time_two;
110 #else
111 static struct timeval time_one;
112 static struct timeval time_two;
113 #endif /* HAVE_GETHRTIME */
114 static HIST time_hist;
115 #endif /* WANT_HISTOGRAM */
116 
117 static char loc_xti_device[32] = "/dev/tcp";
118 static char rem_xti_device[32] = "/dev/tcp";
119 
120 static int  xti_flags = 0;
121 
122 char xti_usage[] = "\n\
123 Usage: netperf [global options] -- [test options] \n\
124 \n\
125 TCP/UDP XTI API Test Options:\n\
126     -D [L][,R]        Set XTI_TCP_NODELAY locally and/or remotely (XTI_TCP_*)\n\
127     -h                Display this text\n\
128     -m bytes          Set the send size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
129     -M bytes          Set the recv size (XTI_TCP_STREAM, XTI_UDP_STREAM)\n\
130     -r bytes          Set request size (XTI_TCP_RR, XTI_UDP_RR)\n\
131     -R bytes          Set response size (XTI_TCP_RR, XTI_UDP_RR)\n\
132     -s send[,recv]    Set local socket send/recv buffer sizes\n\
133     -S send[,recv]    Set remote socket send/recv buffer sizes\n\
134     -X dev[,dev]      Set the local/remote XTI device file name\n\
135 \n\
136 For those options taking two parms, at least one must be specified;\n\
137 specifying one value without a comma will set both parms to that\n\
138 value, specifying a value with a leading comma will set just the second\n\
139 parm, a value with a trailing comma will set just the first. To set\n\
140 each parm to unique values, specify both and separate them with a\n\
141 comma.\n";
142 
143 
144  /* This routine is intended to retrieve interesting aspects of tcp */
145  /* for the data connection. at first, it attempts to retrieve the */
146  /* maximum segment size. later, it might be modified to retrieve */
147  /* other information, but it must be information that can be */
148  /* retrieved quickly as it is called during the timing of the test. */
149  /* for that reason, a second routine may be created that can be */
150  /* called outside of the timing loop */
151 void
get_xti_info(socket,info_struct)152 get_xti_info(socket, info_struct)
153      int socket;
154      struct t_info *info_struct;
155 {
156 
157 }
158 
159 
160  /* This routine will create a data (listen) socket with the apropriate */
161  /* options set and return it to the caller. this replaces all the */
162  /* duplicate code in each of the test routines and should help make */
163  /* things a little easier to understand. since this routine can be */
164  /* called by either the netperf or netserver programs, all output */
165  /* should be directed towards "where." family is generally AF_INET, */
166  /* and type will be either SOCK_STREAM or SOCK_DGRAM */
167 SOCKET
create_xti_endpoint(char * name)168 create_xti_endpoint(char *name)
169 {
170 
171   SOCKET temp_socket;
172 
173   struct t_optmgmt *opt_req;  /* we request an option */
174   struct t_optmgmt *opt_ret;  /* it tells us what we got */
175 
176   /* we use this to pass-in BSD-like socket options through t_optmgmt. */
177   /* it ends up being about as clear as mud. raj 2/95 */
178   struct sock_option {
179     struct t_opthdr myopthdr;
180     long value;
181   } *sock_option;
182 
183   if (debug) {
184     fprintf(where,"create_xti_endpoint: attempting to open %s\n",
185 	    name);
186     fflush(where);
187   }
188 
189   /*set up the data socket                        */
190   temp_socket = t_open(name,O_RDWR,NULL);
191 
192   if (temp_socket == INVALID_SOCKET){
193     fprintf(where,
194 	    "netperf: create_xti_endpoint: t_open %s: errno %d t_errno %d\n",
195 	    name,
196 	    errno,
197 	    t_errno);
198     fflush(where);
199     exit(1);
200   }
201 
202   if (debug) {
203     fprintf(where,"create_xti_endpoint: socket %d obtained...\n",temp_socket);
204     fflush(where);
205   }
206 
207   /* allocate what we need for option mgmt */
208   if ((opt_req = (struct t_optmgmt *)t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
209       NULL) {
210     fprintf(where,
211 	    "netperf: create_xti_endpoint: t_alloc: opt_req errno %d\n",
212 	    errno);
213     fflush(where);
214     exit(1);
215   }
216 
217   if (debug) {
218     fprintf(where,
219 	    "create_xti_endpoint: opt_req->opt.buf %x maxlen %d len %d\n",
220 	    opt_req->opt.buf,
221 	    opt_req->opt.maxlen,
222 	    opt_req->opt.len);
223 
224     fflush(where);
225   }
226 
227   if ((opt_ret = (struct t_optmgmt *) t_alloc(temp_socket,T_OPTMGMT,T_ALL)) ==
228       NULL) {
229     fprintf(where,
230 	    "netperf: create_xti_endpoint: t_alloc: opt_ret errno %d\n",
231 	    errno);
232     fflush(where);
233     exit(1);
234   }
235 
236   if (debug) {
237     fprintf(where,
238 	    "create_xti_endpoint: opt_ret->opt.buf %x maxlen %d len %d\n",
239 	    opt_ret->opt.buf,
240 	    opt_ret->opt.maxlen,
241 	    opt_ret->opt.len);
242     fflush(where);
243   }
244 
245   /* Modify the local socket size. The reason we alter the send buffer */
246   /* size here rather than when the connection is made is to take care */
247   /* of decreases in buffer size. Decreasing the window size after */
248   /* connection establishment is a TCP no-no. Also, by setting the */
249   /* buffer (window) size before the connection is established, we can */
250   /* control the TCP MSS (segment size). The MSS is never more that 1/2 */
251   /* the minimum receive buffer size at each half of the connection. */
252   /* This is why we are altering the receive buffer size on the sending */
253   /* size of a unidirectional transfer. If the user has not requested */
254   /* that the socket buffers be altered, we will try to find-out what */
255   /* their values are. If we cannot touch the socket buffer in any way, */
256   /* we will set the values to -1 to indicate that.  */
257 
258 #ifdef XTI_SNDBUF
259   if (lss_size > 0) {
260     /* we want to "negotiate" the option */
261     opt_req->flags = T_NEGOTIATE;
262   }
263   else {
264     /* we want to accept the default, and know what it is. I assume */
265     /* that when nothing has been changed, that T_CURRENT will return */
266     /* the same as T_DEFAULT raj 3/95 */
267     opt_req->flags = T_CURRENT;
268   }
269 
270   /* the first part is for the netbuf that holds the option we want */
271   /* to negotiate or check */
272   /* the buffer of the netbuf points at the socket options structure */
273 
274   /* we assume that the t_alloc call allocated a buffer that started */
275   /* on a proper alignment */
276   sock_option = (struct sock_option *)opt_req->opt.buf;
277 
278   /* and next, set the fields in the sock_option structure */
279   sock_option->myopthdr.level = XTI_GENERIC;
280   sock_option->myopthdr.name  = XTI_SNDBUF;
281   sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
282   sock_option->value        = lss_size;
283 
284   opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
285 
286   /* now, set-up the stuff to return the value in the end */
287   /* we assume that the t_alloc call allocated a buffer that started */
288   /* on a proper alignment */
289   sock_option = (struct sock_option *)opt_ret->opt.buf;
290 
291   /* finally, call t_optmgmt. clear as mud. */
292   if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
293     fprintf(where,
294 	    "netperf: create_xti_endpoint: XTI_SNDBUF option: t_errno %d\n",
295 	    t_errno);
296     fflush(where);
297     exit(1);
298   }
299 
300   if (sock_option->myopthdr.status == T_SUCCESS) {
301     lss_size = sock_option->value;
302   }
303   else {
304     fprintf(where,"create_xti_endpoint: XTI_SNDBUF option status 0x%.4x",
305 	    sock_option->myopthdr.status);
306     fprintf(where," value %d\n",
307 	    sock_option->value);
308     fflush(where);
309     lss_size = -1;
310   }
311 
312   if (lsr_size > 0) {
313     /* we want to "negotiate" the option */
314     opt_req->flags = T_NEGOTIATE;
315   }
316   else {
317     /* we want to accept the default, and know what it is. I assume */
318     /* that when nothing has been changed, that T_CURRENT will return */
319     /* the same as T_DEFAULT raj 3/95 */
320     opt_req->flags = T_CURRENT;
321   }
322 
323   /* the first part is for the netbuf that holds the option we want */
324   /* to negotiate or check */
325   /* the buffer of the netbuf points at the socket options structure */
326 
327   /* we assume that the t_alloc call allocated a buffer that started */
328   /* on a proper alignment */
329   sock_option = (struct sock_option *)opt_req->opt.buf;
330 
331   /* and next, set the fields in the sock_option structure */
332   sock_option->myopthdr.level = XTI_GENERIC;
333   sock_option->myopthdr.name  = XTI_RCVBUF;
334   sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
335   sock_option->value        = lsr_size;
336 
337   opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
338 
339   /* now, set-up the stuff to return the value in the end */
340   /* we assume that the t_alloc call allocated a buffer that started */
341   /* on a proper alignment */
342   sock_option = (struct sock_option *)opt_ret->opt.buf;
343 
344   /* finally, call t_optmgmt. clear as mud. */
345   if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
346     fprintf(where,
347 	    "netperf: create_xti_endpoint: XTI_RCVBUF option: t_errno %d\n",
348 	    t_errno);
349     fflush(where);
350     exit(1);
351   }
352   lsr_size = sock_option->value;
353 
354   /* this needs code */
355 
356   if (debug) {
357     fprintf(where,"netperf: create_xti_endpoint: socket sizes determined...\n");
358     fprintf(where,"                       send: %d recv: %d\n",
359 	    lss_size,lsr_size);
360     fflush(where);
361   }
362 
363 #else /* XTI_SNDBUF */
364 
365   lss_size = -1;
366   lsr_size = -1;
367 
368 #endif /* XTI_SNDBUF */
369 
370   /* now, we may wish to enable the copy avoidance features on the */
371   /* local system. of course, this may not be possible... */
372 
373   if (loc_rcvavoid) {
374     fprintf(where,
375 	    "netperf: create_xti_endpoint: Could not enable receive copy avoidance");
376     fflush(where);
377     loc_rcvavoid = 0;
378   }
379 
380   if (loc_sndavoid) {
381     fprintf(where,
382 	    "netperf: create_xti_endpoint: Could not enable send copy avoidance");
383     fflush(where);
384     loc_sndavoid = 0;
385   }
386 
387   /* Now, we will see about setting the TCP_NODELAY flag on the local */
388   /* socket. We will only do this for those systems that actually */
389   /* support the option. If it fails, note the fact, but keep going. */
390   /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
391   /* will cause an error to be displayed */
392 
393 #ifdef TCP_NODELAY
394   if ((strcmp(test_name,"XTI_TCP_STREAM") == 0) ||
395       (strcmp(test_name,"XTI_TCP_RR") == 0) ||
396       (strcmp(test_name,"XTI_TCP_CRR") == 0)) {
397     if (loc_nodelay) {
398       /* we want to "negotiate" the option */
399       opt_req->flags = T_NEGOTIATE;
400     }
401     else {
402       /* we want to accept the default, and know what it is. I assume */
403       /* that when nothing has been changed, that T_CURRENT will return */
404       /* the same as T_DEFAULT raj 3/95 */
405       opt_req->flags = T_CURRENT;
406     }
407 
408     /* the first part is for the netbuf that holds the option we want */
409     /* to negotiate or check the buffer of the netbuf points at the */
410     /* socket options structure */
411 
412     /* we assume that the t_alloc call allocated a buffer that started */
413     /* on a proper alignment */
414     sock_option = (struct sock_option *)opt_req->opt.buf;
415 
416     /* and next, set the fields in the sock_option structure */
417     sock_option->myopthdr.level = INET_TCP;
418     sock_option->myopthdr.name  = TCP_NODELAY;
419     sock_option->myopthdr.len   = sizeof(struct t_opthdr) + sizeof(long);
420     sock_option->value          = T_YES;
421 
422     opt_req->opt.len          = sizeof(struct t_opthdr) + sizeof(long);
423 
424     /* now, set-up the stuff to return the value in the end */
425     /* we assume that the t_alloc call allocated a buffer that started */
426     /* on a proper alignment */
427     sock_option = (struct sock_option *)opt_ret->opt.buf;
428 
429     /* finally, call t_optmgmt. clear as mud. */
430     if (t_optmgmt(temp_socket,opt_req,opt_ret) == -1) {
431       fprintf(where,
432 	      "create_xti_endpoint: TCP_NODELAY option: errno %d t_errno %d\n",
433 	      errno,
434 	      t_errno);
435       fflush(where);
436       exit(1);
437     }
438     loc_nodelay = sock_option->value;
439   }
440 #else /* TCP_NODELAY */
441 
442   loc_nodelay = 0;
443 
444 #endif /* TCP_NODELAY */
445 
446   return(temp_socket);
447 
448 }
449 
450 
451 /* This routine implements the TCP unidirectional data transfer test */
452 /* (a.k.a. stream) for the xti interface. It receives its */
453 /* parameters via global variables from the shell and writes its */
454 /* output to the standard output. */
455 
456 
457 void
send_xti_tcp_stream(char remote_host[])458 send_xti_tcp_stream(char remote_host[])
459 {
460 
461   char *tput_title = "\
462 Recv   Send    Send                          \n\
463 Socket Socket  Message  Elapsed              \n\
464 Size   Size    Size     Time     Throughput  \n\
465 bytes  bytes   bytes    secs.    %s/sec  \n\n";
466 
467   char *tput_fmt_0 =
468     "%7.2f\n";
469 
470   char *tput_fmt_1 =
471     "%6d %6d %6d    %-6.2f   %7.2f   \n";
472 
473   char *cpu_title = "\
474 Recv   Send    Send                          Utilization       Service Demand\n\
475 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
476 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
477 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
478 
479   char *cpu_fmt_0 =
480     "%6.3f %c\n";
481 
482   char *cpu_fmt_1 =
483     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
484 
485   char *ksink_fmt = "\n\
486 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
487 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
488 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
489 %5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
490 
491   char *ksink_fmt2 = "\n\
492 Maximum\n\
493 Segment\n\
494 Size (bytes)\n\
495 %6d\n";
496 
497 
498   float			elapsed_time;
499 
500 #ifdef WANT_INTERVALS
501   int interval_count;
502   sigset_t signal_set;
503 #endif
504 
505   /* what we want is to have a buffer space that is at least one */
506   /* send-size greater than our send window. this will insure that we */
507   /* are never trying to re-use a buffer that may still be in the hands */
508   /* of the transport. This buffer will be malloc'd after we have found */
509   /* the size of the local senc socket buffer. We will want to deal */
510   /* with alignment and offset concerns as well. */
511 
512   int	*message_int_ptr;
513 
514   struct ring_elt *send_ring;
515 
516   int len;
517   unsigned int nummessages;
518   SOCKET send_socket;
519   int bytes_remaining;
520   int tcp_mss = -1;  /* possibly uninitialized on printf far below */
521 
522   /* with links like fddi, one can send > 32 bits worth of bytes */
523   /* during a test... ;-) at some point, this should probably become a */
524   /* 64bit integral type, but those are not entirely common yet */
525 
526   double	bytes_sent;
527 
528   float	local_cpu_utilization;
529   float	local_service_demand;
530   float	remote_cpu_utilization;
531   float	remote_service_demand;
532 
533   double	thruput;
534 
535   /* some addressing information */
536   struct	hostent	        *hp;
537   struct	sockaddr_in	server;
538   unsigned      int             addr;
539 
540   struct t_call server_call;
541 
542   struct	xti_tcp_stream_request_struct	*xti_tcp_stream_request;
543   struct	xti_tcp_stream_response_struct	*xti_tcp_stream_response;
544   struct	xti_tcp_stream_results_struct	*xti_tcp_stream_result;
545 
546   xti_tcp_stream_request  =
547     (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
548   xti_tcp_stream_response =
549     (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
550   xti_tcp_stream_result   =
551     (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
552 
553 #ifdef WANT_HISTOGRAM
554   time_hist = HIST_new();
555 #endif /* WANT_HISTOGRAM */
556   /* since we are now disconnected from the code that established the */
557   /* control socket, and since we want to be able to use different */
558   /* protocols and such, we are passed the name of the remote host and */
559   /* must turn that into the test specific addressing information. */
560 
561   bzero((char *)&server,
562 	sizeof(server));
563 
564   /* it would seem that while HP-UX will allow an IP address (as a */
565   /* string) in a call to gethostbyname, other, less enlightened */
566   /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
567   /* order changed to check for IP address first. raj 7/96 */
568 
569   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
570     /* it was not an IP address, try it as a name */
571     if ((hp = gethostbyname(remote_host)) == NULL) {
572       /* we have no idea what it is */
573       fprintf(where,
574 	      "establish_control: could not resolve the destination %s\n",
575 	      remote_host);
576       fflush(where);
577       exit(1);
578     }
579     else {
580       /* it was a valid remote_host */
581       bcopy(hp->h_addr,
582 	    (char *)&server.sin_addr,
583 	    hp->h_length);
584       server.sin_family = hp->h_addrtype;
585     }
586   }
587   else {
588     /* it was a valid IP address */
589     server.sin_addr.s_addr = addr;
590     server.sin_family = AF_INET;
591   }
592 
593   if ( print_headers ) {
594     /* we want to have some additional, interesting information in */
595     /* the headers. we know some of it here, but not all, so we will */
596     /* only print the test title here and will print the results */
597     /* titles after the test is finished */
598     fprintf(where,"XTI TCP STREAM TEST");
599     fprintf(where," to %s", remote_host);
600     if (iteration_max > 1) {
601       fprintf(where,
602 	      " : +/-%3.1f%% @ %2d%% conf.",
603 	      interval/0.02,
604 	      confidence_level);
605       }
606     if (loc_nodelay || rem_nodelay) {
607       fprintf(where," : nodelay");
608     }
609     if (loc_sndavoid ||
610 	loc_rcvavoid ||
611 	rem_sndavoid ||
612 	rem_rcvavoid) {
613       fprintf(where," : copy avoidance");
614     }
615 #ifdef WANT_HISTOGRAM
616     fprintf(where," : histogram");
617 #endif /* WANT_HISTOGRAM */
618 #ifdef WANT_INTERVALS
619     fprintf(where," : interval");
620 #endif /* WANT_INTERVALS */
621 #ifdef DIRTY
622     fprintf(where," : dirty data");
623 #endif /* DIRTY */
624     fprintf(where,"\n");
625   }
626 
627   send_ring = NULL;
628   confidence_iteration = 1;
629   init_stat();
630 
631   /* we have a great-big while loop which controls the number of times */
632   /* we run a particular test. this is for the calculation of a */
633   /* confidence interval (I really should have stayed awake during */
634   /* probstats :). If the user did not request confidence measurement */
635   /* (no confidence is the default) then we will only go though the */
636   /* loop once. the confidence stuff originates from the folks at IBM */
637 
638   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
639 	 (confidence_iteration <= iteration_min)) {
640 
641     /* initialize a few counters. we have to remember that we might be */
642     /* going through the loop more than once. */
643 
644     nummessages    =	0;
645     bytes_sent     =	0.0;
646     times_up       = 	0;
647 
648     /*set up the data socket                        */
649     send_socket = create_xti_endpoint(loc_xti_device);
650 
651     if (send_socket == INVALID_SOCKET) {
652       perror("netperf: send_xti_tcp_stream: tcp stream data socket");
653       exit(1);
654     }
655 
656     if (debug) {
657       fprintf(where,"send_xti_tcp_stream: send_socket obtained...\n");
658     }
659 
660     /* it would seem that with XTI, there is no implicit bind on a */
661     /* connect, so we have to make a call to t_bind. this is not */
662     /* terribly convenient, but I suppose that "standard is better */
663     /* than better" :) raj 2/95 */
664 
665     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
666       t_error("send_xti_tcp_stream: t_bind");
667       exit(1);
668     }
669 
670     /* at this point, we have either retrieved the socket buffer sizes, */
671     /* or have tried to set them, so now, we may want to set the send */
672     /* size based on that (because the user either did not use a -m */
673     /* option, or used one with an argument of 0). If the socket buffer */
674     /* size is not available, we will set the send size to 4KB - no */
675     /* particular reason, just arbitrary... */
676     if (send_size == 0) {
677       if (lss_size > 0) {
678 	send_size = lss_size;
679       }
680       else {
681 	send_size = 4096;
682       }
683     }
684 
685     /* set-up the data buffer ring with the requested alignment and offset. */
686     /* note also that we have allocated a quantity */
687     /* of memory that is at least one send-size greater than our socket */
688     /* buffer size. We want to be sure that there are at least two */
689     /* buffers allocated - this can be a bit of a problem when the */
690     /* send_size is bigger than the socket size, so we must check... the */
691     /* user may have wanted to explicitly set the "width" of our send */
692     /* buffers, we should respect that wish... */
693 
694     if (send_width == 0) {
695       send_width = (lss_size/send_size) + 1;
696       if (send_width == 1) send_width++;
697     }
698 
699     if (send_ring == NULL) {
700       /* only allocate the send ring once. this is a networking test, */
701       /* not a memory allocation test. this way, we do not need a */
702       /* deallocate_buffer_ring() routine, and I don't feel like */
703       /* writing one anyway :) raj 11/94 */
704       send_ring = allocate_buffer_ring(send_width,
705 				       send_size,
706 				       local_send_align,
707 				       local_send_offset);
708     }
709 
710     /* If the user has requested cpu utilization measurements, we must */
711     /* calibrate the cpu(s). We will perform this task within the tests */
712     /* themselves. If the user has specified the cpu rate, then */
713     /* calibrate_local_cpu will return rather quickly as it will have */
714     /* nothing to do. If local_cpu_rate is zero, then we will go through */
715     /* all the "normal" calibration stuff and return the rate back. */
716 
717     if (local_cpu_usage) {
718       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
719     }
720 
721     /* Tell the remote end to do a listen. The server alters the socket */
722     /* paramters on the other side at this point, hence the reason for */
723     /* all the values being passed in the setup message. If the user did */
724     /* not specify any of the parameters, they will be passed as 0, which */
725     /* will indicate to the remote that no changes beyond the system's */
726     /* default should be used. Alignment is the exception, it will */
727     /* default to 1, which will be no alignment alterations. */
728 
729     netperf_request.content.request_type          = DO_XTI_TCP_STREAM;
730     xti_tcp_stream_request->send_buf_size  = rss_size;
731     xti_tcp_stream_request->recv_buf_size  = rsr_size;
732     xti_tcp_stream_request->receive_size   = recv_size;
733     xti_tcp_stream_request->no_delay       = rem_nodelay;
734     xti_tcp_stream_request->recv_alignment = remote_recv_align;
735     xti_tcp_stream_request->recv_offset    = remote_recv_offset;
736     xti_tcp_stream_request->measure_cpu    = remote_cpu_usage;
737     xti_tcp_stream_request->cpu_rate       = remote_cpu_rate;
738     if (test_time) {
739       xti_tcp_stream_request->test_length  = test_time;
740     }
741     else {
742       xti_tcp_stream_request->test_length  = test_bytes;
743     }
744     xti_tcp_stream_request->so_rcvavoid    = rem_rcvavoid;
745     xti_tcp_stream_request->so_sndavoid    = rem_sndavoid;
746 
747     strcpy(xti_tcp_stream_request->xti_device, rem_xti_device);
748 
749 #ifdef __alpha
750 
751     /* ok - even on a DEC box, strings are strings. I didn't really want */
752     /* to ntohl the words of a string. since I don't want to teach the */
753     /* send_ and recv_ _request and _response routines about the types, */
754     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
755     /* solution would be to use XDR, but I am still leary of being able */
756     /* to find XDR libs on all platforms I want running netperf. raj */
757     {
758       int *charword;
759       int *initword;
760       int *lastword;
761 
762       initword = (int *) xti_tcp_stream_request->xti_device;
763       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
764 
765       for (charword = initword;
766 	   charword < lastword;
767 	   charword++) {
768 
769 	*charword = ntohl(*charword);
770       }
771     }
772 #endif /* __alpha */
773 
774 #ifdef DIRTY
775     xti_tcp_stream_request->dirty_count         = rem_dirty_count;
776     xti_tcp_stream_request->clean_count         = rem_clean_count;
777 #endif /* DIRTY */
778 
779 
780     if (debug > 1) {
781       fprintf(where,
782               "netperf: send_xti_tcp_stream: requesting TCP stream test\n");
783     }
784 
785     send_request();
786 
787     /* The response from the remote will contain all of the relevant    */
788     /* socket parameters for this test type. We will put them back into */
789     /* the variables here so they can be displayed if desired.  The     */
790     /* remote will have calibrated CPU if necessary, and will have done */
791     /* all the needed set-up we will have calibrated the cpu locally    */
792     /* before sending the request, and will grab the counter value right*/
793     /* after the connect returns. The remote will grab the counter right*/
794     /* after the accept call. This saves the hassle of extra messages   */
795     /* being sent for the TCP tests.                                    */
796 
797     recv_response();
798 
799     if (!netperf_response.content.serv_errno) {
800       if (debug)
801         fprintf(where,"remote listen done.\n");
802       rsr_size         = xti_tcp_stream_response->recv_buf_size;
803       rss_size         = xti_tcp_stream_response->send_buf_size;
804       rem_nodelay      = xti_tcp_stream_response->no_delay;
805       remote_cpu_usage = xti_tcp_stream_response->measure_cpu;
806       remote_cpu_rate  = xti_tcp_stream_response->cpu_rate;
807 
808       /* we have to make sure that the server port number is in */
809       /* network order */
810       server.sin_port   = (short)xti_tcp_stream_response->data_port_number;
811       server.sin_port   = htons(server.sin_port);
812       rem_rcvavoid      = xti_tcp_stream_response->so_rcvavoid;
813       rem_sndavoid      = xti_tcp_stream_response->so_sndavoid;
814     }
815     else {
816       Set_errno(netperf_response.content.serv_errno);
817       perror("netperf: remote error");
818 
819       exit(1);
820     }
821 
822     /*Connect up to the remote port on the data socket  */
823     memset (&server_call, 0, sizeof(server_call));
824     server_call.addr.maxlen = sizeof(struct sockaddr_in);
825     server_call.addr.len    = sizeof(struct sockaddr_in);
826     server_call.addr.buf    = (char *)&server;
827 
828     if (t_connect(send_socket,
829 		  &server_call,
830 		  NULL) == INVALID_SOCKET){
831       t_error("netperf: send_xti_tcp_stream: data socket connect failed");
832       printf(" port: %d\n",ntohs(server.sin_port));
833       exit(1);
834     }
835 
836     /* Data Socket set-up is finished. If there were problems, either */
837     /* the connect would have failed, or the previous response would */
838     /* have indicated a problem. I failed to see the value of the */
839     /* extra  message after the accept on the remote. If it failed, */
840     /* we'll see it here. If it didn't, we might as well start pumping */
841     /* data. */
842 
843     /* Set-up the test end conditions. For a stream test, they can be */
844     /* either time or byte-count based. */
845 
846     if (test_time) {
847       /* The user wanted to end the test after a period of time. */
848       times_up = 0;
849       bytes_remaining = 0;
850       /* in previous revisions, we had the same code repeated throught */
851       /* all the test suites. this was unnecessary, and meant more */
852       /* work for me when I wanted to switch to POSIX signals, so I */
853       /* have abstracted this out into a routine in netlib.c. if you */
854       /* are experiencing signal problems, you might want to look */
855       /* there. raj 11/94 */
856       start_timer(test_time);
857     }
858     else {
859       /* The tester wanted to send a number of bytes. */
860       bytes_remaining = test_bytes;
861       times_up = 1;
862     }
863 
864     /* The cpu_start routine will grab the current time and possibly */
865     /* value of the idle counter for later use in measuring cpu */
866     /* utilization and/or service demand and thruput. */
867 
868     cpu_start(local_cpu_usage);
869 
870 #ifdef WANT_INTERVALS
871     if ((interval_burst) || (demo_mode)) {
872       /* zero means that we never pause, so we never should need the */
873       /* interval timer, unless we are in demo_mode */
874       start_itimer(interval_wate);
875     }
876     interval_count = interval_burst;
877     /* get the signal set for the call to sigsuspend */
878     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
879       fprintf(where,
880               "send_xti_tcp_stream: unable to get sigmask errno %d\n",
881               errno);
882       fflush(where);
883       exit(1);
884     }
885 #endif /* WANT_INTERVALS */
886 
887     /* before we start, initialize a few variables */
888 
889     /* We use an "OR" to control test execution. When the test is */
890     /* controlled by time, the byte count check will always return false. */
891     /* When the test is controlled by byte count, the time test will */
892     /* always return false. When the test is finished, the whole */
893     /* expression will go false and we will stop sending data. */
894 
895     while ((!times_up) || (bytes_remaining > 0)) {
896 
897 #ifdef DIRTY
898       /* we want to dirty some number of consecutive integers in the buffer */
899       /* we are about to send. we may also want to bring some number of */
900       /* them cleanly into the cache. The clean ones will follow any dirty */
901       /* ones into the cache. at some point, we might want to replace */
902       /* the rand() call with something from a table to reduce our call */
903       /* overhead during the test, but it is not a high priority item. */
904       access_buffer(send_ring->buffer_ptr,
905 		    send_size,
906 		    loc_dirty_count,
907 		    loc_clean_count);
908 #endif /* DIRTY */
909 
910 #ifdef WANT_HISTOGRAM
911       /* timestamp just before we go into send and then again just after */
912       /* we come out raj 8/94 */
913       HIST_timestamp(&time_one);
914 #endif /* WANT_HISTOGRAM */
915 
916       if((len=t_snd(send_socket,
917 		    send_ring->buffer_ptr,
918 		    send_size,
919 		    0)) != send_size) {
920         if ((len >=0) || (errno == EINTR)) {
921           /* the test was interrupted, must be the end of test */
922           break;
923         }
924         fprintf(where,
925 		"send_xti_tcp_stream: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
926 		errno,
927 		t_errno,
928 		t_look(send_socket));
929 	fflush(where);
930         exit(1);
931       }
932 
933 #ifdef WANT_HISTOGRAM
934       /* timestamp the exit from the send call and update the histogram */
935       HIST_timestamp(&time_two);
936       HIST_add(time_hist,delta_micro(&time_one,&time_two));
937 #endif /* WANT_HISTOGRAM */
938 
939 #ifdef WANT_INTERVALS
940       if (demo_mode) {
941         units_this_tick += send_size;
942       }
943       /* in this case, the interval count is the count-down couter */
944       /* to decide to sleep for a little bit */
945       if ((interval_burst) && (--interval_count == 0)) {
946         /* call sigsuspend and wait for the interval timer to get us */
947         /* out */
948         if (debug) {
949           fprintf(where,"about to suspend\n");
950           fflush(where);
951         }
952         if (sigsuspend(&signal_set) == EFAULT) {
953           fprintf(where,
954                   "send_xti_tcp_stream: fault with signal set!\n");
955           fflush(where);
956           exit(1);
957         }
958         interval_count = interval_burst;
959       }
960 #endif /* WANT_INTERVALS */
961 
962       /* now we want to move our pointer to the next position in the */
963       /* data buffer...we may also want to wrap back to the "beginning" */
964       /* of the bufferspace, so we will mod the number of messages sent */
965       /* by the send width, and use that to calculate the offset to add */
966       /* to the base pointer. */
967       nummessages++;
968       send_ring = send_ring->next;
969       if (bytes_remaining) {
970         bytes_remaining -= send_size;
971       }
972     }
973 
974     /* The test is over. Flush the buffers to the remote end. We do a */
975     /* graceful release to insure that all data has been taken by the */
976     /* remote. */
977 
978     /* but first, if the verbosity is greater than 1, find-out what */
979     /* the TCP maximum segment_size was (if possible) */
980     if (verbosity > 1) {
981       tcp_mss = -1;
982       get_xti_info(send_socket,info_struct);
983     }
984 
985     if (t_sndrel(send_socket) == -1) {
986       t_error("netperf: cannot shutdown tcp stream socket");
987       exit(1);
988     }
989 
990     /* hang a t_rcvrel() off the socket to block until the remote has */
991     /* brought all the data up into the application. it will do a */
992     /* t_sedrel to cause a FIN to be sent our way. We will assume that */
993     /* any exit from the t_rcvrel() call is good... raj 2/95 */
994 
995     if (debug > 1) {
996       fprintf(where,"about to hang a receive for graceful release.\n");
997       fflush(where);
998     }
999 
1000     t_rcvrel(send_socket);
1001 
1002     /* this call will always give us the elapsed time for the test, and */
1003     /* will also store-away the necessaries for cpu utilization */
1004 
1005     cpu_stop(local_cpu_usage,&elapsed_time);    /* was cpu being */
1006                                                 /* measured and how */
1007                                                 /* long did we really */
1008                                                 /* run? */
1009 
1010     /* Get the statistics from the remote end. The remote will have */
1011     /* calculated service demand and all those interesting things. If it */
1012     /* wasn't supposed to care, it will return obvious values. */
1013 
1014     recv_response();
1015     if (!netperf_response.content.serv_errno) {
1016       if (debug)
1017         fprintf(where,"remote results obtained\n");
1018     }
1019     else {
1020       Set_errno(netperf_response.content.serv_errno);
1021       perror("netperf: remote error");
1022 
1023       exit(1);
1024     }
1025 
1026     /* We now calculate what our thruput was for the test. In the future, */
1027     /* we may want to include a calculation of the thruput measured by */
1028     /* the remote, but it should be the case that for a TCP stream test, */
1029     /* that the two numbers should be *very* close... We calculate */
1030     /* bytes_sent regardless of the way the test length was controlled. */
1031     /* If it was time, we needed to, and if it was by bytes, the user may */
1032     /* have specified a number of bytes that wasn't a multiple of the */
1033     /* send_size, so we really didn't send what he asked for ;-) */
1034 
1035     bytes_sent  = xti_tcp_stream_result->bytes_received;
1036 
1037     thruput     = calc_thruput(bytes_sent);
1038 
1039     if (local_cpu_usage || remote_cpu_usage) {
1040       /* We must now do a little math for service demand and cpu */
1041       /* utilization for the system(s) */
1042       /* Of course, some of the information might be bogus because */
1043       /* there was no idle counter in the kernel(s). We need to make */
1044       /* a note of this for the user's benefit...*/
1045       if (local_cpu_usage) {
1046 
1047         local_cpu_utilization   = calc_cpu_util(0.0);
1048         local_service_demand    = calc_service_demand(bytes_sent,
1049                                                       0.0,
1050                                                       0.0,
1051 						      0);
1052       }
1053       else {
1054         local_cpu_utilization   = -1.0;
1055         local_service_demand    = -1.0;
1056       }
1057 
1058       if (remote_cpu_usage) {
1059 
1060         remote_cpu_utilization  = xti_tcp_stream_result->cpu_util;
1061         remote_service_demand   = calc_service_demand(bytes_sent,
1062                                                       0.0,
1063                                                       remote_cpu_utilization,
1064 						      xti_tcp_stream_result->num_cpus);
1065       }
1066       else {
1067         remote_cpu_utilization = -1.0;
1068         remote_service_demand  = -1.0;
1069       }
1070     }
1071     else {
1072       /* we were not measuring cpu, for the confidence stuff, we */
1073       /* should make it -1.0 */
1074       local_cpu_utilization  = -1.0;
1075       local_service_demand   = -1.0;
1076       remote_cpu_utilization = -1.0;
1077       remote_service_demand  = -1.0;
1078     }
1079 
1080     /* at this point, we want to calculate the confidence information. */
1081     /* if debugging is on, calculate_confidence will print-out the */
1082     /* parameters we pass it */
1083 
1084     calculate_confidence(confidence_iteration,
1085                          elapsed_time,
1086                          thruput,
1087                          local_cpu_utilization,
1088                          remote_cpu_utilization,
1089                          local_service_demand,
1090                          remote_service_demand);
1091 
1092 
1093     confidence_iteration++;
1094   }
1095 
1096   /* at this point, we have finished making all the runs that we */
1097   /* will be making. so, we should extract what the calcuated values */
1098   /* are for all the confidence stuff. we could make the values */
1099   /* global, but that seemed a little messy, and it did not seem worth */
1100   /* all the mucking with header files. so, we create a routine much */
1101   /* like calcualte_confidence, which just returns the mean values. */
1102   /* raj 11/94 */
1103 
1104   retrieve_confident_values(&elapsed_time,
1105                             &thruput,
1106                             &local_cpu_utilization,
1107                             &remote_cpu_utilization,
1108                             &local_service_demand,
1109                             &remote_service_demand);
1110 
1111   /* We are now ready to print all the information. If the user */
1112   /* has specified zero-level verbosity, we will just print the */
1113   /* local service demand, or the remote service demand. If the */
1114   /* user has requested verbosity level 1, he will get the basic */
1115   /* "streamperf" numbers. If the user has specified a verbosity */
1116   /* of greater than 1, we will display a veritable plethora of */
1117   /* background information from outside of this block as it it */
1118   /* not cpu_measurement specific...  */
1119 
1120   if (confidence < 0) {
1121     /* we did not hit confidence, but were we asked to look for it? */
1122     if (iteration_max > 1) {
1123       display_confidence();
1124     }
1125   }
1126 
1127   if (local_cpu_usage || remote_cpu_usage) {
1128     local_cpu_method = format_cpu_method(cpu_method);
1129     remote_cpu_method = format_cpu_method(xti_tcp_stream_result->cpu_method);
1130 
1131     switch (verbosity) {
1132     case 0:
1133       if (local_cpu_usage) {
1134         fprintf(where,
1135                 cpu_fmt_0,
1136                 local_service_demand,
1137 		local_cpu_method);
1138       }
1139       else {
1140 	fprintf(where,
1141 		cpu_fmt_0,
1142 		remote_service_demand,
1143 		remote_cpu_method);
1144       }
1145       break;
1146     case 1:
1147     case 2:
1148       if (print_headers) {
1149 	fprintf(where,
1150 		cpu_title,
1151 		format_units(),
1152 		local_cpu_method,
1153 		remote_cpu_method);
1154       }
1155 
1156       fprintf(where,
1157 	      cpu_fmt_1,		/* the format string */
1158 	      rsr_size,		        /* remote recvbuf size */
1159 	      lss_size,		        /* local sendbuf size */
1160 	      send_size,		/* how large were the sends */
1161 	      elapsed_time,		/* how long was the test */
1162 	      thruput, 		        /* what was the xfer rate */
1163 	      local_cpu_utilization,	/* local cpu */
1164 	      remote_cpu_utilization,	/* remote cpu */
1165 	      local_service_demand,	/* local service demand */
1166 	      remote_service_demand);	/* remote service demand */
1167       break;
1168     }
1169   }
1170   else {
1171     /* The tester did not wish to measure service demand. */
1172 
1173     switch (verbosity) {
1174     case 0:
1175       fprintf(where,
1176 	      tput_fmt_0,
1177 	      thruput);
1178       break;
1179     case 1:
1180     case 2:
1181       if (print_headers) {
1182 	fprintf(where,tput_title,format_units());
1183       }
1184       fprintf(where,
1185 	      tput_fmt_1,		/* the format string */
1186 	      rsr_size, 		/* remote recvbuf size */
1187 	      lss_size, 		/* local sendbuf size */
1188 	      send_size,		/* how large were the sends */
1189 	      elapsed_time, 		/* how long did it take */
1190 	      thruput);/* how fast did it go */
1191       break;
1192     }
1193   }
1194 
1195   /* it would be a good thing to include information about some of the */
1196   /* other parameters that may have been set for this test, but at the */
1197   /* moment, I do not wish to figure-out all the  formatting, so I will */
1198   /* just put this comment here to help remind me that it is something */
1199   /* that should be done at a later time. */
1200 
1201   if (verbosity > 1) {
1202     /* The user wanted to know it all, so we will give it to him. */
1203     /* This information will include as much as we can find about */
1204     /* TCP statistics, the alignments of the sends and receives */
1205     /* and all that sort of rot... */
1206 
1207     /* this stuff needs to be worked-out in the presence of confidence */
1208     /* intervals and multiple iterations of the test... raj 11/94 */
1209 
1210     fprintf(where,
1211 	    ksink_fmt,
1212 	    "Bytes",
1213 	    "Bytes",
1214 	    "Bytes",
1215 	    local_send_align,
1216 	    remote_recv_align,
1217 	    local_send_offset,
1218 	    remote_recv_offset,
1219 	    bytes_sent,
1220 	    bytes_sent / (double)nummessages,
1221 	    nummessages,
1222 	    bytes_sent / (double)xti_tcp_stream_result->recv_calls,
1223 	    xti_tcp_stream_result->recv_calls);
1224     fprintf(where,
1225 	    ksink_fmt2,
1226 	    tcp_mss);
1227     fflush(where);
1228 #ifdef WANT_HISTOGRAM
1229     fprintf(where,"\n\nHistogram of time spent in send() call.\n");
1230     fflush(where);
1231     HIST_report(time_hist);
1232 #endif /* WANT_HISTOGRAM */
1233   }
1234 
1235 }
1236 
1237 
1238 /* This is the server-side routine for the tcp stream test. It is */
1239 /* implemented as one routine. I could break things-out somewhat, but */
1240 /* didn't feel it was necessary. */
1241 
1242 void
recv_xti_tcp_stream()1243 recv_xti_tcp_stream()
1244 {
1245 
1246   struct sockaddr_in myaddr_in, peeraddr_in;
1247   struct t_bind      bind_req, bind_resp;
1248   struct t_call      call_req;
1249 
1250   SOCKET       s_listen,s_data;
1251   int           addrlen;
1252   int	        len;
1253   unsigned int	receive_calls;
1254   float	        elapsed_time;
1255   double        bytes_received;
1256 
1257   struct ring_elt *recv_ring;
1258 
1259   int   *message_int_ptr;
1260   int   i;
1261 
1262   struct xti_tcp_stream_request_struct	*xti_tcp_stream_request;
1263   struct xti_tcp_stream_response_struct	*xti_tcp_stream_response;
1264   struct xti_tcp_stream_results_struct	*xti_tcp_stream_results;
1265 
1266   xti_tcp_stream_request	=
1267     (struct xti_tcp_stream_request_struct *)netperf_request.content.test_specific_data;
1268   xti_tcp_stream_response	=
1269     (struct xti_tcp_stream_response_struct *)netperf_response.content.test_specific_data;
1270   xti_tcp_stream_results	=
1271     (struct xti_tcp_stream_results_struct *)netperf_response.content.test_specific_data;
1272 
1273   if (debug) {
1274     fprintf(where,"netserver: recv_xti_tcp_stream: entered...\n");
1275     fflush(where);
1276   }
1277 
1278   /* We want to set-up the listen socket with all the desired */
1279   /* parameters and then let the initiator know that all is ready. If */
1280   /* socket size defaults are to be used, then the initiator will have */
1281   /* sent us 0's. If the socket sizes cannot be changed, then we will */
1282   /* send-back what they are. If that information cannot be determined, */
1283   /* then we send-back -1's for the sizes. If things go wrong for any */
1284   /* reason, we will drop back ten yards and punt. */
1285 
1286   /* If anything goes wrong, we want the remote to know about it. It */
1287   /* would be best if the error that the remote reports to the user is */
1288   /* the actual error we encountered, rather than some bogus unexpected */
1289   /* response type message. */
1290 
1291   if (debug) {
1292     fprintf(where,"recv_xti_tcp_stream: setting the response type...\n");
1293     fflush(where);
1294   }
1295 
1296   netperf_response.content.response_type = XTI_TCP_STREAM_RESPONSE;
1297 
1298   if (debug) {
1299     fprintf(where,"recv_xti_tcp_stream: the response type is set...\n");
1300     fflush(where);
1301   }
1302 
1303   /* We now alter the message_ptr variable to be at the desired */
1304   /* alignment with the desired offset. */
1305 
1306   if (debug) {
1307     fprintf(where,"recv_xti_tcp_stream: requested alignment of %d\n",
1308 	    xti_tcp_stream_request->recv_alignment);
1309     fflush(where);
1310   }
1311 
1312   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
1313   /* can put in OUR values !-) At some point, we may want to nail this */
1314   /* socket to a particular network-level address, but for now, */
1315   /* INADDR_ANY should be just fine. */
1316 
1317   bzero((char *)&myaddr_in,
1318 	sizeof(myaddr_in));
1319   myaddr_in.sin_family      = AF_INET;
1320   myaddr_in.sin_addr.s_addr = INADDR_ANY;
1321   myaddr_in.sin_port        = 0;
1322 
1323   /* Grab a socket to listen on, and then listen on it. */
1324 
1325   if (debug) {
1326     fprintf(where,"recv_xti_tcp_stream: grabbing a socket...\n");
1327     fflush(where);
1328   }
1329 
1330   /* create_xti_endpoint expects to find some things in the global */
1331   /* variables, so set the globals based on the values in the request. */
1332   /* once the socket has been created, we will set the response values */
1333   /* based on the updated value of those globals. raj 7/94 */
1334   lss_size = xti_tcp_stream_request->send_buf_size;
1335   lsr_size = xti_tcp_stream_request->recv_buf_size;
1336   loc_nodelay = xti_tcp_stream_request->no_delay;
1337   loc_rcvavoid = xti_tcp_stream_request->so_rcvavoid;
1338   loc_sndavoid = xti_tcp_stream_request->so_sndavoid;
1339 
1340 #ifdef __alpha
1341 
1342   /* ok - even on a DEC box, strings are strings. I din't really want */
1343   /* to ntohl the words of a string. since I don't want to teach the */
1344   /* send_ and recv_ _request and _response routines about the types, */
1345   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
1346   /* solution would be to use XDR, but I am still leary of being able */
1347   /* to find XDR libs on all platforms I want running netperf. raj */
1348   {
1349     int *charword;
1350     int *initword;
1351     int *lastword;
1352 
1353     initword = (int *) xti_tcp_stream_request->xti_device;
1354     lastword = initword + ((xti_tcp_stream_request->dev_name_len + 3) / 4);
1355 
1356     for (charword = initword;
1357 	 charword < lastword;
1358 	 charword++) {
1359 
1360       *charword = htonl(*charword);
1361     }
1362   }
1363 
1364 #endif /* __alpha */
1365 
1366   s_listen = create_xti_endpoint(xti_tcp_stream_request->xti_device);
1367 
1368   if (s_listen == INVALID_SOCKET) {
1369     netperf_response.content.serv_errno = errno;
1370     send_response();
1371     exit(1);
1372   }
1373 
1374   /* Let's get an address assigned to this socket so we can tell the */
1375   /* initiator how to reach the data socket. There may be a desire to */
1376   /* nail this socket to a specific IP address in a multi-homed, */
1377   /* multi-connection situation, but for now, we'll ignore the issue */
1378   /* and concentrate on single connection testing. */
1379 
1380   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
1381   bind_req.addr.len    = sizeof(struct sockaddr_in);
1382   bind_req.addr.buf    = (char *)&myaddr_in;
1383   bind_req.qlen        = 1;
1384 
1385   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
1386   bind_resp.addr.len    = sizeof(struct sockaddr_in);
1387   bind_resp.addr.buf    = (char *)&myaddr_in;
1388   bind_resp.qlen        = 1;
1389 
1390   if (t_bind(s_listen,
1391 	     &bind_req,
1392 	     &bind_resp) == SOCKET_ERROR) {
1393     netperf_response.content.serv_errno = t_errno;
1394     close(s_listen);
1395     send_response();
1396 
1397     exit(1);
1398   }
1399 
1400   if (debug) {
1401     fprintf(where,
1402 	    "recv_xti_tcp_stream: t_bind complete port %d\n",
1403 	    ntohs(myaddr_in.sin_port));
1404     fflush(where);
1405   }
1406 
1407   /* what sort of sizes did we end-up with? */
1408   if (xti_tcp_stream_request->receive_size == 0) {
1409     if (lsr_size > 0) {
1410       recv_size = lsr_size;
1411     }
1412     else {
1413       recv_size = 4096;
1414     }
1415   }
1416   else {
1417     recv_size = xti_tcp_stream_request->receive_size;
1418   }
1419 
1420   /* we want to set-up our recv_ring in a manner analagous to what we */
1421   /* do on the sending side. this is more for the sake of symmetry */
1422   /* than for the needs of say copy avoidance, but it might also be */
1423   /* more realistic - this way one could conceivably go with a */
1424   /* double-buffering scheme when taking the data an putting it into */
1425   /* the filesystem or something like that. raj 7/94 */
1426 
1427   if (recv_width == 0) {
1428     recv_width = (lsr_size/recv_size) + 1;
1429     if (recv_width == 1) recv_width++;
1430   }
1431 
1432   recv_ring = allocate_buffer_ring(recv_width,
1433 				   recv_size,
1434 				   xti_tcp_stream_request->recv_alignment,
1435 				   xti_tcp_stream_request->recv_offset);
1436 
1437   if (debug) {
1438     fprintf(where,"recv_xti_tcp_stream: recv alignment and offset set...\n");
1439     fflush(where);
1440   }
1441 
1442   /* Now myaddr_in contains the port and the internet address this is */
1443   /* returned to the sender also implicitly telling the sender that the */
1444   /* socket buffer sizing has been done. */
1445 
1446   xti_tcp_stream_response->data_port_number =
1447     (int) ntohs(myaddr_in.sin_port);
1448   netperf_response.content.serv_errno   = 0;
1449 
1450   /* But wait, there's more. If the initiator wanted cpu measurements, */
1451   /* then we must call the calibrate routine, which will return the max */
1452   /* rate back to the initiator. If the CPU was not to be measured, or */
1453   /* something went wrong with the calibration, we will return a -1 to */
1454   /* the initiator. */
1455 
1456   xti_tcp_stream_response->cpu_rate = 0.0; 	/* assume no cpu */
1457   if (xti_tcp_stream_request->measure_cpu) {
1458     xti_tcp_stream_response->measure_cpu = 1;
1459     xti_tcp_stream_response->cpu_rate =
1460       calibrate_local_cpu(xti_tcp_stream_request->cpu_rate);
1461   }
1462   else {
1463     xti_tcp_stream_response->measure_cpu = 0;
1464   }
1465 
1466   /* before we send the response back to the initiator, pull some of */
1467   /* the socket parms from the globals */
1468   xti_tcp_stream_response->send_buf_size = lss_size;
1469   xti_tcp_stream_response->recv_buf_size = lsr_size;
1470   xti_tcp_stream_response->no_delay = loc_nodelay;
1471   xti_tcp_stream_response->so_rcvavoid = loc_rcvavoid;
1472   xti_tcp_stream_response->so_sndavoid = loc_sndavoid;
1473   xti_tcp_stream_response->receive_size = recv_size;
1474 
1475   send_response();
1476 
1477   /* Now, let's set-up the socket to listen for connections. for xti, */
1478   /* the t_listen call is blocking by default - this is different */
1479   /* semantics from BSD - probably has to do with being able to reject */
1480   /* a call before an accept */
1481   call_req.addr.maxlen = sizeof(struct sockaddr_in);
1482   call_req.addr.len    = sizeof(struct sockaddr_in);
1483   call_req.addr.buf    = (char *)&peeraddr_in;
1484   call_req.opt.maxlen  = 0;
1485   call_req.opt.len     = 0;
1486   call_req.opt.buf     = NULL;
1487   call_req.udata.maxlen= 0;
1488   call_req.udata.len   = 0;
1489   call_req.udata.buf   = 0;
1490 
1491   if (t_listen(s_listen, &call_req) == -1) {
1492     fprintf(where,
1493 	    "recv_xti_tcp_stream: t_listen: errno %d t_errno %d\n",
1494 	    errno,
1495 	    t_errno);
1496     fflush(where);
1497     netperf_response.content.serv_errno = t_errno;
1498     close(s_listen);
1499     send_response();
1500     exit(1);
1501   }
1502 
1503   if (debug) {
1504     fprintf(where,
1505 	    "recv_xti_tcp_stream: t_listen complete t_look 0x%.4x\n",
1506 	    t_look(s_listen));
1507     fflush(where);
1508   }
1509 
1510   /* now just rubber stamp the thing. we want to use the same fd? so */
1511   /* we will just equate s_data with s_listen. this seems a little */
1512   /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
1513   s_data = s_listen;
1514   if (t_accept(s_listen,
1515 	       s_data,
1516 	       &call_req) == -1) {
1517     fprintf(where,
1518 	    "recv_xti_tcp_stream: t_accept: errno %d t_errno %d\n",
1519 	    errno,
1520 	    t_errno);
1521     fflush(where);
1522     close(s_listen);
1523     exit(1);
1524   }
1525 
1526   if (debug) {
1527     fprintf(where,
1528 	    "recv_xti_tcp_stream: t_accept complete t_look 0x%.4x\n",
1529 	    t_look(s_data));
1530     fprintf(where,
1531 	    "                     remote is %s port %d\n",
1532 	    inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
1533 	    ntohs(peeraddr_in.sin_port));
1534     fflush(where);
1535   }
1536 
1537   /* Now it's time to start receiving data on the connection. We will */
1538   /* first grab the apropriate counters and then start grabbing. */
1539 
1540   cpu_start(xti_tcp_stream_request->measure_cpu);
1541 
1542   /* The loop will exit when the sender does a t_sndrel, which will */
1543   /* return T_LOOK error from the t_recv */
1544 
1545 #ifdef DIRTY
1546     /* we want to dirty some number of consecutive integers in the buffer */
1547     /* we are about to recv. we may also want to bring some number of */
1548     /* them cleanly into the cache. The clean ones will follow any dirty */
1549     /* ones into the cache. */
1550 
1551   access_buffer(recv_ring->buffer_ptr,
1552 		recv_size,
1553 		xti_tcp_stream_request->dirty_count,
1554 		xti_tcp_stream_request->clean_count);
1555 
1556 #endif /* DIRTY */
1557 
1558   bytes_received = 0;
1559   receive_calls  = 0;
1560 
1561   while ((len = t_rcv(s_data,
1562 		      recv_ring->buffer_ptr,
1563 		      recv_size,
1564 		      &xti_flags)) != -1) {
1565     bytes_received += len;
1566     receive_calls++;
1567 
1568     /* more to the next buffer in the recv_ring */
1569     recv_ring = recv_ring->next;
1570 
1571 #ifdef DIRTY
1572 
1573   access_buffer(recv_ring->buffer_ptr,
1574 		recv_size,
1575 		xti_tcp_stream_request->dirty_count,
1576 		xti_tcp_stream_request->clean_count);
1577 
1578 #endif /* DIRTY */
1579   }
1580 
1581   if (t_look(s_data) == T_ORDREL) {
1582     /* this is a normal exit path */
1583     if (debug) {
1584       fprintf(where,
1585 	      "recv_xti_tcp_stream: t_rcv T_ORDREL indicated\n");
1586       fflush(where);
1587     }
1588   }
1589   else {
1590     /* something went wrong */
1591     fprintf(where,
1592 	    "recv_xti_tcp_stream: t_rcv: errno %d t_errno %d len %d",
1593 	    errno,
1594 	    t_errno,
1595 	    len);
1596     fprintf(where,
1597 	    " t_look 0x%.4x",
1598 	    t_look(s_data));
1599     fflush(where);
1600     netperf_response.content.serv_errno = t_errno;
1601     send_response();
1602     exit(1);
1603   }
1604 
1605   /* receive the release and let the initiator know that we have */
1606   /* received all the data. raj 3/95 */
1607 
1608   if (t_rcvrel(s_data) == -1) {
1609     netperf_response.content.serv_errno = errno;
1610     send_response();
1611     exit(1);
1612   }
1613 
1614   if (debug) {
1615     fprintf(where,
1616 	    "recv_xti_tcp_stream: t_rcvrel complete\n");
1617     fflush(where);
1618   }
1619 
1620   if (t_sndrel(s_data) == -1) {
1621     netperf_response.content.serv_errno = errno;
1622     send_response();
1623     exit(1);
1624   }
1625 
1626   if (debug) {
1627     fprintf(where,
1628 	    "recv_xti_tcp_stream: t_sndrel complete\n");
1629     fflush(where);
1630   }
1631 
1632   cpu_stop(xti_tcp_stream_request->measure_cpu,&elapsed_time);
1633 
1634   /* send the results to the sender			*/
1635 
1636   if (debug) {
1637     fprintf(where,
1638 	    "recv_xti_tcp_stream: got %g bytes\n",
1639 	    bytes_received);
1640     fprintf(where,
1641 	    "recv_xti_tcp_stream: got %d recvs\n",
1642 	    receive_calls);
1643     fflush(where);
1644   }
1645 
1646   xti_tcp_stream_results->bytes_received	= bytes_received;
1647   xti_tcp_stream_results->elapsed_time	= elapsed_time;
1648   xti_tcp_stream_results->recv_calls	= receive_calls;
1649 
1650   if (xti_tcp_stream_request->measure_cpu) {
1651     xti_tcp_stream_results->cpu_util	= calc_cpu_util(0.0);
1652   };
1653 
1654   if (debug) {
1655     fprintf(where,
1656 	    "recv_xti_tcp_stream: test complete, sending results.\n");
1657     fprintf(where,
1658 	    "                 bytes_received %g receive_calls %d\n",
1659 	    bytes_received,
1660 	    receive_calls);
1661     fprintf(where,
1662 	    "                 len %d\n",
1663 	    len);
1664     fflush(where);
1665   }
1666 
1667   xti_tcp_stream_results->cpu_method = cpu_method;
1668   send_response();
1669 
1670   /* we are now done with the socket */
1671   t_close(s_data);
1672 
1673 }
1674 
1675 
1676  /* this routine implements the sending (netperf) side of the XTI_TCP_RR */
1677  /* test. */
1678 
1679 void
send_xti_tcp_rr(char remote_host[])1680 send_xti_tcp_rr(char remote_host[])
1681 {
1682 
1683   char *tput_title = "\
1684 Local /Remote\n\
1685 Socket Size   Request  Resp.   Elapsed  Trans.\n\
1686 Send   Recv   Size     Size    Time     Rate         \n\
1687 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
1688 
1689   char *tput_fmt_0 =
1690     "%7.2f\n";
1691 
1692   char *tput_fmt_1_line_1 = "\
1693 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
1694   char *tput_fmt_1_line_2 = "\
1695 %-6d %-6d\n";
1696 
1697   char *cpu_title = "\
1698 Local /Remote\n\
1699 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
1700 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
1701 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
1702 
1703   char *cpu_fmt_0 =
1704     "%6.3f %c\n";
1705 
1706   char *cpu_fmt_1_line_1 = "\
1707 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f\n";
1708 
1709   char *cpu_fmt_1_line_2 = "\
1710 %-6d %-6d\n";
1711 
1712   char *ksink_fmt = "\
1713 Alignment      Offset\n\
1714 Local  Remote  Local  Remote\n\
1715 Send   Recv    Send   Recv\n\
1716 %5d  %5d   %5d  %5d\n";
1717 
1718 
1719   int			timed_out = 0;
1720   float			elapsed_time;
1721 
1722   int	len;
1723   char	*temp_message_ptr;
1724   int	nummessages;
1725   SOCKET send_socket;
1726   int	trans_remaining;
1727   double	bytes_xferd;
1728 
1729   struct ring_elt *send_ring;
1730   struct ring_elt *recv_ring;
1731 
1732   int	rsp_bytes_left;
1733   int	rsp_bytes_recvd;
1734 
1735   float	local_cpu_utilization;
1736   float	local_service_demand;
1737   float	remote_cpu_utilization;
1738   float	remote_service_demand;
1739   double	thruput;
1740 
1741   struct	hostent	        *hp;
1742   struct	sockaddr_in	server;
1743   unsigned      int             addr;
1744 
1745   struct t_call server_call;
1746 
1747   struct	xti_tcp_rr_request_struct	*xti_tcp_rr_request;
1748   struct	xti_tcp_rr_response_struct	*xti_tcp_rr_response;
1749   struct	xti_tcp_rr_results_struct	*xti_tcp_rr_result;
1750 
1751 #ifdef WANT_INTERVALS
1752   int	interval_count;
1753   sigset_t signal_set;
1754 #endif /* WANT_INTERVALS */
1755 
1756   xti_tcp_rr_request =
1757     (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
1758   xti_tcp_rr_response=
1759     (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
1760   xti_tcp_rr_result	=
1761     (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
1762 
1763 #ifdef WANT_HISTOGRAM
1764   time_hist = HIST_new();
1765 #endif /* WANT_HISTOGRAM */
1766 
1767   /* since we are now disconnected from the code that established the */
1768   /* control socket, and since we want to be able to use different */
1769   /* protocols and such, we are passed the name of the remote host and */
1770   /* must turn that into the test specific addressing information. */
1771 
1772   bzero((char *)&server,
1773 	sizeof(server));
1774 
1775   /* it would seem that while HP-UX will allow an IP address (as a */
1776   /* string) in a call to gethostbyname, other, less enlightened */
1777   /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
1778   /* order changed to check for IP address first. raj 7/96 */
1779 
1780   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
1781     /* it was not an IP address, try it as a name */
1782     if ((hp = gethostbyname(remote_host)) == NULL) {
1783       /* we have no idea what it is */
1784       fprintf(where,
1785 	      "establish_control: could not resolve the destination %s\n",
1786 	      remote_host);
1787       fflush(where);
1788       exit(1);
1789     }
1790     else {
1791       /* it was a valid remote_host */
1792       bcopy(hp->h_addr,
1793 	    (char *)&server.sin_addr,
1794 	    hp->h_length);
1795       server.sin_family = hp->h_addrtype;
1796     }
1797   }
1798   else {
1799     /* it was a valid IP address */
1800     server.sin_addr.s_addr = addr;
1801     server.sin_family = AF_INET;
1802   }
1803 
1804   if ( print_headers ) {
1805     fprintf(where,"XTI TCP REQUEST/RESPONSE TEST");
1806     fprintf(where," to %s", remote_host);
1807     if (iteration_max > 1) {
1808       fprintf(where,
1809 	      " : +/-%3.1f%% @ %2d%% conf.",
1810 	      interval/0.02,
1811 	      confidence_level);
1812       }
1813     if (loc_nodelay || rem_nodelay) {
1814       fprintf(where," : nodelay");
1815     }
1816     if (loc_sndavoid ||
1817 	loc_rcvavoid ||
1818 	rem_sndavoid ||
1819 	rem_rcvavoid) {
1820       fprintf(where," : copy avoidance");
1821     }
1822 #ifdef WANT_HISTOGRAM
1823     fprintf(where," : histogram");
1824 #endif /* WANT_HISTOGRAM */
1825 #ifdef WANT_INTERVALS
1826     fprintf(where," : interval");
1827 #endif /* WANT_INTERVALS */
1828 #ifdef DIRTY
1829     fprintf(where," : dirty data");
1830 #endif /* DIRTY */
1831     fprintf(where,"\n");
1832   }
1833 
1834   /* initialize a few counters */
1835 
1836   send_ring = NULL;
1837   recv_ring = NULL;
1838   confidence_iteration = 1;
1839   init_stat();
1840 
1841   /* we have a great-big while loop which controls the number of times */
1842   /* we run a particular test. this is for the calculation of a */
1843   /* confidence interval (I really should have stayed awake during */
1844   /* probstats :). If the user did not request confidence measurement */
1845   /* (no confidence is the default) then we will only go though the */
1846   /* loop once. the confidence stuff originates from the folks at IBM */
1847 
1848   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
1849 	 (confidence_iteration <= iteration_min)) {
1850 
1851     /* initialize a few counters. we have to remember that we might be */
1852     /* going through the loop more than once. */
1853 
1854     nummessages     = 0;
1855     bytes_xferd     = 0.0;
1856     times_up        = 0;
1857     timed_out       = 0;
1858     trans_remaining = 0;
1859 
1860     /* set-up the data buffers with the requested alignment and offset. */
1861     /* since this is a request/response test, default the send_width and */
1862     /* recv_width to 1 and not two raj 7/94 */
1863 
1864     if (send_width == 0) send_width = 1;
1865     if (recv_width == 0) recv_width = 1;
1866 
1867     if (send_ring == NULL) {
1868       send_ring = allocate_buffer_ring(send_width,
1869 				       req_size,
1870 				       local_send_align,
1871 				       local_send_offset);
1872     }
1873 
1874     if (recv_ring == NULL) {
1875       recv_ring = allocate_buffer_ring(recv_width,
1876 				       rsp_size,
1877 				       local_recv_align,
1878 				       local_recv_offset);
1879     }
1880 
1881     /*set up the data socket                        */
1882     send_socket = create_xti_endpoint(loc_xti_device);
1883 
1884     if (send_socket == INVALID_SOCKET){
1885       perror("netperf: send_xti_tcp_rr: tcp stream data socket");
1886       exit(1);
1887     }
1888 
1889     if (debug) {
1890       fprintf(where,"send_xti_tcp_rr: send_socket obtained...\n");
1891     }
1892 
1893     /* it would seem that with XTI, there is no implicit bind on a */
1894     /* connect, so we have to make a call to t_bind. this is not */
1895     /* terribly convenient, but I suppose that "standard is better */
1896     /* than better" :) raj 2/95 */
1897 
1898     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
1899       t_error("send_xti_tcp_stream: t_bind");
1900       exit(1);
1901     }
1902 
1903     /* If the user has requested cpu utilization measurements, we must */
1904     /* calibrate the cpu(s). We will perform this task within the tests */
1905     /* themselves. If the user has specified the cpu rate, then */
1906     /* calibrate_local_cpu will return rather quickly as it will have */
1907     /* nothing to do. If local_cpu_rate is zero, then we will go through */
1908     /* all the "normal" calibration stuff and return the rate back.*/
1909 
1910     if (local_cpu_usage) {
1911       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1912     }
1913 
1914     /* Tell the remote end to do a listen. The server alters the socket */
1915     /* paramters on the other side at this point, hence the reason for */
1916     /* all the values being passed in the setup message. If the user did */
1917     /* not specify any of the parameters, they will be passed as 0, which */
1918     /* will indicate to the remote that no changes beyond the system's */
1919     /* default should be used. Alignment is the exception, it will */
1920     /* default to 8, which will be no alignment alterations. */
1921 
1922     netperf_request.content.request_type	=	DO_XTI_TCP_RR;
1923     xti_tcp_rr_request->recv_buf_size	=	rsr_size;
1924     xti_tcp_rr_request->send_buf_size	=	rss_size;
1925     xti_tcp_rr_request->recv_alignment  =	remote_recv_align;
1926     xti_tcp_rr_request->recv_offset	=	remote_recv_offset;
1927     xti_tcp_rr_request->send_alignment  =	remote_send_align;
1928     xti_tcp_rr_request->send_offset	=	remote_send_offset;
1929     xti_tcp_rr_request->request_size	=	req_size;
1930     xti_tcp_rr_request->response_size	=	rsp_size;
1931     xti_tcp_rr_request->no_delay	=	rem_nodelay;
1932     xti_tcp_rr_request->measure_cpu	=	remote_cpu_usage;
1933     xti_tcp_rr_request->cpu_rate	=	remote_cpu_rate;
1934     xti_tcp_rr_request->so_rcvavoid	=	rem_rcvavoid;
1935     xti_tcp_rr_request->so_sndavoid	=	rem_sndavoid;
1936     if (test_time) {
1937       xti_tcp_rr_request->test_length	=	test_time;
1938     }
1939     else {
1940       xti_tcp_rr_request->test_length	=	test_trans * -1;
1941     }
1942 
1943     strcpy(xti_tcp_rr_request->xti_device, rem_xti_device);
1944 
1945 #ifdef __alpha
1946 
1947     /* ok - even on a DEC box, strings are strings. I didn't really want */
1948     /* to ntohl the words of a string. since I don't want to teach the */
1949     /* send_ and recv_ _request and _response routines about the types, */
1950     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
1951     /* solution would be to use XDR, but I am still leary of being able */
1952     /* to find XDR libs on all platforms I want running netperf. raj */
1953     {
1954       int *charword;
1955       int *initword;
1956       int *lastword;
1957 
1958       initword = (int *) xti_tcp_rr_request->xti_device;
1959       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
1960 
1961       for (charword = initword;
1962 	   charword < lastword;
1963 	   charword++) {
1964 
1965 	*charword = ntohl(*charword);
1966       }
1967     }
1968 #endif /* __alpha */
1969 
1970     if (debug > 1) {
1971       fprintf(where,"netperf: send_xti_tcp_rr: requesting TCP rr test\n");
1972     }
1973 
1974     send_request();
1975 
1976     /* The response from the remote will contain all of the relevant 	*/
1977     /* socket parameters for this test type. We will put them back into */
1978     /* the variables here so they can be displayed if desired.  The	*/
1979     /* remote will have calibrated CPU if necessary, and will have done	*/
1980     /* all the needed set-up we will have calibrated the cpu locally	*/
1981     /* before sending the request, and will grab the counter value right*/
1982     /* after the connect returns. The remote will grab the counter right*/
1983     /* after the accept call. This saves the hassle of extra messages	*/
1984     /* being sent for the TCP tests.					*/
1985 
1986     recv_response();
1987 
1988     if (!netperf_response.content.serv_errno) {
1989       if (debug)
1990 	fprintf(where,"remote listen done.\n");
1991       rsr_size          = xti_tcp_rr_response->recv_buf_size;
1992       rss_size          = xti_tcp_rr_response->send_buf_size;
1993       rem_nodelay       = xti_tcp_rr_response->no_delay;
1994       remote_cpu_usage  = xti_tcp_rr_response->measure_cpu;
1995       remote_cpu_rate   = xti_tcp_rr_response->cpu_rate;
1996       /* make sure that port numbers are in network order */
1997       server.sin_port   = (short)xti_tcp_rr_response->data_port_number;
1998       server.sin_port   = htons(server.sin_port);
1999     }
2000     else {
2001       Set_errno(netperf_response.content.serv_errno);
2002       perror("netperf: remote error");
2003 
2004       exit(1);
2005     }
2006 
2007     /*Connect up to the remote port on the data socket  */
2008     memset (&server_call, 0, sizeof(server_call));
2009     server_call.addr.maxlen = sizeof(struct sockaddr_in);
2010     server_call.addr.len    = sizeof(struct sockaddr_in);
2011     server_call.addr.buf    = (char *)&server;
2012 
2013     if (t_connect(send_socket,
2014 		  &server_call,
2015 		  NULL) == INVALID_SOCKET){
2016       t_error("netperf: send_xti_tcp_rr: data socket connect failed");
2017       printf(" port: %d\n",ntohs(server.sin_port));
2018       exit(1);
2019     }
2020 
2021     /* Data Socket set-up is finished. If there were problems, either the */
2022     /* connect would have failed, or the previous response would have */
2023     /* indicated a problem. I failed to see the value of the extra */
2024     /* message after the accept on the remote. If it failed, we'll see it */
2025     /* here. If it didn't, we might as well start pumping data. */
2026 
2027     /* Set-up the test end conditions. For a request/response test, they */
2028     /* can be either time or transaction based. */
2029 
2030     if (test_time) {
2031       /* The user wanted to end the test after a period of time. */
2032       times_up = 0;
2033       trans_remaining = 0;
2034       start_timer(test_time);
2035     }
2036     else {
2037       /* The tester wanted to send a number of bytes. */
2038       trans_remaining = test_bytes;
2039       times_up = 1;
2040     }
2041 
2042     /* The cpu_start routine will grab the current time and possibly */
2043     /* value of the idle counter for later use in measuring cpu */
2044     /* utilization and/or service demand and thruput. */
2045 
2046     cpu_start(local_cpu_usage);
2047 
2048 #ifdef WANT_INTERVALS
2049     if ((interval_burst) || (demo_mode)) {
2050       /* zero means that we never pause, so we never should need the */
2051       /* interval timer, unless we are in demo_mode */
2052       start_itimer(interval_wate);
2053     }
2054     interval_count = interval_burst;
2055     /* get the signal set for the call to sigsuspend */
2056     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
2057       fprintf(where,
2058 	      "send_xti_tcp_rr: unable to get sigmask errno %d\n",
2059 	      errno);
2060       fflush(where);
2061       exit(1);
2062     }
2063 #endif /* WANT_INTERVALS */
2064 
2065     /* We use an "OR" to control test execution. When the test is */
2066     /* controlled by time, the byte count check will always return false. */
2067     /* When the test is controlled by byte count, the time test will */
2068     /* always return false. When the test is finished, the whole */
2069     /* expression will go false and we will stop sending data. I think I */
2070     /* just arbitrarily decrement trans_remaining for the timed test, but */
2071     /* will not do that just yet... One other question is whether or not */
2072     /* the send buffer and the receive buffer should be the same buffer. */
2073 
2074     while ((!times_up) || (trans_remaining > 0)) {
2075       /* send the request. we assume that if we use a blocking socket, */
2076       /* the request will be sent at one shot. */
2077 
2078 #ifdef WANT_HISTOGRAM
2079       /* timestamp just before our call to send, and then again just */
2080       /* after the receive raj 8/94 */
2081       HIST_timestamp(&time_one);
2082 #endif /* WANT_HISTOGRAM */
2083 
2084       if((len=t_snd(send_socket,
2085 		    send_ring->buffer_ptr,
2086 		    req_size,
2087 		    0)) != req_size) {
2088 	if ((errno == EINTR) || (errno == 0)) {
2089 	  /* we hit the end of a */
2090 	  /* timed test. */
2091 	  timed_out = 1;
2092 	  break;
2093 	}
2094         fprintf(where,
2095 		"send_xti_tcp_rr: t_snd: errno %d t_errno %d t_look 0x%.4x\n",
2096 		errno,
2097 		t_errno,
2098 		t_look(send_socket));
2099 	fflush(where);
2100         exit(1);
2101       }
2102       send_ring = send_ring->next;
2103 
2104       /* receive the response */
2105       rsp_bytes_left = rsp_size;
2106       temp_message_ptr  = recv_ring->buffer_ptr;
2107       while(rsp_bytes_left > 0) {
2108 	if((rsp_bytes_recvd=t_rcv(send_socket,
2109 				  temp_message_ptr,
2110 				  rsp_bytes_left,
2111 				  &xti_flags)) == SOCKET_ERROR) {
2112 	  if (errno == EINTR) {
2113 	    /* We hit the end of a timed test. */
2114 	    timed_out = 1;
2115 	    break;
2116 	  }
2117 	  fprintf(where,
2118 		  "send_xti_tcp_rr: t_rcv: errno %d t_errno %d t_look 0x%x\n",
2119 		  errno,
2120 		  t_errno,
2121 		  t_look(send_socket));
2122 	  fflush(where);
2123 	  exit(1);
2124 	}
2125 	rsp_bytes_left -= rsp_bytes_recvd;
2126 	temp_message_ptr  += rsp_bytes_recvd;
2127       }
2128       recv_ring = recv_ring->next;
2129 
2130       if (timed_out) {
2131 	/* we may have been in a nested while loop - we need */
2132 	/* another call to break. */
2133 	break;
2134       }
2135 
2136 #ifdef WANT_HISTOGRAM
2137       HIST_timestamp(&time_two);
2138       HIST_add(time_hist,delta_micro(&time_one,&time_two));
2139 #endif /* WANT_HISTOGRAM */
2140 #ifdef WANT_INTERVALS
2141       if (demo_mode) {
2142 	units_this_tick += 1;
2143       }
2144       /* in this case, the interval count is the count-down couter */
2145       /* to decide to sleep for a little bit */
2146       if ((interval_burst) && (--interval_count == 0)) {
2147 	/* call sigsuspend and wait for the interval timer to get us */
2148 	/* out */
2149 	if (debug) {
2150 	  fprintf(where,"about to suspend\n");
2151 	  fflush(where);
2152 	}
2153 	if (sigsuspend(&signal_set) == EFAULT) {
2154 	  fprintf(where,
2155 		  "send_xti_udp_rr: fault with signal set!\n");
2156 	  fflush(where);
2157 	  exit(1);
2158 	}
2159 	interval_count = interval_burst;
2160       }
2161 #endif /* WANT_INTERVALS */
2162 
2163       nummessages++;
2164       if (trans_remaining) {
2165 	trans_remaining--;
2166       }
2167 
2168       if (debug > 3) {
2169 	if ((nummessages % 100) == 0) {
2170 	  fprintf(where,
2171 		  "Transaction %d completed\n",
2172 		  nummessages);
2173 	  fflush(where);
2174 	}
2175       }
2176     }
2177 
2178 
2179     /* this call will always give us the elapsed time for the test, and */
2180     /* will also store-away the necessaries for cpu utilization */
2181 
2182     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
2183 						/* measured? how long */
2184 						/* did we really run? */
2185 
2186     /* Get the statistics from the remote end. The remote will have */
2187     /* calculated service demand and all those interesting things. If it */
2188     /* wasn't supposed to care, it will return obvious values. */
2189 
2190     recv_response();
2191     if (!netperf_response.content.serv_errno) {
2192       if (debug)
2193 	fprintf(where,"remote results obtained\n");
2194     }
2195     else {
2196       Set_errno(netperf_response.content.serv_errno);
2197       perror("netperf: remote error");
2198 
2199       exit(1);
2200     }
2201 
2202     /* We now calculate what our thruput was for the test. */
2203 
2204     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
2205     thruput	= nummessages/elapsed_time;
2206 
2207     if (local_cpu_usage || remote_cpu_usage) {
2208       /* We must now do a little math for service demand and cpu */
2209       /* utilization for the system(s) */
2210       /* Of course, some of the information might be bogus because */
2211       /* there was no idle counter in the kernel(s). We need to make */
2212       /* a note of this for the user's benefit...*/
2213       if (local_cpu_usage) {
2214 	local_cpu_utilization = calc_cpu_util(0.0);
2215 	/* since calc_service demand is doing ms/Kunit we will */
2216 	/* multiply the number of transaction by 1024 to get */
2217 	/* "good" numbers */
2218 	local_service_demand  = calc_service_demand((double) nummessages*1024,
2219 						    0.0,
2220 						    0.0,
2221 						    0);
2222       }
2223       else {
2224 	local_cpu_utilization	= -1.0;
2225 	local_service_demand	= -1.0;
2226       }
2227 
2228       if (remote_cpu_usage) {
2229 	remote_cpu_utilization = xti_tcp_rr_result->cpu_util;
2230 	/* since calc_service demand is doing ms/Kunit we will */
2231 	/* multiply the number of transaction by 1024 to get */
2232 	/* "good" numbers */
2233 	remote_service_demand = calc_service_demand((double) nummessages*1024,
2234 						    0.0,
2235 						    remote_cpu_utilization,
2236 						    xti_tcp_rr_result->num_cpus);
2237       }
2238       else {
2239 	remote_cpu_utilization = -1.0;
2240 	remote_service_demand  = -1.0;
2241       }
2242 
2243     }
2244     else {
2245       /* we were not measuring cpu, for the confidence stuff, we */
2246       /* should make it -1.0 */
2247       local_cpu_utilization	= -1.0;
2248       local_service_demand	= -1.0;
2249       remote_cpu_utilization = -1.0;
2250       remote_service_demand  = -1.0;
2251     }
2252 
2253     /* at this point, we want to calculate the confidence information. */
2254     /* if debugging is on, calculate_confidence will print-out the */
2255     /* parameters we pass it */
2256 
2257     calculate_confidence(confidence_iteration,
2258 			 elapsed_time,
2259 			 thruput,
2260 			 local_cpu_utilization,
2261 			 remote_cpu_utilization,
2262 			 local_service_demand,
2263 			 remote_service_demand);
2264 
2265 
2266     confidence_iteration++;
2267 
2268     /* we are now done with the socket, so close it */
2269     t_close(send_socket);
2270 
2271   }
2272 
2273   retrieve_confident_values(&elapsed_time,
2274 			    &thruput,
2275 			    &local_cpu_utilization,
2276 			    &remote_cpu_utilization,
2277 			    &local_service_demand,
2278 			    &remote_service_demand);
2279 
2280   /* We are now ready to print all the information. If the user */
2281   /* has specified zero-level verbosity, we will just print the */
2282   /* local service demand, or the remote service demand. If the */
2283   /* user has requested verbosity level 1, he will get the basic */
2284   /* "streamperf" numbers. If the user has specified a verbosity */
2285   /* of greater than 1, we will display a veritable plethora of */
2286   /* background information from outside of this block as it it */
2287   /* not cpu_measurement specific...  */
2288 
2289   if (confidence < 0) {
2290     /* we did not hit confidence, but were we asked to look for it? */
2291     if (iteration_max > 1) {
2292       display_confidence();
2293     }
2294   }
2295 
2296   if (local_cpu_usage || remote_cpu_usage) {
2297     local_cpu_method = format_cpu_method(cpu_method);
2298     remote_cpu_method = format_cpu_method(xti_tcp_rr_result->cpu_method);
2299 
2300     switch (verbosity) {
2301     case 0:
2302       if (local_cpu_usage) {
2303 	fprintf(where,
2304 		cpu_fmt_0,
2305 		local_service_demand,
2306 		local_cpu_method);
2307       }
2308       else {
2309 	fprintf(where,
2310 		cpu_fmt_0,
2311 		remote_service_demand,
2312 		remote_cpu_method);
2313       }
2314       break;
2315     case 1:
2316     case 2:
2317       if (print_headers) {
2318 	fprintf(where,
2319 		cpu_title,
2320 		local_cpu_method,
2321 		remote_cpu_method);
2322       }
2323 
2324       fprintf(where,
2325 	      cpu_fmt_1_line_1,		/* the format string */
2326 	      lss_size,		/* local sendbuf size */
2327 	      lsr_size,
2328 	      req_size,		/* how large were the requests */
2329 	      rsp_size,		/* guess */
2330 	      elapsed_time,		/* how long was the test */
2331 	      thruput,
2332 	      local_cpu_utilization,	/* local cpu */
2333 	      remote_cpu_utilization,	/* remote cpu */
2334 	      local_service_demand,	/* local service demand */
2335 	      remote_service_demand);	/* remote service demand */
2336       fprintf(where,
2337 	      cpu_fmt_1_line_2,
2338 	      rss_size,
2339 	      rsr_size);
2340       break;
2341     }
2342   }
2343   else {
2344     /* The tester did not wish to measure service demand. */
2345 
2346     switch (verbosity) {
2347     case 0:
2348       fprintf(where,
2349 	      tput_fmt_0,
2350 	      thruput);
2351       break;
2352     case 1:
2353     case 2:
2354       if (print_headers) {
2355 	fprintf(where,tput_title,format_units());
2356       }
2357 
2358       fprintf(where,
2359 	      tput_fmt_1_line_1,	/* the format string */
2360 	      lss_size,
2361 	      lsr_size,
2362 	      req_size,		/* how large were the requests */
2363 	      rsp_size,		/* how large were the responses */
2364 	      elapsed_time, 		/* how long did it take */
2365 	      thruput);
2366       fprintf(where,
2367 	      tput_fmt_1_line_2,
2368 	      rss_size, 		/* remote recvbuf size */
2369 	      rsr_size);
2370 
2371       break;
2372     }
2373   }
2374 
2375   /* it would be a good thing to include information about some of the */
2376   /* other parameters that may have been set for this test, but at the */
2377   /* moment, I do not wish to figure-out all the  formatting, so I will */
2378   /* just put this comment here to help remind me that it is something */
2379   /* that should be done at a later time. */
2380 
2381   /* how to handle the verbose information in the presence of */
2382   /* confidence intervals is yet to be determined... raj 11/94 */
2383   if (verbosity > 1) {
2384     /* The user wanted to know it all, so we will give it to him. */
2385     /* This information will include as much as we can find about */
2386     /* TCP statistics, the alignments of the sends and receives */
2387     /* and all that sort of rot... */
2388 
2389     fprintf(where,
2390 	    ksink_fmt,
2391 	    local_send_align,
2392 	    remote_recv_offset,
2393 	    local_send_offset,
2394 	    remote_recv_offset);
2395 
2396 #ifdef WANT_HISTOGRAM
2397     fprintf(where,"\nHistogram of request/response times\n");
2398     fflush(where);
2399     HIST_report(time_hist);
2400 #endif /* WANT_HISTOGRAM */
2401 
2402   }
2403 
2404 }
2405 
2406 void
send_xti_udp_stream(char remote_host[])2407 send_xti_udp_stream(char remote_host[])
2408 {
2409   /**********************************************************************/
2410   /*									*/
2411   /*               	UDP Unidirectional Send Test                    */
2412   /*									*/
2413   /**********************************************************************/
2414   char *tput_title = "\
2415 Socket  Message  Elapsed      Messages                \n\
2416 Size    Size     Time         Okay Errors   Throughput\n\
2417 bytes   bytes    secs            #      #   %s/sec\n\n";
2418 
2419   char *tput_fmt_0 =
2420     "%7.2f\n";
2421 
2422   char *tput_fmt_1 = "\
2423 %6d  %6d   %-7.2f   %7d %6d    %7.2f\n\
2424 %6d           %-7.2f   %7d           %7.2f\n\n";
2425 
2426 
2427   char *cpu_title = "\
2428 Socket  Message  Elapsed      Messages                   CPU      Service\n\
2429 Size    Size     Time         Okay Errors   Throughput   Util     Demand\n\
2430 bytes   bytes    secs            #      #   %s/sec %% %c%c     us/KB\n\n";
2431 
2432   char *cpu_fmt_0 =
2433     "%6.2f %c\n";
2434 
2435   char *cpu_fmt_1 = "\
2436 %6d  %6d   %-7.2f   %7d %6d    %7.1f     %-6.2f   %-6.3f\n\
2437 %6d           %-7.2f   %7d           %7.1f     %-6.2f   %-6.3f\n\n";
2438 
2439   unsigned int	messages_recvd;
2440   unsigned int 	messages_sent;
2441   unsigned int	failed_sends;
2442 
2443   float	elapsed_time,
2444         recv_elapsed,
2445         local_cpu_utilization,
2446         remote_cpu_utilization;
2447 
2448   float	 local_service_demand, remote_service_demand;
2449   double local_thruput, remote_thruput;
2450   double bytes_sent;
2451   double bytes_recvd;
2452 
2453 
2454   int	len;
2455   int	*message_int_ptr;
2456   struct ring_elt *send_ring;
2457   SOCKET data_socket;
2458 
2459   unsigned int sum_messages_sent;
2460   unsigned int sum_messages_recvd;
2461   unsigned int sum_failed_sends;
2462   double sum_local_thruput;
2463 
2464 #ifdef WANT_INTERVALS
2465   int	interval_count;
2466   sigset_t signal_set;
2467 #endif /* WANT_INTERVALS */
2468 
2469   struct   hostent     *hp;
2470   struct   sockaddr_in server;
2471   unsigned int         addr;
2472 
2473   struct t_unitdata unitdata;
2474 
2475   struct xti_udp_stream_request_struct	*xti_udp_stream_request;
2476   struct xti_udp_stream_response_struct	*xti_udp_stream_response;
2477   struct xti_udp_stream_results_struct	*xti_udp_stream_results;
2478 
2479   xti_udp_stream_request  =
2480     (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
2481   xti_udp_stream_response =
2482     (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
2483   xti_udp_stream_results  =
2484     (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
2485 
2486 #ifdef WANT_HISTOGRAM
2487   time_hist = HIST_new();
2488 #endif /* WANT_HISTOGRAM */
2489 
2490   /* since we are now disconnected from the code that established the */
2491   /* control socket, and since we want to be able to use different */
2492   /* protocols and such, we are passed the name of the remote host and */
2493   /* must turn that into the test specific addressing information. */
2494 
2495   bzero((char *)&server,
2496 	sizeof(server));
2497 
2498   /* it would seem that while HP-UX will allow an IP address (as a */
2499   /* string) in a call to gethostbyname, other, less enlightened */
2500   /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
2501   /* order changed to check for IP address first. raj 7/96 */
2502 
2503   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
2504     /* it was not an IP address, try it as a name */
2505     if ((hp = gethostbyname(remote_host)) == NULL) {
2506       /* we have no idea what it is */
2507       fprintf(where,
2508 	      "establish_control: could not resolve the destination %s\n",
2509 	      remote_host);
2510       fflush(where);
2511       exit(1);
2512     }
2513     else {
2514       /* it was a valid remote_host */
2515       bcopy(hp->h_addr,
2516 	    (char *)&server.sin_addr,
2517 	    hp->h_length);
2518       server.sin_family = hp->h_addrtype;
2519     }
2520   }
2521   else {
2522     /* it was a valid IP address */
2523     server.sin_addr.s_addr = addr;
2524     server.sin_family = AF_INET;
2525   }
2526 
2527   if ( print_headers ) {
2528     fprintf(where,"UDP UNIDIRECTIONAL SEND TEST");
2529     fprintf(where," to %s", remote_host);
2530     if (iteration_max > 1) {
2531       fprintf(where,
2532 	      " : +/-%3.1f%% @ %2d%% conf.",
2533 	      interval/0.02,
2534 	      confidence_level);
2535       }
2536     if (loc_sndavoid ||
2537 	loc_rcvavoid ||
2538 	rem_sndavoid ||
2539 	rem_rcvavoid) {
2540       fprintf(where," : copy avoidance");
2541     }
2542 #ifdef WANT_HISTOGRAM
2543     fprintf(where," : histogram");
2544 #endif /* WANT_HISTOGRAM */
2545 #ifdef WANT_INTERVALS
2546     fprintf(where," : interval");
2547 #endif /* WANT_INTERVALS */
2548 #ifdef DIRTY
2549     fprintf(where," : dirty data");
2550 #endif /* DIRTY */
2551     fprintf(where,"\n");
2552   }
2553 
2554   send_ring            = NULL;
2555   confidence_iteration = 1;
2556   init_stat();
2557   sum_messages_sent    = 0;
2558   sum_messages_recvd   = 0;
2559   sum_failed_sends     = 0;
2560   sum_local_thruput    = 0.0;
2561 
2562   /* we have a great-big while loop which controls the number of times */
2563   /* we run a particular test. this is for the calculation of a */
2564   /* confidence interval (I really should have stayed awake during */
2565   /* probstats :). If the user did not request confidence measurement */
2566   /* (no confidence is the default) then we will only go though the */
2567   /* loop once. the confidence stuff originates from the folks at IBM */
2568 
2569   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2570 	 (confidence_iteration <= iteration_min)) {
2571 
2572     /* initialize a few counters. we have to remember that we might be */
2573     /* going through the loop more than once. */
2574     messages_sent  = 0;
2575     messages_recvd = 0;
2576     failed_sends   = 0;
2577     times_up       = 0;
2578 
2579     /*set up the data socket			*/
2580     data_socket = create_xti_endpoint(loc_xti_device);
2581 
2582     if (data_socket == INVALID_SOCKET) {
2583       perror("send_xti_udp_stream: create_xti_endpoint");
2584       exit(1);
2585     }
2586 
2587     if (t_bind(data_socket, NULL, NULL) == SOCKET_ERROR) {
2588       t_error("send_xti_udp_stream: t_bind");
2589       exit(1);
2590     }
2591 
2592     /* now, we want to see if we need to set the send_size */
2593     if (send_size == 0) {
2594       if (lss_size > 0) {
2595 	send_size = lss_size;
2596       }
2597       else {
2598 	send_size = 4096;
2599       }
2600     }
2601 
2602     /* set-up the data buffer with the requested alignment and offset, */
2603     /* most of the numbers here are just a hack to pick something nice */
2604     /* and big in an attempt to never try to send a buffer a second time */
2605     /* before it leaves the node...unless the user set the width */
2606     /* explicitly. */
2607     if (send_width == 0) send_width = 32;
2608 
2609     if (send_ring == NULL ) {
2610       send_ring = allocate_buffer_ring(send_width,
2611 				       send_size,
2612 				       local_send_align,
2613 				       local_send_offset);
2614     }
2615 
2616 
2617     /* if the user supplied a cpu rate, this call will complete rather */
2618     /* quickly, otherwise, the cpu rate will be retured to us for */
2619     /* possible display. The Library will keep it's own copy of this data */
2620     /* for use elsewhere. We will only display it. (Does that make it */
2621     /* "opaque" to us?) */
2622 
2623     if (local_cpu_usage)
2624       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2625 
2626     /* Tell the remote end to set up the data connection. The server */
2627     /* sends back the port number and alters the socket parameters there. */
2628     /* Of course this is a datagram service so no connection is actually */
2629     /* set up, the server just sets up the socket and binds it. */
2630 
2631     netperf_request.content.request_type      = DO_XTI_UDP_STREAM;
2632     xti_udp_stream_request->recv_buf_size  = rsr_size;
2633     xti_udp_stream_request->message_size   = send_size;
2634     xti_udp_stream_request->recv_alignment = remote_recv_align;
2635     xti_udp_stream_request->recv_offset    = remote_recv_offset;
2636     xti_udp_stream_request->measure_cpu    = remote_cpu_usage;
2637     xti_udp_stream_request->cpu_rate       = remote_cpu_rate;
2638     xti_udp_stream_request->test_length    = test_time;
2639     xti_udp_stream_request->so_rcvavoid    = rem_rcvavoid;
2640     xti_udp_stream_request->so_sndavoid    = rem_sndavoid;
2641 
2642     strcpy(xti_udp_stream_request->xti_device, rem_xti_device);
2643 
2644 #ifdef __alpha
2645 
2646     /* ok - even on a DEC box, strings are strings. I didn't really want */
2647     /* to ntohl the words of a string. since I don't want to teach the */
2648     /* send_ and recv_ _request and _response routines about the types, */
2649     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
2650     /* solution would be to use XDR, but I am still leary of being able */
2651     /* to find XDR libs on all platforms I want running netperf. raj */
2652     {
2653       int *charword;
2654       int *initword;
2655       int *lastword;
2656 
2657       initword = (int *) xti_udp_stream_request->xti_device;
2658       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
2659 
2660       for (charword = initword;
2661 	   charword < lastword;
2662 	   charword++) {
2663 
2664 	*charword = ntohl(*charword);
2665       }
2666     }
2667 #endif /* __alpha */
2668 
2669     send_request();
2670 
2671     recv_response();
2672 
2673     if (!netperf_response.content.serv_errno) {
2674       if (debug)
2675 	fprintf(where,"send_xti_udp_stream: remote data connection done.\n");
2676     }
2677     else {
2678       Set_errno(netperf_response.content.serv_errno);
2679       perror("send_xti_udp_stream: error on remote");
2680       exit(1);
2681     }
2682 
2683     /* Place the port number returned by the remote into the sockaddr */
2684     /* structure so our sends can be sent to the correct place. Also get */
2685     /* some of the returned socket buffer information for user display. */
2686 
2687     /* make sure that port numbers are in the proper order */
2688     server.sin_port = (short)xti_udp_stream_response->data_port_number;
2689     server.sin_port = htons(server.sin_port);
2690     rsr_size        = xti_udp_stream_response->recv_buf_size;
2691     rss_size        = xti_udp_stream_response->send_buf_size;
2692     remote_cpu_rate = xti_udp_stream_response->cpu_rate;
2693 
2694     /* it would seem that XTI does not allow the expedient of */
2695     /* "connecting" a UDP end-point the way BSD does. so, we will do */
2696     /* everything with t_sndudata and t_rcvudata. Our "virtual" */
2697     /* connect here will be to assign the destination portion of the */
2698     /* t_unitdata struct here, where we would have otherwise called */
2699     /* t_connect() raj 3/95 */
2700 
2701     memset (&unitdata, 0, sizeof(unitdata));
2702     unitdata.addr.maxlen = sizeof(struct sockaddr_in);
2703     unitdata.addr.len    = sizeof(struct sockaddr_in);
2704     unitdata.addr.buf    = (char *)&server;
2705 
2706     /* we don't use any options, so might as well set that part here */
2707     /* too */
2708 
2709     unitdata.opt.maxlen = 0;
2710     unitdata.opt.len    = 0;
2711     unitdata.opt.buf    = NULL;
2712 
2713     /* we need to initialize the send buffer for the first time as */
2714     /* well since we move to the next pointer after the send call. */
2715 
2716     unitdata.udata.maxlen = send_size;
2717     unitdata.udata.len    = send_size;
2718     unitdata.udata.buf    = send_ring->buffer_ptr;
2719 
2720     /* set up the timer to call us after test_time. one of these days, */
2721     /* it might be nice to figure-out a nice reliable way to have the */
2722     /* test controlled by a byte count as well, but since UDP is not */
2723     /* reliable, that could prove difficult. so, in the meantime, we */
2724     /* only allow a XTI_UDP_STREAM test to be a timed test. */
2725 
2726     if (test_time) {
2727       times_up = 0;
2728       start_timer(test_time);
2729     }
2730     else {
2731       fprintf(where,"Sorry, XTI_UDP_STREAM tests must be timed.\n");
2732       fflush(where);
2733       exit(1);
2734     }
2735 
2736     /* Get the start count for the idle counter and the start time */
2737 
2738     cpu_start(local_cpu_usage);
2739 
2740 #ifdef WANT_INTERVALS
2741     if ((interval_burst) || (demo_mode)) {
2742       /* zero means that we never pause, so we never should need the */
2743       /* interval timer, unless we are in demo_mode */
2744       start_itimer(interval_wate);
2745     }
2746     interval_count = interval_burst;
2747     /* get the signal set for the call to sigsuspend */
2748     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
2749       fprintf(where,
2750 	      "send_xti_udp_stream: unable to get sigmask errno %d\n",
2751 	      errno);
2752       fflush(where);
2753       exit(1);
2754     }
2755 #endif /* WANT_INTERVALS */
2756 
2757     /* Send datagrams like there was no tomorrow. at somepoint it might */
2758     /* be nice to set this up so that a quantity of bytes could be sent, */
2759     /* but we still need some sort of end of test trigger on the receive */
2760     /* side. that could be a select with a one second timeout, but then */
2761     /* if there is a test where none of the data arrives for awile and */
2762     /* then starts again, we would end the test too soon. something to */
2763     /* think about... */
2764     while (!times_up) {
2765 
2766 #ifdef DIRTY
2767       /* we want to dirty some number of consecutive integers in the buffer */
2768       /* we are about to send. we may also want to bring some number of */
2769       /* them cleanly into the cache. The clean ones will follow any dirty */
2770       /* ones into the cache. */
2771 
2772       access_buffer(send_ring->buffer_ptr,
2773 		    send_size,
2774 		    loc_dirty_count,
2775 		    loc_clean_count);
2776 
2777 #endif /* DIRTY */
2778 
2779 #ifdef WANT_HISTOGRAM
2780       HIST_timestamp(&time_one);
2781 #endif /* WANT_HISTOGRAM */
2782 
2783       if ((t_sndudata(data_socket,
2784 		      &unitdata))  != 0) {
2785 	if (errno == EINTR)
2786 	  break;
2787 	if (errno == ENOBUFS) {
2788 	  failed_sends++;
2789 	  continue;
2790 	}
2791 	perror("xti_udp_send: data send error");
2792 	t_error("xti_udp_send: data send error");
2793 	exit(1);
2794       }
2795       messages_sent++;
2796 
2797       /* now we want to move our pointer to the next position in the */
2798       /* data buffer...and update the unitdata structure */
2799 
2800       send_ring          = send_ring->next;
2801       unitdata.udata.buf = send_ring->buffer_ptr;
2802 
2803 #ifdef WANT_HISTOGRAM
2804       /* get the second timestamp */
2805       HIST_timestamp(&time_two);
2806       HIST_add(time_hist,delta_micro(&time_one,&time_two));
2807 #endif /* WANT_HISTOGRAM */
2808 #ifdef WANT_INTERVALS
2809       if (demo_mode) {
2810 	units_this_tick += send_size;
2811       }
2812       /* in this case, the interval count is the count-down couter */
2813       /* to decide to sleep for a little bit */
2814       if ((interval_burst) && (--interval_count == 0)) {
2815 	/* call sigsuspend and wait for the interval timer to get us */
2816 	/* out */
2817 	if (debug) {
2818 	  fprintf(where,"about to suspend\n");
2819 	  fflush(where);
2820 	}
2821 	if (sigsuspend(&signal_set) == EFAULT) {
2822 	  fprintf(where,
2823 		  "send_xti_udp_stream: fault with signal set!\n");
2824 	  fflush(where);
2825 	  exit(1);
2826 	}
2827 	interval_count = interval_burst;
2828       }
2829 #endif /* WANT_INTERVALS */
2830 
2831     }
2832 
2833     /* This is a timed test, so the remote will be returning to us after */
2834     /* a time. We should not need to send any "strange" messages to tell */
2835     /* the remote that the test is completed, unless we decide to add a */
2836     /* number of messages to the test. */
2837 
2838     /* the test is over, so get stats and stuff */
2839     cpu_stop(local_cpu_usage,
2840 	     &elapsed_time);
2841 
2842     /* Get the statistics from the remote end	*/
2843     recv_response();
2844     if (!netperf_response.content.serv_errno) {
2845       if (debug)
2846 	fprintf(where,"send_xti_udp_stream: remote results obtained\n");
2847     }
2848     else {
2849       Set_errno(netperf_response.content.serv_errno);
2850       perror("send_xti_udp_stream: error on remote");
2851       exit(1);
2852     }
2853 
2854     bytes_sent    = (double) send_size * (double) messages_sent;
2855     local_thruput = calc_thruput(bytes_sent);
2856 
2857     messages_recvd = xti_udp_stream_results->messages_recvd;
2858     bytes_recvd    = (double) send_size * (double) messages_recvd;
2859 
2860     /* we asume that the remote ran for as long as we did */
2861 
2862     remote_thruput = calc_thruput(bytes_recvd);
2863 
2864     /* print the results for this socket and message size */
2865 
2866     if (local_cpu_usage || remote_cpu_usage) {
2867       /* We must now do a little math for service demand and cpu */
2868       /* utilization for the system(s) We pass zeros for the local */
2869       /* cpu utilization and elapsed time to tell the routine to use */
2870       /* the libraries own values for those. */
2871       if (local_cpu_usage) {
2872 	local_cpu_utilization	= calc_cpu_util(0.0);
2873 	/* shouldn't this really be based on bytes_recvd, since that is */
2874 	/* the effective throughput of the test? I think that it should, */
2875 	/* so will make the change raj 11/94 */
2876 	local_service_demand	= calc_service_demand(bytes_recvd,
2877 						      0.0,
2878 						      0.0,
2879 						      0);
2880       }
2881       else {
2882 	local_cpu_utilization	= -1.0;
2883 	local_service_demand	= -1.0;
2884       }
2885 
2886       /* The local calculations could use variables being kept by */
2887       /* the local netlib routines. The remote calcuations need to */
2888       /* have a few things passed to them. */
2889       if (remote_cpu_usage) {
2890 	remote_cpu_utilization	= xti_udp_stream_results->cpu_util;
2891 	remote_service_demand	= calc_service_demand(bytes_recvd,
2892 						      0.0,
2893 						      remote_cpu_utilization,
2894 						      xti_udp_stream_results->num_cpus);
2895       }
2896       else {
2897 	remote_cpu_utilization	= -1.0;
2898 	remote_service_demand	= -1.0;
2899       }
2900     }
2901     else {
2902       /* we were not measuring cpu, for the confidence stuff, we */
2903       /* should make it -1.0 */
2904       local_cpu_utilization  = -1.0;
2905       local_service_demand   = -1.0;
2906       remote_cpu_utilization = -1.0;
2907       remote_service_demand  = -1.0;
2908     }
2909 
2910     /* at this point, we want to calculate the confidence information. */
2911     /* if debugging is on, calculate_confidence will print-out the */
2912     /* parameters we pass it */
2913 
2914     calculate_confidence(confidence_iteration,
2915 			 elapsed_time,
2916 			 remote_thruput,
2917 			 local_cpu_utilization,
2918 			 remote_cpu_utilization,
2919 			 local_service_demand,
2920 			 remote_service_demand);
2921 
2922     /* since the routine calculate_confidence is rather generic, and */
2923     /* we have a few other parms of interest, we will do a little work */
2924     /* here to caclulate their average. */
2925     sum_messages_sent  += messages_sent;
2926     sum_messages_recvd += messages_recvd;
2927     sum_failed_sends   += failed_sends;
2928     sum_local_thruput  += local_thruput;
2929 
2930     confidence_iteration++;
2931 
2932     /* this datapoint is done, so we don't need the socket any longer */
2933     close(data_socket);
2934 
2935   }
2936 
2937   /* we should reach this point once the test is finished */
2938 
2939   retrieve_confident_values(&elapsed_time,
2940 			    &remote_thruput,
2941 			    &local_cpu_utilization,
2942 			    &remote_cpu_utilization,
2943 			    &local_service_demand,
2944 			    &remote_service_demand);
2945 
2946   /* some of the interesting values aren't covered by the generic */
2947   /* confidence routine */
2948   messages_sent    = sum_messages_sent / (confidence_iteration -1);
2949   messages_recvd   = sum_messages_recvd / (confidence_iteration -1);
2950   failed_sends     = sum_failed_sends / (confidence_iteration -1);
2951   local_thruput    = sum_local_thruput / (confidence_iteration -1);
2952 
2953   /* We are now ready to print all the information. If the user */
2954   /* has specified zero-level verbosity, we will just print the */
2955   /* local service demand, or the remote service demand. If the */
2956   /* user has requested verbosity level 1, he will get the basic */
2957   /* "streamperf" numbers. If the user has specified a verbosity */
2958   /* of greater than 1, we will display a veritable plethora of */
2959   /* background information from outside of this block as it it */
2960   /* not cpu_measurement specific...  */
2961 
2962 
2963   if (confidence < 0) {
2964     /* we did not hit confidence, but were we asked to look for it? */
2965     if (iteration_max > 1) {
2966       display_confidence();
2967     }
2968   }
2969 
2970   if (local_cpu_usage || remote_cpu_usage) {
2971     local_cpu_method = format_cpu_method(cpu_method);
2972     remote_cpu_method = format_cpu_method(xti_udp_stream_results->cpu_method);
2973 
2974     switch (verbosity) {
2975     case 0:
2976       if (local_cpu_usage) {
2977 	fprintf(where,
2978 		cpu_fmt_0,
2979 		local_service_demand,
2980 		local_cpu_method);
2981       }
2982       else {
2983 	fprintf(where,
2984 		cpu_fmt_0,
2985 		remote_service_demand,
2986 		local_cpu_method);
2987       }
2988       break;
2989     case 1:
2990     case 2:
2991       if (print_headers) {
2992 	fprintf(where,
2993 		cpu_title,
2994 		format_units(),
2995 		local_cpu_method,
2996 		remote_cpu_method);
2997       }
2998 
2999       fprintf(where,
3000 	      cpu_fmt_1,		/* the format string */
3001 	      lss_size,		        /* local sendbuf size */
3002 	      send_size,		/* how large were the sends */
3003 	      elapsed_time,		/* how long was the test */
3004 	      messages_sent,
3005 	      failed_sends,
3006 	      local_thruput, 		/* what was the xfer rate */
3007 	      local_cpu_utilization,	/* local cpu */
3008 	      local_service_demand,	/* local service demand */
3009 	      rsr_size,
3010 	      elapsed_time,
3011 	      messages_recvd,
3012 	      remote_thruput,
3013 	      remote_cpu_utilization,	/* remote cpu */
3014 	      remote_service_demand);	/* remote service demand */
3015       break;
3016     }
3017   }
3018   else {
3019     /* The tester did not wish to measure service demand. */
3020     switch (verbosity) {
3021     case 0:
3022       fprintf(where,
3023 	      tput_fmt_0,
3024 	      local_thruput);
3025       break;
3026     case 1:
3027     case 2:
3028       if (print_headers) {
3029 	fprintf(where,tput_title,format_units());
3030       }
3031       fprintf(where,
3032 	      tput_fmt_1,		/* the format string */
3033 	      lss_size, 		/* local sendbuf size */
3034 	      send_size,		/* how large were the sends */
3035 	      elapsed_time, 		/* how long did it take */
3036 	      messages_sent,
3037 	      failed_sends,
3038 	      local_thruput,
3039 	      rsr_size, 		/* remote recvbuf size */
3040 	      elapsed_time,
3041 	      messages_recvd,
3042 	      remote_thruput);
3043       break;
3044     }
3045   }
3046 
3047   fflush(where);
3048 #ifdef WANT_HISTOGRAM
3049   if (verbosity > 1) {
3050     fprintf(where,"\nHistogram of time spent in send() call\n");
3051     fflush(where);
3052     HIST_report(time_hist);
3053   }
3054 #endif /* WANT_HISTOGRAM */
3055 
3056 }
3057 
3058 
3059  /* this routine implements the receive side (netserver) of the */
3060  /* XTI_UDP_STREAM performance test. */
3061 
3062 void
recv_xti_udp_stream()3063 recv_xti_udp_stream()
3064 {
3065   struct ring_elt *recv_ring;
3066 
3067   struct t_bind bind_req, bind_resp;
3068   struct t_unitdata unitdata;
3069   int	            flags = 0;
3070 
3071   struct sockaddr_in myaddr_in;
3072   struct sockaddr_in fromaddr_in;
3073 
3074   SOCKET s_data;
3075   int 	addrlen;
3076   unsigned int	bytes_received = 0;
3077   float	elapsed_time;
3078 
3079   unsigned int	message_size;
3080   unsigned int	messages_recvd = 0;
3081 
3082   struct xti_udp_stream_request_struct	*xti_udp_stream_request;
3083   struct xti_udp_stream_response_struct	*xti_udp_stream_response;
3084   struct xti_udp_stream_results_struct	*xti_udp_stream_results;
3085 
3086   xti_udp_stream_request  =
3087     (struct xti_udp_stream_request_struct *)netperf_request.content.test_specific_data;
3088   xti_udp_stream_response =
3089     (struct xti_udp_stream_response_struct *)netperf_response.content.test_specific_data;
3090   xti_udp_stream_results  =
3091     (struct xti_udp_stream_results_struct *)netperf_response.content.test_specific_data;
3092 
3093   if (debug) {
3094     fprintf(where,"netserver: recv_xti_udp_stream: entered...\n");
3095     fflush(where);
3096   }
3097 
3098   /* We want to set-up the listen socket with all the desired */
3099   /* parameters and then let the initiator know that all is ready. If */
3100   /* socket size defaults are to be used, then the initiator will have */
3101   /* sent us 0's. If the socket sizes cannot be changed, then we will */
3102   /* send-back what they are. If that information cannot be determined, */
3103   /* then we send-back -1's for the sizes. If things go wrong for any */
3104   /* reason, we will drop back ten yards and punt. */
3105 
3106   /* If anything goes wrong, we want the remote to know about it. It */
3107   /* would be best if the error that the remote reports to the user is */
3108   /* the actual error we encountered, rather than some bogus unexpected */
3109   /* response type message. */
3110 
3111   if (debug > 1) {
3112     fprintf(where,"recv_xti_udp_stream: setting the response type...\n");
3113     fflush(where);
3114   }
3115 
3116   netperf_response.content.response_type = XTI_UDP_STREAM_RESPONSE;
3117 
3118   if (debug > 2) {
3119     fprintf(where,"recv_xti_udp_stream: the response type is set...\n");
3120     fflush(where);
3121   }
3122 
3123   /* We now alter the message_ptr variable to be at the desired */
3124   /* alignment with the desired offset. */
3125 
3126   if (debug > 1) {
3127     fprintf(where,"recv_xti_udp_stream: requested alignment of %d\n",
3128 	    xti_udp_stream_request->recv_alignment);
3129     fflush(where);
3130   }
3131 
3132   if (recv_width == 0) recv_width = 1;
3133 
3134   recv_ring = allocate_buffer_ring(recv_width,
3135 				   xti_udp_stream_request->message_size,
3136 				   xti_udp_stream_request->recv_alignment,
3137 				   xti_udp_stream_request->recv_offset);
3138 
3139   if (debug > 1) {
3140     fprintf(where,"recv_xti_udp_stream: receive alignment and offset set...\n");
3141     fflush(where);
3142   }
3143 
3144   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
3145   /* can put in OUR values !-) At some point, we may want to nail this */
3146   /* socket to a particular network-level address, but for now, */
3147   /* INADDR_ANY should be just fine. */
3148 
3149   bzero((char *)&myaddr_in,
3150 	sizeof(myaddr_in));
3151   myaddr_in.sin_family      = AF_INET;
3152   myaddr_in.sin_addr.s_addr = INADDR_ANY;
3153   myaddr_in.sin_port        = 0;
3154 
3155   /* Grab a socket to listen on, and then listen on it. */
3156 
3157   if (debug > 1) {
3158     fprintf(where,"recv_xti_udp_stream: grabbing a socket...\n");
3159     fflush(where);
3160   }
3161 
3162   /* create_xti_endpoint expects to find some things in the global */
3163   /* variables, so set the globals based on the values in the request. */
3164   /* once the socket has been created, we will set the response values */
3165   /* based on the updated value of those globals. raj 7/94 */
3166   lsr_size = xti_udp_stream_request->recv_buf_size;
3167   loc_rcvavoid = xti_udp_stream_request->so_rcvavoid;
3168   loc_sndavoid = xti_udp_stream_request->so_sndavoid;
3169 
3170 #ifdef __alpha
3171 
3172   /* ok - even on a DEC box, strings are strings. I din't really want */
3173   /* to ntohl the words of a string. since I don't want to teach the */
3174   /* send_ and recv_ _request and _response routines about the types, */
3175   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
3176   /* solution would be to use XDR, but I am still leary of being able */
3177   /* to find XDR libs on all platforms I want running netperf. raj */
3178   {
3179     int *charword;
3180     int *initword;
3181     int *lastword;
3182 
3183     initword = (int *) xti_udp_stream_request->xti_device;
3184     lastword = initword + ((xti_udp_stream_request->dev_name_len + 3) / 4);
3185 
3186     for (charword = initword;
3187 	 charword < lastword;
3188 	 charword++) {
3189 
3190       *charword = htonl(*charword);
3191     }
3192   }
3193 
3194 #endif /* __alpha */
3195 
3196   s_data = create_xti_endpoint(xti_udp_stream_request->xti_device);
3197 
3198   if (s_data == INVALID_SOCKET) {
3199     netperf_response.content.serv_errno = errno;
3200     send_response();
3201     exit(1);
3202   }
3203 
3204   /* Let's get an address assigned to this socket so we can tell the */
3205   /* initiator how to reach the data socket. There may be a desire to */
3206   /* nail this socket to a specific IP address in a multi-homed, */
3207   /* multi-connection situation, but for now, we'll ignore the issue */
3208   /* and concentrate on single connection testing. */
3209 
3210   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
3211   bind_req.addr.len    = sizeof(struct sockaddr_in);
3212   bind_req.addr.buf    = (char *)&myaddr_in;
3213   bind_req.qlen        = 1;
3214 
3215   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
3216   bind_resp.addr.len    = sizeof(struct sockaddr_in);
3217   bind_resp.addr.buf    = (char *)&myaddr_in;
3218   bind_resp.qlen        = 1;
3219 
3220   if (t_bind(s_data,
3221 	     &bind_req,
3222 	     &bind_resp) == SOCKET_ERROR) {
3223     netperf_response.content.serv_errno = t_errno;
3224     send_response();
3225 
3226     exit(1);
3227   }
3228 
3229   xti_udp_stream_response->test_length =
3230     xti_udp_stream_request->test_length;
3231 
3232   /* Now myaddr_in contains the port and the internet address this is */
3233   /* returned to the sender also implicitly telling the sender that the */
3234   /* socket buffer sizing has been done. */
3235 
3236   xti_udp_stream_response->data_port_number =
3237     (int) ntohs(myaddr_in.sin_port);
3238   netperf_response.content.serv_errno   = 0;
3239 
3240   /* But wait, there's more. If the initiator wanted cpu measurements, */
3241   /* then we must call the calibrate routine, which will return the max */
3242   /* rate back to the initiator. If the CPU was not to be measured, or */
3243   /* something went wrong with the calibration, we will return a -1 to */
3244   /* the initiator. */
3245 
3246   xti_udp_stream_response->cpu_rate    = 0.0; /* assume no cpu */
3247   xti_udp_stream_response->measure_cpu = 0;
3248   if (xti_udp_stream_request->measure_cpu) {
3249     /* We will pass the rate into the calibration routine. If the */
3250     /* user did not specify one, it will be 0.0, and we will do a */
3251     /* "real" calibration. Otherwise, all it will really do is */
3252     /* store it away... */
3253     xti_udp_stream_response->measure_cpu = 1;
3254     xti_udp_stream_response->cpu_rate =
3255       calibrate_local_cpu(xti_udp_stream_request->cpu_rate);
3256   }
3257 
3258   message_size	= xti_udp_stream_request->message_size;
3259   test_time	= xti_udp_stream_request->test_length;
3260 
3261   /* before we send the response back to the initiator, pull some of */
3262   /* the socket parms from the globals */
3263   xti_udp_stream_response->send_buf_size = lss_size;
3264   xti_udp_stream_response->recv_buf_size = lsr_size;
3265   xti_udp_stream_response->so_rcvavoid = loc_rcvavoid;
3266   xti_udp_stream_response->so_sndavoid = loc_sndavoid;
3267 
3268   /* since we are going to call t_rcvudata() instead of t_rcv() we */
3269   /* need to init the unitdata structure raj 3/95 */
3270 
3271   unitdata.addr.maxlen = sizeof(fromaddr_in);
3272   unitdata.addr.len    = sizeof(fromaddr_in);
3273   unitdata.addr.buf    = (char *)&fromaddr_in;
3274 
3275   unitdata.opt.maxlen = 0;
3276   unitdata.opt.len    = 0;
3277   unitdata.opt.buf    = NULL;
3278 
3279   unitdata.udata.maxlen = xti_udp_stream_request->message_size;
3280   unitdata.udata.len    = xti_udp_stream_request->message_size;
3281   unitdata.udata.buf    = recv_ring->buffer_ptr;
3282 
3283   send_response();
3284 
3285   /* Now it's time to start receiving data on the connection. We will */
3286   /* first grab the apropriate counters and then start grabbing. */
3287 
3288   cpu_start(xti_udp_stream_request->measure_cpu);
3289 
3290   /* The loop will exit when the timer pops, or if we happen to recv a */
3291   /* message of less than send_size bytes... */
3292 
3293   times_up = 0;
3294   start_timer(test_time + PAD_TIME);
3295 
3296   if (debug) {
3297     fprintf(where,"recv_xti_udp_stream: about to enter inner sanctum.\n");
3298     fflush(where);
3299   }
3300 
3301   while (!times_up) {
3302 #ifdef RAJ_DEBUG
3303     if (debug) {
3304       fprintf(where,"t_rcvudata, errno %d, t_errno %d",
3305 	      errno,
3306 	      t_errno);
3307       fprintf(where," after %d messages\n",messages_recvd);
3308       fprintf(where,"addrmax %d addrlen %d addrbuf %x\n",
3309 	      unitdata.addr.maxlen,
3310 	      unitdata.addr.len,
3311 	      unitdata.addr.buf);
3312       fprintf(where,"optmax %d optlen %d optbuf %x\n",
3313 	      unitdata.opt.maxlen,
3314 	      unitdata.opt.len,
3315 	      unitdata.opt.buf);
3316       fprintf(where,"udatamax %d udatalen %d udatabuf %x\n",
3317 	      unitdata.udata.maxlen,
3318 	      unitdata.udata.len,
3319 	      unitdata.udata.buf);
3320       fflush(where);
3321     }
3322 #endif /* RAJ_DEBUG */
3323     if (t_rcvudata(s_data,
3324 		   &unitdata,
3325 		   &flags) != 0) {
3326       if (errno == TNODATA) {
3327 	continue;
3328       }
3329       if (errno != EINTR) {
3330 	netperf_response.content.serv_errno = t_errno;
3331 	send_response();
3332 	exit(1);
3333       }
3334       break;
3335     }
3336     messages_recvd++;
3337     recv_ring = recv_ring->next;
3338     unitdata.udata.buf = recv_ring->buffer_ptr;
3339   }
3340 
3341   if (debug) {
3342     fprintf(where,"recv_xti_udp_stream: got %d messages.\n",messages_recvd);
3343     fflush(where);
3344   }
3345 
3346 
3347   /* The loop now exits due timer or < send_size bytes received. */
3348 
3349   cpu_stop(xti_udp_stream_request->measure_cpu,&elapsed_time);
3350 
3351   if (times_up) {
3352     /* we ended on a timer, subtract the PAD_TIME */
3353     elapsed_time -= (float)PAD_TIME;
3354   }
3355   else {
3356     stop_timer();
3357   }
3358 
3359   if (debug) {
3360     fprintf(where,"recv_xti_udp_stream: test ended in %f seconds.\n",elapsed_time);
3361     fflush(where);
3362   }
3363 
3364   bytes_received = (messages_recvd * message_size);
3365 
3366   /* send the results to the sender			*/
3367 
3368   if (debug) {
3369     fprintf(where,
3370 	    "recv_xti_udp_stream: got %d bytes\n",
3371 	    bytes_received);
3372     fflush(where);
3373   }
3374 
3375   netperf_response.content.response_type	= XTI_UDP_STREAM_RESULTS;
3376   xti_udp_stream_results->bytes_received	= bytes_received;
3377   xti_udp_stream_results->messages_recvd	= messages_recvd;
3378   xti_udp_stream_results->elapsed_time	= elapsed_time;
3379   xti_udp_stream_results->cpu_method        = cpu_method;
3380   if (xti_udp_stream_request->measure_cpu) {
3381     xti_udp_stream_results->cpu_util	= calc_cpu_util(elapsed_time);
3382   }
3383   else {
3384     xti_udp_stream_results->cpu_util	= -1.0;
3385   }
3386 
3387   if (debug > 1) {
3388     fprintf(where,
3389 	    "recv_xti_udp_stream: test complete, sending results.\n");
3390     fflush(where);
3391   }
3392 
3393   send_response();
3394 
3395 }
3396 
send_xti_udp_rr(char remote_host[])3397 void send_xti_udp_rr(char remote_host[])
3398 {
3399 
3400   char *tput_title = "\
3401 Local /Remote\n\
3402 Socket Size   Request  Resp.   Elapsed  Trans.\n\
3403 Send   Recv   Size     Size    Time     Rate         \n\
3404 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
3405 
3406   char *tput_fmt_0 =
3407     "%7.2f\n";
3408 
3409   char *tput_fmt_1_line_1 = "\
3410 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
3411   char *tput_fmt_1_line_2 = "\
3412 %-6d %-6d\n";
3413 
3414   char *cpu_title = "\
3415 Local /Remote\n\
3416 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
3417 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
3418 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
3419 
3420   char *cpu_fmt_0 =
3421     "%6.3f %c\n";
3422 
3423   char *cpu_fmt_1_line_1 = "\
3424 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
3425 
3426   char *cpu_fmt_1_line_2 = "\
3427 %-6d %-6d\n";
3428 
3429   char *ksink_fmt = "\
3430 Alignment      Offset\n\
3431 Local  Remote  Local  Remote\n\
3432 Send   Recv    Send   Recv\n\
3433 %5d  %5d   %5d  %5d\n";
3434 
3435 
3436   float			elapsed_time;
3437 
3438   struct ring_elt *send_ring;
3439   struct ring_elt *recv_ring;
3440 
3441   struct t_bind bind_req, bind_resp;
3442   struct t_unitdata unitdata;
3443   struct t_unitdata send_unitdata;
3444   struct t_unitdata recv_unitdata;
3445   int	            flags = 0;
3446 
3447   int	len;
3448   int	nummessages;
3449   SOCKET send_socket;
3450   int	trans_remaining;
3451   int	bytes_xferd;
3452 
3453   int	rsp_bytes_recvd;
3454 
3455   float	local_cpu_utilization;
3456   float	local_service_demand;
3457   float	remote_cpu_utilization;
3458   float	remote_service_demand;
3459   double thruput;
3460 
3461   struct	hostent	        *hp;
3462   struct	sockaddr_in	server, myaddr_in;
3463   unsigned      int             addr;
3464   int	                        addrlen;
3465 
3466   struct	xti_udp_rr_request_struct	*xti_udp_rr_request;
3467   struct	xti_udp_rr_response_struct	*xti_udp_rr_response;
3468   struct	xti_udp_rr_results_struct	*xti_udp_rr_result;
3469 
3470 #ifdef WANT_INTERVALS
3471   int	interval_count;
3472   sigset_t signal_set;
3473 #endif /* WANT_INTERVALS */
3474 
3475   xti_udp_rr_request  =
3476     (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
3477   xti_udp_rr_response =
3478     (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
3479   xti_udp_rr_result	 =
3480     (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
3481 
3482 #ifdef WANT_HISTOGRAM
3483   time_hist = HIST_new();
3484 #endif
3485 
3486   /* since we are now disconnected from the code that established the */
3487   /* control socket, and since we want to be able to use different */
3488   /* protocols and such, we are passed the name of the remote host and */
3489   /* must turn that into the test specific addressing information. */
3490 
3491   bzero((char *)&server,
3492 	sizeof(server));
3493 
3494   /* it would seem that while HP-UX will allow an IP address (as a */
3495   /* string) in a call to gethostbyname, other, less enlightened */
3496   /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
3497   /* order changed to check for IP address first. raj 7/96 */
3498 
3499   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
3500     /* it was not an IP address, try it as a name */
3501     if ((hp = gethostbyname(remote_host)) == NULL) {
3502       /* we have no idea what it is */
3503       fprintf(where,
3504 	      "establish_control: could not resolve the destination %s\n",
3505 	      remote_host);
3506       fflush(where);
3507       exit(1);
3508     }
3509     else {
3510       /* it was a valid remote_host */
3511       bcopy(hp->h_addr,
3512 	    (char *)&server.sin_addr,
3513 	    hp->h_length);
3514       server.sin_family = hp->h_addrtype;
3515     }
3516   }
3517   else {
3518     /* it was a valid IP address */
3519     server.sin_addr.s_addr = addr;
3520     server.sin_family = AF_INET;
3521   }
3522 
3523   if ( print_headers ) {
3524     fprintf(where,"XTI UDP REQUEST/RESPONSE TEST");
3525         fprintf(where," to %s", remote_host);
3526     if (iteration_max > 1) {
3527       fprintf(where,
3528 	      " : +/-%3.1f%% @ %2d%% conf.",
3529 	      interval/0.02,
3530 	      confidence_level);
3531       }
3532     if (loc_sndavoid ||
3533 	loc_rcvavoid ||
3534 	rem_sndavoid ||
3535 	rem_rcvavoid) {
3536       fprintf(where," : copy avoidance");
3537     }
3538 #ifdef WANT_HISTOGRAM
3539     fprintf(where," : histogram");
3540 #endif /* WANT_HISTOGRAM */
3541 #ifdef WANT_INTERVALS
3542     fprintf(where," : interval");
3543 #endif /* WANT_INTERVALS */
3544 #ifdef DIRTY
3545     fprintf(where," : dirty data");
3546 #endif /* DIRTY */
3547     fprintf(where,"\n");
3548   }
3549 
3550   /* initialize a few counters */
3551 
3552   send_ring     = NULL;
3553   recv_ring     = NULL;
3554   nummessages	= 0;
3555   bytes_xferd	= 0;
3556   times_up 	= 0;
3557   confidence_iteration = 1;
3558   init_stat();
3559 
3560 
3561   /* we have a great-big while loop which controls the number of times */
3562   /* we run a particular test. this is for the calculation of a */
3563   /* confidence interval (I really should have stayed awake during */
3564   /* probstats :). If the user did not request confidence measurement */
3565   /* (no confidence is the default) then we will only go though the */
3566   /* loop once. the confidence stuff originates from the folks at IBM */
3567 
3568   while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
3569 	 (confidence_iteration <= iteration_min)) {
3570 
3571     nummessages     = 0;
3572     bytes_xferd     = 0.0;
3573     times_up        = 0;
3574     trans_remaining = 0;
3575 
3576     /* set-up the data buffers with the requested alignment and offset */
3577 
3578     if (send_width == 0) send_width = 1;
3579     if (recv_width == 0) recv_width = 1;
3580 
3581     if (send_ring == NULL) {
3582       send_ring = allocate_buffer_ring(send_width,
3583 				       req_size,
3584 				       local_send_align,
3585 				       local_send_offset);
3586     }
3587 
3588     if (recv_ring == NULL) {
3589       recv_ring = allocate_buffer_ring(recv_width,
3590 				       rsp_size,
3591 				       local_recv_align,
3592 				       local_recv_offset);
3593     }
3594 
3595   /* since we are going to call t_rcvudata() instead of t_rcv() we */
3596   /* need to init the unitdata structure raj 8/95 */
3597 
3598     memset (&recv_unitdata, 0, sizeof(recv_unitdata));
3599     recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
3600     recv_unitdata.addr.len    = sizeof(struct sockaddr_in);
3601     recv_unitdata.addr.buf    = (char *)&server;
3602 
3603     recv_unitdata.opt.maxlen = 0;
3604     recv_unitdata.opt.len    = 0;
3605     recv_unitdata.opt.buf    = NULL;
3606 
3607     recv_unitdata.udata.maxlen = rsp_size;
3608     recv_unitdata.udata.len    = rsp_size;
3609     recv_unitdata.udata.buf    = recv_ring->buffer_ptr;
3610 
3611     /* since we are going to call t_sndudata() instead of t_snd() we */
3612     /* need to init the unitdata structure raj 8/95 */
3613 
3614     memset (&send_unitdata, 0, sizeof(send_unitdata));
3615     send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
3616     send_unitdata.addr.len    = sizeof(struct sockaddr_in);
3617     send_unitdata.addr.buf    = (char *)&server;
3618 
3619     send_unitdata.opt.maxlen = 0;
3620     send_unitdata.opt.len    = 0;
3621     send_unitdata.opt.buf    = NULL;
3622 
3623     send_unitdata.udata.maxlen = req_size;
3624     send_unitdata.udata.len    = req_size;
3625     send_unitdata.udata.buf    = send_ring->buffer_ptr;
3626 
3627     /*set up the data socket                        */
3628     send_socket = create_xti_endpoint(loc_xti_device);
3629 
3630     if (send_socket == INVALID_SOCKET){
3631       perror("netperf: send_xti_udp_rr: udp rr data socket");
3632       exit(1);
3633     }
3634 
3635     if (debug) {
3636       fprintf(where,"send_xti_udp_rr: send_socket obtained...\n");
3637     }
3638 
3639     /* it would seem that with XTI, there is no implicit bind  */
3640     /* so we have to make a call to t_bind. this is not */
3641     /* terribly convenient, but I suppose that "standard is better */
3642     /* than better" :) raj 2/95 */
3643 
3644     if (t_bind(send_socket, NULL, NULL) == SOCKET_ERROR) {
3645       t_error("send_xti_tcp_stream: t_bind");
3646       exit(1);
3647     }
3648 
3649     /* If the user has requested cpu utilization measurements, we must */
3650     /* calibrate the cpu(s). We will perform this task within the tests */
3651     /* themselves. If the user has specified the cpu rate, then */
3652     /* calibrate_local_cpu will return rather quickly as it will have */
3653     /* nothing to do. If local_cpu_rate is zero, then we will go through */
3654     /* all the "normal" calibration stuff and return the rate back. If */
3655     /* there is no idle counter in the kernel idle loop, the */
3656     /* local_cpu_rate will be set to -1. */
3657 
3658     if (local_cpu_usage) {
3659       local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3660     }
3661 
3662     /* Tell the remote end to do a listen. The server alters the socket */
3663     /* paramters on the other side at this point, hence the reason for */
3664     /* all the values being passed in the setup message. If the user did */
3665     /* not specify any of the parameters, they will be passed as 0, which */
3666     /* will indicate to the remote that no changes beyond the system's */
3667     /* default should be used. Alignment is the exception, it will */
3668     /* default to 8, which will be no alignment alterations. */
3669 
3670     netperf_request.content.request_type	= DO_XTI_UDP_RR;
3671     xti_udp_rr_request->recv_buf_size	= rsr_size;
3672     xti_udp_rr_request->send_buf_size	= rss_size;
3673     xti_udp_rr_request->recv_alignment  = remote_recv_align;
3674     xti_udp_rr_request->recv_offset	= remote_recv_offset;
3675     xti_udp_rr_request->send_alignment  = remote_send_align;
3676     xti_udp_rr_request->send_offset	= remote_send_offset;
3677     xti_udp_rr_request->request_size	= req_size;
3678     xti_udp_rr_request->response_size	= rsp_size;
3679     xti_udp_rr_request->measure_cpu	= remote_cpu_usage;
3680     xti_udp_rr_request->cpu_rate	= remote_cpu_rate;
3681     xti_udp_rr_request->so_rcvavoid	= rem_rcvavoid;
3682     xti_udp_rr_request->so_sndavoid	= rem_sndavoid;
3683     if (test_time) {
3684       xti_udp_rr_request->test_length	= test_time;
3685     }
3686     else {
3687       xti_udp_rr_request->test_length	= test_trans * -1;
3688     }
3689 
3690     strcpy(xti_udp_rr_request->xti_device, rem_xti_device);
3691 
3692 #ifdef __alpha
3693 
3694     /* ok - even on a DEC box, strings are strings. I didn't really want */
3695     /* to ntohl the words of a string. since I don't want to teach the */
3696     /* send_ and recv_ _request and _response routines about the types, */
3697     /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
3698     /* solution would be to use XDR, but I am still leary of being able */
3699     /* to find XDR libs on all platforms I want running netperf. raj */
3700     {
3701       int *charword;
3702       int *initword;
3703       int *lastword;
3704 
3705       initword = (int *) xti_udp_rr_request->xti_device;
3706       lastword = initword + ((strlen(rem_xti_device) + 3) / 4);
3707 
3708       for (charword = initword;
3709 	   charword < lastword;
3710 	   charword++) {
3711 
3712 	*charword = ntohl(*charword);
3713       }
3714     }
3715 #endif /* __alpha */
3716 
3717     if (debug > 1) {
3718       fprintf(where,"netperf: send_xti_udp_rr: requesting UDP r/r test\n");
3719     }
3720 
3721     send_request();
3722 
3723     /* The response from the remote will contain all of the relevant 	*/
3724     /* socket parameters for this test type. We will put them back into */
3725     /* the variables here so they can be displayed if desired.  The	*/
3726     /* remote will have calibrated CPU if necessary, and will have done	*/
3727     /* all the needed set-up we will have calibrated the cpu locally	*/
3728     /* before sending the request, and will grab the counter value right*/
3729     /* after the connect returns. The remote will grab the counter right*/
3730     /* after the accept call. This saves the hassle of extra messages	*/
3731     /* being sent for the UDP tests.					*/
3732 
3733     recv_response();
3734 
3735     if (!netperf_response.content.serv_errno) {
3736       if (debug)
3737 	fprintf(where,"remote listen done.\n");
3738       rsr_size	       =	xti_udp_rr_response->recv_buf_size;
3739       rss_size	       =	xti_udp_rr_response->send_buf_size;
3740       remote_cpu_usage =	xti_udp_rr_response->measure_cpu;
3741       remote_cpu_rate  = 	xti_udp_rr_response->cpu_rate;
3742       /* port numbers in proper order */
3743       server.sin_port  =	(short)xti_udp_rr_response->data_port_number;
3744       server.sin_port  = 	htons(server.sin_port);
3745     }
3746     else {
3747       Set_errno(netperf_response.content.serv_errno);
3748       perror("netperf: remote error");
3749 
3750       exit(1);
3751     }
3752 
3753     /* Data Socket set-up is finished. If there were problems, either the */
3754     /* connect would have failed, or the previous response would have */
3755     /* indicated a problem. I failed to see the value of the extra */
3756     /* message after the accept on the remote. If it failed, we'll see it */
3757     /* here. If it didn't, we might as well start pumping data. */
3758 
3759     /* Set-up the test end conditions. For a request/response test, they */
3760     /* can be either time or transaction based. */
3761 
3762     if (test_time) {
3763       /* The user wanted to end the test after a period of time. */
3764       times_up = 0;
3765       trans_remaining = 0;
3766       start_timer(test_time);
3767     }
3768     else {
3769       /* The tester wanted to send a number of bytes. */
3770       trans_remaining = test_bytes;
3771       times_up = 1;
3772     }
3773 
3774     /* The cpu_start routine will grab the current time and possibly */
3775     /* value of the idle counter for later use in measuring cpu */
3776     /* utilization and/or service demand and thruput. */
3777 
3778     cpu_start(local_cpu_usage);
3779 
3780 #ifdef WANT_INTERVALS
3781     if ((interval_burst) || (demo_mode)) {
3782       /* zero means that we never pause, so we never should need the */
3783       /* interval timer, unless we are in demo_mode */
3784       start_itimer(interval_wate);
3785     }
3786     interval_count = interval_burst;
3787     /* get the signal set for the call to sigsuspend */
3788     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
3789       fprintf(where,
3790 	      "send_xti_udp_rr: unable to get sigmask errno %d\n",
3791 	      errno);
3792       fflush(where);
3793       exit(1);
3794     }
3795 #endif /* WANT_INTERVALS */
3796 
3797     /* We use an "OR" to control test execution. When the test is */
3798     /* controlled by time, the byte count check will always return */
3799     /* false. When the test is controlled by byte count, the time test */
3800     /* will always return false. When the test is finished, the whole */
3801     /* expression will go false and we will stop sending data. I think */
3802     /* I just arbitrarily decrement trans_remaining for the timed */
3803     /* test, but will not do that just yet... One other question is */
3804     /* whether or not the send buffer and the receive buffer should be */
3805     /* the same buffer. */
3806 
3807     while ((!times_up) || (trans_remaining > 0)) {
3808       /* send the request */
3809 #ifdef WANT_HISTOGRAM
3810       HIST_timestamp(&time_one);
3811 #endif
3812       if((t_sndudata(send_socket,
3813 		     &send_unitdata)) != 0) {
3814 	if (errno == EINTR) {
3815 	  /* We likely hit */
3816 	  /* test-end time. */
3817 	  break;
3818 	}
3819         fprintf(where,
3820 		"send_xti_udp_rr: t_sndudata: errno %d t_errno %d t_look 0x%.4x\n",
3821 		errno,
3822 		t_errno,
3823 		t_look(send_socket));
3824 	fflush(where);
3825 	exit(1);
3826       }
3827       send_ring = send_ring->next;
3828 
3829       /* receive the response. with UDP we will get it all, or nothing */
3830 
3831       if((t_rcvudata(send_socket,
3832 		     &recv_unitdata,
3833 		     &flags)) != 0) {
3834 	if (errno == TNODATA) {
3835 	  continue;
3836 	}
3837 	if (errno == EINTR) {
3838 	  /* Again, we have likely hit test-end time */
3839 	  break;
3840 	}
3841 	fprintf(where,
3842 		"send_xti_udp_rr: t_rcvudata: errno %d t_errno %d t_look 0x%x\n",
3843 		errno,
3844 		t_errno,
3845 		t_look(send_socket));
3846 	fprintf(where,
3847 		"recv_unitdata.udata.buf %x\n",recv_unitdata.udata.buf);
3848 	fprintf(where,
3849 		"recv_unitdata.udata.maxlen %x\n",recv_unitdata.udata.maxlen);
3850 	fprintf(where,
3851 		"recv_unitdata.udata.len %x\n",recv_unitdata.udata.len);
3852 	fprintf(where,
3853 		"recv_unitdata.addr.buf %x\n",recv_unitdata.addr.buf);
3854 	fprintf(where,
3855 		"recv_unitdata.addr.maxlen %x\n",recv_unitdata.addr.maxlen);
3856 	fprintf(where,
3857 		"recv_unitdata.addr.len %x\n",recv_unitdata.addr.len);
3858 	fflush(where);
3859 	exit(1);
3860       }
3861       recv_ring = recv_ring->next;
3862 
3863 #ifdef WANT_HISTOGRAM
3864       HIST_timestamp(&time_two);
3865       HIST_add(time_hist,delta_micro(&time_one,&time_two));
3866 
3867       /* at this point, we may wish to sleep for some period of */
3868       /* time, so we see how long that last transaction just took, */
3869       /* and sleep for the difference of that and the interval. We */
3870       /* will not sleep if the time would be less than a */
3871       /* millisecond.  */
3872 #endif
3873 #ifdef WANT_INTERVALS
3874       if (demo_mode) {
3875 	units_this_tick += 1;
3876       }
3877       /* in this case, the interval count is the count-down couter */
3878       /* to decide to sleep for a little bit */
3879       if ((interval_burst) && (--interval_count == 0)) {
3880 	/* call sigsuspend and wait for the interval timer to get us */
3881 	/* out */
3882 	if (debug) {
3883 	  fprintf(where,"about to suspend\n");
3884 	  fflush(where);
3885 	}
3886 	if (sigsuspend(&signal_set) == EFAULT) {
3887 	  fprintf(where,
3888 		  "send_xti_udp_rr: fault with signal set!\n");
3889 	  fflush(where);
3890 	  exit(1);
3891 	}
3892 	interval_count = interval_burst;
3893       }
3894 #endif /* WANT_INTERVALS */
3895 
3896       nummessages++;
3897       if (trans_remaining) {
3898 	trans_remaining--;
3899       }
3900 
3901       if (debug > 3) {
3902 	if ((nummessages % 100) == 0) {
3903 	  fprintf(where,"Transaction %d completed\n",nummessages);
3904 	  fflush(where);
3905 	}
3906       }
3907 
3908     }
3909 
3910     /* this call will always give us the elapsed time for the test, and */
3911     /* will also store-away the necessaries for cpu utilization */
3912 
3913     cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
3914 						/* measured? how long */
3915 						/* did we really run? */
3916 
3917     /* Get the statistics from the remote end. The remote will have */
3918     /* calculated service demand and all those interesting things. If */
3919     /* it wasn't supposed to care, it will return obvious values. */
3920 
3921     recv_response();
3922     if (!netperf_response.content.serv_errno) {
3923       if (debug)
3924 	fprintf(where,"remote results obtained\n");
3925     }
3926     else {
3927       Set_errno(netperf_response.content.serv_errno);
3928       perror("netperf: remote error");
3929 
3930       exit(1);
3931     }
3932 
3933     /* We now calculate what our thruput was for the test. In the */
3934     /* future, we may want to include a calculation of the thruput */
3935     /* measured by the remote, but it should be the case that for a */
3936     /* UDP rr test, that the two numbers should be *very* close... */
3937     /* We calculate bytes_sent regardless of the way the test length */
3938     /* was controlled.  */
3939 
3940     bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
3941     thruput	= nummessages / elapsed_time;
3942 
3943     if (local_cpu_usage || remote_cpu_usage) {
3944 
3945       /* We must now do a little math for service demand and cpu */
3946       /* utilization for the system(s) Of course, some of the */
3947       /* information might be bogus because there was no idle counter */
3948       /* in the kernel(s). We need to make a note of this for the */
3949       /* user's benefit by placing a code for the metod used in the */
3950       /* test banner */
3951 
3952       if (local_cpu_usage) {
3953 	local_cpu_utilization = calc_cpu_util(0.0);
3954 
3955 	/* since calc_service demand is doing ms/Kunit we will */
3956 	/* multiply the number of transaction by 1024 to get */
3957 	/* "good" numbers */
3958 
3959 	local_service_demand  = calc_service_demand((double) nummessages*1024,
3960 						    0.0,
3961 						    0.0,
3962 						    0);
3963       }
3964       else {
3965 	local_cpu_utilization	= -1.0;
3966 	local_service_demand	= -1.0;
3967       }
3968 
3969       if (remote_cpu_usage) {
3970 	remote_cpu_utilization = xti_udp_rr_result->cpu_util;
3971 
3972 	/* since calc_service demand is doing ms/Kunit we will */
3973 	/* multiply the number of transaction by 1024 to get */
3974 	/* "good" numbers */
3975 
3976 	remote_service_demand  = calc_service_demand((double) nummessages*1024,
3977 						     0.0,
3978 						     remote_cpu_utilization,
3979 						     xti_udp_rr_result->num_cpus);
3980       }
3981       else {
3982 	remote_cpu_utilization = -1.0;
3983 	remote_service_demand  = -1.0;
3984       }
3985     }
3986     else {
3987       /* we were not measuring cpu, for the confidence stuff, we */
3988       /* should make it -1.0 */
3989       local_cpu_utilization	= -1.0;
3990       local_service_demand	= -1.0;
3991       remote_cpu_utilization = -1.0;
3992       remote_service_demand  = -1.0;
3993     }
3994 
3995     /* at this point, we want to calculate the confidence information. */
3996     /* if debugging is on, calculate_confidence will print-out the */
3997     /* parameters we pass it */
3998 
3999     calculate_confidence(confidence_iteration,
4000 			 elapsed_time,
4001 			 thruput,
4002 			 local_cpu_utilization,
4003 			 remote_cpu_utilization,
4004 			 local_service_demand,
4005 			 remote_service_demand);
4006 
4007 
4008     confidence_iteration++;
4009 
4010     /* we are done with the socket */
4011     t_close(send_socket);
4012   }
4013 
4014   /* at this point, we have made all the iterations we are going to */
4015   /* make. */
4016   retrieve_confident_values(&elapsed_time,
4017 			    &thruput,
4018 			    &local_cpu_utilization,
4019 			    &remote_cpu_utilization,
4020 			    &local_service_demand,
4021 			    &remote_service_demand);
4022 
4023   /* We are now ready to print all the information. If the user */
4024   /* has specified zero-level verbosity, we will just print the */
4025   /* local service demand, or the remote service demand. If the */
4026   /* user has requested verbosity level 1, he will get the basic */
4027   /* "streamperf" numbers. If the user has specified a verbosity */
4028   /* of greater than 1, we will display a veritable plethora of */
4029   /* background information from outside of this block as it it */
4030   /* not cpu_measurement specific...  */
4031 
4032   if (confidence < 0) {
4033     /* we did not hit confidence, but were we asked to look for it? */
4034     if (iteration_max > 1) {
4035       display_confidence();
4036     }
4037   }
4038 
4039   if (local_cpu_usage || remote_cpu_usage) {
4040     local_cpu_method = format_cpu_method(cpu_method);
4041     remote_cpu_method = format_cpu_method(xti_udp_rr_result->cpu_method);
4042 
4043     switch (verbosity) {
4044     case 0:
4045       if (local_cpu_usage) {
4046 	fprintf(where,
4047 		cpu_fmt_0,
4048 		local_service_demand,
4049 		local_cpu_method);
4050       }
4051       else {
4052 	fprintf(where,
4053 		cpu_fmt_0,
4054 		remote_service_demand,
4055 		remote_cpu_method);
4056       }
4057       break;
4058     case 1:
4059     case 2:
4060       if (print_headers) {
4061 	fprintf(where,
4062 		cpu_title,
4063 		local_cpu_method,
4064 		remote_cpu_method);
4065       }
4066 
4067       fprintf(where,
4068 	      cpu_fmt_1_line_1,		/* the format string */
4069 	      lss_size,		/* local sendbuf size */
4070 	      lsr_size,
4071 	      req_size,		/* how large were the requests */
4072 	      rsp_size,		/* guess */
4073 	      elapsed_time,		/* how long was the test */
4074 	      nummessages/elapsed_time,
4075 	      local_cpu_utilization,	/* local cpu */
4076 	      remote_cpu_utilization,	/* remote cpu */
4077 	      local_service_demand,	/* local service demand */
4078 	      remote_service_demand);	/* remote service demand */
4079       fprintf(where,
4080 	      cpu_fmt_1_line_2,
4081 	      rss_size,
4082 	      rsr_size);
4083       break;
4084     }
4085   }
4086   else {
4087     /* The tester did not wish to measure service demand. */
4088     switch (verbosity) {
4089     case 0:
4090       fprintf(where,
4091 	      tput_fmt_0,
4092 	      nummessages/elapsed_time);
4093       break;
4094     case 1:
4095     case 2:
4096       if (print_headers) {
4097 	fprintf(where,tput_title,format_units());
4098       }
4099 
4100       fprintf(where,
4101 	      tput_fmt_1_line_1,	/* the format string */
4102 	      lss_size,
4103 	      lsr_size,
4104 	      req_size,		/* how large were the requests */
4105 	      rsp_size,		/* how large were the responses */
4106 	      elapsed_time, 		/* how long did it take */
4107 	      nummessages/elapsed_time);
4108       fprintf(where,
4109 	      tput_fmt_1_line_2,
4110 	      rss_size, 		/* remote recvbuf size */
4111 	      rsr_size);
4112 
4113       break;
4114     }
4115   }
4116   fflush(where);
4117 
4118   /* it would be a good thing to include information about some of the */
4119   /* other parameters that may have been set for this test, but at the */
4120   /* moment, I do not wish to figure-out all the  formatting, so I will */
4121   /* just put this comment here to help remind me that it is something */
4122   /* that should be done at a later time. */
4123 
4124   /* how to handle the verbose information in the presence of */
4125   /* confidence intervals is yet to be determined... raj 11/94 */
4126 
4127   if (verbosity > 1) {
4128     /* The user wanted to know it all, so we will give it to him. */
4129     /* This information will include as much as we can find about */
4130     /* UDP statistics, the alignments of the sends and receives */
4131     /* and all that sort of rot... */
4132 
4133 #ifdef WANT_HISTOGRAM
4134     fprintf(where,"\nHistogram of request/reponse times.\n");
4135     fflush(where);
4136     HIST_report(time_hist);
4137 #endif /* WANT_HISTOGRAM */
4138   }
4139 }
4140 
4141  /* this routine implements the receive side (netserver) of a XTI_UDP_RR */
4142  /* test. */
4143 void
recv_xti_udp_rr()4144   recv_xti_udp_rr()
4145 {
4146 
4147   struct ring_elt *recv_ring;
4148   struct ring_elt *send_ring;
4149 
4150   struct t_bind bind_req, bind_resp;
4151   struct t_unitdata send_unitdata;
4152   struct t_unitdata recv_unitdata;
4153   int	            flags = 0;
4154 
4155   struct sockaddr_in myaddr_in, peeraddr_in;
4156   SOCKET s_data;
4157   int 	addrlen;
4158   int	trans_received;
4159   int	trans_remaining;
4160   float	elapsed_time;
4161 
4162   struct	xti_udp_rr_request_struct	*xti_udp_rr_request;
4163   struct	xti_udp_rr_response_struct	*xti_udp_rr_response;
4164   struct	xti_udp_rr_results_struct	*xti_udp_rr_results;
4165 
4166 
4167   /* a little variable initialization */
4168   memset (&myaddr_in, 0, sizeof(struct sockaddr_in));
4169   myaddr_in.sin_family      = AF_INET;
4170   myaddr_in.sin_addr.s_addr = INADDR_ANY;
4171   myaddr_in.sin_port        = 0;
4172   memset (&peeraddr_in, 0, sizeof(struct sockaddr_in));
4173 
4174   /* and some not so paranoid :) */
4175   xti_udp_rr_request  =
4176     (struct xti_udp_rr_request_struct *)netperf_request.content.test_specific_data;
4177   xti_udp_rr_response =
4178     (struct xti_udp_rr_response_struct *)netperf_response.content.test_specific_data;
4179   xti_udp_rr_results  =
4180     (struct xti_udp_rr_results_struct *)netperf_response.content.test_specific_data;
4181 
4182   if (debug) {
4183     fprintf(where,"netserver: recv_xti_udp_rr: entered...\n");
4184     fflush(where);
4185   }
4186 
4187   /* We want to set-up the listen socket with all the desired */
4188   /* parameters and then let the initiator know that all is ready. If */
4189   /* socket size defaults are to be used, then the initiator will have */
4190   /* sent us 0's. If the socket sizes cannot be changed, then we will */
4191   /* send-back what they are. If that information cannot be determined, */
4192   /* then we send-back -1's for the sizes. If things go wrong for any */
4193   /* reason, we will drop back ten yards and punt. */
4194 
4195   /* If anything goes wrong, we want the remote to know about it. It */
4196   /* would be best if the error that the remote reports to the user is */
4197   /* the actual error we encountered, rather than some bogus unexpected */
4198   /* response type message. */
4199 
4200   if (debug) {
4201     fprintf(where,"recv_xti_udp_rr: setting the response type...\n");
4202     fflush(where);
4203   }
4204 
4205   netperf_response.content.response_type = XTI_UDP_RR_RESPONSE;
4206 
4207   if (debug) {
4208     fprintf(where,"recv_xti_udp_rr: the response type is set...\n");
4209     fflush(where);
4210   }
4211 
4212   /* We now alter the message_ptr variables to be at the desired */
4213   /* alignments with the desired offsets. */
4214 
4215   if (debug) {
4216     fprintf(where,"recv_xti_udp_rr: requested recv alignment of %d offset %d\n",
4217 	    xti_udp_rr_request->recv_alignment,
4218 	    xti_udp_rr_request->recv_offset);
4219     fprintf(where,"recv_xti_udp_rr: requested send alignment of %d offset %d\n",
4220 	    xti_udp_rr_request->send_alignment,
4221 	    xti_udp_rr_request->send_offset);
4222     fflush(where);
4223   }
4224 
4225   if (send_width == 0) send_width = 1;
4226   if (recv_width == 0) recv_width = 1;
4227 
4228   recv_ring = allocate_buffer_ring(recv_width,
4229 				   xti_udp_rr_request->request_size,
4230 				   xti_udp_rr_request->recv_alignment,
4231 				   xti_udp_rr_request->recv_offset);
4232 
4233   send_ring = allocate_buffer_ring(send_width,
4234 				   xti_udp_rr_request->response_size,
4235 				   xti_udp_rr_request->send_alignment,
4236 				   xti_udp_rr_request->send_offset);
4237 
4238   if (debug) {
4239     fprintf(where,"recv_xti_udp_rr: receive alignment and offset set...\n");
4240     fflush(where);
4241   }
4242 
4243   /* create_xti_endpoint expects to find some things in the global */
4244   /* variables, so set the globals based on the values in the request. */
4245   /* once the socket has been created, we will set the response values */
4246   /* based on the updated value of those globals. raj 7/94 */
4247   lss_size = xti_udp_rr_request->send_buf_size;
4248   lsr_size = xti_udp_rr_request->recv_buf_size;
4249   loc_rcvavoid = xti_udp_rr_request->so_rcvavoid;
4250   loc_sndavoid = xti_udp_rr_request->so_sndavoid;
4251 
4252 #ifdef __alpha
4253 
4254   /* ok - even on a DEC box, strings are strings. I din't really want */
4255   /* to ntohl the words of a string. since I don't want to teach the */
4256   /* send_ and recv_ _request and _response routines about the types, */
4257   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
4258   /* solution would be to use XDR, but I am still leary of being able */
4259   /* to find XDR libs on all platforms I want running netperf. raj */
4260   {
4261     int *charword;
4262     int *initword;
4263     int *lastword;
4264 
4265     initword = (int *) xti_udp_rr_request->xti_device;
4266     lastword = initword + ((xti_udp_rr_request->dev_name_len + 3) / 4);
4267 
4268     for (charword = initword;
4269 	 charword < lastword;
4270 	 charword++) {
4271 
4272       *charword = htonl(*charword);
4273     }
4274   }
4275 
4276 #endif /* __alpha */
4277 
4278   s_data = create_xti_endpoint(xti_udp_rr_request->xti_device);
4279 
4280   if (s_data == INVALID_SOCKET) {
4281     netperf_response.content.serv_errno = errno;
4282     send_response();
4283     exit(1);
4284   }
4285 
4286   if (debug) {
4287     fprintf(where,"recv_xti_udp_rr: endpoint created...\n");
4288     fflush(where);
4289   }
4290 
4291   /* Let's get an address assigned to this socket so we can tell the */
4292   /* initiator how to reach the data socket. There may be a desire to */
4293   /* nail this socket to a specific IP address in a multi-homed, */
4294   /* multi-connection situation, but for now, we'll ignore the issue */
4295   /* and concentrate on single connection testing. */
4296 
4297   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
4298   bind_req.addr.len    = sizeof(struct sockaddr_in);
4299   bind_req.addr.buf    = (char *)&myaddr_in;
4300   bind_req.qlen        = 1;
4301 
4302   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
4303   bind_resp.addr.len    = sizeof(struct sockaddr_in);
4304   bind_resp.addr.buf    = (char *)&myaddr_in;
4305   bind_resp.qlen        = 1;
4306 
4307   if (t_bind(s_data,
4308 	     &bind_req,
4309 	     &bind_resp) == SOCKET_ERROR) {
4310     if (debug) {
4311       fprintf(where,
4312 	      "recv_xti_udp_rr: t_bind failed, t_errno %d errno %d\n",
4313 	      t_errno,
4314 	      errno);
4315       fflush(where);
4316     }
4317 
4318     netperf_response.content.serv_errno = t_errno;
4319     send_response();
4320 
4321     exit(1);
4322   }
4323 
4324   if (debug) {
4325     fprintf(where,
4326 	    "recv_xti_udp_rr: endpoint bound to port %d...\n",
4327 	    ntohs(myaddr_in.sin_port));
4328     fflush(where);
4329   }
4330 
4331   xti_udp_rr_response->test_length =
4332     xti_udp_rr_request->test_length;
4333 
4334 
4335   /* Now myaddr_in contains the port and the internet address this is */
4336   /* returned to the sender also implicitly telling the sender that the */
4337   /* socket buffer sizing has been done. */
4338 
4339   xti_udp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
4340   netperf_response.content.serv_errno   = 0;
4341 
4342   fprintf(where,"recv port number %d\n",myaddr_in.sin_port);
4343   fflush(where);
4344 
4345   /* But wait, there's more. If the initiator wanted cpu measurements, */
4346   /* then we must call the calibrate routine, which will return the max */
4347   /* rate back to the initiator. If the CPU was not to be measured, or */
4348   /* something went wrong with the calibration, we will return a 0.0 to */
4349   /* the initiator. */
4350 
4351   xti_udp_rr_response->cpu_rate    = 0.0; 	/* assume no cpu */
4352   xti_udp_rr_response->measure_cpu = 0;
4353   if (xti_udp_rr_request->measure_cpu) {
4354     xti_udp_rr_response->measure_cpu = 1;
4355     xti_udp_rr_response->cpu_rate =
4356       calibrate_local_cpu(xti_udp_rr_request->cpu_rate);
4357   }
4358 
4359   /* before we send the response back to the initiator, pull some of */
4360   /* the socket parms from the globals */
4361   xti_udp_rr_response->send_buf_size = lss_size;
4362   xti_udp_rr_response->recv_buf_size = lsr_size;
4363   xti_udp_rr_response->so_rcvavoid   = loc_rcvavoid;
4364   xti_udp_rr_response->so_sndavoid   = loc_sndavoid;
4365 
4366   /* since we are going to call t_rcvudata() instead of t_rcv() we */
4367   /* need to init the unitdata structure raj 3/95 */
4368 
4369   memset (&recv_unitdata, 0, sizeof(recv_unitdata));
4370   recv_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
4371   recv_unitdata.addr.len    = sizeof(struct sockaddr_in);
4372   recv_unitdata.addr.buf    = (char *)&peeraddr_in;
4373 
4374   recv_unitdata.opt.maxlen = 0;
4375   recv_unitdata.opt.len    = 0;
4376   recv_unitdata.opt.buf    = NULL;
4377 
4378   recv_unitdata.udata.maxlen = xti_udp_rr_request->request_size;
4379   recv_unitdata.udata.len    = xti_udp_rr_request->request_size;
4380   recv_unitdata.udata.buf    = recv_ring->buffer_ptr;
4381 
4382   /* since we are going to call t_sndudata() instead of t_snd() we */
4383   /* need to init the unitdata structure raj 8/95 */
4384 
4385   memset (&send_unitdata, 0, sizeof(send_unitdata));
4386   send_unitdata.addr.maxlen = sizeof(struct sockaddr_in);
4387   send_unitdata.addr.len    = sizeof(struct sockaddr_in);
4388   send_unitdata.addr.buf    = (char *)&peeraddr_in;
4389 
4390   send_unitdata.opt.maxlen = 0;
4391   send_unitdata.opt.len    = 0;
4392   send_unitdata.opt.buf    = NULL;
4393 
4394   send_unitdata.udata.maxlen = xti_udp_rr_request->response_size;
4395   send_unitdata.udata.len    = xti_udp_rr_request->response_size;
4396   send_unitdata.udata.buf    = send_ring->buffer_ptr;
4397 
4398   send_response();
4399 
4400 
4401   /* Now it's time to start receiving data on the connection. We will */
4402   /* first grab the apropriate counters and then start grabbing. */
4403 
4404   cpu_start(xti_udp_rr_request->measure_cpu);
4405 
4406   if (xti_udp_rr_request->test_length > 0) {
4407     times_up = 0;
4408     trans_remaining = 0;
4409     start_timer(xti_udp_rr_request->test_length + PAD_TIME);
4410   }
4411   else {
4412     times_up = 1;
4413     trans_remaining = xti_udp_rr_request->test_length * -1;
4414   }
4415 
4416   addrlen = sizeof(peeraddr_in);
4417   bzero((char *)&peeraddr_in, addrlen);
4418 
4419   trans_received = 0;
4420 
4421   while ((!times_up) || (trans_remaining > 0)) {
4422 
4423     /* receive the request from the other side */
4424     if (t_rcvudata(s_data,
4425 		   &recv_unitdata,
4426 		   &flags) != 0) {
4427       if (errno == TNODATA) {
4428 	continue;
4429       }
4430       if (errno == EINTR) {
4431 	/* we must have hit the end of test time. */
4432 	break;
4433       }
4434       if (debug) {
4435 	fprintf(where,
4436 		"recv_xti_udp_rr: t_rcvudata failed, t_errno %d errno %d\n",
4437 		t_errno,
4438 		errno);
4439 	fflush(where);
4440       }
4441       netperf_response.content.serv_errno = t_errno;
4442       send_response();
4443       exit(1);
4444     }
4445     recv_ring = recv_ring->next;
4446     recv_unitdata.udata.buf = recv_ring->buffer_ptr;
4447 
4448     /* Now, send the response to the remote */
4449     if (t_sndudata(s_data,
4450 		   &send_unitdata) != 0) {
4451       if (errno == EINTR) {
4452 	/* we have hit end of test time. */
4453 	break;
4454       }
4455       if (debug) {
4456 	fprintf(where,
4457 		"recv_xti_udp_rr: t_sndudata failed, t_errno %d errno %d\n",
4458 		t_errno,
4459 		errno);
4460 	fflush(where);
4461       }
4462       netperf_response.content.serv_errno = errno;
4463       send_response();
4464       exit(1);
4465     }
4466     send_ring = send_ring->next;
4467     send_unitdata.udata.buf = send_ring->buffer_ptr;
4468 
4469     trans_received++;
4470     if (trans_remaining) {
4471       trans_remaining--;
4472     }
4473 
4474     if (debug) {
4475       fprintf(where,
4476 	      "recv_xti_udp_rr: Transaction %d complete.\n",
4477 	      trans_received);
4478       fflush(where);
4479     }
4480 
4481   }
4482 
4483 
4484   /* The loop now exits due to timeout or transaction count being */
4485   /* reached */
4486 
4487   cpu_stop(xti_udp_rr_request->measure_cpu,&elapsed_time);
4488 
4489   if (times_up) {
4490     /* we ended the test by time, which was at least 2 seconds */
4491     /* longer than we wanted to run. so, we want to subtract */
4492     /* PAD_TIME from the elapsed_time. */
4493     elapsed_time -= PAD_TIME;
4494   }
4495   /* send the results to the sender			*/
4496 
4497   if (debug) {
4498     fprintf(where,
4499 	    "recv_xti_udp_rr: got %d transactions\n",
4500 	    trans_received);
4501     fflush(where);
4502   }
4503 
4504   xti_udp_rr_results->bytes_received = (trans_received *
4505 				    (xti_udp_rr_request->request_size +
4506 				     xti_udp_rr_request->response_size));
4507   xti_udp_rr_results->trans_received = trans_received;
4508   xti_udp_rr_results->elapsed_time	 = elapsed_time;
4509   xti_udp_rr_results->cpu_method     = cpu_method;
4510   if (xti_udp_rr_request->measure_cpu) {
4511     xti_udp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
4512   }
4513 
4514   if (debug) {
4515     fprintf(where,
4516 	    "recv_xti_udp_rr: test complete, sending results.\n");
4517     fflush(where);
4518   }
4519 
4520   send_response();
4521 
4522   /* we are done with the socket now */
4523   close(s_data);
4524 
4525 }
4526 
4527  /* this routine implements the receive (netserver) side of a XTI_TCP_RR */
4528  /* test */
4529 void
recv_xti_tcp_rr()4530 recv_xti_tcp_rr()
4531 {
4532 
4533   struct ring_elt *send_ring;
4534   struct ring_elt *recv_ring;
4535 
4536   struct sockaddr_in  myaddr_in,  peeraddr_in;
4537   struct t_bind bind_req, bind_resp;
4538   struct t_call call_req;
4539 
4540   SOCKET s_listen,s_data;
4541   int 	addrlen;
4542   char	*temp_message_ptr;
4543   int	trans_received;
4544   int	trans_remaining;
4545   int	bytes_sent;
4546   int	request_bytes_recvd;
4547   int	request_bytes_remaining;
4548   int	timed_out = 0;
4549   float	elapsed_time;
4550 
4551   struct	xti_tcp_rr_request_struct	*xti_tcp_rr_request;
4552   struct	xti_tcp_rr_response_struct	*xti_tcp_rr_response;
4553   struct	xti_tcp_rr_results_struct	*xti_tcp_rr_results;
4554 
4555   xti_tcp_rr_request =
4556     (struct xti_tcp_rr_request_struct *)netperf_request.content.test_specific_data;
4557   xti_tcp_rr_response =
4558     (struct xti_tcp_rr_response_struct *)netperf_response.content.test_specific_data;
4559   xti_tcp_rr_results =
4560     (struct xti_tcp_rr_results_struct *)netperf_response.content.test_specific_data;
4561 
4562   if (debug) {
4563     fprintf(where,"netserver: recv_xti_tcp_rr: entered...\n");
4564     fflush(where);
4565   }
4566 
4567   /* We want to set-up the listen socket with all the desired */
4568   /* parameters and then let the initiator know that all is ready. If */
4569   /* socket size defaults are to be used, then the initiator will have */
4570   /* sent us 0's. If the socket sizes cannot be changed, then we will */
4571   /* send-back what they are. If that information cannot be determined, */
4572   /* then we send-back -1's for the sizes. If things go wrong for any */
4573   /* reason, we will drop back ten yards and punt. */
4574 
4575   /* If anything goes wrong, we want the remote to know about it. It */
4576   /* would be best if the error that the remote reports to the user is */
4577   /* the actual error we encountered, rather than some bogus unexpected */
4578   /* response type message. */
4579 
4580   if (debug) {
4581     fprintf(where,"recv_xti_tcp_rr: setting the response type...\n");
4582     fflush(where);
4583   }
4584 
4585   netperf_response.content.response_type = XTI_TCP_RR_RESPONSE;
4586 
4587   if (debug) {
4588     fprintf(where,"recv_xti_tcp_rr: the response type is set...\n");
4589     fflush(where);
4590   }
4591 
4592   /* allocate the recv and send rings with the requested alignments */
4593   /* and offsets. raj 7/94 */
4594   if (debug) {
4595     fprintf(where,"recv_xti_tcp_rr: requested recv alignment of %d offset %d\n",
4596 	    xti_tcp_rr_request->recv_alignment,
4597 	    xti_tcp_rr_request->recv_offset);
4598     fprintf(where,"recv_xti_tcp_rr: requested send alignment of %d offset %d\n",
4599 	    xti_tcp_rr_request->send_alignment,
4600 	    xti_tcp_rr_request->send_offset);
4601     fflush(where);
4602   }
4603 
4604   /* at some point, these need to come to us from the remote system */
4605   if (send_width == 0) send_width = 1;
4606   if (recv_width == 0) recv_width = 1;
4607 
4608   send_ring = allocate_buffer_ring(send_width,
4609 				   xti_tcp_rr_request->response_size,
4610 				   xti_tcp_rr_request->send_alignment,
4611 				   xti_tcp_rr_request->send_offset);
4612 
4613   recv_ring = allocate_buffer_ring(recv_width,
4614 				   xti_tcp_rr_request->request_size,
4615 				   xti_tcp_rr_request->recv_alignment,
4616 				   xti_tcp_rr_request->recv_offset);
4617 
4618 
4619   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
4620   /* can put in OUR values !-) At some point, we may want to nail this */
4621   /* socket to a particular network-level address, but for now, */
4622   /* INADDR_ANY should be just fine. */
4623 
4624   bzero((char *)&myaddr_in,
4625 	sizeof(myaddr_in));
4626   myaddr_in.sin_family      = AF_INET;
4627   myaddr_in.sin_addr.s_addr = INADDR_ANY;
4628   myaddr_in.sin_port        = 0;
4629 
4630   /* Grab a socket to listen on, and then listen on it. */
4631 
4632   if (debug) {
4633     fprintf(where,"recv_xti_tcp_rr: grabbing a socket...\n");
4634     fflush(where);
4635   }
4636 
4637   /* create_xti_endpoint expects to find some things in the global */
4638   /* variables, so set the globals based on the values in the request. */
4639   /* once the socket has been created, we will set the response values */
4640   /* based on the updated value of those globals. raj 7/94 */
4641   lss_size = xti_tcp_rr_request->send_buf_size;
4642   lsr_size = xti_tcp_rr_request->recv_buf_size;
4643   loc_nodelay = xti_tcp_rr_request->no_delay;
4644   loc_rcvavoid = xti_tcp_rr_request->so_rcvavoid;
4645   loc_sndavoid = xti_tcp_rr_request->so_sndavoid;
4646 
4647 #ifdef __alpha
4648 
4649   /* ok - even on a DEC box, strings are strings. I din't really want */
4650   /* to ntohl the words of a string. since I don't want to teach the */
4651   /* send_ and recv_ _request and _response routines about the types, */
4652   /* I will put "anti-ntohl" calls here. I imagine that the "pure" */
4653   /* solution would be to use XDR, but I am still leary of being able */
4654   /* to find XDR libs on all platforms I want running netperf. raj */
4655   {
4656     int *charword;
4657     int *initword;
4658     int *lastword;
4659 
4660     initword = (int *) xti_tcp_rr_request->xti_device;
4661     lastword = initword + ((xti_tcp_rr_request->dev_name_len + 3) / 4);
4662 
4663     for (charword = initword;
4664 	 charword < lastword;
4665 	 charword++) {
4666 
4667       *charword = htonl(*charword);
4668     }
4669   }
4670 
4671 #endif /* __alpha */
4672 
4673   s_listen = create_xti_endpoint(xti_tcp_rr_request->xti_device);
4674 
4675   if (s_listen == INVALID_SOCKET) {
4676     netperf_response.content.serv_errno = errno;
4677     send_response();
4678 
4679     exit(1);
4680   }
4681 
4682   /* Let's get an address assigned to this socket so we can tell the */
4683   /* initiator how to reach the data socket. There may be a desire to */
4684   /* nail this socket to a specific IP address in a multi-homed, */
4685   /* multi-connection situation, but for now, we'll ignore the issue */
4686   /* and concentrate on single connection testing. */
4687 
4688   bind_req.addr.maxlen = sizeof(struct sockaddr_in);
4689   bind_req.addr.len    = sizeof(struct sockaddr_in);
4690   bind_req.addr.buf    = (char *)&myaddr_in;
4691   bind_req.qlen        = 1;
4692 
4693   bind_resp.addr.maxlen = sizeof(struct sockaddr_in);
4694   bind_resp.addr.len    = sizeof(struct sockaddr_in);
4695   bind_resp.addr.buf    = (char *)&myaddr_in;
4696   bind_resp.qlen        = 1;
4697 
4698   if (t_bind(s_listen,
4699 	     &bind_req,
4700 	     &bind_resp) == SOCKET_ERROR) {
4701     netperf_response.content.serv_errno = t_errno;
4702     close(s_listen);
4703     send_response();
4704 
4705     exit(1);
4706   }
4707 
4708   if (debug) {
4709     fprintf(where,
4710 	    "recv_xti_tcp_rr: t_bind complete port %d\n",
4711 	    ntohs(myaddr_in.sin_port));
4712     fflush(where);
4713   }
4714 
4715   /* Now myaddr_in contains the port and the internet address this is */
4716   /* returned to the sender also implicitly telling the sender that the */
4717   /* socket buffer sizing has been done. */
4718 
4719   xti_tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
4720   netperf_response.content.serv_errno   = 0;
4721 
4722   /* But wait, there's more. If the initiator wanted cpu measurements, */
4723   /* then we must call the calibrate routine, which will return the max */
4724   /* rate back to the initiator. If the CPU was not to be measured, or */
4725   /* something went wrong with the calibration, we will return a 0.0 to */
4726   /* the initiator. */
4727 
4728   xti_tcp_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
4729   xti_tcp_rr_response->measure_cpu = 0;
4730 
4731   if (xti_tcp_rr_request->measure_cpu) {
4732     xti_tcp_rr_response->measure_cpu = 1;
4733     xti_tcp_rr_response->cpu_rate = calibrate_local_cpu(xti_tcp_rr_request->cpu_rate);
4734   }
4735 
4736 
4737   /* before we send the response back to the initiator, pull some of */
4738   /* the socket parms from the globals */
4739   xti_tcp_rr_response->send_buf_size = lss_size;
4740   xti_tcp_rr_response->recv_buf_size = lsr_size;
4741   xti_tcp_rr_response->no_delay = loc_nodelay;
4742   xti_tcp_rr_response->so_rcvavoid = loc_rcvavoid;
4743   xti_tcp_rr_response->so_sndavoid = loc_sndavoid;
4744   xti_tcp_rr_response->test_length = xti_tcp_rr_request->test_length;
4745   send_response();
4746 
4747   /* Now, let's set-up the socket to listen for connections. for xti, */
4748   /* the t_listen call is blocking by default - this is different */
4749   /* semantics from BSD - probably has to do with being able to reject */
4750   /* a call before an accept */
4751   call_req.addr.maxlen = sizeof(struct sockaddr_in);
4752   call_req.addr.len    = sizeof(struct sockaddr_in);
4753   call_req.addr.buf    = (char *)&peeraddr_in;
4754   call_req.opt.maxlen  = 0;
4755   call_req.opt.len     = 0;
4756   call_req.opt.buf     = NULL;
4757   call_req.udata.maxlen= 0;
4758   call_req.udata.len   = 0;
4759   call_req.udata.buf   = 0;
4760 
4761   if (t_listen(s_listen, &call_req) == -1) {
4762     fprintf(where,
4763 	    "recv_xti_tcp_rr: t_listen: errno %d t_errno %d\n",
4764 	    errno,
4765 	    t_errno);
4766     fflush(where);
4767     netperf_response.content.serv_errno = t_errno;
4768     close(s_listen);
4769     send_response();
4770     exit(1);
4771   }
4772 
4773   if (debug) {
4774     fprintf(where,
4775 	    "recv_xti_tcp_rr: t_listen complete t_look 0x%.4x\n",
4776 	    t_look(s_listen));
4777     fflush(where);
4778   }
4779 
4780   /* now just rubber stamp the thing. we want to use the same fd? so */
4781   /* we will just equate s_data with s_listen. this seems a little */
4782   /* hokey to me, but then I'm a BSD biggot still. raj 2/95 */
4783   s_data = s_listen;
4784   if (t_accept(s_listen,
4785 	       s_data,
4786 	       &call_req) == -1) {
4787     fprintf(where,
4788 	    "recv_xti_tcp_rr: t_accept: errno %d t_errno %d\n",
4789 	    errno,
4790 	    t_errno);
4791     fflush(where);
4792     close(s_listen);
4793     exit(1);
4794   }
4795 
4796   if (debug) {
4797     fprintf(where,
4798 	    "recv_xti_tcp_rr: t_accept complete t_look 0x%.4x",
4799 	    t_look(s_data));
4800     fprintf(where,
4801 	    " remote is %s port %d\n",
4802 	    inet_ntoa(*(struct in_addr *)&peeraddr_in.sin_addr),
4803 	    ntohs(peeraddr_in.sin_port));
4804     fflush(where);
4805   }
4806 
4807   /* Now it's time to start receiving data on the connection. We will */
4808   /* first grab the apropriate counters and then start grabbing. */
4809 
4810   cpu_start(xti_tcp_rr_request->measure_cpu);
4811 
4812   if (xti_tcp_rr_request->test_length > 0) {
4813     times_up = 0;
4814     trans_remaining = 0;
4815     start_timer(xti_tcp_rr_request->test_length + PAD_TIME);
4816   }
4817   else {
4818     times_up = 1;
4819     trans_remaining = xti_tcp_rr_request->test_length * -1;
4820   }
4821 
4822   trans_received = 0;
4823 
4824   while ((!times_up) || (trans_remaining > 0)) {
4825     temp_message_ptr = recv_ring->buffer_ptr;
4826     request_bytes_remaining	= xti_tcp_rr_request->request_size;
4827     while(request_bytes_remaining > 0) {
4828       if((request_bytes_recvd=t_rcv(s_data,
4829 				    temp_message_ptr,
4830 				    request_bytes_remaining,
4831 				    &xti_flags)) == SOCKET_ERROR) {
4832 	if (errno == EINTR) {
4833 	  /* the timer popped */
4834 	  timed_out = 1;
4835 	  break;
4836 	}
4837 	fprintf(where,
4838 		"recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
4839 		errno,
4840 		t_errno,
4841 		request_bytes_recvd);
4842 	fprintf(where,
4843 		" t_look 0x%x",
4844 		t_look(s_data));
4845 	fflush(where);
4846 	netperf_response.content.serv_errno = t_errno;
4847 	send_response();
4848 	exit(1);
4849       }
4850       else {
4851 	request_bytes_remaining -= request_bytes_recvd;
4852 	temp_message_ptr  += request_bytes_recvd;
4853       }
4854     }
4855 
4856     recv_ring = recv_ring->next;
4857 
4858     if (timed_out) {
4859       /* we hit the end of the test based on time - lets */
4860       /* bail out of here now... */
4861       if (debug) {
4862 	fprintf(where,"yo5\n");
4863 	fflush(where);
4864       }
4865       break;
4866     }
4867 
4868     /* Now, send the response to the remote */
4869     if((bytes_sent=t_snd(s_data,
4870 			 send_ring->buffer_ptr,
4871 			 xti_tcp_rr_request->response_size,
4872 			 0)) == -1) {
4873       if (errno == EINTR) {
4874 	/* the test timer has popped */
4875 	timed_out = 1;
4876 	if (debug) {
4877 	  fprintf(where,"yo6\n");
4878 	  fflush(where);
4879 	}
4880 	break;
4881       }
4882       fprintf(where,
4883 	      "recv_xti_tcp_rr: t_rcv: errno %d t_errno %d len %d",
4884 	      errno,
4885 	      t_errno,
4886 	      bytes_sent);
4887       fprintf(where,
4888 	      " t_look 0x%x",
4889 	      t_look(s_data));
4890       fflush(where);
4891       netperf_response.content.serv_errno = t_errno;
4892       send_response();
4893       exit(1);
4894     }
4895 
4896     send_ring = send_ring->next;
4897 
4898     trans_received++;
4899     if (trans_remaining) {
4900       trans_remaining--;
4901     }
4902   }
4903 
4904 
4905   /* The loop now exits due to timeout or transaction count being */
4906   /* reached */
4907 
4908   cpu_stop(xti_tcp_rr_request->measure_cpu,&elapsed_time);
4909 
4910   stop_timer(); /* this is probably unnecessary, but it shouldn't hurt */
4911 
4912   if (timed_out) {
4913     /* we ended the test by time, which was at least 2 seconds */
4914     /* longer than we wanted to run. so, we want to subtract */
4915     /* PAD_TIME from the elapsed_time. */
4916     elapsed_time -= PAD_TIME;
4917   }
4918 
4919   /* send the results to the sender			*/
4920 
4921   if (debug) {
4922     fprintf(where,
4923 	    "recv_xti_tcp_rr: got %d transactions\n",
4924 	    trans_received);
4925     fflush(where);
4926   }
4927 
4928   xti_tcp_rr_results->bytes_received = (trans_received *
4929 					(xti_tcp_rr_request->request_size +
4930 					 xti_tcp_rr_request->response_size));
4931   xti_tcp_rr_results->trans_received = trans_received;
4932   xti_tcp_rr_results->elapsed_time   = elapsed_time;
4933   xti_tcp_rr_results->cpu_method     = cpu_method;
4934   if (xti_tcp_rr_request->measure_cpu) {
4935     xti_tcp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
4936   }
4937 
4938   if (debug) {
4939     fprintf(where,
4940 	    "recv_xti_tcp_rr: test complete, sending results.\n");
4941     fflush(where);
4942   }
4943 
4944   /* we are done with the socket, free it */
4945   t_close(s_data);
4946 
4947   send_response();
4948 
4949 }
4950 
4951 
4952 
4953  /* this test is intended to test the performance of establishing a */
4954  /* connection, exchanging a request/response pair, and repeating. it */
4955  /* is expected that this would be a good starting-point for */
4956  /* comparision of T/TCP with classic TCP for transactional workloads. */
4957  /* it will also look (can look) much like the communication pattern */
4958  /* of http for www access. */
4959 
4960 void
send_xti_tcp_conn_rr(char remote_host[])4961 send_xti_tcp_conn_rr(char remote_host[])
4962 {
4963 
4964   char *tput_title = "\
4965 Local /Remote\n\
4966 Socket Size   Request  Resp.   Elapsed  Trans.\n\
4967 Send   Recv   Size     Size    Time     Rate         \n\
4968 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
4969 
4970   char *tput_fmt_0 =
4971     "%7.2f\n";
4972 
4973   char *tput_fmt_1_line_1 = "\
4974 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
4975   char *tput_fmt_1_line_2 = "\
4976 %-6d %-6d\n";
4977 
4978   char *cpu_title = "\
4979 Local /Remote\n\
4980 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
4981 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
4982 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
4983 
4984   char *cpu_fmt_0 =
4985     "%6.3f\n";
4986 
4987   char *cpu_fmt_1_line_1 = "\
4988 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
4989 
4990   char *cpu_fmt_1_line_2 = "\
4991 %-6d %-6d\n";
4992 
4993   char *ksink_fmt = "\
4994 Alignment      Offset\n\
4995 Local  Remote  Local  Remote\n\
4996 Send   Recv    Send   Recv\n\
4997 %5d  %5d   %5d  %5d\n";
4998 
4999 
5000   int 			one = 1;
5001   int			timed_out = 0;
5002   float			elapsed_time;
5003 
5004   int	len;
5005   struct ring_elt *send_ring;
5006   struct ring_elt *recv_ring;
5007   char	*temp_message_ptr;
5008   int	nummessages;
5009   SOCKET send_socket;
5010   int	trans_remaining;
5011   double	bytes_xferd;
5012   int	sock_opt_len = sizeof(int);
5013   int	rsp_bytes_left;
5014   int	rsp_bytes_recvd;
5015 
5016   float	local_cpu_utilization;
5017   float	local_service_demand;
5018   float	remote_cpu_utilization;
5019   float	remote_service_demand;
5020   double	thruput;
5021 
5022   struct	hostent	        *hp;
5023   struct	sockaddr_in	server;
5024   struct        sockaddr_in     *myaddr;
5025   unsigned      int             addr;
5026   int                           myport;
5027 
5028   struct	xti_tcp_conn_rr_request_struct	*xti_tcp_conn_rr_request;
5029   struct	xti_tcp_conn_rr_response_struct	*xti_tcp_conn_rr_response;
5030   struct	xti_tcp_conn_rr_results_struct	*xti_tcp_conn_rr_result;
5031 
5032   xti_tcp_conn_rr_request =
5033     (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
5034   xti_tcp_conn_rr_response =
5035     (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
5036   xti_tcp_conn_rr_result =
5037     (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
5038 
5039   /* since we are now disconnected from the code that established the */
5040   /* control socket, and since we want to be able to use different */
5041   /* protocols and such, we are passed the name of the remote host and */
5042   /* must turn that into the test specific addressing information. */
5043 
5044   myaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
5045   if (myaddr == NULL) {
5046     printf("malloc(%d) failed!\n", sizeof(struct sockaddr_in));
5047     exit(1);
5048   }
5049 
5050   bzero((char *)&server,
5051 	sizeof(server));
5052   bzero((char *)myaddr,
5053 	sizeof(struct sockaddr_in));
5054   myaddr->sin_family = AF_INET;
5055 
5056   /* it would seem that while HP-UX will allow an IP address (as a */
5057   /* string) in a call to gethostbyname, other, less enlightened */
5058   /* systems do not. fix from awjacks@ca.sandia.gov raj 10/95 */
5059   /* order changed to check for IP address first. raj 7/96 */
5060 
5061   if ((addr = inet_addr(remote_host)) == SOCKET_ERROR) {
5062     /* it was not an IP address, try it as a name */
5063     if ((hp = gethostbyname(remote_host)) == NULL) {
5064       /* we have no idea what it is */
5065       fprintf(where,
5066 	      "establish_control: could not resolve the destination %s\n",
5067 	      remote_host);
5068       fflush(where);
5069       exit(1);
5070     }
5071     else {
5072       /* it was a valid remote_host */
5073       bcopy(hp->h_addr,
5074 	    (char *)&server.sin_addr,
5075 	    hp->h_length);
5076       server.sin_family = hp->h_addrtype;
5077     }
5078   }
5079   else {
5080     /* it was a valid IP address */
5081     server.sin_addr.s_addr = addr;
5082     server.sin_family = AF_INET;
5083   }
5084 
5085   if ( print_headers ) {
5086     fprintf(where,"TCP Connect/Request/Response Test\n");
5087     if (local_cpu_usage || remote_cpu_usage)
5088       fprintf(where,cpu_title,format_units());
5089     else
5090       fprintf(where,tput_title,format_units());
5091   }
5092 
5093   /* initialize a few counters */
5094 
5095   nummessages	=	0;
5096   bytes_xferd	=	0.0;
5097   times_up 	= 	0;
5098 
5099   /* set-up the data buffers with the requested alignment and offset */
5100   if (send_width == 0) send_width = 1;
5101   if (recv_width == 0) recv_width = 1;
5102 
5103   send_ring = allocate_buffer_ring(send_width,
5104 				   req_size,
5105 				   local_send_align,
5106 				   local_send_offset);
5107 
5108   recv_ring = allocate_buffer_ring(recv_width,
5109 				   rsp_size,
5110 				   local_recv_align,
5111 				   local_recv_offset);
5112 
5113 
5114   if (debug) {
5115     fprintf(where,"send_xti_tcp_conn_rr: send_socket obtained...\n");
5116   }
5117 
5118   /* If the user has requested cpu utilization measurements, we must */
5119   /* calibrate the cpu(s). We will perform this task within the tests */
5120   /* themselves. If the user has specified the cpu rate, then */
5121   /* calibrate_local_cpu will return rather quickly as it will have */
5122   /* nothing to do. If local_cpu_rate is zero, then we will go through */
5123   /* all the "normal" calibration stuff and return the rate back.*/
5124 
5125   if (local_cpu_usage) {
5126     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
5127   }
5128 
5129   /* Tell the remote end to do a listen. The server alters the socket */
5130   /* paramters on the other side at this point, hence the reason for */
5131   /* all the values being passed in the setup message. If the user did */
5132   /* not specify any of the parameters, they will be passed as 0, which */
5133   /* will indicate to the remote that no changes beyond the system's */
5134   /* default should be used. Alignment is the exception, it will */
5135   /* default to 8, which will be no alignment alterations. */
5136 
5137   netperf_request.content.request_type	        =	DO_XTI_TCP_CRR;
5138   xti_tcp_conn_rr_request->recv_buf_size	=	rsr_size;
5139   xti_tcp_conn_rr_request->send_buf_size	=	rss_size;
5140   xti_tcp_conn_rr_request->recv_alignment	=	remote_recv_align;
5141   xti_tcp_conn_rr_request->recv_offset	=	remote_recv_offset;
5142   xti_tcp_conn_rr_request->send_alignment	=	remote_send_align;
5143   xti_tcp_conn_rr_request->send_offset	=	remote_send_offset;
5144   xti_tcp_conn_rr_request->request_size	=	req_size;
5145   xti_tcp_conn_rr_request->response_size	=	rsp_size;
5146   xti_tcp_conn_rr_request->no_delay	        =	rem_nodelay;
5147   xti_tcp_conn_rr_request->measure_cpu	=	remote_cpu_usage;
5148   xti_tcp_conn_rr_request->cpu_rate	        =	remote_cpu_rate;
5149   xti_tcp_conn_rr_request->so_rcvavoid	=	rem_rcvavoid;
5150   xti_tcp_conn_rr_request->so_sndavoid	=	rem_sndavoid;
5151   if (test_time) {
5152     xti_tcp_conn_rr_request->test_length	=	test_time;
5153   }
5154   else {
5155     xti_tcp_conn_rr_request->test_length	=	test_trans * -1;
5156   }
5157 
5158   if (debug > 1) {
5159     fprintf(where,"netperf: send_xti_tcp_conn_rr: requesting TCP crr test\n");
5160   }
5161 
5162   send_request();
5163 
5164   /* The response from the remote will contain all of the relevant 	*/
5165   /* socket parameters for this test type. We will put them back into 	*/
5166   /* the variables here so they can be displayed if desired.  The	*/
5167   /* remote will have calibrated CPU if necessary, and will have done	*/
5168   /* all the needed set-up we will have calibrated the cpu locally	*/
5169   /* before sending the request, and will grab the counter value right	*/
5170   /* after the connect returns. The remote will grab the counter right	*/
5171   /* after the accept call. This saves the hassle of extra messages	*/
5172   /* being sent for the TCP tests.					*/
5173 
5174   recv_response();
5175 
5176   if (!netperf_response.content.serv_errno) {
5177     rsr_size	=	xti_tcp_conn_rr_response->recv_buf_size;
5178     rss_size	=	xti_tcp_conn_rr_response->send_buf_size;
5179     rem_nodelay	=	xti_tcp_conn_rr_response->no_delay;
5180     remote_cpu_usage=	xti_tcp_conn_rr_response->measure_cpu;
5181     remote_cpu_rate = 	xti_tcp_conn_rr_response->cpu_rate;
5182     /* make sure that port numbers are in network order */
5183     server.sin_port	=	(short)xti_tcp_conn_rr_response->data_port_number;
5184     server.sin_port =	htons(server.sin_port);
5185     if (debug) {
5186       fprintf(where,"remote listen done.\n");
5187       fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
5188       fflush(where);
5189     }
5190   }
5191   else {
5192     Set_errno(netperf_response.content.serv_errno);
5193     perror("netperf: remote error");
5194 
5195     exit(1);
5196   }
5197 
5198   /* Set-up the test end conditions. For a request/response test, they */
5199   /* can be either time or transaction based. */
5200 
5201   if (test_time) {
5202     /* The user wanted to end the test after a period of time. */
5203     times_up = 0;
5204     trans_remaining = 0;
5205     start_timer(test_time);
5206   }
5207   else {
5208     /* The tester wanted to send a number of bytes. */
5209     trans_remaining = test_bytes;
5210     times_up = 1;
5211   }
5212 
5213   /* The cpu_start routine will grab the current time and possibly */
5214   /* value of the idle counter for later use in measuring cpu */
5215   /* utilization and/or service demand and thruput. */
5216 
5217   cpu_start(local_cpu_usage);
5218 
5219   /* We use an "OR" to control test execution. When the test is */
5220   /* controlled by time, the byte count check will always return false. */
5221   /* When the test is controlled by byte count, the time test will */
5222   /* always return false. When the test is finished, the whole */
5223   /* expression will go false and we will stop sending data. I think I */
5224   /* just arbitrarily decrement trans_remaining for the timed test, but */
5225   /* will not do that just yet... One other question is whether or not */
5226   /* the send buffer and the receive buffer should be the same buffer. */
5227 
5228   /* just for grins, start the port numbers at 65530. this should */
5229   /* quickly flush-out those broken implementations of TCP which treat */
5230   /* the port number as a signed 16 bit quantity. */
5231   myport = 65530;
5232   myaddr->sin_port = htons(myport);
5233 
5234   while ((!times_up) || (trans_remaining > 0)) {
5235 
5236     /* set up the data socket */
5237     send_socket = create_xti_endpoint(loc_xti_device);
5238 
5239     if (send_socket == INVALID_SOCKET) {
5240       perror("netperf: send_xti_tcp_conn_rr: tcp stream data socket");
5241       exit(1);
5242     }
5243 
5244     /* we set SO_REUSEADDR on the premis that no unreserved port */
5245     /* number on the local system is going to be already connected to */
5246     /* the remote netserver's port number. we might still have a */
5247     /* problem if there is a port in the unconnected state. In that */
5248     /* case, we might want to throw-in a goto to the point where we */
5249     /* increment the port number by one and try again. of course, this */
5250     /* could lead to a big load of spinning. one thing that I might */
5251     /* try later is to have the remote actually allocate a couple of */
5252     /* port numbers and cycle through those as well. depends on if we */
5253     /* can get through all the unreserved port numbers in less than */
5254     /* the length of the TIME_WAIT state raj 8/94 */
5255     one = 1;
5256     if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
5257 		  (char *)&one, sock_opt_len) == SOCKET_ERROR) {
5258       perror("netperf: send_xti_tcp_conn_rr: so_reuseaddr");
5259       exit(1);
5260     }
5261 
5262     /* we want to bind our socket to a particular port number. */
5263     if (bind(send_socket,
5264 	     (struct sockaddr *)myaddr,
5265 	     sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
5266       printf("netperf: send_xti_tcp_conn_rr: tried to bind to port %d\n",
5267 	     ntohs(myaddr->sin_port));
5268       perror("netperf: send_xti_tcp_conn_rr: bind");
5269       exit(1);
5270     }
5271 
5272     /* Connect up to the remote port on the data socket  */
5273     if (connect(send_socket,
5274 		(struct sockaddr *)&server,
5275 		sizeof(server)) == INVALID_SOCKET){
5276       if (errno == EINTR) {
5277 	/* we hit the end of a */
5278 	/* timed test. */
5279 	timed_out = 1;
5280 	break;
5281       }
5282       perror("netperf: data socket connect failed");
5283       printf("\tattempted to connect on socket %d to port %d",
5284 	     send_socket,
5285 	     ntohs(server.sin_port));
5286       printf(" from port %d \n",ntohs(myaddr->sin_port));
5287       exit(1);
5288     }
5289 
5290     /* send the request */
5291     if((len=send(send_socket,
5292 		 send_ring->buffer_ptr,
5293 		 req_size,
5294 		 0)) != req_size) {
5295       if (errno == EINTR) {
5296 	/* we hit the end of a */
5297 	/* timed test. */
5298 	timed_out = 1;
5299 	break;
5300       }
5301       perror("send_xti_tcp_conn_rr: data send error");
5302       exit(1);
5303     }
5304     send_ring = send_ring->next;
5305 
5306     /* receive the response */
5307     rsp_bytes_left = rsp_size;
5308     temp_message_ptr  = recv_ring->buffer_ptr;
5309     while(rsp_bytes_left > 0) {
5310       if((rsp_bytes_recvd=recv(send_socket,
5311 			       temp_message_ptr,
5312 			       rsp_bytes_left,
5313 			       0)) == SOCKET_ERROR) {
5314 	if (errno == EINTR) {
5315 	  /* We hit the end of a timed test. */
5316 	  timed_out = 1;
5317 	  break;
5318 	}
5319 	perror("send_xti_tcp_conn_rr: data recv error");
5320 	exit(1);
5321       }
5322       rsp_bytes_left -= rsp_bytes_recvd;
5323       temp_message_ptr  += rsp_bytes_recvd;
5324     }
5325     recv_ring = recv_ring->next;
5326 
5327     if (timed_out) {
5328       /* we may have been in a nested while loop - we need */
5329       /* another call to break. */
5330       break;
5331     }
5332 
5333     close(send_socket);
5334 
5335     nummessages++;
5336     if (trans_remaining) {
5337       trans_remaining--;
5338     }
5339 
5340     if (debug > 3) {
5341       fprintf(where,
5342 	      "Transaction %d completed on local port %d\n",
5343 	      nummessages,
5344 	      ntohs(myaddr->sin_port));
5345       fflush(where);
5346     }
5347 
5348 newport:
5349     /* pick a new port number */
5350     myport = ntohs(myaddr->sin_port);
5351     myport++;
5352     /* we do not want to use the port number that the server is */
5353     /* sitting at - this would cause us to fail in a loopback test */
5354 
5355     if (myport == ntohs(server.sin_port)) myport++;
5356 
5357     /* wrap the port number when we get to 65535. NOTE, some broken */
5358     /* TCP's might treat the port number as a signed 16 bit quantity. */
5359     /* we aren't interested in testing such broekn implementations :) */
5360     /* raj 8/94  */
5361     if (myport == 65535) {
5362       myport = 5000;
5363     }
5364     myaddr->sin_port = htons(myport);
5365 
5366     if (debug) {
5367       if ((myport % 1000) == 0) {
5368 	printf("port %d\n",myport);
5369       }
5370     }
5371 
5372   }
5373 
5374   /* this call will always give us the elapsed time for the test, and */
5375   /* will also store-away the necessaries for cpu utilization */
5376 
5377   cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being measured? */
5378   /* how long did we really run? */
5379 
5380   /* Get the statistics from the remote end. The remote will have */
5381   /* calculated service demand and all those interesting things. If it */
5382   /* wasn't supposed to care, it will return obvious values. */
5383 
5384   recv_response();
5385   if (!netperf_response.content.serv_errno) {
5386     if (debug)
5387       fprintf(where,"remote results obtained\n");
5388   }
5389   else {
5390     Set_errno(netperf_response.content.serv_errno);
5391     perror("netperf: remote error");
5392 
5393     exit(1);
5394   }
5395 
5396   /* We now calculate what our thruput was for the test. In the future, */
5397   /* we may want to include a calculation of the thruput measured by */
5398   /* the remote, but it should be the case that for a TCP stream test, */
5399   /* that the two numbers should be *very* close... We calculate */
5400   /* bytes_sent regardless of the way the test length was controlled. */
5401   /* If it was time, we needed to, and if it was by bytes, the user may */
5402   /* have specified a number of bytes that wasn't a multiple of the */
5403   /* send_size, so we really didn't send what he asked for ;-) We use */
5404   /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
5405   /* 1024. A future enhancement *might* be to choose from a couple of */
5406   /* unit selections. */
5407 
5408   bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
5409   thruput	= calc_thruput(bytes_xferd);
5410 
5411   if (local_cpu_usage || remote_cpu_usage) {
5412     /* We must now do a little math for service demand and cpu */
5413     /* utilization for the system(s) */
5414     /* Of course, some of the information might be bogus because */
5415     /* there was no idle counter in the kernel(s). We need to make */
5416     /* a note of this for the user's benefit...*/
5417     if (local_cpu_usage) {
5418       if (local_cpu_rate == 0.0) {
5419 	fprintf(where,"WARNING WARNING WARNING  WARNING WARNING WARNING  WARNING!\n");
5420 	fprintf(where,"Local CPU usage numbers based on process information only!\n");
5421 	fflush(where);
5422       }
5423       local_cpu_utilization = calc_cpu_util(0.0);
5424       /* since calc_service demand is doing ms/Kunit we will */
5425       /* multiply the number of transaction by 1024 to get */
5426       /* "good" numbers */
5427       local_service_demand  = calc_service_demand((double) nummessages*1024,
5428 						  0.0,
5429 						  0.0,
5430 						  0);
5431     }
5432     else {
5433       local_cpu_utilization	= -1.0;
5434       local_service_demand	= -1.0;
5435     }
5436 
5437     if (remote_cpu_usage) {
5438       if (remote_cpu_rate == 0.0) {
5439 	fprintf(where,"DANGER  DANGER  DANGER    DANGER  DANGER  DANGER    DANGER!\n");
5440 	fprintf(where,"Remote CPU usage numbers based on process information only!\n");
5441 	fflush(where);
5442       }
5443       remote_cpu_utilization = xti_tcp_conn_rr_result->cpu_util;
5444       /* since calc_service demand is doing ms/Kunit we will */
5445       /* multiply the number of transaction by 1024 to get */
5446       /* "good" numbers */
5447       remote_service_demand = calc_service_demand((double) nummessages*1024,
5448 						  0.0,
5449 						  remote_cpu_utilization,
5450 						  xti_tcp_conn_rr_result->num_cpus);
5451     }
5452     else {
5453       remote_cpu_utilization = -1.0;
5454       remote_service_demand  = -1.0;
5455     }
5456 
5457     /* We are now ready to print all the information. If the user */
5458     /* has specified zero-level verbosity, we will just print the */
5459     /* local service demand, or the remote service demand. If the */
5460     /* user has requested verbosity level 1, he will get the basic */
5461     /* "streamperf" numbers. If the user has specified a verbosity */
5462     /* of greater than 1, we will display a veritable plethora of */
5463     /* background information from outside of this block as it it */
5464     /* not cpu_measurement specific...  */
5465 
5466     switch (verbosity) {
5467     case 0:
5468       if (local_cpu_usage) {
5469 	fprintf(where,
5470 		cpu_fmt_0,
5471 		local_service_demand);
5472       }
5473       else {
5474 	fprintf(where,
5475 		cpu_fmt_0,
5476 		remote_service_demand);
5477       }
5478       break;
5479     case 1:
5480       fprintf(where,
5481 	      cpu_fmt_1_line_1,		/* the format string */
5482 	      lss_size,		/* local sendbuf size */
5483 	      lsr_size,
5484 	      req_size,		/* how large were the requests */
5485 	      rsp_size,		/* guess */
5486 	      elapsed_time,		/* how long was the test */
5487 	      nummessages/elapsed_time,
5488 	      local_cpu_utilization,	/* local cpu */
5489 	      remote_cpu_utilization,	/* remote cpu */
5490 	      local_service_demand,	/* local service demand */
5491 	      remote_service_demand);	/* remote service demand */
5492       fprintf(where,
5493 	      cpu_fmt_1_line_2,
5494 	      rss_size,
5495 	      rsr_size);
5496       break;
5497     }
5498   }
5499   else {
5500     /* The tester did not wish to measure service demand. */
5501     switch (verbosity) {
5502     case 0:
5503       fprintf(where,
5504 	      tput_fmt_0,
5505 	      nummessages/elapsed_time);
5506       break;
5507     case 1:
5508       fprintf(where,
5509 	      tput_fmt_1_line_1,	/* the format string */
5510 	      lss_size,
5511 	      lsr_size,
5512 	      req_size,		/* how large were the requests */
5513 	      rsp_size,		/* how large were the responses */
5514 	      elapsed_time, 		/* how long did it take */
5515 	      nummessages/elapsed_time);
5516       fprintf(where,
5517 	      tput_fmt_1_line_2,
5518 	      rss_size, 		/* remote recvbuf size */
5519 	      rsr_size);
5520 
5521       break;
5522     }
5523   }
5524 
5525   /* it would be a good thing to include information about some of the */
5526   /* other parameters that may have been set for this test, but at the */
5527   /* moment, I do not wish to figure-out all the  formatting, so I will */
5528   /* just put this comment here to help remind me that it is something */
5529   /* that should be done at a later time. */
5530 
5531   if (verbosity > 1) {
5532     /* The user wanted to know it all, so we will give it to him. */
5533     /* This information will include as much as we can find about */
5534     /* TCP statistics, the alignments of the sends and receives */
5535     /* and all that sort of rot... */
5536 
5537     fprintf(where,
5538 	    ksink_fmt);
5539   }
5540 
5541 }
5542 
5543 
5544 void
recv_xti_tcp_conn_rr()5545 recv_xti_tcp_conn_rr()
5546 {
5547 
5548   char  *message;
5549   struct	sockaddr_in        myaddr_in,
5550   peeraddr_in;
5551   SOCKET s_listen,s_data;
5552   int 	addrlen;
5553   char	*recv_message_ptr;
5554   char	*send_message_ptr;
5555   char	*temp_message_ptr;
5556   int	trans_received;
5557   int	trans_remaining;
5558   int	bytes_sent;
5559   int	request_bytes_recvd;
5560   int	request_bytes_remaining;
5561   int	timed_out = 0;
5562   float	elapsed_time;
5563 
5564   struct	xti_tcp_conn_rr_request_struct	*xti_tcp_conn_rr_request;
5565   struct	xti_tcp_conn_rr_response_struct	*xti_tcp_conn_rr_response;
5566   struct	xti_tcp_conn_rr_results_struct	*xti_tcp_conn_rr_results;
5567 
5568   xti_tcp_conn_rr_request =
5569     (struct xti_tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
5570   xti_tcp_conn_rr_response =
5571     (struct xti_tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
5572   xti_tcp_conn_rr_results =
5573     (struct xti_tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
5574 
5575   if (debug) {
5576     fprintf(where,"netserver: recv_xti_tcp_conn_rr: entered...\n");
5577     fflush(where);
5578   }
5579 
5580   /* We want to set-up the listen socket with all the desired */
5581   /* parameters and then let the initiator know that all is ready. If */
5582   /* socket size defaults are to be used, then the initiator will have */
5583   /* sent us 0's. If the socket sizes cannot be changed, then we will */
5584   /* send-back what they are. If that information cannot be determined, */
5585   /* then we send-back -1's for the sizes. If things go wrong for any */
5586   /* reason, we will drop back ten yards and punt. */
5587 
5588   /* If anything goes wrong, we want the remote to know about it. It */
5589   /* would be best if the error that the remote reports to the user is */
5590   /* the actual error we encountered, rather than some bogus unexpected */
5591   /* response type message. */
5592 
5593   if (debug) {
5594     fprintf(where,"recv_xti_tcp_conn_rr: setting the response type...\n");
5595     fflush(where);
5596   }
5597 
5598   netperf_response.content.response_type = XTI_TCP_CRR_RESPONSE;
5599 
5600   if (debug) {
5601     fprintf(where,"recv_xti_tcp_conn_rr: the response type is set...\n");
5602     fflush(where);
5603   }
5604 
5605   /* set-up the data buffer with the requested alignment and offset */
5606   message = (char *)malloc(DATABUFFERLEN);
5607   if (message == NULL) {
5608     printf("malloc(%d) failed!\n", DATABUFFERLEN);
5609     exit(1);
5610   }
5611 
5612   /* We now alter the message_ptr variables to be at the desired */
5613   /* alignments with the desired offsets. */
5614 
5615   if (debug) {
5616     fprintf(where,
5617 	    "recv_xti_tcp_conn_rr: requested recv alignment of %d offset %d\n",
5618 	    xti_tcp_conn_rr_request->recv_alignment,
5619 	    xti_tcp_conn_rr_request->recv_offset);
5620     fprintf(where,
5621 	    "recv_xti_tcp_conn_rr: requested send alignment of %d offset %d\n",
5622 	    xti_tcp_conn_rr_request->send_alignment,
5623 	    xti_tcp_conn_rr_request->send_offset);
5624     fflush(where);
5625   }
5626 
5627   recv_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->recv_alignment, xti_tcp_conn_rr_request->recv_offset);
5628 
5629   send_message_ptr = ALIGN_BUFFER(message, xti_tcp_conn_rr_request->send_alignment, xti_tcp_conn_rr_request->send_offset);
5630 
5631   if (debug) {
5632     fprintf(where,"recv_xti_tcp_conn_rr: receive alignment and offset set...\n");
5633     fflush(where);
5634   }
5635 
5636   /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
5637   /* can put in OUR values !-) At some point, we may want to nail this */
5638   /* socket to a particular network-level address, but for now, */
5639   /* INADDR_ANY should be just fine. */
5640 
5641   bzero((char *)&myaddr_in,
5642 	sizeof(myaddr_in));
5643   myaddr_in.sin_family      = AF_INET;
5644   myaddr_in.sin_addr.s_addr = INADDR_ANY;
5645   myaddr_in.sin_port        = 0;
5646 
5647   /* Grab a socket to listen on, and then listen on it. */
5648 
5649   if (debug) {
5650     fprintf(where,"recv_xti_tcp_conn_rr: grabbing a socket...\n");
5651     fflush(where);
5652   }
5653 
5654   /* create_xti_endpoint expects to find some things in the global */
5655   /* variables, so set the globals based on the values in the request. */
5656   /* once the socket has been created, we will set the response values */
5657   /* based on the updated value of those globals. raj 7/94 */
5658   lss_size = xti_tcp_conn_rr_request->send_buf_size;
5659   lsr_size = xti_tcp_conn_rr_request->recv_buf_size;
5660   loc_nodelay = xti_tcp_conn_rr_request->no_delay;
5661   loc_rcvavoid = xti_tcp_conn_rr_request->so_rcvavoid;
5662   loc_sndavoid = xti_tcp_conn_rr_request->so_sndavoid;
5663 
5664   s_listen = create_xti_endpoint(loc_xti_device);
5665 
5666   if (s_listen == INVALID_SOCKET) {
5667     netperf_response.content.serv_errno = errno;
5668     send_response();
5669     if (debug) {
5670       fprintf(where,"could not create data socket\n");
5671       fflush(where);
5672     }
5673     exit(1);
5674   }
5675 
5676   /* Let's get an address assigned to this socket so we can tell the */
5677   /* initiator how to reach the data socket. There may be a desire to */
5678   /* nail this socket to a specific IP address in a multi-homed, */
5679   /* multi-connection situation, but for now, we'll ignore the issue */
5680   /* and concentrate on single connection testing. */
5681 
5682   if (bind(s_listen,
5683 	   (struct sockaddr *)&myaddr_in,
5684 	   sizeof(myaddr_in)) == SOCKET_ERROR) {
5685     netperf_response.content.serv_errno = errno;
5686     close(s_listen);
5687     send_response();
5688     if (debug) {
5689       fprintf(where,"could not bind\n");
5690       fflush(where);
5691     }
5692     exit(1);
5693   }
5694 
5695   /* Now, let's set-up the socket to listen for connections */
5696   if (listen(s_listen, 5) == SOCKET_ERROR) {
5697     netperf_response.content.serv_errno = errno;
5698     close(s_listen);
5699     send_response();
5700     if (debug) {
5701       fprintf(where,"could not listen\n");
5702       fflush(where);
5703     }
5704     exit(1);
5705   }
5706 
5707   /* now get the port number assigned by the system  */
5708   addrlen = sizeof(myaddr_in);
5709   if (getsockname(s_listen,
5710 		  (struct sockaddr *)&myaddr_in,
5711 		  &addrlen) == SOCKET_ERROR){
5712     netperf_response.content.serv_errno = errno;
5713     close(s_listen);
5714     send_response();
5715     if (debug) {
5716       fprintf(where,"could not geetsockname\n");
5717       fflush(where);
5718     }
5719     exit(1);
5720   }
5721 
5722   /* Now myaddr_in contains the port and the internet address this is */
5723   /* returned to the sender also implicitly telling the sender that the */
5724   /* socket buffer sizing has been done. */
5725 
5726   xti_tcp_conn_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
5727   if (debug) {
5728     fprintf(where,"telling the remote to call me at %d\n",
5729 	    xti_tcp_conn_rr_response->data_port_number);
5730     fflush(where);
5731   }
5732   netperf_response.content.serv_errno   = 0;
5733 
5734   /* But wait, there's more. If the initiator wanted cpu measurements, */
5735   /* then we must call the calibrate routine, which will return the max */
5736   /* rate back to the initiator. If the CPU was not to be measured, or */
5737   /* something went wrong with the calibration, we will return a 0.0 to */
5738   /* the initiator. */
5739 
5740   xti_tcp_conn_rr_response->cpu_rate = 0.0; 	/* assume no cpu */
5741   if (xti_tcp_conn_rr_request->measure_cpu) {
5742     xti_tcp_conn_rr_response->measure_cpu = 1;
5743     xti_tcp_conn_rr_response->cpu_rate =
5744       calibrate_local_cpu(xti_tcp_conn_rr_request->cpu_rate);
5745   }
5746 
5747 
5748 
5749   /* before we send the response back to the initiator, pull some of */
5750   /* the socket parms from the globals */
5751   xti_tcp_conn_rr_response->send_buf_size = lss_size;
5752   xti_tcp_conn_rr_response->recv_buf_size = lsr_size;
5753   xti_tcp_conn_rr_response->no_delay = loc_nodelay;
5754   xti_tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
5755   xti_tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
5756 
5757   send_response();
5758 
5759   addrlen = sizeof(peeraddr_in);
5760 
5761   /* Now it's time to start receiving data on the connection. We will */
5762   /* first grab the apropriate counters and then start grabbing. */
5763 
5764   cpu_start(xti_tcp_conn_rr_request->measure_cpu);
5765 
5766   /* The loop will exit when the sender does a shutdown, which will */
5767   /* return a length of zero   */
5768 
5769   if (xti_tcp_conn_rr_request->test_length > 0) {
5770     times_up = 0;
5771     trans_remaining = 0;
5772     start_timer(xti_tcp_conn_rr_request->test_length + PAD_TIME);
5773   }
5774   else {
5775     times_up = 1;
5776     trans_remaining = xti_tcp_conn_rr_request->test_length * -1;
5777   }
5778 
5779   trans_received = 0;
5780 
5781   while ((!times_up) || (trans_remaining > 0)) {
5782 
5783     /* accept a connection from the remote */
5784     if ((s_data=accept(s_listen,
5785 		       (struct sockaddr *)&peeraddr_in,
5786 		       &addrlen)) == INVALID_SOCKET) {
5787       if (errno == EINTR) {
5788 	/* the timer popped */
5789 	timed_out = 1;
5790 	break;
5791       }
5792       fprintf(where,"recv_xti_tcp_conn_rr: accept: errno = %d\n",errno);
5793       fflush(where);
5794       close(s_listen);
5795 
5796       exit(1);
5797     }
5798 
5799     if (debug) {
5800       fprintf(where,"recv_xti_tcp_conn_rr: accepted data connection.\n");
5801       fflush(where);
5802     }
5803 
5804     temp_message_ptr	= recv_message_ptr;
5805     request_bytes_remaining	= xti_tcp_conn_rr_request->request_size;
5806 
5807     /* receive the request from the other side */
5808     while(request_bytes_remaining > 0) {
5809       if((request_bytes_recvd=recv(s_data,
5810 				   temp_message_ptr,
5811 				   request_bytes_remaining,
5812 				   0)) == SOCKET_ERROR) {
5813 	if (errno == EINTR) {
5814 	  /* the timer popped */
5815 	  timed_out = 1;
5816 	  break;
5817 	}
5818 	netperf_response.content.serv_errno = errno;
5819 	send_response();
5820 	exit(1);
5821       }
5822       else {
5823 	request_bytes_remaining -= request_bytes_recvd;
5824 	temp_message_ptr  += request_bytes_recvd;
5825       }
5826     }
5827 
5828     if (timed_out) {
5829       /* we hit the end of the test based on time - lets */
5830       /* bail out of here now... */
5831       fprintf(where,"yo5\n");
5832       fflush(where);
5833       break;
5834     }
5835 
5836     /* Now, send the response to the remote */
5837     if((bytes_sent=send(s_data,
5838 			send_message_ptr,
5839 			xti_tcp_conn_rr_request->response_size,
5840 			0)) == SOCKET_ERROR) {
5841       if (errno == EINTR) {
5842 	/* the test timer has popped */
5843 	timed_out = 1;
5844 	fprintf(where,"yo6\n");
5845 	fflush(where);
5846 	break;
5847       }
5848       netperf_response.content.serv_errno = 99;
5849       send_response();
5850       exit(1);
5851     }
5852 
5853     trans_received++;
5854     if (trans_remaining) {
5855       trans_remaining--;
5856     }
5857 
5858     if (debug) {
5859       fprintf(where,
5860 	      "recv_xti_tcp_conn_rr: Transaction %d complete\n",
5861 	      trans_received);
5862       fflush(where);
5863     }
5864 
5865     /* close the connection */
5866     close(s_data);
5867 
5868   }
5869 
5870 
5871   /* The loop now exits due to timeout or transaction count being */
5872   /* reached */
5873 
5874   cpu_stop(xti_tcp_conn_rr_request->measure_cpu,&elapsed_time);
5875 
5876   if (timed_out) {
5877     /* we ended the test by time, which was at least 2 seconds */
5878     /* longer than we wanted to run. so, we want to subtract */
5879     /* PAD_TIME from the elapsed_time. */
5880     elapsed_time -= PAD_TIME;
5881   }
5882   /* send the results to the sender			*/
5883 
5884   if (debug) {
5885     fprintf(where,
5886 	    "recv_xti_tcp_conn_rr: got %d transactions\n",
5887 	    trans_received);
5888     fflush(where);
5889   }
5890 
5891   xti_tcp_conn_rr_results->bytes_received	= (trans_received *
5892 					   (xti_tcp_conn_rr_request->request_size +
5893 					    xti_tcp_conn_rr_request->response_size));
5894   xti_tcp_conn_rr_results->trans_received	= trans_received;
5895   xti_tcp_conn_rr_results->elapsed_time	= elapsed_time;
5896   if (xti_tcp_conn_rr_request->measure_cpu) {
5897     xti_tcp_conn_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
5898   }
5899 
5900   if (debug) {
5901     fprintf(where,
5902 	    "recv_xti_tcp_conn_rr: test complete, sending results.\n");
5903     fflush(where);
5904   }
5905 
5906   send_response();
5907 
5908 }
5909 
5910 void
print_xti_usage()5911 print_xti_usage()
5912 {
5913 
5914   fwrite(xti_usage, sizeof(char), strlen(xti_usage), stdout);
5915   exit(1);
5916 
5917 }
5918 
5919 void
scan_xti_args(int argc,char * argv[])5920 scan_xti_args(int argc, char *argv[])
5921 {
5922 #define XTI_ARGS "Dhm:M:r:s:S:Vw:W:X:"
5923   extern int	optind, opterrs;  /* index of first unused arg 	*/
5924   extern char	*optarg;	  /* pointer to option string	*/
5925 
5926   int		c;
5927 
5928   char
5929     arg1[BUFSIZ],  /* argument holders		*/
5930     arg2[BUFSIZ];
5931 
5932   if (no_control) {
5933     fprintf(where,
5934 	    "The XTI tests do not know how to run with no control connection\n");
5935     exit(-1);
5936   }
5937 
5938   /* Go through all the command line arguments and break them */
5939   /* out. For those options that take two parms, specifying only */
5940   /* the first will set both to that value. Specifying only the */
5941   /* second will leave the first untouched. To change only the */
5942   /* first, use the form "first," (see the routine break_args.. */
5943 
5944   while ((c= getopt(argc, argv, XTI_ARGS)) != EOF) {
5945     switch (c) {
5946     case '?':
5947     case 'h':
5948       print_xti_usage();
5949       exit(1);
5950     case 'D':
5951       /* set the TCP nodelay flag */
5952       loc_nodelay = 1;
5953       rem_nodelay = 1;
5954       break;
5955     case 's':
5956       /* set local socket sizes */
5957       break_args(optarg,arg1,arg2);
5958       if (arg1[0])
5959 	lss_size = convert(arg1);
5960       if (arg2[0])
5961 	lsr_size = convert(arg2);
5962       break;
5963     case 'S':
5964       /* set remote socket sizes */
5965       break_args(optarg,arg1,arg2);
5966       if (arg1[0])
5967 	rss_size = convert(arg1);
5968       if (arg2[0])
5969 	rsr_size = convert(arg2);
5970       break;
5971     case 'r':
5972       /* set the request/response sizes */
5973       break_args(optarg,arg1,arg2);
5974       if (arg1[0])
5975 	req_size = convert(arg1);
5976       if (arg2[0])
5977 	rsp_size = convert(arg2);
5978       break;
5979     case 'm':
5980       /* set the send size */
5981       send_size = convert(optarg);
5982       break;
5983     case 'M':
5984       /* set the recv size */
5985       recv_size = convert(optarg);
5986       break;
5987     case 'W':
5988       /* set the "width" of the user space data */
5989       /* buffer. This will be the number of */
5990       /* send_size buffers malloc'd in the */
5991       /* *_STREAM test. It may be enhanced to set */
5992       /* both send and receive "widths" but for now */
5993       /* it is just the sending *_STREAM. */
5994       send_width = convert(optarg);
5995       break;
5996     case 'V' :
5997       /* we want to do copy avoidance and will set */
5998       /* it for everything, everywhere, if we really */
5999       /* can. of course, we don't know anything */
6000       /* about the remote... */
6001 #ifdef SO_SND_COPYAVOID
6002       loc_sndavoid = 1;
6003 #else
6004       loc_sndavoid = 0;
6005       printf("Local send copy avoidance not available.\n");
6006 #endif
6007 #ifdef SO_RCV_COPYAVOID
6008       loc_rcvavoid = 1;
6009 #else
6010       loc_rcvavoid = 0;
6011       printf("Local recv copy avoidance not available.\n");
6012 #endif
6013       rem_sndavoid = 1;
6014       rem_rcvavoid = 1;
6015       break;
6016     case 'X':
6017       /* set the xti device file name(s) */
6018       break_args(optarg,arg1,arg2);
6019       if (arg1[0])
6020 	strcpy(loc_xti_device,arg1);
6021       if (arg2[0])
6022 	strcpy(rem_xti_device,arg2);
6023       break;
6024     };
6025   }
6026 }
6027 #endif /* WANT_XTI */
6028