1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#ifdef WANT_XTI
6#ifndef lint
7char	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
78static 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
88static  int   confidence_iteration;
89static  char  local_cpu_method;
90static  char  remote_cpu_method;
91
92 /* different options for the xti				*/
93
94static 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
102static struct t_info info_struct;
103
104#ifdef WANT_HISTOGRAM
105#ifdef HAVE_GETHRTIME
106hrtime_t time_one;
107hrtime_t time_two;
108#else
109static struct timeval time_one;
110static struct timeval time_two;
111#endif /* HAVE_GETHRTIME */
112static HIST time_hist;
113#endif /* WANT_HISTOGRAM */
114
115static char loc_xti_device[32] = "/dev/tcp";
116static char rem_xti_device[32] = "/dev/tcp";
117
118static int  xti_flags = 0;
119
120char xti_usage[] = "\n\
121Usage: netperf [global options] -- [test options] \n\
122\n\
123TCP/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\
134For those options taking two parms, at least one must be specified;\n\
135specifying one value without a comma will set both parms to that\n\
136value, specifying a value with a leading comma will set just the second\n\
137parm, a value with a trailing comma will set just the first. To set\n\
138each parm to unique values, specify both and separate them with a\n\
139comma.\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 */
149void
150get_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 */
165SOCKET
166create_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
455void
456send_xti_tcp_stream(char remote_host[])
457{
458
459  char *tput_title = "\
460Recv   Send    Send                          \n\
461Socket Socket  Message  Elapsed              \n\
462Size   Size    Size     Time     Throughput  \n\
463bytes  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 = "\
472Recv   Send    Send                          Utilization       Service Demand\n\
473Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
474Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
475bytes  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\
484Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
485Local  Remote  Local  Remote  Xfered   Per                 Per\n\
486Send   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\
490Maximum\n\
491Segment\n\
492Size (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
1240void
1241recv_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
1677void
1678send_xti_tcp_rr(char remote_host[])
1679{
1680
1681  char *tput_title = "\
1682Local /Remote\n\
1683Socket Size   Request  Resp.   Elapsed  Trans.\n\
1684Send   Recv   Size     Size    Time     Rate         \n\
1685bytes  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 = "\
1696Local /Remote\n\
1697Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
1698Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
1699bytes  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 = "\
1711Alignment      Offset\n\
1712Local  Remote  Local  Remote\n\
1713Send   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
2404void
2405send_xti_udp_stream(char remote_host[])
2406{
2407  /**********************************************************************/
2408  /*									*/
2409  /*               	UDP Unidirectional Send Test                    */
2410  /*									*/
2411  /**********************************************************************/
2412  char *tput_title = "\
2413Socket  Message  Elapsed      Messages                \n\
2414Size    Size     Time         Okay Errors   Throughput\n\
2415bytes   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 = "\
2426Socket  Message  Elapsed      Messages                   CPU      Service\n\
2427Size    Size     Time         Okay Errors   Throughput   Util     Demand\n\
2428bytes   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
3060void
3061recv_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
3395void send_xti_udp_rr(char remote_host[])
3396{
3397
3398  char *tput_title = "\
3399Local /Remote\n\
3400Socket Size   Request  Resp.   Elapsed  Trans.\n\
3401Send   Recv   Size     Size    Time     Rate         \n\
3402bytes  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 = "\
3413Local /Remote\n\
3414Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
3415Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
3416bytes  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 = "\
3428Alignment      Offset\n\
3429Local  Remote  Local  Remote\n\
3430Send   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. */
4141void
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 */
4527void
4528recv_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
4958void
4959send_xti_tcp_conn_rr(char remote_host[])
4960{
4961
4962  char *tput_title = "\
4963Local /Remote\n\
4964Socket Size   Request  Resp.   Elapsed  Trans.\n\
4965Send   Recv   Size     Size    Time     Rate         \n\
4966bytes  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 = "\
4977Local /Remote\n\
4978Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
4979Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
4980bytes  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 = "\
4992Alignment      Offset\n\
4993Local  Remote  Local  Remote\n\
4994Send   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
5346newport:
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
5542void
5543recv_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
5908void
5909print_xti_usage()
5910{
5911
5912  fwrite(xti_usage, sizeof(char), strlen(xti_usage), stdout);
5913  exit(1);
5914
5915}
5916
5917void
5918scan_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