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