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