1#ifndef lint
2char	nettest_sctp[]="\
3@(#)nettest_sctp.c (c) Copyright 2005-2007 Hewlett-Packard Co. Version 2.4.3";
4#else
5#define DIRTY
6#define WANT_HISTOGRAM
7#define WANT_INTERVALS
8#endif /* lint */
9
10/****************************************************************/
11/*								*/
12/*	nettest_sctp.c						*/
13/*								*/
14/*                                                              */
15/*      scan_sctp_args()        get the sctp command line args  */
16/*                                                              */
17/*	the actual test routines...				*/
18/*								*/
19/*	send_sctp_stream()	perform a sctp stream test	*/
20/*	recv_sctp_stream()					*/
21/*	send_sctp_rr()		perform a sctp request/response	*/
22/*	recv_sctp_rr()						*/
23/*	send_sctp_stream_udp()	perform a sctp request/response	*/
24/*	recv_sctp_stream_upd()	using UDP style API		*/
25/*	send_sctp_rr_udp()	perform a sctp request/response	*/
26/*	recv_sctp_rr_upd()	using UDP style API		*/
27/*								*/
28/*      relies on create_data_socket in nettest_bsd.c           */
29/****************************************************************/
30
31#if HAVE_CONFIG_H
32# include <config.h>
33#endif
34
35#if defined(WANT_SCTP)
36
37#include <sys/types.h>
38#include <fcntl.h>
39#include <errno.h>
40#include <signal.h>
41#include <stdio.h>
42#include <string.h>
43#include <time.h>
44#ifdef NOSTDLIBH
45#include <malloc.h>
46#else /* NOSTDLIBH */
47#include <stdlib.h>
48#endif /* NOSTDLIBH */
49
50#if !defined(__VMS)
51#include <sys/ipc.h>
52#endif /* !defined(__VMS) */
53#include <unistd.h>
54#include <sys/types.h>
55#include <sys/socket.h>
56#include <netinet/in.h>
57#include <netinet/tcp.h>
58#include <netinet/sctp.h>
59#include <arpa/inet.h>
60#include <netdb.h>
61
62/* would seem that not all sctp.h files define a MSG_EOF, but that
63   MSG_EOF can be the same as MSG_FIN so lets work with that
64   assumption.  initial find by Jon Pedersen. raj 2006-02-01 */
65#ifndef MSG_EOF
66#ifdef MSG_FIN
67#define MSG_EOF MSG_FIN
68#else
69#error Must have either MSG_EOF or MSG_FIN defined
70#endif
71#endif
72
73#include "netlib.h"
74#include "netsh.h"
75/* get some of the functions from nettest_bsd.c */
76#include "nettest_bsd.h"
77#include "nettest_sctp.h"
78
79#ifdef WANT_HISTOGRAM
80#ifdef __sgi
81#include <sys/time.h>
82#endif /* __sgi */
83#include "hist.h"
84#endif /* WANT_HISTOGRAM */
85
86#ifdef WANT_FIRST_BURST
87extern int first_burst_size;
88#endif /* WANT_FIRST_BURST */
89
90
91
92/* these variables are specific to SCTP tests. declare */
93/* them static to make them global only to this file. */
94
95static int
96  msg_count = 0,	/* number of messages to transmit on association */
97  non_block = 0,	/* default to blocking sockets */
98  num_associations = 1; /* number of associations on the endpoint */
99
100static  int confidence_iteration;
101static  char  local_cpu_method;
102static  char  remote_cpu_method;
103
104#ifdef WANT_HISTOGRAM
105static struct timeval time_one;
106static struct timeval time_two;
107static HIST time_hist;
108#endif /* WANT_HISTOGRAM */
109
110
111char sctp_usage[] = "\n\
112Usage: netperf [global options] -- [test options] \n\
113\n\
114SCTP Sockets Test Options:\n\
115    -b number         Send number requests at the start of _RR tests\n\
116    -D [L][,R]        Set SCTP_NODELAY locally and/or remotely\n\
117    -h                Display this text\n\
118    -H name,fam       Use name (or IP) and family as target of data connection\n\
119    -L name,fam       Use name (or IP) and family as source of data connextion\n\
120    -m bytes          Set the size of each sent message\n\
121    -M bytes          Set the size of each received messages\n\
122    -P local[,remote] Set the local/remote port for the data socket\n\
123    -r req,[rsp]      Set request/response sizes (_RR tests)\n\
124    -s send[,recv]    Set local socket send/recv buffer sizes\n\
125    -S send[,recv]    Set remote socket send/recv buffer sizes\n\
126    -V 		      Enable copy avoidance if supported\n\
127    -N number	      Specifies the number of messages to send (_STREAM tests)\n\
128    -B		      run the test in non-blocking mode\n\
129    -T number	      Number of associations to create (_MANY tests)\n\
130    -4                Use AF_INET (eg IPv4) on both ends of the data conn\n\
131    -6                Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
132\n\
133For those options taking two parms, at least one must be specified;\n\
134specifying one value without a comma will set both parms to that\n\
135value, specifying a value with a leading comma will set just the second\n\
136parm, a value with a trailing comma will set just the first. To set\n\
137each parm to unique values, specify both and separate them with a\n\
138comma.\n";
139
140
141 /* This routine is intended to retrieve interesting aspects of tcp */
142 /* for the data connection. at first, it attempts to retrieve the */
143 /* maximum segment size. later, it might be modified to retrieve */
144 /* other information, but it must be information that can be */
145 /* retrieved quickly as it is called during the timing of the test. */
146 /* for that reason, a second routine may be created that can be */
147 /* called outside of the timing loop */
148static
149void
150get_sctp_info(socket, mss)
151     int socket;
152     int *mss;
153{
154
155  int sock_opt_len;
156
157  if (sctp_opt_info(socket,
158		    0,
159		    SCTP_MAXSEG,
160		    mss,
161		    &sock_opt_len) < 0) {
162    lss_size = -1;
163  }
164}
165
166
167static
168void
169sctp_enable_events(socket, ev_mask)
170    int socket;
171    int ev_mask;
172{
173    struct sctp_event_subscribe ev;
174
175    bzero(&ev, sizeof(ev));
176
177    if (ev_mask & SCTP_SNDRCV_INFO_EV)
178	ev.sctp_data_io_event = 1;
179
180    if (ev_mask & SCTP_ASSOC_CHANGE_EV)
181	ev.sctp_association_event = 1;
182
183    if (ev_mask & SCTP_PEERADDR_CHANGE_EV)
184	ev.sctp_address_event = 1;
185
186    if (ev_mask & SCTP_SND_FAILED_EV)
187	ev.sctp_send_failure_event = 1;
188
189    if (ev_mask & SCTP_REMOTE_ERROR_EV)
190	ev.sctp_peer_error_event = 1;
191
192    if (ev_mask & SCTP_SHUTDOWN_EV)
193	ev.sctp_shutdown_event = 1;
194
195    if (ev_mask & SCTP_PD_EV)
196	ev.sctp_partial_delivery_event = 1;
197
198    if (ev_mask & SCTP_ADAPT_EV)
199#ifdef HAVE_SCTP_ADAPTATION_LAYER_EVENT
200	ev.sctp_adaptation_layer_event = 1;
201#else
202	ev.sctp_adaption_layer_event = 1;
203#endif
204
205    if (setsockopt(socket,
206		   IPPROTO_SCTP,
207#ifdef SCTP_EVENTS
208		   SCTP_EVENTS,
209#else
210		   SCTP_SET_EVENTS,
211#endif
212		   (const char*)&ev,
213		   sizeof(ev)) != 0 ) {
214      fprintf(where,
215	      "sctp_enable_event: could not set sctp events errno %d\n",
216	      errno);
217      fflush(where);
218      exit(1);
219    }
220}
221
222
223static
224sctp_disposition_t
225sctp_process_event(socket, buf)
226    int socket;
227    void *buf;
228{
229
230    struct sctp_assoc_change *sac;
231    struct sctp_send_failed *ssf;
232    struct sctp_paddr_change *spc;
233    struct sctp_remote_error *sre;
234    union sctp_notification *snp;
235
236    snp = buf;
237
238    switch (snp->sn_header.sn_type) {
239    case SCTP_ASSOC_CHANGE:
240	if (debug) {
241	    fprintf(where, "\tSCTP_ASSOC_CHANGE event, type:");
242	    fflush(where);
243	}
244	sac = &snp->sn_assoc_change;
245	switch (sac->sac_type) {
246	    case SCTP_COMM_UP:
247		if (debug) {
248		    fprintf(where, "  SCTP_COMM_UP\n");
249		    fflush(where);
250		}
251		break;
252	    case SCTP_RESTART:
253		if (debug) {
254		    fprintf(where, "  SCTP_RESTART\n");
255		    fflush(where);
256		}
257		break;
258	    case SCTP_CANT_STR_ASSOC:
259		if (debug) {
260		    fprintf(where, "  SCTP_CANT_STR_ASSOC\n");
261		    fflush(where);
262		}
263		break;	/* FIXME ignore above status changes */
264	    case SCTP_COMM_LOST:
265		if (debug) {
266		    fprintf(where, "  SCTP_COMM_LOST\n");
267		    fflush(where);
268		}
269		return SCTP_CLOSE;
270	    case SCTP_SHUTDOWN_COMP:
271		if (debug) {
272		    fprintf(where, "  SCTP_SHUTDOWN_COMPLETE\n");
273		    fflush(where);
274		}
275		return SCTP_CLOSE;
276		break;
277	}
278
279    case SCTP_SEND_FAILED:
280	if (debug) {
281	    fprintf(where, "\tSCTP_SEND_FAILED event\n");
282	    fflush(where);
283	}
284	ssf = &snp->sn_send_failed;
285	break;  /* FIXME ??? ignore this for now */
286
287    case SCTP_PEER_ADDR_CHANGE:
288	if (debug) {
289	    fprintf(where, "\tSCTP_PEER_ADDR_CHANGE event\n");
290	    fflush(where);
291	}
292	spc = &snp->sn_paddr_change;
293	break;	/* FIXME ??? ignore this for now */
294
295    case SCTP_REMOTE_ERROR:
296	if (debug) {
297	    fprintf(where, "\tSCTP_REMOTE_ERROR event\n");
298	    fflush(where);
299	}
300	sre = &snp->sn_remote_error;
301	break;	/* FIXME ??? ignore this for now */
302    case SCTP_SHUTDOWN_EVENT:
303	if (debug) {
304	    fprintf(where, "\tSCTP_SHUTDOWN event\n");
305	    fflush(where);
306	}
307	return SCTP_CLOSE;
308    default:
309	fprintf(where, "unknown type: %hu\n", snp->sn_header.sn_type);
310	fflush(where);
311	break;
312    }
313    return SCTP_OK;
314}
315
316
317
318/* This routine implements the SCTP unidirectional data transfer test */
319/* (a.k.a. stream) for the sockets interface. It receives its */
320/* parameters via global variables from the shell and writes its */
321/* output to the standard output. */
322
323
324void
325send_sctp_stream(remote_host)
326char	remote_host[];
327{
328
329  char *tput_title = "\
330Recv   Send    Send                          \n\
331Socket Socket  Message  Elapsed              \n\
332Size   Size    Size     Time     Throughput  \n\
333bytes  bytes   bytes    secs.    %s/sec  \n\n";
334
335  char *tput_fmt_0 =
336    "%7.2f\n";
337
338  char *tput_fmt_1 =
339    "%6d %6d %6d    %-6.2f   %7.2f   \n";
340
341  char *cpu_title = "\
342Recv   Send    Send                          Utilization       Service Demand\n\
343Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
344Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
345bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
346
347  char *cpu_fmt_0 =
348    "%6.3f %c\n";
349
350  char *cpu_fmt_1 =
351    "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
352
353  char *ksink_fmt = "\n\
354Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
355Local  Remote  Local  Remote  Xfered   Per                 Per\n\
356Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
357%5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
358
359  char *ksink_fmt2 = "\n\
360Maximum\n\
361Segment\n\
362Size (bytes)\n\
363%6d\n";
364
365
366  float			elapsed_time;
367
368#ifdef WANT_INTERVALS
369  int interval_count;
370  sigset_t signal_set;
371#endif
372
373  /* what we want is to have a buffer space that is at least one */
374  /* send-size greater than our send window. this will insure that we */
375  /* are never trying to re-use a buffer that may still be in the hands */
376  /* of the transport. This buffer will be malloc'd after we have found */
377  /* the size of the local senc socket buffer. We will want to deal */
378  /* with alignment and offset concerns as well. */
379
380#ifdef DIRTY
381  int	*message_int_ptr;
382#endif
383
384  struct ring_elt *send_ring;
385
386  int len;
387  unsigned int nummessages = 0;
388  int send_socket;
389  int bytes_remaining;
390  int sctp_mss;
391  int timed_out;
392
393  /* with links like fddi, one can send > 32 bits worth of bytes */
394  /* during a test... ;-) at some point, this should probably become a */
395  /* 64bit integral type, but those are not entirely common yet */
396  double	bytes_sent = 0.0;
397
398#ifdef DIRTY
399  int	i;
400#endif /* DIRTY */
401
402  float	local_cpu_utilization;
403  float	local_service_demand;
404  float	remote_cpu_utilization;
405  float	remote_service_demand;
406
407  double	thruput;
408
409  struct addrinfo	*remote_res;
410  struct addrinfo	*local_res;
411  struct addrinfo	*local_remote_res;
412  struct addrinfo	*local_local_res;
413
414  struct	sctp_stream_request_struct	*sctp_stream_request;
415  struct	sctp_stream_response_struct	*sctp_stream_response;
416  struct	sctp_stream_results_struct	*sctp_stream_result;
417
418  sctp_stream_request  =
419    (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
420  sctp_stream_response =
421    (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
422  sctp_stream_result   =
423    (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
424
425#ifdef WANT_HISTOGRAM
426  time_hist = HIST_new();
427#endif /* WANT_HISTOGRAM */
428  /* since we are now disconnected from the code that established the */
429  /* control socket, and since we want to be able to use different */
430  /* protocols and such, we are passed the name of the remote host and */
431  /* must turn that into the test specific addressing information. */
432
433  /* complete_addrinfos will either succede or exit the process */
434  complete_addrinfos(&remote_res,
435		     &local_res,
436		     remote_host,
437		     SOCK_STREAM,
438		     IPPROTO_SCTP,
439		     0);
440
441  if ( print_headers ) {
442    print_top_test_header("SCTP STREAM TEST", local_res, remote_res);
443  }
444
445  send_ring = NULL;
446  confidence_iteration = 1;
447  init_stat();
448
449  /* we have a great-big while loop which controls the number of times */
450  /* we run a particular test. this is for the calculation of a */
451  /* confidence interval (I really should have stayed awake during */
452  /* probstats :). If the user did not request confidence measurement */
453  /* (no confidence is the default) then we will only go though the */
454  /* loop once. the confidence stuff originates from the folks at IBM */
455
456  while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
457	 (confidence_iteration <= iteration_min)) {
458
459    /* initialize a few counters. we have to remember that we might be */
460    /* going through the loop more than once. */
461
462    nummessages    =	0;
463    bytes_sent     =	0.0;
464    times_up       = 	0;
465    timed_out	   =    0;
466
467    /*set up the data socket                        */
468    send_socket = create_data_socket(local_res);
469
470    if (send_socket == INVALID_SOCKET){
471      perror("netperf: send_sctp_stream: sctp stream data socket");
472      exit(1);
473    }
474
475    if (debug) {
476      fprintf(where,"send_sctp_stream: send_socket obtained...\n");
477    }
478
479    /* at this point, we have either retrieved the socket buffer sizes, */
480    /* or have tried to set them, so now, we may want to set the send */
481    /* size based on that (because the user either did not use a -m */
482    /* option, or used one with an argument of 0). If the socket buffer */
483    /* size is not available, we will set the send size to 4KB - no */
484    /* particular reason, just arbitrary... */
485    if (send_size == 0) {
486      if (lss_size > 0) {
487	send_size = lss_size;
488      }
489      else {
490	send_size = 4096;
491      }
492    }
493
494    /* set-up the data buffer ring with the requested alignment and offset. */
495    /* note also that we have allocated a quantity */
496    /* of memory that is at least one send-size greater than our socket */
497    /* buffer size. We want to be sure that there are at least two */
498    /* buffers allocated - this can be a bit of a problem when the */
499    /* send_size is bigger than the socket size, so we must check... the */
500    /* user may have wanted to explicitly set the "width" of our send */
501    /* buffers, we should respect that wish... */
502    if (send_width == 0) {
503      send_width = (lss_size/send_size) + 1;
504      if (send_width == 1) send_width++;
505    }
506
507    if (send_ring == NULL) {
508      /* only allocate the send ring once. this is a networking test, */
509      /* not a memory allocation test. this way, we do not need a */
510      /* deallocate_buffer_ring() routine, and I don't feel like */
511      /* writing one anyway :) raj 11/94 */
512      send_ring = allocate_buffer_ring(send_width,
513				       send_size,
514				       local_send_align,
515				       local_send_offset);
516    }
517
518    /* If the user has requested cpu utilization measurements, we must */
519    /* calibrate the cpu(s). We will perform this task within the tests */
520    /* themselves. If the user has specified the cpu rate, then */
521    /* calibrate_local_cpu will return rather quickly as it will have */
522    /* nothing to do. If local_cpu_rate is zero, then we will go through */
523    /* all the "normal" calibration stuff and return the rate back. */
524
525    if (local_cpu_usage) {
526      local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
527    }
528
529    /* Tell the remote end to do a listen. The server alters the socket */
530    /* paramters on the other side at this point, hence the reason for */
531    /* all the values being passed in the setup message. If the user did */
532    /* not specify any of the parameters, they will be passed as 0, which */
533    /* will indicate to the remote that no changes beyond the system's */
534    /* default should be used. Alignment is the exception, it will */
535    /* default to 1, which will be no alignment alterations. */
536
537    netperf_request.content.request_type	=	DO_SCTP_STREAM;
538    sctp_stream_request->send_buf_size	=	rss_size_req;
539    sctp_stream_request->recv_buf_size	=	rsr_size_req;
540    sctp_stream_request->receive_size	=	recv_size;
541    sctp_stream_request->no_delay	=	rem_nodelay;
542    sctp_stream_request->recv_alignment	=	remote_recv_align;
543    sctp_stream_request->recv_offset	=	remote_recv_offset;
544    sctp_stream_request->measure_cpu	=	remote_cpu_usage;
545    sctp_stream_request->cpu_rate	=	remote_cpu_rate;
546    if (test_time) {
547      sctp_stream_request->test_length	=	test_time;
548    }
549    else {
550      if (msg_count)
551	  test_bytes = send_size * msg_count;
552
553      sctp_stream_request->test_length	=	test_bytes;
554    }
555    sctp_stream_request->so_rcvavoid	=	rem_rcvavoid;
556    sctp_stream_request->so_sndavoid	=	rem_sndavoid;
557#ifdef DIRTY
558    sctp_stream_request->dirty_count    =       rem_dirty_count;
559    sctp_stream_request->clean_count    =       rem_clean_count;
560#endif /* DIRTY */
561    sctp_stream_request->port		=	htonl(atoi(remote_data_port));
562    sctp_stream_request->ipfamily	=	af_to_nf(remote_res->ai_family);
563    sctp_stream_request->non_blocking   =	non_block;
564
565
566    if (debug > 1) {
567      fprintf(where,
568	      "netperf: send_sctp_stream: requesting sctp stream test\n");
569    }
570
571    send_request();
572
573    /* The response from the remote will contain all of the relevant 	*/
574    /* socket parameters for this test type. We will put them back into */
575    /* the variables here so they can be displayed if desired.  The	*/
576    /* remote will have calibrated CPU if necessary, and will have done	*/
577    /* all the needed set-up we will have calibrated the cpu locally	*/
578    /* before sending the request, and will grab the counter value right*/
579    /* after the connect returns. The remote will grab the counter right*/
580    /* after the accept call. This saves the hassle of extra messages	*/
581    /* being sent for the sctp tests.					*/
582
583    recv_response();
584
585    if (!netperf_response.content.serv_errno) {
586      if (debug)
587	fprintf(where,"remote listen done.\n");
588      rsr_size	      =	sctp_stream_response->recv_buf_size;
589      rss_size	      =	sctp_stream_response->send_buf_size;
590      rem_nodelay     =	sctp_stream_response->no_delay;
591      remote_cpu_usage=	sctp_stream_response->measure_cpu;
592      remote_cpu_rate = sctp_stream_response->cpu_rate;
593
594      /* we have to make sure that the server port number is in */
595      /* network order */
596      set_port_number(remote_res, (short)sctp_stream_response->data_port_number);
597
598      rem_rcvavoid	= sctp_stream_response->so_rcvavoid;
599      rem_sndavoid	= sctp_stream_response->so_sndavoid;
600    }
601    else {
602      Set_errno(netperf_response.content.serv_errno);
603      fprintf(where,
604	      "netperf: remote error %d",
605	      netperf_response.content.serv_errno);
606      perror("");
607      fflush(where);
608
609      exit(1);
610    }
611
612    /*Connect up to the remote port on the data socket  */
613    if (connect(send_socket,
614		remote_res->ai_addr,
615		remote_res->ai_addrlen) == INVALID_SOCKET) {
616      perror("netperf: send_sctp_stream: data socket connect failed");
617      exit(1);
618    }
619
620    sctp_enable_events(send_socket, SCTP_ASSOC_CHANGE_EV);
621
622    if (non_block) {
623	/* now that we are connected, mark the socket as non-blocking */
624	if (!set_nonblock(send_socket)) {
625	  perror("netperf: fcntl");
626	  exit(1);
627	}
628    }
629
630    /* Data Socket set-up is finished. If there were problems, either */
631    /* the connect would have failed, or the previous response would */
632    /* have indicated a problem. I failed to see the value of the */
633    /* extra  message after the accept on the remote. If it failed, */
634    /* we'll see it here. If it didn't, we might as well start pumping */
635    /* data. */
636
637    /* Set-up the test end conditions. For a stream test, they can be */
638    /* either time or byte-count based. */
639
640    if (test_time) {
641      /* The user wanted to end the test after a period of time. */
642      times_up = 0;
643      bytes_remaining = 0;
644      /* in previous revisions, we had the same code repeated throught */
645      /* all the test suites. this was unnecessary, and meant more */
646      /* work for me when I wanted to switch to POSIX signals, so I */
647      /* have abstracted this out into a routine in netlib.c. if you */
648      /* are experiencing signal problems, you might want to look */
649      /* there. raj 11/94 */
650      start_timer(test_time);
651    }
652    else {
653      /* The tester wanted to send a number of bytes. */
654      bytes_remaining = test_bytes;
655      times_up = 1;
656    }
657
658    /* The cpu_start routine will grab the current time and possibly */
659    /* value of the idle counter for later use in measuring cpu */
660    /* utilization and/or service demand and thruput. */
661
662    cpu_start(local_cpu_usage);
663
664#ifdef WANT_INTERVALS
665    if ((interval_burst) || (demo_mode)) {
666      /* zero means that we never pause, so we never should need the */
667      /* interval timer, unless we are in demo_mode */
668      start_itimer(interval_wate);
669    }
670    interval_count = interval_burst;
671    /* get the signal set for the call to sigsuspend */
672    if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
673      fprintf(where,
674	      "send_sctp_stream: unable to get sigmask errno %d\n",
675	      errno);
676      fflush(where);
677      exit(1);
678    }
679#endif /* WANT_INTERVALS */
680
681#ifdef DIRTY
682    /* initialize the random number generator for putting dirty stuff */
683    /* into the send buffer. raj */
684    srand((int) getpid());
685#endif
686
687    /* before we start, initialize a few variables */
688
689    /* We use an "OR" to control test execution. When the test is */
690    /* controlled by time, the byte count check will always return false. */
691    /* When the test is controlled by byte count, the time test will */
692    /* always return false. When the test is finished, the whole */
693    /* expression will go false and we will stop sending data. */
694
695    while ((!times_up) || (bytes_remaining > 0)) {
696
697#ifdef DIRTY
698      /* we want to dirty some number of consecutive integers in the buffer */
699      /* we are about to send. we may also want to bring some number of */
700      /* them cleanly into the cache. The clean ones will follow any dirty */
701      /* ones into the cache. at some point, we might want to replace */
702      /* the rand() call with something from a table to reduce our call */
703      /* overhead during the test, but it is not a high priority item. */
704      message_int_ptr = (int *)(send_ring->buffer_ptr);
705      for (i = 0; i < loc_dirty_count; i++) {
706	*message_int_ptr = rand();
707	message_int_ptr++;
708      }
709      for (i = 0; i < loc_clean_count; i++) {
710	loc_dirty_count = *message_int_ptr;
711	message_int_ptr++;
712      }
713#endif /* DIRTY */
714
715#ifdef WANT_HISTOGRAM
716      /* timestamp just before we go into send and then again just after */
717      /* we come out raj 8/94 */
718      HIST_timestamp(&time_one);
719#endif /* WANT_HISTOGRAM */
720
721      while ((len=sctp_sendmsg(send_socket,
722			       send_ring->buffer_ptr, send_size,
723			       NULL, 0,
724			       0, 0, 0, 0, 0)) != send_size) {
725	if (non_block && errno == EAGAIN)
726	    continue;
727	else if ((len >=0) || SOCKET_EINTR(len)) {
728	  /* the test was interrupted, must be the end of test */
729	  timed_out = 1;
730	  break;
731	}
732	perror("netperf: data send error");
733	printf("len was %d\n",len);
734	exit(1);
735      }
736
737      if (timed_out)
738	  break;	/* we timed out durint sendmsg, done with test */
739
740#ifdef WANT_HISTOGRAM
741      /* timestamp the exit from the send call and update the histogram */
742      HIST_timestamp(&time_two);
743      HIST_add(time_hist,delta_micro(&time_one,&time_two));
744#endif /* WANT_HISTOGRAM */
745
746#ifdef WANT_INTERVALS
747      if (demo_mode) {
748	units_this_tick += send_size;
749      }
750      /* in this case, the interval count is the count-down couter */
751      /* to decide to sleep for a little bit */
752      if ((interval_burst) && (--interval_count == 0)) {
753	/* call sigsuspend and wait for the interval timer to get us */
754	/* out */
755	if (debug > 1) {
756	  fprintf(where,"about to suspend\n");
757	  fflush(where);
758	}
759	if (sigsuspend(&signal_set) == EFAULT) {
760	  fprintf(where,
761		  "send_sctp_stream: fault with sigsuspend.\n");
762	  fflush(where);
763	  exit(1);
764	}
765	interval_count = interval_burst;
766      }
767#endif /* WANT_INTERVALS */
768
769      /* now we want to move our pointer to the next position in the */
770      /* data buffer...we may also want to wrap back to the "beginning" */
771      /* of the bufferspace, so we will mod the number of messages sent */
772      /* by the send width, and use that to calculate the offset to add */
773      /* to the base pointer. */
774      nummessages++;
775      send_ring = send_ring->next;
776      if (bytes_remaining) {
777	bytes_remaining -= send_size;
778      }
779    }
780
781    /* The test is over. Flush the buffers to the remote end. We do a */
782    /* graceful release to insure that all data has been taken by the */
783    /* remote. */
784
785    /* but first, if the verbosity is greater than 1, find-out what */
786    /* the sctp maximum segment_size was (if possible) */
787    if (verbosity > 1) {
788      sctp_mss = -1;
789      get_sctp_info(send_socket, &sctp_mss);
790    }
791
792    shutdown(send_socket, SHUT_WR);
793
794    /* The test server will signal to us when it wants to shutdown.
795     * In blocking mode, we can call recvmsg.  In non-blocking
796     * mode, we need to select on the socket for reading.
797     * We'll assume that all returns are succefull
798     */
799    if (non_block) {
800	fd_set readfds;
801
802	FD_ZERO(&readfds);
803	FD_SET(send_socket, &readfds);
804	select(send_socket+1, &readfds, NULL, NULL, NULL);
805    } else {
806	sctp_recvmsg(send_socket, send_ring->buffer_ptr, send_size, NULL,
807		0, NULL, 0);
808    }
809
810    /* this call will always give us the elapsed time for the test, and */
811    /* will also store-away the necessaries for cpu utilization */
812
813    cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
814						/* measured and how */
815						/* long did we really */
816						/* run? */
817
818    /* we are finished with the socket, so close it to prevent hitting */
819    /* the limit on maximum open files. */
820    close(send_socket);
821
822    /* Get the statistics from the remote end. The remote will have */
823    /* calculated service demand and all those interesting things. If it */
824    /* wasn't supposed to care, it will return obvious values. */
825
826    recv_response();
827    if (!netperf_response.content.serv_errno) {
828      if (debug)
829	fprintf(where,"remote results obtained\n");
830    }
831    else {
832      Set_errno(netperf_response.content.serv_errno);
833      fprintf(where,
834	      "netperf: remote error %d",
835	      netperf_response.content.serv_errno);
836      perror("");
837      fflush(where);
838
839      exit(1);
840    }
841
842    /* We now calculate what our thruput was for the test. In the future, */
843    /* we may want to include a calculation of the thruput measured by */
844    /* the remote, but it should be the case that for a sctp stream test, */
845    /* that the two numbers should be *very* close... We calculate */
846    /* bytes_sent regardless of the way the test length was controlled. */
847    /* If it was time, we needed to, and if it was by bytes, the user may */
848    /* have specified a number of bytes that wasn't a multiple of the */
849    /* send_size, so we really didn't send what he asked for ;-) */
850
851    bytes_sent	= ntohd(sctp_stream_result->bytes_received);
852
853    thruput	= (double) calc_thruput(bytes_sent);
854
855    if (local_cpu_usage || remote_cpu_usage) {
856      /* We must now do a little math for service demand and cpu */
857      /* utilization for the system(s) */
858      /* Of course, some of the information might be bogus because */
859      /* there was no idle counter in the kernel(s). We need to make */
860      /* a note of this for the user's benefit...*/
861      if (local_cpu_usage) {
862
863	local_cpu_utilization	= calc_cpu_util(0.0);
864	local_service_demand	= calc_service_demand(bytes_sent,
865						      0.0,
866						      0.0,
867						      0);
868      }
869      else {
870	local_cpu_utilization	= (float) -1.0;
871	local_service_demand	= (float) -1.0;
872      }
873
874      if (remote_cpu_usage) {
875
876	remote_cpu_utilization	= sctp_stream_result->cpu_util;
877	remote_service_demand	= calc_service_demand(bytes_sent,
878						      0.0,
879						      remote_cpu_utilization,
880						      sctp_stream_result->num_cpus);
881      }
882      else {
883	remote_cpu_utilization = (float) -1.0;
884	remote_service_demand  = (float) -1.0;
885      }
886    }
887    else {
888      /* we were not measuring cpu, for the confidence stuff, we */
889      /* should make it -1.0 */
890      local_cpu_utilization	= (float) -1.0;
891      local_service_demand	= (float) -1.0;
892      remote_cpu_utilization = (float) -1.0;
893      remote_service_demand  = (float) -1.0;
894    }
895
896    /* at this point, we want to calculate the confidence information. */
897    /* if debugging is on, calculate_confidence will print-out the */
898    /* parameters we pass it */
899
900    calculate_confidence(confidence_iteration,
901			 elapsed_time,
902			 thruput,
903			 local_cpu_utilization,
904			 remote_cpu_utilization,
905			 local_service_demand,
906			 remote_service_demand);
907
908
909    confidence_iteration++;
910  }
911
912  /* at this point, we have finished making all the runs that we */
913  /* will be making. so, we should extract what the calcuated values */
914  /* are for all the confidence stuff. we could make the values */
915  /* global, but that seemed a little messy, and it did not seem worth */
916  /* all the mucking with header files. so, we create a routine much */
917  /* like calcualte_confidence, which just returns the mean values. */
918  /* raj 11/94 */
919
920  retrieve_confident_values(&elapsed_time,
921			    &thruput,
922			    &local_cpu_utilization,
923			    &remote_cpu_utilization,
924			    &local_service_demand,
925			    &remote_service_demand);
926
927  /* We are now ready to print all the information. If the user */
928  /* has specified zero-level verbosity, we will just print the */
929  /* local service demand, or the remote service demand. If the */
930  /* user has requested verbosity level 1, he will get the basic */
931  /* "streamperf" numbers. If the user has specified a verbosity */
932  /* of greater than 1, we will display a veritable plethora of */
933  /* background information from outside of this block as it it */
934  /* not cpu_measurement specific...  */
935
936  if (confidence < 0) {
937    /* we did not hit confidence, but were we asked to look for it? */
938    if (iteration_max > 1) {
939      display_confidence();
940    }
941  }
942
943  if (local_cpu_usage || remote_cpu_usage) {
944    local_cpu_method = format_cpu_method(cpu_method);
945    remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method);
946
947    switch (verbosity) {
948    case 0:
949      if (local_cpu_usage) {
950	fprintf(where,
951		cpu_fmt_0,
952		local_service_demand,
953		local_cpu_method);
954      }
955      else {
956	fprintf(where,
957		cpu_fmt_0,
958		remote_service_demand,
959		remote_cpu_method);
960      }
961      break;
962    case 1:
963    case 2:
964      if (print_headers) {
965	fprintf(where,
966		cpu_title,
967		format_units(),
968		local_cpu_method,
969		remote_cpu_method);
970      }
971
972      fprintf(where,
973	      cpu_fmt_1,		/* the format string */
974	      rsr_size,		        /* remote recvbuf size */
975	      lss_size,		        /* local sendbuf size */
976	      send_size,		/* how large were the sends */
977	      elapsed_time,		/* how long was the test */
978	      thruput, 		        /* what was the xfer rate */
979	      local_cpu_utilization,	/* local cpu */
980	      remote_cpu_utilization,	/* remote cpu */
981	      local_service_demand,	/* local service demand */
982	      remote_service_demand);	/* remote service demand */
983      break;
984    }
985  }
986  else {
987    /* The tester did not wish to measure service demand. */
988
989    switch (verbosity) {
990    case 0:
991      fprintf(where,
992	      tput_fmt_0,
993	      thruput);
994      break;
995    case 1:
996    case 2:
997      if (print_headers) {
998	fprintf(where,tput_title,format_units());
999      }
1000      fprintf(where,
1001	      tput_fmt_1,		/* the format string */
1002	      rsr_size, 		/* remote recvbuf size */
1003	      lss_size, 		/* local sendbuf size */
1004	      send_size,		/* how large were the sends */
1005	      elapsed_time, 		/* how long did it take */
1006	      thruput);/* how fast did it go */
1007      break;
1008    }
1009  }
1010
1011  /* it would be a good thing to include information about some of the */
1012  /* other parameters that may have been set for this test, but at the */
1013  /* moment, I do not wish to figure-out all the  formatting, so I will */
1014  /* just put this comment here to help remind me that it is something */
1015  /* that should be done at a later time. */
1016
1017  if (verbosity > 1) {
1018    /* The user wanted to know it all, so we will give it to him. */
1019    /* This information will include as much as we can find about */
1020    /* sctp statistics, the alignments of the sends and receives */
1021    /* and all that sort of rot... */
1022
1023    /* this stuff needs to be worked-out in the presence of confidence */
1024    /* intervals and multiple iterations of the test... raj 11/94 */
1025
1026    fprintf(where,
1027	    ksink_fmt,
1028	    "Bytes",
1029	    "Bytes",
1030	    "Bytes",
1031	    local_send_align,
1032	    remote_recv_align,
1033	    local_send_offset,
1034	    remote_recv_offset,
1035	    bytes_sent,
1036	    bytes_sent / (double)nummessages,
1037	    nummessages,
1038	    bytes_sent / (double)sctp_stream_result->recv_calls,
1039	    sctp_stream_result->recv_calls);
1040    fprintf(where,
1041	    ksink_fmt2,
1042	    sctp_mss);
1043    fflush(where);
1044#ifdef WANT_HISTOGRAM
1045    fprintf(where,"\n\nHistogram of time spent in send() call.\n");
1046    fflush(where);
1047    HIST_report(time_hist);
1048#endif /* WANT_HISTOGRAM */
1049  }
1050
1051}
1052
1053
1054
1055
1056/* This is the server-side routine for the sctp stream test. It is */
1057/* implemented as one routine. I could break things-out somewhat, but */
1058/* didn't feel it was necessary. */
1059
1060void
1061recv_sctp_stream()
1062{
1063
1064  struct sockaddr_in myaddr_in; /* needed to get port number */
1065  struct sockaddr_storage peeraddr;	/* used in accept */
1066  int	s_listen,s_data;
1067  int 	addrlen;
1068  int	len;
1069  unsigned int	receive_calls;
1070  float	elapsed_time;
1071  double   bytes_received;
1072
1073  struct ring_elt *recv_ring;
1074
1075  struct addrinfo *local_res;
1076  char local_name[BUFSIZ];
1077  char port_buffer[PORTBUFSIZE];
1078  int  msg_flags = 0;
1079
1080#ifdef DIRTY
1081  int   *message_int_ptr;
1082  int   dirty_count;
1083  int   clean_count;
1084  int   i;
1085#endif
1086
1087#ifdef DO_SELECT
1088  fd_set readfds;
1089  struct timeval timeout;
1090#endif /* DO_SELECT */
1091
1092  struct	sctp_stream_request_struct	*sctp_stream_request;
1093  struct	sctp_stream_response_struct	*sctp_stream_response;
1094  struct	sctp_stream_results_struct	*sctp_stream_results;
1095
1096#ifdef DO_SELECT
1097  FD_ZERO(&readfds);
1098  timeout.tv_sec = 1;
1099  timeout.tv_usec = 0;
1100#endif /* DO_SELECT */
1101
1102  sctp_stream_request	=
1103    (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
1104  sctp_stream_response	=
1105    (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
1106  sctp_stream_results	=
1107    (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
1108
1109  if (debug) {
1110    fprintf(where,"netserver: recv_sctp_stream: entered...\n");
1111    fflush(where);
1112  }
1113
1114  /* We want to set-up the listen socket with all the desired */
1115  /* parameters and then let the initiator know that all is ready. If */
1116  /* socket size defaults are to be used, then the initiator will have */
1117  /* sent us 0's. If the socket sizes cannot be changed, then we will */
1118  /* send-back what they are. If that information cannot be determined, */
1119  /* then we send-back -1's for the sizes. If things go wrong for any */
1120  /* reason, we will drop back ten yards and punt. */
1121
1122  /* If anything goes wrong, we want the remote to know about it. It */
1123  /* would be best if the error that the remote reports to the user is */
1124  /* the actual error we encountered, rather than some bogus unexpected */
1125  /* response type message. */
1126
1127  if (debug) {
1128    fprintf(where,"recv_sctp_stream: setting the response type...\n");
1129    fflush(where);
1130  }
1131
1132  netperf_response.content.response_type = SCTP_STREAM_RESPONSE;
1133
1134  if (debug) {
1135    fprintf(where,"recv_sctp_stream: the response type is set...\n");
1136    fflush(where);
1137  }
1138
1139  /* We now alter the message_ptr variable to be at the desired */
1140  /* alignment with the desired offset. */
1141
1142  if (debug) {
1143    fprintf(where,"recv_sctp_stream: requested alignment of %d\n",
1144	    sctp_stream_request->recv_alignment);
1145    fflush(where);
1146  }
1147
1148  /* create_data_socket expects to find some things in the global */
1149  /* variables, so set the globals based on the values in the request. */
1150  /* once the socket has been created, we will set the response values */
1151  /* based on the updated value of those globals. raj 7/94 */
1152  lss_size_req = sctp_stream_request->send_buf_size;
1153  lsr_size_req = sctp_stream_request->recv_buf_size;
1154  loc_nodelay = sctp_stream_request->no_delay;
1155  loc_rcvavoid = sctp_stream_request->so_rcvavoid;
1156  loc_sndavoid = sctp_stream_request->so_sndavoid;
1157  non_block = sctp_stream_request->non_blocking;
1158
1159  set_hostname_and_port(local_name,
1160			port_buffer,
1161			nf_to_af(sctp_stream_request->ipfamily),
1162			sctp_stream_request->port);
1163
1164  local_res = complete_addrinfo(local_name,
1165				local_name,
1166				port_buffer,
1167				nf_to_af(sctp_stream_request->ipfamily),
1168				SOCK_STREAM,
1169				IPPROTO_SCTP,
1170				0);
1171
1172  s_listen = create_data_socket(local_res);
1173
1174  if (s_listen < 0) {
1175    netperf_response.content.serv_errno = errno;
1176    send_response();
1177    exit(1);
1178  }
1179
1180  /* what sort of sizes did we end-up with? */
1181  if (sctp_stream_request->receive_size == 0) {
1182    if (lsr_size > 0) {
1183      recv_size = lsr_size;
1184    }
1185    else {
1186      recv_size = 4096;
1187    }
1188  }
1189  else {
1190    recv_size = sctp_stream_request->receive_size;
1191  }
1192
1193  /* we want to set-up our recv_ring in a manner analagous to what we */
1194  /* do on the sending side. this is more for the sake of symmetry */
1195  /* than for the needs of say copy avoidance, but it might also be */
1196  /* more realistic - this way one could conceivably go with a */
1197  /* double-buffering scheme when taking the data an putting it into */
1198  /* the filesystem or something like that. raj 7/94 */
1199
1200  if (recv_width == 0) {
1201    recv_width = (lsr_size/recv_size) + 1;
1202    if (recv_width == 1) recv_width++;
1203  }
1204
1205  recv_ring = allocate_buffer_ring(recv_width,
1206				   recv_size,
1207				   sctp_stream_request->recv_alignment,
1208				   sctp_stream_request->recv_offset);
1209
1210  if (debug) {
1211    fprintf(where,"recv_sctp_stream: set recv_size = %d, align = %d, offset = %d.\n",
1212		   recv_size, sctp_stream_request->recv_alignment,
1213		   sctp_stream_request->recv_offset);
1214    fflush(where);
1215  }
1216
1217  /* now get the port number assigned by the system  */
1218  addrlen = sizeof(myaddr_in);
1219  if (getsockname(s_listen,
1220		  (struct sockaddr *)&myaddr_in,
1221		  &addrlen) == -1){
1222    netperf_response.content.serv_errno = errno;
1223    close(s_listen);
1224    send_response();
1225
1226    exit(1);
1227  }
1228
1229  /* Now myaddr_in contains the port and the internet address this is */
1230  /* returned to the sender also implicitly telling the sender that the */
1231  /* socket buffer sizing has been done. */
1232
1233  sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
1234  netperf_response.content.serv_errno   = 0;
1235
1236  /* But wait, there's more. If the initiator wanted cpu measurements, */
1237  /* then we must call the calibrate routine, which will return the max */
1238  /* rate back to the initiator. If the CPU was not to be measured, or */
1239  /* something went wrong with the calibration, we will return a -1 to */
1240  /* the initiator. */
1241
1242  sctp_stream_response->cpu_rate = (float)0.0; 	/* assume no cpu */
1243  if (sctp_stream_request->measure_cpu) {
1244    sctp_stream_response->measure_cpu = 1;
1245    sctp_stream_response->cpu_rate =
1246      calibrate_local_cpu(sctp_stream_request->cpu_rate);
1247  }
1248  else {
1249    sctp_stream_response->measure_cpu = 0;
1250  }
1251
1252  /* before we send the response back to the initiator, pull some of */
1253  /* the socket parms from the globals */
1254  sctp_stream_response->send_buf_size = lss_size;
1255  sctp_stream_response->recv_buf_size = lsr_size;
1256  sctp_stream_response->no_delay = loc_nodelay;
1257  sctp_stream_response->so_rcvavoid = loc_rcvavoid;
1258  sctp_stream_response->so_sndavoid = loc_sndavoid;
1259  sctp_stream_response->receive_size = recv_size;
1260
1261  /* Now, let's set-up the socket to listen for connections */
1262  if (listen(s_listen, 5) == -1) {
1263    netperf_response.content.serv_errno = errno;
1264    close(s_listen);
1265    send_response();
1266
1267    exit(1);
1268  }
1269
1270  send_response();
1271
1272  addrlen = sizeof(peeraddr);
1273
1274  if ((s_data = accept(s_listen,
1275		      (struct sockaddr *)&peeraddr,
1276		      &addrlen)) == INVALID_SOCKET) {
1277    /* Let's just punt. The remote will be given some information */
1278    close(s_listen);
1279    exit(1);
1280  }
1281
1282  sctp_enable_events(s_data, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV);
1283
1284  /* now that we are connected, mark the socket as non-blocking */
1285  if (non_block) {
1286      fprintf(where, "setting socket as nonblocking\n");
1287      fflush(where);
1288      if (!set_nonblock(s_data)) {
1289	close(s_data);
1290	exit(1);
1291      }
1292  }
1293
1294#ifdef KLUDGE_SOCKET_OPTIONS
1295  /* this is for those systems which *INCORRECTLY* fail to pass */
1296  /* attributes across an accept() call. Including this goes against */
1297  /* my better judgement :( raj 11/95 */
1298
1299  kludge_socket_options(s_data);
1300
1301#endif /* KLUDGE_SOCKET_OPTIONS */
1302
1303  /* Now it's time to start receiving data on the connection. We will */
1304  /* first grab the apropriate counters and then start grabbing. */
1305
1306  cpu_start(sctp_stream_request->measure_cpu);
1307
1308  /* The loop will exit when the sender does a shutdown, which will */
1309  /* return a length of zero   */
1310
1311#ifdef DIRTY
1312    /* we want to dirty some number of consecutive integers in the buffer */
1313    /* we are about to recv. we may also want to bring some number of */
1314    /* them cleanly into the cache. The clean ones will follow any dirty */
1315    /* ones into the cache. */
1316
1317  dirty_count = sctp_stream_request->dirty_count;
1318  clean_count = sctp_stream_request->clean_count;
1319  message_int_ptr = (int *)recv_ring->buffer_ptr;
1320  for (i = 0; i < dirty_count; i++) {
1321    *message_int_ptr = rand();
1322    message_int_ptr++;
1323  }
1324  for (i = 0; i < clean_count; i++) {
1325    dirty_count = *message_int_ptr;
1326    message_int_ptr++;
1327  }
1328#endif /* DIRTY */
1329
1330  bytes_received = 0;
1331  receive_calls  = 0;
1332
1333  while ((len = sctp_recvmsg(s_data,
1334			    recv_ring->buffer_ptr, recv_size,
1335			    NULL, 0, NULL, &msg_flags)) != 0) {
1336    if (len == SOCKET_ERROR) {
1337	if (non_block && errno == EAGAIN) {
1338	   if (debug){
1339	     fprintf(where,
1340		    "recv_sctp_stream: sctp_recvmsg timed out, trying again\n");
1341	     fflush(where);
1342	   }
1343	   Set_errno(0);
1344	   continue;
1345	}
1346	if (debug) {
1347	    fprintf(where,
1348		    "recv_sctp_stream: sctp_recvmsg error %d, exiting",
1349		    errno);
1350	    fflush(where);
1351        }
1352	netperf_response.content.serv_errno = errno;
1353	send_response();
1354	close(s_data);
1355	exit(1);
1356    }
1357
1358    if (msg_flags & MSG_NOTIFICATION) {
1359	 msg_flags = 0;
1360	 if (debug) {
1361	   fprintf(where,
1362		    "recv_sctp_stream: Got notification... processing\n");
1363	     fflush(where);
1364	}
1365	if (sctp_process_event(s_data, recv_ring->buffer_ptr) == SCTP_CLOSE)
1366	    break;	/* break out of the recvmsg loop */
1367
1368	continue;
1369    }
1370
1371    bytes_received += len;
1372    receive_calls++;
1373
1374    /* more to the next buffer in the recv_ring */
1375    recv_ring = recv_ring->next;
1376
1377#ifdef PAUSE
1378    sleep(1);
1379#endif /* PAUSE */
1380
1381#ifdef DIRTY
1382    message_int_ptr = (int *)(recv_ring->buffer_ptr);
1383    for (i = 0; i < dirty_count; i++) {
1384      *message_int_ptr = rand();
1385      message_int_ptr++;
1386    }
1387    for (i = 0; i < clean_count; i++) {
1388      dirty_count = *message_int_ptr;
1389      message_int_ptr++;
1390    }
1391#endif /* DIRTY */
1392
1393#ifdef DO_SELECT
1394	FD_SET(s_data,&readfds);
1395	select(s_data+1,&readfds,NULL,NULL,&timeout);
1396#endif /* DO_SELECT */
1397
1398  }
1399
1400  /* perform a shutdown to signal the sender that */
1401  /* we have received all the data sent. raj 4/93 */
1402
1403  if (close(s_data) == -1) {
1404      netperf_response.content.serv_errno = errno;
1405      send_response();
1406      exit(1);
1407    }
1408
1409  cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time);
1410
1411  /* send the results to the sender			*/
1412
1413  if (debug) {
1414    fprintf(where,
1415	    "recv_sctp_stream: got %g bytes\n",
1416	    bytes_received);
1417    fprintf(where,
1418	    "recv_sctp_stream: got %d recvs\n",
1419	    receive_calls);
1420    fflush(where);
1421  }
1422
1423  sctp_stream_results->bytes_received	= htond(bytes_received);
1424  sctp_stream_results->elapsed_time	= elapsed_time;
1425  sctp_stream_results->recv_calls	= receive_calls;
1426
1427  if (sctp_stream_request->measure_cpu) {
1428    sctp_stream_results->cpu_util	= calc_cpu_util(0.0);
1429  };
1430
1431  if (debug) {
1432    fprintf(where,
1433	    "recv_sctp_stream: test complete, sending results.\n");
1434    fprintf(where,
1435	    "                 bytes_received %g receive_calls %d\n",
1436	    bytes_received,
1437	    receive_calls);
1438    fprintf(where,
1439	    "                 len %d\n",
1440	    len);
1441    fflush(where);
1442  }
1443
1444  sctp_stream_results->cpu_method = cpu_method;
1445  sctp_stream_results->num_cpus   = lib_num_loc_cpus;
1446  send_response();
1447
1448  /* we are now done with the sockets */
1449  close(s_listen);
1450
1451}
1452
1453
1454/* This routine implements the SCTP unidirectional data transfer test */
1455/* (a.k.a. stream) for the sockets interface. It receives its */
1456/* parameters via global variables from the shell and writes its */
1457/* output to the standard output. */
1458
1459
1460void
1461send_sctp_stream_1toMany(remote_host)
1462char	remote_host[];
1463{
1464
1465  char *tput_title = "\
1466Recv   Send    Send                          \n\
1467Socket Socket  Message  Elapsed              \n\
1468Size   Size    Size     Time     Throughput  \n\
1469bytes  bytes   bytes    secs.    %s/sec  \n\n";
1470
1471  char *tput_fmt_0 =
1472    "%7.2f\n";
1473
1474  char *tput_fmt_1 =
1475    "%6d %6d %6d    %-6.2f   %7.2f   \n";
1476
1477  char *cpu_title = "\
1478Recv   Send    Send                          Utilization       Service Demand\n\
1479Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
1480Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
1481bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
1482
1483  char *cpu_fmt_0 =
1484    "%6.3f %c\n";
1485
1486  char *cpu_fmt_1 =
1487    "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f\n";
1488
1489  char *ksink_fmt = "\n\
1490Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
1491Local  Remote  Local  Remote  Xfered   Per                 Per\n\
1492Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
1493%5d   %5d  %5d   %5d %6.4g  %6.2f    %6d   %6.2f %6d\n";
1494
1495  char *ksink_fmt2 = "\n\
1496Maximum\n\
1497Segment\n\
1498Size (bytes)\n\
1499%6d\n";
1500
1501
1502  float			elapsed_time;
1503
1504#ifdef WANT_INTERVALS
1505  int interval_count;
1506  sigset_t signal_set;
1507#endif
1508
1509  /* what we want is to have a buffer space that is at least one */
1510  /* send-size greater than our send window. this will insure that we */
1511  /* are never trying to re-use a buffer that may still be in the hands */
1512  /* of the transport. This buffer will be malloc'd after we have found */
1513  /* the size of the local senc socket buffer. We will want to deal */
1514  /* with alignment and offset concerns as well. */
1515
1516#ifdef DIRTY
1517  int	*message_int_ptr;
1518#endif
1519
1520  struct ring_elt *send_ring;
1521
1522  int len;
1523  unsigned int nummessages = 0;
1524  int *send_socket;
1525  int bytes_remaining;
1526  int sctp_mss;
1527
1528  /* with links like fddi, one can send > 32 bits worth of bytes */
1529  /* during a test... ;-) at some point, this should probably become a */
1530  /* 64bit integral type, but those are not entirely common yet */
1531  double	bytes_sent = 0.0;
1532
1533#ifdef DIRTY
1534  int	i;
1535#endif /* DIRTY */
1536  int j;
1537
1538  float	local_cpu_utilization;
1539  float	local_service_demand;
1540  float	remote_cpu_utilization;
1541  float	remote_service_demand;
1542
1543  double	thruput;
1544
1545  struct addrinfo *remote_res;
1546  struct addrinfo *local_res;
1547  struct addrinfo *last_remote_res;
1548  struct addrinfo *last_local_res;
1549
1550  struct	sctp_stream_request_struct	*sctp_stream_request;
1551  struct	sctp_stream_response_struct	*sctp_stream_response;
1552  struct	sctp_stream_results_struct	*sctp_stream_result;
1553
1554  sctp_stream_request  =
1555    (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
1556  sctp_stream_response =
1557    (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
1558  sctp_stream_result   =
1559    (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
1560
1561#ifdef WANT_HISTOGRAM
1562  time_hist = HIST_new();
1563#endif /* WANT_HISTOGRAM */
1564
1565  complete_addrinfos(&remote_res,
1566		     &local_res,
1567		     remote_host,
1568		     SOCK_SEQPACKET,
1569		     IPPROTO_SCTP,
1570		     0);
1571
1572  if ( print_headers ) {
1573    print_top_test_header("SCTP 1-TO-MANY STREAM TEST",local_res,remote_res);
1574  }
1575
1576  send_ring = NULL;
1577  confidence_iteration = 1;
1578  init_stat();
1579
1580  send_socket = malloc(sizeof (int) * num_associations);
1581  if (send_socket == NULL) {
1582      fprintf(where, "send_sctp_stream_1toMany: failed to allocation sockets!\n");
1583      exit(1);
1584  }
1585
1586  /* we have a great-big while loop which controls the number of times */
1587  /* we run a particular test. this is for the calculation of a */
1588  /* confidence interval (I really should have stayed awake during */
1589  /* probstats :). If the user did not request confidence measurement */
1590  /* (no confidence is the default) then we will only go though the */
1591  /* loop once. the confidence stuff originates from the folks at IBM */
1592
1593  while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
1594	 (confidence_iteration <= iteration_min)) {
1595
1596    int		j=0;
1597    int		timed_out = 0;
1598
1599
1600    /* initialize a few counters. we have to remember that we might be */
1601    /* going through the loop more than once. */
1602
1603    nummessages    =	0;
1604    bytes_sent     =	0.0;
1605    times_up       = 	0;
1606
1607    /* at this point, we have either retrieved the socket buffer sizes, */
1608    /* or have tried to set them, so now, we may want to set the send */
1609    /* size based on that (because the user either did not use a -m */
1610    /* option, or used one with an argument of 0). If the socket buffer */
1611    /* size is not available, we will set the send size to 4KB - no */
1612    /* particular reason, just arbitrary... */
1613    if (send_size == 0) {
1614      if (lss_size > 0) {
1615	send_size = lss_size;
1616      }
1617      else {
1618	send_size = 4096;
1619      }
1620    }
1621
1622    /* set-up the data buffer ring with the requested alignment and offset. */
1623    /* note also that we have allocated a quantity */
1624    /* of memory that is at least one send-size greater than our socket */
1625    /* buffer size. We want to be sure that there are at least two */
1626    /* buffers allocated - this can be a bit of a problem when the */
1627    /* send_size is bigger than the socket size, so we must check... the */
1628    /* user may have wanted to explicitly set the "width" of our send */
1629    /* buffers, we should respect that wish... */
1630    if (send_width == 0) {
1631      send_width = (lss_size/send_size) + 1;
1632      if (send_width == 1) send_width++;
1633    }
1634
1635    if (send_ring == NULL) {
1636      /* only allocate the send ring once. this is a networking test, */
1637      /* not a memory allocation test. this way, we do not need a */
1638      /* deallocate_buffer_ring() routine, and I don't feel like */
1639      /* writing one anyway :) raj 11/94 */
1640      send_ring = allocate_buffer_ring(send_width,
1641				       send_size,
1642				       local_send_align,
1643				       local_send_offset);
1644    }
1645
1646    /* If the user has requested cpu utilization measurements, we must */
1647    /* calibrate the cpu(s). We will perform this task within the tests */
1648    /* themselves. If the user has specified the cpu rate, then */
1649    /* calibrate_local_cpu will return rather quickly as it will have */
1650    /* nothing to do. If local_cpu_rate is zero, then we will go through */
1651    /* all the "normal" calibration stuff and return the rate back. */
1652
1653    if (local_cpu_usage) {
1654      local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1655    }
1656
1657    /* Tell the remote end to do a listen. The server alters the socket */
1658    /* paramters on the other side at this point, hence the reason for */
1659    /* all the values being passed in the setup message. If the user did */
1660    /* not specify any of the parameters, they will be passed as 0, which */
1661    /* will indicate to the remote that no changes beyond the system's */
1662    /* default should be used. Alignment is the exception, it will */
1663    /* default to 1, which will be no alignment alterations. */
1664
1665    netperf_request.content.request_type	=	DO_SCTP_STREAM_MANY;
1666    sctp_stream_request->send_buf_size	=	rss_size_req;
1667    sctp_stream_request->recv_buf_size	=	rsr_size_req;
1668    sctp_stream_request->receive_size	=	recv_size;
1669    sctp_stream_request->no_delay	=	rem_nodelay;
1670    sctp_stream_request->recv_alignment	=	remote_recv_align;
1671    sctp_stream_request->recv_offset	=	remote_recv_offset;
1672    sctp_stream_request->measure_cpu	=	remote_cpu_usage;
1673    sctp_stream_request->cpu_rate	=	remote_cpu_rate;
1674    if (test_time) {
1675      sctp_stream_request->test_length	=	test_time;
1676    }
1677    else {
1678      if (msg_count)
1679	  test_bytes = send_size * msg_count;
1680
1681      sctp_stream_request->test_length	=	test_bytes*num_associations;
1682    }
1683    sctp_stream_request->so_rcvavoid	=	rem_rcvavoid;
1684    sctp_stream_request->so_sndavoid	=	rem_sndavoid;
1685#ifdef DIRTY
1686    sctp_stream_request->dirty_count    =       rem_dirty_count;
1687    sctp_stream_request->clean_count    =       rem_clean_count;
1688#endif /* DIRTY */
1689    sctp_stream_request->port		= 	(atoi(remote_data_port));
1690    sctp_stream_request->ipfamily	=	af_to_nf(remote_res->ai_family);
1691    sctp_stream_request->non_blocking   =	non_block;
1692
1693
1694    if (debug > 1) {
1695      fprintf(where,
1696	      "netperf: send_sctp_stream_1toMany: requesting sctp stream test\n");
1697    }
1698
1699    send_request();
1700
1701    /* The response from the remote will contain all of the relevant 	*/
1702    /* socket parameters for this test type. We will put them back into */
1703    /* the variables here so they can be displayed if desired.  The	*/
1704    /* remote will have calibrated CPU if necessary, and will have done	*/
1705    /* all the needed set-up we will have calibrated the cpu locally	*/
1706    /* before sending the request, and will grab the counter value right*/
1707    /* after the connect returns. The remote will grab the counter right*/
1708    /* after the accept call. This saves the hassle of extra messages	*/
1709    /* being sent for the sctp tests.					*/
1710
1711    recv_response();
1712
1713    if (!netperf_response.content.serv_errno) {
1714      if (debug)
1715	fprintf(where,"remote listen done.\n");
1716      rsr_size	      =	sctp_stream_response->recv_buf_size;
1717      rss_size	      =	sctp_stream_response->send_buf_size;
1718      rem_nodelay     =	sctp_stream_response->no_delay;
1719      remote_cpu_usage=	sctp_stream_response->measure_cpu;
1720      remote_cpu_rate = sctp_stream_response->cpu_rate;
1721
1722      /* we have to make sure that the server port number is in */
1723      /* network order */
1724      set_port_number(remote_res, (unsigned short)sctp_stream_response->data_port_number);
1725      rem_rcvavoid	= sctp_stream_response->so_rcvavoid;
1726      rem_sndavoid	= sctp_stream_response->so_sndavoid;
1727    }
1728    else {
1729      Set_errno(netperf_response.content.serv_errno);
1730      fprintf(where,
1731	      "netperf: remote error %d",
1732	      netperf_response.content.serv_errno);
1733      perror("");
1734      fflush(where);
1735
1736      exit(1);
1737    }
1738
1739    /*set up the the array of data sockets  and connect them to the server */
1740
1741    for (j = 0; j < num_associations; j++) {
1742	send_socket[j] = create_data_socket(local_res);
1743
1744	if (send_socket[j] < 0){
1745	  perror("netperf: send_sctp_stream_1toMany: sctp stream data socket");
1746	  exit(1);
1747	}
1748
1749	if (debug) {
1750	  fprintf(where,"send_sctp_stream_1toMany: send_socket obtained...\n");
1751	}
1752
1753	/*Connect up to the remote port on the data socket  */
1754	if (connect(send_socket[j],
1755		    remote_res->ai_addr,
1756		    remote_res->ai_addrlen) == INVALID_SOCKET){
1757	  perror("netperf: send_sctp_stream_1toMany: data socket connect failed");
1758	  exit(1);
1759	}
1760
1761	/* Do it after connect is successfull, so that we don't see COMM_UP */
1762	sctp_enable_events(send_socket[j], SCTP_ASSOC_CHANGE_EV);
1763
1764	if (non_block) {
1765	    /* now that we are connected, mark the socket as non-blocking */
1766	    if (!set_nonblock(send_socket[j])) {
1767	      perror("netperf: fcntl");
1768	      exit(1);
1769	    }
1770	}
1771    }
1772
1773    /* Data Socket set-up is finished. If there were problems, either */
1774    /* the connect would have failed, or the previous response would */
1775    /* have indicated a problem. I failed to see the value of the */
1776    /* extra  message after the accept on the remote. If it failed, */
1777    /* we'll see it here. If it didn't, we might as well start pumping */
1778    /* data. */
1779
1780    /* Set-up the test end conditions. For a stream test, they can be */
1781    /* either time or byte-count based. */
1782
1783    if (test_time) {
1784      /* The user wanted to end the test after a period of time. */
1785      times_up = 0;
1786      bytes_remaining = 0;
1787      /* in previous revisions, we had the same code repeated throught */
1788      /* all the test suites. this was unnecessary, and meant more */
1789      /* work for me when I wanted to switch to POSIX signals, so I */
1790      /* have abstracted this out into a routine in netlib.c. if you */
1791      /* are experiencing signal problems, you might want to look */
1792      /* there. raj 11/94 */
1793      start_timer(test_time);
1794    }
1795    else {
1796      /* The tester wanted to send a number of bytes. */
1797      bytes_remaining = test_bytes * num_associations;
1798      times_up = 1;
1799    }
1800
1801    /* The cpu_start routine will grab the current time and possibly */
1802    /* value of the idle counter for later use in measuring cpu */
1803    /* utilization and/or service demand and thruput. */
1804
1805    cpu_start(local_cpu_usage);
1806
1807#ifdef WANT_INTERVALS
1808    if ((interval_burst) || (demo_mode)) {
1809      /* zero means that we never pause, so we never should need the */
1810      /* interval timer, unless we are in demo_mode */
1811      start_itimer(interval_wate);
1812    }
1813    interval_count = interval_burst;
1814    /* get the signal set for the call to sigsuspend */
1815    if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
1816      fprintf(where,
1817	      "send_sctp_stream_1toMany: unable to get sigmask errno %d\n",
1818	      errno);
1819      fflush(where);
1820      exit(1);
1821    }
1822#endif /* WANT_INTERVALS */
1823
1824#ifdef DIRTY
1825    /* initialize the random number generator for putting dirty stuff */
1826    /* into the send buffer. raj */
1827    srand((int) getpid());
1828#endif
1829
1830    /* before we start, initialize a few variables */
1831
1832    /* We use an "OR" to control test execution. When the test is */
1833    /* controlled by time, the byte count check will always return false. */
1834    /* When the test is controlled by byte count, the time test will */
1835    /* always return false. When the test is finished, the whole */
1836    /* expression will go false and we will stop sending data. */
1837
1838    while ((!times_up) || (bytes_remaining > 0)) {
1839
1840#ifdef DIRTY
1841      /* we want to dirty some number of consecutive integers in the buffer */
1842      /* we are about to send. we may also want to bring some number of */
1843      /* them cleanly into the cache. The clean ones will follow any dirty */
1844      /* ones into the cache. at some point, we might want to replace */
1845      /* the rand() call with something from a table to reduce our call */
1846      /* overhead during the test, but it is not a high priority item. */
1847      message_int_ptr = (int *)(send_ring->buffer_ptr);
1848      for (i = 0; i < loc_dirty_count; i++) {
1849	*message_int_ptr = rand();
1850	message_int_ptr++;
1851      }
1852      for (i = 0; i < loc_clean_count; i++) {
1853	loc_dirty_count = *message_int_ptr;
1854	message_int_ptr++;
1855      }
1856#endif /* DIRTY */
1857
1858#ifdef WANT_HISTOGRAM
1859      /* timestamp just before we go into send and then again just after */
1860      /* we come out raj 8/94 */
1861      gettimeofday(&time_one,NULL);
1862#endif /* WANT_HISTOGRAM */
1863
1864      for (j = 0; j < num_associations; j++) {
1865
1866	  if((len=sctp_sendmsg(send_socket[j],
1867			       send_ring->buffer_ptr,
1868			       send_size,
1869			       (struct sockaddr *)remote_res->ai_addr,
1870			       remote_res->ai_addrlen,
1871			       0, 0, 0, 0, 0)) != send_size) {
1872	    if ((len >=0) || SOCKET_EINTR(len)) {
1873	      /* the test was interrupted, must be the end of test */
1874	      timed_out = 1;
1875	      break;
1876	    } else if (non_block && errno == EAGAIN) {
1877		j--;	 /* send again on the same socket */
1878		Set_errno(0);
1879		continue;
1880	    }
1881	    perror("netperf: data send error");
1882	    printf("len was %d\n",len);
1883	    exit(1);
1884	  }
1885      }
1886
1887      if (timed_out)
1888	  break;	/* test is over, try next iteration */
1889
1890#ifdef WANT_HISTOGRAM
1891      /* timestamp the exit from the send call and update the histogram */
1892      gettimeofday(&time_two,NULL);
1893      HIST_add(time_hist,delta_micro(&time_one,&time_two));
1894#endif /* WANT_HISTOGRAM */
1895
1896#ifdef WANT_INTERVALS
1897      if (demo_mode) {
1898	units_this_tick += send_size;
1899      }
1900      /* in this case, the interval count is the count-down couter */
1901      /* to decide to sleep for a little bit */
1902      if ((interval_burst) && (--interval_count == 0)) {
1903	/* call sigsuspend and wait for the interval timer to get us */
1904	/* out */
1905	if (debug > 1) {
1906	  fprintf(where,"about to suspend\n");
1907	  fflush(where);
1908	}
1909	if (sigsuspend(&signal_set) == EFAULT) {
1910	  fprintf(where,
1911		  "send_sctp_stream_1toMany: fault with sigsuspend.\n");
1912	  fflush(where);
1913	  exit(1);
1914	}
1915	interval_count = interval_burst;
1916      }
1917#endif /* WANT_INTERVALS */
1918
1919      /* now we want to move our pointer to the next position in the */
1920      /* data buffer...we may also want to wrap back to the "beginning" */
1921      /* of the bufferspace, so we will mod the number of messages sent */
1922      /* by the send width, and use that to calculate the offset to add */
1923      /* to the base pointer. */
1924      nummessages++;
1925      send_ring = send_ring->next;
1926      if (bytes_remaining) {
1927	bytes_remaining -= send_size;
1928      }
1929    }
1930
1931    /* The test is over. Flush the buffers to the remote end. We do a */
1932    /* graceful release to insure that all data has been taken by the */
1933    /* remote. */
1934
1935    /* but first, if the verbosity is greater than 1, find-out what */
1936    /* the sctp maximum segment_size was (if possible) */
1937    if (verbosity > 1) {
1938      sctp_mss = -1;
1939      get_sctp_info(send_socket[0], &sctp_mss);
1940    }
1941
1942    /* signal the server that we are all done writing, this will
1943     * initiate a shutdonw of one of the associations on the
1944     * server and trigger an event telling the server it's all done
1945     */
1946    sctp_sendmsg(send_socket[0], NULL, 0, remote_res->ai_addr,
1947		 remote_res->ai_addrlen, 0, MSG_EOF, 0, 0, 0);
1948
1949
1950    /* The test server will initiate closure of all associations
1951     * when it's done reading. We want a basic mechanism to catch this
1952     * and are using SCTP events for this.
1953     * In blocking mode, we can call recvmsg with the last socket we created.
1954     * In non-blocking  mode, we need to select on the socket for reading.
1955     * We'll assume that all returns are succefull and signify
1956     * closure.
1957     * It is sufficient to do this on a single socket in the client.
1958     * We choose to do it on a socket other then the one that send MSG_EOF.
1959     * This means that anything comming in on that socket will be a shutdown.
1960     */
1961    if (non_block) {
1962	fd_set readfds;
1963
1964	FD_ZERO(&readfds);
1965	FD_SET(send_socket[num_associations-1], &readfds);
1966	select(send_socket[num_associations-1]+1, &readfds, NULL, NULL, NULL);
1967    } else {
1968	sctp_recvmsg(send_socket[num_associations], send_ring->buffer_ptr,
1969		     send_size, NULL, 0, NULL, 0);
1970    }
1971
1972    /* this call will always give us the elapsed time for the test, and */
1973    /* will also store-away the necessaries for cpu utilization */
1974
1975    cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
1976						/* measured and how */
1977						/* long did we really */
1978						/* run? */
1979
1980    /* we are finished with our sockets, so close them to prevent hitting */
1981    /* the limit on maximum open files. */
1982    for (j = 0; j < num_associations; j++)
1983	close(send_socket[j]);
1984
1985    /* Get the statistics from the remote end. The remote will have */
1986    /* calculated service demand and all those interesting things. If it */
1987    /* wasn't supposed to care, it will return obvious values. */
1988
1989    recv_response();
1990    if (!netperf_response.content.serv_errno) {
1991      if (debug)
1992	fprintf(where,"remote results obtained\n");
1993    }
1994    else {
1995      Set_errno(netperf_response.content.serv_errno);
1996      fprintf(where,
1997	      "netperf: remote error %d",
1998	      netperf_response.content.serv_errno);
1999      perror("");
2000      fflush(where);
2001
2002      exit(1);
2003    }
2004
2005    /* We now calculate what our thruput was for the test. In the future, */
2006    /* we may want to include a calculation of the thruput measured by */
2007    /* the remote, but it should be the case that for a sctp stream test, */
2008    /* that the two numbers should be *very* close... We calculate */
2009    /* bytes_sent regardless of the way the test length was controlled. */
2010    /* If it was time, we needed to, and if it was by bytes, the user may */
2011    /* have specified a number of bytes that wasn't a multiple of the */
2012    /* send_size, so we really didn't send what he asked for ;-) */
2013
2014    bytes_sent	= ntohd(sctp_stream_result->bytes_received);
2015
2016    thruput	= (double) calc_thruput(bytes_sent);
2017
2018    if (local_cpu_usage || remote_cpu_usage) {
2019      /* We must now do a little math for service demand and cpu */
2020      /* utilization for the system(s) */
2021      /* Of course, some of the information might be bogus because */
2022      /* there was no idle counter in the kernel(s). We need to make */
2023      /* a note of this for the user's benefit...*/
2024      if (local_cpu_usage) {
2025
2026	local_cpu_utilization	= calc_cpu_util(0.0);
2027	local_service_demand	= calc_service_demand(bytes_sent,
2028						      0.0,
2029						      0.0,
2030						      0);
2031      }
2032      else {
2033	local_cpu_utilization	= (float) -1.0;
2034	local_service_demand	= (float) -1.0;
2035      }
2036
2037      if (remote_cpu_usage) {
2038
2039	remote_cpu_utilization	= sctp_stream_result->cpu_util;
2040	remote_service_demand	= calc_service_demand(bytes_sent,
2041						      0.0,
2042						      remote_cpu_utilization,
2043						      sctp_stream_result->num_cpus);
2044      }
2045      else {
2046	remote_cpu_utilization = (float) -1.0;
2047	remote_service_demand  = (float) -1.0;
2048      }
2049    }
2050    else {
2051      /* we were not measuring cpu, for the confidence stuff, we */
2052      /* should make it -1.0 */
2053      local_cpu_utilization	= (float) -1.0;
2054      local_service_demand	= (float) -1.0;
2055      remote_cpu_utilization = (float) -1.0;
2056      remote_service_demand  = (float) -1.0;
2057    }
2058
2059    /* at this point, we want to calculate the confidence information. */
2060    /* if debugging is on, calculate_confidence will print-out the */
2061    /* parameters we pass it */
2062
2063    calculate_confidence(confidence_iteration,
2064			 elapsed_time,
2065			 thruput,
2066			 local_cpu_utilization,
2067			 remote_cpu_utilization,
2068			 local_service_demand,
2069			 remote_service_demand);
2070
2071
2072    confidence_iteration++;
2073  }
2074
2075  /* at this point, we have finished making all the runs that we */
2076  /* will be making. so, we should extract what the calcuated values */
2077  /* are for all the confidence stuff. we could make the values */
2078  /* global, but that seemed a little messy, and it did not seem worth */
2079  /* all the mucking with header files. so, we create a routine much */
2080  /* like calcualte_confidence, which just returns the mean values. */
2081  /* raj 11/94 */
2082
2083  retrieve_confident_values(&elapsed_time,
2084			    &thruput,
2085			    &local_cpu_utilization,
2086			    &remote_cpu_utilization,
2087			    &local_service_demand,
2088			    &remote_service_demand);
2089
2090  /* We are now ready to print all the information. If the user */
2091  /* has specified zero-level verbosity, we will just print the */
2092  /* local service demand, or the remote service demand. If the */
2093  /* user has requested verbosity level 1, he will get the basic */
2094  /* "streamperf" numbers. If the user has specified a verbosity */
2095  /* of greater than 1, we will display a veritable plethora of */
2096  /* background information from outside of this block as it it */
2097  /* not cpu_measurement specific...  */
2098
2099  if (confidence < 0) {
2100    /* we did not hit confidence, but were we asked to look for it? */
2101    if (iteration_max > 1) {
2102      display_confidence();
2103    }
2104  }
2105
2106  if (local_cpu_usage || remote_cpu_usage) {
2107    local_cpu_method = format_cpu_method(cpu_method);
2108    remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method);
2109
2110    switch (verbosity) {
2111    case 0:
2112      if (local_cpu_usage) {
2113	fprintf(where,
2114		cpu_fmt_0,
2115		local_service_demand,
2116		local_cpu_method);
2117      }
2118      else {
2119	fprintf(where,
2120		cpu_fmt_0,
2121		remote_service_demand,
2122		remote_cpu_method);
2123      }
2124      break;
2125    case 1:
2126    case 2:
2127      if (print_headers) {
2128	fprintf(where,
2129		cpu_title,
2130		format_units(),
2131		local_cpu_method,
2132		remote_cpu_method);
2133      }
2134
2135      fprintf(where,
2136	      cpu_fmt_1,		/* the format string */
2137	      rsr_size,		        /* remote recvbuf size */
2138	      lss_size,		        /* local sendbuf size */
2139	      send_size,		/* how large were the sends */
2140	      elapsed_time,		/* how long was the test */
2141	      thruput, 		        /* what was the xfer rate */
2142	      local_cpu_utilization,	/* local cpu */
2143	      remote_cpu_utilization,	/* remote cpu */
2144	      local_service_demand,	/* local service demand */
2145	      remote_service_demand);	/* remote service demand */
2146      break;
2147    }
2148  }
2149  else {
2150    /* The tester did not wish to measure service demand. */
2151
2152    switch (verbosity) {
2153    case 0:
2154      fprintf(where,
2155	      tput_fmt_0,
2156	      thruput);
2157      break;
2158    case 1:
2159    case 2:
2160      if (print_headers) {
2161	fprintf(where,tput_title,format_units());
2162      }
2163      fprintf(where,
2164	      tput_fmt_1,		/* the format string */
2165	      rsr_size, 		/* remote recvbuf size */
2166	      lss_size, 		/* local sendbuf size */
2167	      send_size,		/* how large were the sends */
2168	      elapsed_time, 		/* how long did it take */
2169	      thruput);/* how fast did it go */
2170      break;
2171    }
2172  }
2173
2174  /* it would be a good thing to include information about some of the */
2175  /* other parameters that may have been set for this test, but at the */
2176  /* moment, I do not wish to figure-out all the  formatting, so I will */
2177  /* just put this comment here to help remind me that it is something */
2178  /* that should be done at a later time. */
2179
2180  if (verbosity > 1) {
2181    /* The user wanted to know it all, so we will give it to him. */
2182    /* This information will include as much as we can find about */
2183    /* sctp statistics, the alignments of the sends and receives */
2184    /* and all that sort of rot... */
2185
2186    /* this stuff needs to be worked-out in the presence of confidence */
2187    /* intervals and multiple iterations of the test... raj 11/94 */
2188
2189    fprintf(where,
2190	    ksink_fmt,
2191	    "Bytes",
2192	    "Bytes",
2193	    "Bytes",
2194	    local_send_align,
2195	    remote_recv_align,
2196	    local_send_offset,
2197	    remote_recv_offset,
2198	    bytes_sent,
2199	    bytes_sent / (double)nummessages,
2200	    nummessages,
2201	    bytes_sent / (double)sctp_stream_result->recv_calls,
2202	    sctp_stream_result->recv_calls);
2203    fprintf(where,
2204	    ksink_fmt2,
2205	    sctp_mss);
2206    fflush(where);
2207#ifdef WANT_HISTOGRAM
2208    fprintf(where,"\n\nHistogram of time spent in send() call.\n");
2209    fflush(where);
2210    HIST_report(time_hist);
2211#endif /* WANT_HISTOGRAM */
2212  }
2213
2214}
2215
2216
2217
2218/* This is the server-side routine for the sctp stream test. It is */
2219/* implemented as one routine. I could break things-out somewhat, but */
2220/* didn't feel it was necessary. */
2221
2222void
2223recv_sctp_stream_1toMany()
2224{
2225
2226  struct sockaddr_in myaddr_in;
2227  int	s_recv;
2228  int 	addrlen;
2229  int	len;
2230  unsigned int	receive_calls;
2231  float	elapsed_time;
2232  double   bytes_received;
2233  int	msg_flags = 0;
2234
2235  struct ring_elt *recv_ring;
2236
2237  struct addrinfo *local_res;
2238  char local_name[BUFSIZ];
2239  char port_buffer[PORTBUFSIZE];
2240
2241#ifdef DIRTY
2242  int   *message_int_ptr;
2243  int   dirty_count;
2244  int   clean_count;
2245  int   i;
2246#endif
2247
2248#ifdef DO_SELECT
2249  fd_set readfds;
2250  struct timeval timeout;
2251#endif
2252
2253  struct	sctp_stream_request_struct	*sctp_stream_request;
2254  struct	sctp_stream_response_struct	*sctp_stream_response;
2255  struct	sctp_stream_results_struct	*sctp_stream_results;
2256
2257#ifdef DO_SELECT
2258  FD_ZERO(&readfds);
2259  timeout.tv_sec = 1;
2260  timeout.tv_usec = 0;
2261#endif
2262
2263  sctp_stream_request	=
2264    (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data;
2265  sctp_stream_response	=
2266    (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data;
2267  sctp_stream_results	=
2268    (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data;
2269
2270  if (debug) {
2271    fprintf(where,"netserver: recv_sctp_stream: entered...\n");
2272    fflush(where);
2273  }
2274
2275  /* We want to set-up the listen socket with all the desired */
2276  /* parameters and then let the initiator know that all is ready. If */
2277  /* socket size defaults are to be used, then the initiator will have */
2278  /* sent us 0's. If the socket sizes cannot be changed, then we will */
2279  /* send-back what they are. If that information cannot be determined, */
2280  /* then we send-back -1's for the sizes. If things go wrong for any */
2281  /* reason, we will drop back ten yards and punt. */
2282
2283  /* If anything goes wrong, we want the remote to know about it. It */
2284  /* would be best if the error that the remote reports to the user is */
2285  /* the actual error we encountered, rather than some bogus unexpected */
2286  /* response type message. */
2287
2288  if (debug) {
2289    fprintf(where,"recv_sctp_stream_1toMany: setting the response type...\n");
2290    fflush(where);
2291  }
2292
2293  netperf_response.content.response_type = SCTP_STREAM_MANY_RESPONSE;
2294
2295  if (debug) {
2296    fprintf(where,"recv_sctp_stream_1toMany: the response type is set...\n");
2297    fflush(where);
2298  }
2299
2300  /* We now alter the message_ptr variable to be at the desired */
2301  /* alignment with the desired offset. */
2302
2303  if (debug) {
2304    fprintf(where,"recv_sctp_stream_1toMany: requested alignment of %d\n",
2305	    sctp_stream_request->recv_alignment);
2306    fflush(where);
2307  }
2308
2309  /* create_data_socket expects to find some things in the global */
2310  /* variables, so set the globals based on the values in the request. */
2311  /* once the socket has been created, we will set the response values */
2312  /* based on the updated value of those globals. raj 7/94 */
2313  lss_size_req = sctp_stream_request->send_buf_size;
2314  lsr_size_req = sctp_stream_request->recv_buf_size;
2315  loc_nodelay = sctp_stream_request->no_delay;
2316  loc_rcvavoid = sctp_stream_request->so_rcvavoid;
2317  loc_sndavoid = sctp_stream_request->so_sndavoid;
2318  non_block = sctp_stream_request->non_blocking;
2319
2320  set_hostname_and_port(local_name,
2321			port_buffer,
2322			nf_to_af(sctp_stream_request->ipfamily),
2323			sctp_stream_request->port);
2324
2325  local_res = complete_addrinfo(local_name,
2326				local_name,
2327				port_buffer,
2328				nf_to_af(sctp_stream_request->ipfamily),
2329				SOCK_SEQPACKET,
2330				IPPROTO_SCTP,
2331				0);
2332
2333  s_recv = create_data_socket(local_res);
2334
2335  if (s_recv < 0) {
2336    netperf_response.content.serv_errno = errno;
2337    send_response();
2338    exit(1);
2339  }
2340
2341  /* what sort of sizes did we end-up with? */
2342  if (sctp_stream_request->receive_size == 0) {
2343    if (lsr_size > 0) {
2344      recv_size = lsr_size;
2345    }
2346    else {
2347      recv_size = 4096;
2348    }
2349  }
2350  else {
2351    recv_size = sctp_stream_request->receive_size;
2352  }
2353
2354  /* we want to set-up our recv_ring in a manner analagous to what we */
2355  /* do on the sending side. this is more for the sake of symmetry */
2356  /* than for the needs of say copy avoidance, but it might also be */
2357  /* more realistic - this way one could conceivably go with a */
2358  /* double-buffering scheme when taking the data an putting it into */
2359  /* the filesystem or something like that. raj 7/94 */
2360
2361  if (recv_width == 0) {
2362    recv_width = (lsr_size/recv_size) + 1;
2363    if (recv_width == 1) recv_width++;
2364  }
2365
2366  recv_ring = allocate_buffer_ring(recv_width,
2367				   recv_size,
2368				   sctp_stream_request->recv_alignment,
2369				   sctp_stream_request->recv_offset);
2370
2371  if (debug) {
2372    fprintf(where,"recv_sctp_stream: receive alignment and offset set...\n");
2373    fflush(where);
2374  }
2375
2376  /* Now, let's set-up the socket to listen for connections */
2377  if (listen(s_recv, 5) == -1) {
2378    netperf_response.content.serv_errno = errno;
2379    close(s_recv);
2380    send_response();
2381
2382    exit(1);
2383  }
2384
2385  /* now get the port number assigned by the system  */
2386  addrlen = sizeof(myaddr_in);
2387  if (getsockname(s_recv,
2388		  (struct sockaddr *)&myaddr_in,
2389		  &addrlen) == -1){
2390    netperf_response.content.serv_errno = errno;
2391    close(s_recv);
2392    send_response();
2393
2394    exit(1);
2395  }
2396
2397  /* Now myaddr_in contains the port and the internet address this is */
2398  /* returned to the sender also implicitly telling the sender that the */
2399  /* socket buffer sizing has been done. */
2400
2401  sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
2402  netperf_response.content.serv_errno   = 0;
2403
2404  /* But wait, there's more. If the initiator wanted cpu measurements, */
2405  /* then we must call the calibrate routine, which will return the max */
2406  /* rate back to the initiator. If the CPU was not to be measured, or */
2407  /* something went wrong with the calibration, we will return a -1 to */
2408  /* the initiator. */
2409
2410  sctp_stream_response->cpu_rate = (float)0.0; 	/* assume no cpu */
2411  if (sctp_stream_request->measure_cpu) {
2412    sctp_stream_response->measure_cpu = 1;
2413    sctp_stream_response->cpu_rate =
2414      calibrate_local_cpu(sctp_stream_request->cpu_rate);
2415  }
2416  else {
2417    sctp_stream_response->measure_cpu = 0;
2418  }
2419
2420  /* before we send the response back to the initiator, pull some of */
2421  /* the socket parms from the globals */
2422  sctp_stream_response->send_buf_size = lss_size;
2423  sctp_stream_response->recv_buf_size = lsr_size;
2424  sctp_stream_response->no_delay = loc_nodelay;
2425  sctp_stream_response->so_rcvavoid = loc_rcvavoid;
2426  sctp_stream_response->so_sndavoid = loc_sndavoid;
2427  sctp_stream_response->receive_size = recv_size;
2428
2429  send_response();
2430
2431
2432  sctp_enable_events(s_recv, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV);
2433
2434  /* now that we are connected, mark the socket as non-blocking */
2435  if (non_block) {
2436      if (!set_nonblock(s_recv)) {
2437	close(s_recv);
2438	exit(1);
2439      }
2440  }
2441
2442
2443  /* Now it's time to start receiving data on the connection. We will */
2444  /* first grab the apropriate counters and then start grabbing. */
2445
2446  cpu_start(sctp_stream_request->measure_cpu);
2447
2448  /* The loop will exit when the sender does a shutdown, which will */
2449  /* return a length of zero   */
2450
2451#ifdef DIRTY
2452    /* we want to dirty some number of consecutive integers in the buffer */
2453    /* we are about to recv. we may also want to bring some number of */
2454    /* them cleanly into the cache. The clean ones will follow any dirty */
2455    /* ones into the cache. */
2456
2457  dirty_count = sctp_stream_request->dirty_count;
2458  clean_count = sctp_stream_request->clean_count;
2459  message_int_ptr = (int *)recv_ring->buffer_ptr;
2460  for (i = 0; i < dirty_count; i++) {
2461    *message_int_ptr = rand();
2462    message_int_ptr++;
2463  }
2464  for (i = 0; i < clean_count; i++) {
2465    dirty_count = *message_int_ptr;
2466    message_int_ptr++;
2467  }
2468#endif /* DIRTY */
2469
2470  bytes_received = 0;
2471  receive_calls  = 0;
2472
2473  while ((len = sctp_recvmsg(s_recv, recv_ring->buffer_ptr, recv_size,
2474			     NULL, 0,  /* we don't care who it's from */
2475			     NULL, &msg_flags)) != 0) {
2476    if (len < 0) {
2477      if (non_block && errno == EAGAIN) {
2478	Set_errno(0);
2479	continue;
2480      }
2481      netperf_response.content.serv_errno = errno;
2482      send_response();
2483      close(s_recv);
2484      exit(1);
2485    }
2486
2487    if (msg_flags & MSG_NOTIFICATION) {
2488	if (sctp_process_event(s_recv, recv_ring->buffer_ptr) == SCTP_CLOSE)
2489	    break;
2490
2491	continue;
2492    }
2493
2494    bytes_received += len;
2495    receive_calls++;
2496
2497    /* more to the next buffer in the recv_ring */
2498    recv_ring = recv_ring->next;
2499
2500#ifdef PAUSE
2501    sleep(1);
2502#endif /* PAUSE */
2503
2504#ifdef DIRTY
2505    message_int_ptr = (int *)(recv_ring->buffer_ptr);
2506    for (i = 0; i < dirty_count; i++) {
2507      *message_int_ptr = rand();
2508      message_int_ptr++;
2509    }
2510    for (i = 0; i < clean_count; i++) {
2511      dirty_count = *message_int_ptr;
2512      message_int_ptr++;
2513    }
2514#endif /* DIRTY */
2515
2516#ifdef DO_SELECT
2517	FD_SET(s_recv,&readfds);
2518	select(s_recv+1,&readfds,NULL,NULL,&timeout);
2519#endif /* DO_SELECT */
2520
2521  }
2522
2523  /* perform a shutdown to signal the sender.  in this case, sctp
2524   * will close all associations on this socket
2525   */
2526  if (close(s_recv) == -1) {
2527      netperf_response.content.serv_errno = errno;
2528      send_response();
2529      exit(1);
2530  }
2531
2532  cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time);
2533
2534  /* send the results to the sender			*/
2535
2536  if (debug) {
2537    fprintf(where,
2538	    "recv_sctp_stream: got %g bytes\n",
2539	    bytes_received);
2540    fprintf(where,
2541	    "recv_sctp_stream: got %d recvs\n",
2542	    receive_calls);
2543    fflush(where);
2544  }
2545
2546  sctp_stream_results->bytes_received	= htond(bytes_received);
2547  sctp_stream_results->elapsed_time	= elapsed_time;
2548  sctp_stream_results->recv_calls	= receive_calls;
2549
2550  if (sctp_stream_request->measure_cpu) {
2551    sctp_stream_results->cpu_util	= calc_cpu_util(0.0);
2552  };
2553
2554  if (debug) {
2555    fprintf(where,
2556	    "recv_sctp_stream: test complete, sending results.\n");
2557    fprintf(where,
2558	    "                 bytes_received %g receive_calls %d\n",
2559	    bytes_received,
2560	    receive_calls);
2561    fprintf(where,
2562	    "                 len %d\n",
2563	    len);
2564    fflush(where);
2565  }
2566
2567  sctp_stream_results->cpu_method = cpu_method;
2568  sctp_stream_results->num_cpus   = lib_num_loc_cpus;
2569  send_response();
2570}
2571
2572
2573 /* this routine implements the sending (netperf) side of the SCTP_RR */
2574 /* test. */
2575
2576void
2577send_sctp_rr(remote_host)
2578     char	remote_host[];
2579{
2580
2581  char *tput_title = "\
2582Local /Remote\n\
2583Socket Size   Request  Resp.   Elapsed  Trans.\n\
2584Send   Recv   Size     Size    Time     Rate         \n\
2585bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
2586
2587  char *tput_fmt_0 =
2588    "%7.2f\n";
2589
2590  char *tput_fmt_1_line_1 = "\
2591%-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
2592  char *tput_fmt_1_line_2 = "\
2593%-6d %-6d\n";
2594
2595  char *cpu_title = "\
2596Local /Remote\n\
2597Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
2598Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
2599bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
2600
2601  char *cpu_fmt_0 =
2602    "%6.3f %c\n";
2603
2604  char *cpu_fmt_1_line_1 = "\
2605%-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f\n";
2606
2607  char *cpu_fmt_1_line_2 = "\
2608%-6d %-6d\n";
2609
2610  char *ksink_fmt = "\
2611Alignment      Offset\n\
2612Local  Remote  Local  Remote\n\
2613Send   Recv    Send   Recv\n\
2614%5d  %5d   %5d  %5d\n";
2615
2616
2617  int			timed_out = 0;
2618  float			elapsed_time;
2619
2620  int	len;
2621  char	*temp_message_ptr;
2622  int	nummessages;
2623  int	send_socket;
2624  int	trans_remaining;
2625  int   msg_flags = 0;
2626  double	bytes_xferd;
2627
2628  struct ring_elt *send_ring;
2629  struct ring_elt *recv_ring;
2630
2631  int	rsp_bytes_left;
2632  int	rsp_bytes_recvd;
2633
2634  float	local_cpu_utilization;
2635  float	local_service_demand;
2636  float	remote_cpu_utilization;
2637  float	remote_service_demand;
2638  double	thruput;
2639
2640  struct sockaddr_storage peer;
2641  struct addrinfo *remote_res;
2642  struct addrinfo *local_res;
2643
2644  struct	sctp_rr_request_struct	*sctp_rr_request;
2645  struct	sctp_rr_response_struct	*sctp_rr_response;
2646  struct	sctp_rr_results_struct	*sctp_rr_result;
2647
2648#ifdef WANT_INTERVALS
2649  int	interval_count;
2650  sigset_t signal_set;
2651#endif /* WANT_INTERVALS */
2652
2653  sctp_rr_request =
2654    (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
2655  sctp_rr_response =
2656    (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
2657  sctp_rr_result =
2658    (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
2659
2660#ifdef WANT_HISTOGRAM
2661  time_hist = HIST_new();
2662#endif /* WANT_HISTOGRAM */
2663
2664  /* since we are now disconnected from the code that established the */
2665  /* control socket, and since we want to be able to use different */
2666  /* protocols and such, we are passed the name of the remote host and */
2667  /* must turn that into the test specific addressing information. */
2668
2669  /* complete_addrinfos will either succede or exit the process */
2670  complete_addrinfos(&remote_res,
2671		     &local_res,
2672		     remote_host,
2673		     SOCK_STREAM,
2674		     IPPROTO_SCTP,
2675		     0);
2676
2677  if ( print_headers ) {
2678    print_top_test_header("SCTP REQUEST/RESPONSE TEST", local_res, remote_res);
2679  }
2680
2681  /* initialize a few counters */
2682
2683  send_ring = NULL;
2684  recv_ring = NULL;
2685  confidence_iteration = 1;
2686  init_stat();
2687
2688  /* we have a great-big while loop which controls the number of times */
2689  /* we run a particular test. this is for the calculation of a */
2690  /* confidence interval (I really should have stayed awake during */
2691  /* probstats :). If the user did not request confidence measurement */
2692  /* (no confidence is the default) then we will only go though the */
2693  /* loop once. the confidence stuff originates from the folks at IBM */
2694
2695  while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2696	 (confidence_iteration <= iteration_min)) {
2697
2698    /* initialize a few counters. we have to remember that we might be */
2699    /* going through the loop more than once. */
2700
2701    nummessages     = 0;
2702    bytes_xferd     = 0.0;
2703    times_up        = 0;
2704    timed_out       = 0;
2705    trans_remaining = 0;
2706
2707    /* set-up the data buffers with the requested alignment and offset. */
2708    /* since this is a request/response test, default the send_width and */
2709    /* recv_width to 1 and not two raj 7/94 */
2710
2711    if (send_width == 0) send_width = 1;
2712    if (recv_width == 0) recv_width = 1;
2713
2714    if (send_ring == NULL) {
2715      send_ring = allocate_buffer_ring(send_width,
2716				       req_size,
2717				       local_send_align,
2718				       local_send_offset);
2719    }
2720
2721    if (recv_ring == NULL) {
2722      recv_ring = allocate_buffer_ring(recv_width,
2723				       rsp_size,
2724				       local_recv_align,
2725				       local_recv_offset);
2726    }
2727
2728    /*set up the data socket                        */
2729    send_socket = create_data_socket(local_res);
2730
2731    if (send_socket < 0){
2732      perror("netperf: send_sctp_rr: sctp stream data socket");
2733      exit(1);
2734    }
2735
2736    if (debug) {
2737      fprintf(where,"send_sctp_rr: send_socket obtained...\n");
2738    }
2739
2740    /* If the user has requested cpu utilization measurements, we must */
2741    /* calibrate the cpu(s). We will perform this task within the tests */
2742    /* themselves. If the user has specified the cpu rate, then */
2743    /* calibrate_local_cpu will return rather quickly as it will have */
2744    /* nothing to do. If local_cpu_rate is zero, then we will go through */
2745    /* all the "normal" calibration stuff and return the rate back.*/
2746
2747    if (local_cpu_usage) {
2748      local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2749    }
2750
2751    /* Tell the remote end to do a listen. The server alters the socket */
2752    /* paramters on the other side at this point, hence the reason for */
2753    /* all the values being passed in the setup message. If the user did */
2754    /* not specify any of the parameters, they will be passed as 0, which */
2755    /* will indicate to the remote that no changes beyond the system's */
2756    /* default should be used. Alignment is the exception, it will */
2757    /* default to 8, which will be no alignment alterations. */
2758
2759    netperf_request.content.request_type	=	DO_SCTP_RR;
2760    sctp_rr_request->recv_buf_size	=	rsr_size_req;
2761    sctp_rr_request->send_buf_size	=	rss_size_req;
2762    sctp_rr_request->recv_alignment     =	remote_recv_align;
2763    sctp_rr_request->recv_offset        =	remote_recv_offset;
2764    sctp_rr_request->send_alignment     =	remote_send_align;
2765    sctp_rr_request->send_offset	=	remote_send_offset;
2766    sctp_rr_request->request_size	=	req_size;
2767    sctp_rr_request->response_size	=	rsp_size;
2768    sctp_rr_request->no_delay	        =	rem_nodelay;
2769    sctp_rr_request->measure_cpu	=	remote_cpu_usage;
2770    sctp_rr_request->cpu_rate	        =	remote_cpu_rate;
2771    sctp_rr_request->so_rcvavoid	        =	rem_rcvavoid;
2772    sctp_rr_request->so_sndavoid	        =	rem_sndavoid;
2773    if (test_time) {
2774      sctp_rr_request->test_length	=	test_time;
2775    }
2776    else {
2777      sctp_rr_request->test_length	=	test_trans * -1;
2778    }
2779    sctp_rr_request->non_blocking	= 	non_block;
2780    sctp_rr_request->ipfamily           = af_to_nf(remote_res->ai_family);
2781
2782    if (debug > 1) {
2783      fprintf(where,"netperf: send_sctp_rr: requesting SCTP rr test\n");
2784    }
2785
2786    send_request();
2787
2788    /* The response from the remote will contain all of the relevant 	*/
2789    /* socket parameters for this test type. We will put them back into */
2790    /* the variables here so they can be displayed if desired.  The	*/
2791    /* remote will have calibrated CPU if necessary, and will have done	*/
2792    /* all the needed set-up we will have calibrated the cpu locally	*/
2793    /* before sending the request, and will grab the counter value right*/
2794    /* after the connect returns. The remote will grab the counter right*/
2795    /* after the accept call. This saves the hassle of extra messages	*/
2796    /* being sent for the sctp tests.					*/
2797
2798    recv_response();
2799
2800    if (!netperf_response.content.serv_errno) {
2801      if (debug)
2802	fprintf(where,"remote listen done.\n");
2803      rsr_size          = sctp_rr_response->recv_buf_size;
2804      rss_size          = sctp_rr_response->send_buf_size;
2805      rem_nodelay       = sctp_rr_response->no_delay;
2806      remote_cpu_usage  = sctp_rr_response->measure_cpu;
2807      remote_cpu_rate   = sctp_rr_response->cpu_rate;
2808      /* make sure that port numbers are in network order */
2809      set_port_number(remote_res,
2810		      (unsigned short)sctp_rr_response->data_port_number);
2811    }
2812    else {
2813      Set_errno(netperf_response.content.serv_errno);
2814      fprintf(where,
2815	      "netperf: remote error %d",
2816	      netperf_response.content.serv_errno);
2817      perror("");
2818      fflush(where);
2819
2820      exit(1);
2821    }
2822
2823    /*Connect up to the remote port on the data socket  */
2824    if (connect(send_socket,
2825		remote_res->ai_addr,
2826		remote_res->ai_addrlen) <0){
2827      perror("netperf: send_sctp_rr data socket connect failed");
2828      exit(1);
2829    }
2830
2831    /* don't need events for 1-to-1 API with request-response tests */
2832    sctp_enable_events(send_socket, 0);
2833
2834    /* set non-blocking if needed */
2835    if (non_block) {
2836       if (!set_nonblock(send_socket)) {
2837	    close(send_socket);
2838	    exit(1);
2839	}
2840    }
2841
2842    /* Data Socket set-up is finished. If there were problems, either the */
2843    /* connect would have failed, or the previous response would have */
2844    /* indicated a problem. I failed to see the value of the extra */
2845    /* message after the accept on the remote. If it failed, we'll see it */
2846    /* here. If it didn't, we might as well start pumping data. */
2847
2848    /* Set-up the test end conditions. For a request/response test, they */
2849    /* can be either time or transaction based. */
2850
2851    if (test_time) {
2852      /* The user wanted to end the test after a period of time. */
2853      times_up = 0;
2854      trans_remaining = 0;
2855      start_timer(test_time);
2856    }
2857    else {
2858      /* The tester wanted to send a number of bytes. */
2859      trans_remaining = test_bytes;
2860      times_up = 1;
2861    }
2862
2863    /* The cpu_start routine will grab the current time and possibly */
2864    /* value of the idle counter for later use in measuring cpu */
2865    /* utilization and/or service demand and thruput. */
2866
2867    cpu_start(local_cpu_usage);
2868
2869#ifdef WANT_INTERVALS
2870    if ((interval_burst) || (demo_mode)) {
2871      /* zero means that we never pause, so we never should need the */
2872      /* interval timer, unless we are in demo_mode */
2873      start_itimer(interval_wate);
2874    }
2875    interval_count = interval_burst;
2876    /* get the signal set for the call to sigsuspend */
2877    if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
2878      fprintf(where,
2879	      "send_sctp_rr: unable to get sigmask errno %d\n",
2880	      errno);
2881      fflush(where);
2882      exit(1);
2883    }
2884#endif /* WANT_INTERVALS */
2885
2886    /* We use an "OR" to control test execution. When the test is */
2887    /* controlled by time, the byte count check will always return false. */
2888    /* When the test is controlled by byte count, the time test will */
2889    /* always return false. When the test is finished, the whole */
2890    /* expression will go false and we will stop sending data. I think I */
2891    /* just arbitrarily decrement trans_remaining for the timed test, but */
2892    /* will not do that just yet... One other question is whether or not */
2893    /* the send buffer and the receive buffer should be the same buffer. */
2894
2895#ifdef WANT_FIRST_BURST
2896    {
2897      int i;
2898      for (i = 0; i < first_burst_size; i++) {
2899 	if((len=sctp_sendmsg(send_socket,
2900 			     send_ring->buffer_ptr, req_size,
2901 			     NULL, 0,	/* don't need addrs with 1-to-1 */
2902 			     0, 0, 0, 0, 0)) != req_size) {
2903	  /* we should never hit the end of the test in the first burst */
2904	  perror("send_sctp_rr: initial burst data send error");
2905	  exit(1);
2906	}
2907      }
2908    }
2909#endif /* WANT_FIRST_BURST */
2910
2911    while ((!times_up) || (trans_remaining > 0)) {
2912      /* send the request. we assume that if we use a blocking socket, */
2913      /* the request will be sent at one shot. */
2914
2915#ifdef WANT_HISTOGRAM
2916      /* timestamp just before our call to send, and then again just */
2917      /* after the receive raj 8/94 */
2918      HIST_timestamp(&time_one);
2919#endif /* WANT_HISTOGRAM */
2920
2921      while ((len=sctp_sendmsg(send_socket,
2922			       send_ring->buffer_ptr, req_size,
2923			       NULL, 0, /* don't need addrs with 1-to-1 */
2924			       0, 0, 0, 0, 0)) != req_size) {
2925	if (non_block && errno == EAGAIN) {
2926	    /* try sending again */
2927	    continue;
2928	} else if (SOCKET_EINTR(len) || (errno == 0)) {
2929	  /* we hit the end of a */
2930	  /* timed test. */
2931	  timed_out = 1;
2932	  break;
2933	}
2934	perror("send_sctp_rr: data send error");
2935	exit(1);
2936      }
2937
2938      if (timed_out) {
2939	/* we timed out while sending. break out another level */
2940	break;
2941      }
2942      send_ring = send_ring->next;
2943
2944      /* receive the response */
2945      rsp_bytes_left = rsp_size;
2946      temp_message_ptr  = recv_ring->buffer_ptr;
2947      do {
2948	msg_flags = 0;
2949	if ((rsp_bytes_recvd=sctp_recvmsg(send_socket,
2950					 temp_message_ptr, rsp_bytes_left,
2951					 NULL, 0,
2952					 NULL, &msg_flags)) < 0) {
2953	  if (errno == EINTR) {
2954	    /* We hit the end of a timed test. */
2955	    timed_out = 1;
2956	    break;
2957	  } else if (non_block && errno == EAGAIN) {
2958	      continue;
2959	  }
2960	  perror("send_sctp_rr: data recv error");
2961	  exit(1);
2962	}
2963	rsp_bytes_left -= rsp_bytes_recvd;
2964	temp_message_ptr  += rsp_bytes_recvd;
2965      }	while (!(msg_flags & MSG_EOR));
2966
2967      recv_ring = recv_ring->next;
2968
2969      if (timed_out) {
2970	/* we may have been in a nested while loop - we need */
2971	/* another call to break. */
2972	break;
2973      }
2974
2975#ifdef WANT_HISTOGRAM
2976      HIST_timestamp(&time_two);
2977      HIST_add(time_hist,delta_micro(&time_one,&time_two));
2978#endif /* WANT_HISTOGRAM */
2979#ifdef WANT_INTERVALS
2980      if (demo_mode) {
2981	units_this_tick += 1;
2982      }
2983      /* in this case, the interval count is the count-down couter */
2984      /* to decide to sleep for a little bit */
2985      if ((interval_burst) && (--interval_count == 0)) {
2986	/* call sigsuspend and wait for the interval timer to get us */
2987	/* out */
2988	if (debug > 1) {
2989	  fprintf(where,"about to suspend\n");
2990	  fflush(where);
2991	}
2992	if (sigsuspend(&signal_set) == EFAULT) {
2993	  fprintf(where,
2994		  "send_sctp_rr: fault with signal set!\n");
2995	  fflush(where);
2996	  exit(1);
2997	}
2998	interval_count = interval_burst;
2999      }
3000#endif /* WANT_INTERVALS */
3001
3002      nummessages++;
3003      if (trans_remaining) {
3004	trans_remaining--;
3005      }
3006
3007      if (debug > 3) {
3008	if ((nummessages % 100) == 0) {
3009	  fprintf(where,
3010		  "Transaction %d completed\n",
3011		  nummessages);
3012	  fflush(where);
3013	}
3014      }
3015    }
3016
3017    /* At this point we used to call shutdown on the data socket to be */
3018    /* sure all the data was delivered, but this was not germane in a */
3019    /* request/response test, and it was causing the tests to "hang" when */
3020    /* they were being controlled by time. So, I have replaced this */
3021    /* shutdown call with a call to close that can be found later in the */
3022    /* procedure. */
3023
3024    /* this call will always give us the elapsed time for the test, and */
3025    /* will also store-away the necessaries for cpu utilization */
3026
3027    cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
3028						/* measured? how long */
3029						/* did we really run? */
3030
3031    /* Get the statistics from the remote end. The remote will have */
3032    /* calculated CPU utilization. If it wasn't supposed to care, it */
3033    /* will return obvious values. */
3034
3035    recv_response();
3036    if (!netperf_response.content.serv_errno) {
3037      if (debug)
3038	fprintf(where,"remote results obtained\n");
3039    }
3040    else {
3041      Set_errno(netperf_response.content.serv_errno);
3042      fprintf(where,"netperf: remote error %d",
3043	      netperf_response.content.serv_errno);
3044      perror("");
3045      fflush(where);
3046      exit(1);
3047    }
3048
3049    /* We now calculate what our throughput was for the test. */
3050
3051    bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
3052    thruput	= nummessages/elapsed_time;
3053
3054    if (local_cpu_usage || remote_cpu_usage) {
3055      /* We must now do a little math for service demand and cpu */
3056      /* utilization for the system(s) */
3057      /* Of course, some of the information might be bogus because */
3058      /* there was no idle counter in the kernel(s). We need to make */
3059      /* a note of this for the user's benefit...*/
3060      if (local_cpu_usage) {
3061	local_cpu_utilization = calc_cpu_util(0.0);
3062	/* since calc_service demand is doing ms/Kunit we will */
3063	/* multiply the number of transaction by 1024 to get */
3064	/* "good" numbers */
3065	local_service_demand  = calc_service_demand((double) nummessages*1024,
3066						    0.0,
3067						    0.0,
3068						    0);
3069      }
3070      else {
3071	local_cpu_utilization	= (float) -1.0;
3072	local_service_demand	= (float) -1.0;
3073      }
3074
3075      if (remote_cpu_usage) {
3076	remote_cpu_utilization = sctp_rr_result->cpu_util;
3077	/* since calc_service demand is doing ms/Kunit we will */
3078	/* multiply the number of transaction by 1024 to get */
3079	/* "good" numbers */
3080	remote_service_demand = calc_service_demand((double) nummessages*1024,
3081						    0.0,
3082						    remote_cpu_utilization,
3083						    sctp_rr_result->num_cpus);
3084      }
3085      else {
3086	remote_cpu_utilization = (float) -1.0;
3087	remote_service_demand  = (float) -1.0;
3088      }
3089
3090    }
3091    else {
3092      /* we were not measuring cpu, for the confidence stuff, we */
3093      /* should make it -1.0 */
3094      local_cpu_utilization	= (float) -1.0;
3095      local_service_demand	= (float) -1.0;
3096      remote_cpu_utilization = (float) -1.0;
3097      remote_service_demand  = (float) -1.0;
3098    }
3099
3100    /* at this point, we want to calculate the confidence information. */
3101    /* if debugging is on, calculate_confidence will print-out the */
3102    /* parameters we pass it */
3103
3104    calculate_confidence(confidence_iteration,
3105			 elapsed_time,
3106			 thruput,
3107			 local_cpu_utilization,
3108			 remote_cpu_utilization,
3109			 local_service_demand,
3110			 remote_service_demand);
3111
3112
3113    confidence_iteration++;
3114
3115    /* we are now done with the socket, so close it */
3116    close(send_socket);
3117
3118  }
3119
3120  retrieve_confident_values(&elapsed_time,
3121			    &thruput,
3122			    &local_cpu_utilization,
3123			    &remote_cpu_utilization,
3124			    &local_service_demand,
3125			    &remote_service_demand);
3126
3127  /* We are now ready to print all the information. If the user */
3128  /* has specified zero-level verbosity, we will just print the */
3129  /* local service demand, or the remote service demand. If the */
3130  /* user has requested verbosity level 1, he will get the basic */
3131  /* "streamperf" numbers. If the user has specified a verbosity */
3132  /* of greater than 1, we will display a veritable plethora of */
3133  /* background information from outside of this block as it it */
3134  /* not cpu_measurement specific...  */
3135
3136  if (confidence < 0) {
3137    /* we did not hit confidence, but were we asked to look for it? */
3138    if (iteration_max > 1) {
3139      display_confidence();
3140    }
3141  }
3142
3143  if (local_cpu_usage || remote_cpu_usage) {
3144    local_cpu_method = format_cpu_method(cpu_method);
3145    remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method);
3146
3147    switch (verbosity) {
3148    case 0:
3149      if (local_cpu_usage) {
3150	fprintf(where,
3151		cpu_fmt_0,
3152		local_service_demand,
3153		local_cpu_method);
3154      }
3155      else {
3156	fprintf(where,
3157		cpu_fmt_0,
3158		remote_service_demand,
3159		remote_cpu_method);
3160      }
3161      break;
3162    case 1:
3163    case 2:
3164      if (print_headers) {
3165	fprintf(where,
3166		cpu_title,
3167		local_cpu_method,
3168		remote_cpu_method);
3169      }
3170
3171      fprintf(where,
3172	      cpu_fmt_1_line_1,		/* the format string */
3173	      lss_size,		/* local sendbuf size */
3174	      lsr_size,
3175	      req_size,		/* how large were the requests */
3176	      rsp_size,		/* guess */
3177	      elapsed_time,		/* how long was the test */
3178	      thruput,
3179	      local_cpu_utilization,	/* local cpu */
3180	      remote_cpu_utilization,	/* remote cpu */
3181	      local_service_demand,	/* local service demand */
3182	      remote_service_demand);	/* remote service demand */
3183      fprintf(where,
3184	      cpu_fmt_1_line_2,
3185	      rss_size,
3186	      rsr_size);
3187      break;
3188    }
3189  }
3190  else {
3191    /* The tester did not wish to measure service demand. */
3192
3193    switch (verbosity) {
3194    case 0:
3195      fprintf(where,
3196	      tput_fmt_0,
3197	      thruput);
3198      break;
3199    case 1:
3200    case 2:
3201      if (print_headers) {
3202	fprintf(where,tput_title,format_units());
3203      }
3204
3205      fprintf(where,
3206	      tput_fmt_1_line_1,	/* the format string */
3207	      lss_size,
3208	      lsr_size,
3209	      req_size,		/* how large were the requests */
3210	      rsp_size,		/* how large were the responses */
3211	      elapsed_time, 		/* how long did it take */
3212	      thruput);
3213      fprintf(where,
3214	      tput_fmt_1_line_2,
3215	      rss_size, 		/* remote recvbuf size */
3216	      rsr_size);
3217
3218      break;
3219    }
3220  }
3221
3222  /* it would be a good thing to include information about some of the */
3223  /* other parameters that may have been set for this test, but at the */
3224  /* moment, I do not wish to figure-out all the  formatting, so I will */
3225  /* just put this comment here to help remind me that it is something */
3226  /* that should be done at a later time. */
3227
3228  /* how to handle the verbose information in the presence of */
3229  /* confidence intervals is yet to be determined... raj 11/94 */
3230  if (verbosity > 1) {
3231    /* The user wanted to know it all, so we will give it to him. */
3232    /* This information will include as much as we can find about */
3233    /* TCP statistics, the alignments of the sends and receives */
3234    /* and all that sort of rot... */
3235
3236    fprintf(where,
3237	    ksink_fmt,
3238	    local_send_align,
3239	    remote_recv_offset,
3240	    local_send_offset,
3241	    remote_recv_offset);
3242
3243#ifdef WANT_HISTOGRAM
3244    fprintf(where,"\nHistogram of request/response times\n");
3245    fflush(where);
3246    HIST_report(time_hist);
3247#endif /* WANT_HISTOGRAM */
3248
3249  }
3250
3251}
3252
3253
3254 /* this routine implements the receive (netserver) side of a TCP_RR */
3255 /* test */
3256void
3257recv_sctp_rr()
3258{
3259
3260  struct ring_elt *send_ring;
3261  struct ring_elt *recv_ring;
3262
3263  struct addrinfo *local_res;
3264  char local_name[BUFSIZ];
3265  char port_buffer[PORTBUFSIZE];
3266
3267  struct sockaddr_in        myaddr_in, peeraddr_in;
3268  int	s_listen, s_data;
3269  int 	addrlen;
3270  char	*temp_message_ptr;
3271  int	trans_received;
3272  int	trans_remaining;
3273  int	bytes_sent;
3274  int	request_bytes_recvd;
3275  int	request_bytes_remaining;
3276  int	timed_out = 0;
3277  float	elapsed_time;
3278
3279  struct	sctp_rr_request_struct	*sctp_rr_request;
3280  struct	sctp_rr_response_struct	*sctp_rr_response;
3281  struct	sctp_rr_results_struct	*sctp_rr_results;
3282
3283  sctp_rr_request =
3284    (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
3285  sctp_rr_response =
3286    (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
3287  sctp_rr_results =
3288    (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
3289
3290  if (debug) {
3291    fprintf(where,"netserver: recv_sctp_rr: entered...\n");
3292    fflush(where);
3293  }
3294
3295  /* We want to set-up the listen socket with all the desired */
3296  /* parameters and then let the initiator know that all is ready. If */
3297  /* socket size defaults are to be used, then the initiator will have */
3298  /* sent us 0's. If the socket sizes cannot be changed, then we will */
3299  /* send-back what they are. If that information cannot be determined, */
3300  /* then we send-back -1's for the sizes. If things go wrong for any */
3301  /* reason, we will drop back ten yards and punt. */
3302
3303  /* If anything goes wrong, we want the remote to know about it. It */
3304  /* would be best if the error that the remote reports to the user is */
3305  /* the actual error we encountered, rather than some bogus unexpected */
3306  /* response type message. */
3307
3308  if (debug) {
3309    fprintf(where,"recv_sctp_rr: setting the response type...\n");
3310    fflush(where);
3311  }
3312
3313  netperf_response.content.response_type = SCTP_RR_RESPONSE;
3314
3315  if (debug) {
3316    fprintf(where,"recv_sctp_rr: the response type is set...\n");
3317    fflush(where);
3318  }
3319
3320  /* allocate the recv and send rings with the requested alignments */
3321  /* and offsets. raj 7/94 */
3322  if (debug) {
3323    fprintf(where,"recv_sctp_rr: requested recv alignment of %d offset %d\n",
3324	    sctp_rr_request->recv_alignment,
3325	    sctp_rr_request->recv_offset);
3326    fprintf(where,"recv_sctp_rr: requested send alignment of %d offset %d\n",
3327	    sctp_rr_request->send_alignment,
3328	    sctp_rr_request->send_offset);
3329    fflush(where);
3330  }
3331
3332  /* at some point, these need to come to us from the remote system */
3333  if (send_width == 0) send_width = 1;
3334  if (recv_width == 0) recv_width = 1;
3335
3336  send_ring = allocate_buffer_ring(send_width,
3337				   sctp_rr_request->response_size,
3338				   sctp_rr_request->send_alignment,
3339				   sctp_rr_request->send_offset);
3340
3341  recv_ring = allocate_buffer_ring(recv_width,
3342				   sctp_rr_request->request_size,
3343				   sctp_rr_request->recv_alignment,
3344				   sctp_rr_request->recv_offset);
3345
3346
3347  /* Grab a socket to listen on, and then listen on it. */
3348
3349  if (debug) {
3350    fprintf(where,"recv_sctp_rr: grabbing a socket...\n");
3351    fflush(where);
3352  }
3353
3354  /* create_data_socket expects to find some things in the global */
3355  /* variables, so set the globals based on the values in the request. */
3356  /* once the socket has been created, we will set the response values */
3357  /* based on the updated value of those globals. raj 7/94 */
3358  lss_size_req = sctp_rr_request->send_buf_size;
3359  lsr_size_req = sctp_rr_request->recv_buf_size;
3360  loc_nodelay = sctp_rr_request->no_delay;
3361  loc_rcvavoid = sctp_rr_request->so_rcvavoid;
3362  loc_sndavoid = sctp_rr_request->so_sndavoid;
3363  non_block = sctp_rr_request->non_blocking;
3364
3365  set_hostname_and_port(local_name,
3366			port_buffer,
3367			nf_to_af(sctp_rr_request->ipfamily),
3368			sctp_rr_request->port);
3369
3370  local_res = complete_addrinfo(local_name,
3371				local_name,
3372				port_buffer,
3373				nf_to_af(sctp_rr_request->ipfamily),
3374				SOCK_STREAM,
3375				IPPROTO_SCTP,
3376				0);
3377
3378  s_listen = create_data_socket(local_res);
3379
3380  if (s_listen < 0) {
3381    netperf_response.content.serv_errno = errno;
3382    send_response();
3383
3384    exit(1);
3385  }
3386
3387  /* Now, let's set-up the socket to listen for connections */
3388  if (listen(s_listen, 5) == -1) {
3389    netperf_response.content.serv_errno = errno;
3390    close(s_listen);
3391    send_response();
3392
3393    exit(1);
3394  }
3395
3396
3397  /* now get the port number assigned by the system  */
3398  addrlen = sizeof(myaddr_in);
3399  if (getsockname(s_listen,
3400		  (struct sockaddr *)&myaddr_in, &addrlen) == -1){
3401    netperf_response.content.serv_errno = errno;
3402    close(s_listen);
3403    send_response();
3404
3405    exit(1);
3406  }
3407
3408  /* Now myaddr_in contains the port and the internet address this is */
3409  /* returned to the sender also implicitly telling the sender that the */
3410  /* socket buffer sizing has been done. */
3411
3412  sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
3413  netperf_response.content.serv_errno   = 0;
3414
3415  /* But wait, there's more. If the initiator wanted cpu measurements, */
3416  /* then we must call the calibrate routine, which will return the max */
3417  /* rate back to the initiator. If the CPU was not to be measured, or */
3418  /* something went wrong with the calibration, we will return a 0.0 to */
3419  /* the initiator. */
3420
3421  sctp_rr_response->cpu_rate = (float)0.0; 	/* assume no cpu */
3422  sctp_rr_response->measure_cpu = 0;
3423
3424  if (sctp_rr_request->measure_cpu) {
3425    sctp_rr_response->measure_cpu = 1;
3426    sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate);
3427  }
3428
3429
3430  /* before we send the response back to the initiator, pull some of */
3431  /* the socket parms from the globals */
3432  sctp_rr_response->send_buf_size = lss_size;
3433  sctp_rr_response->recv_buf_size = lsr_size;
3434  sctp_rr_response->no_delay = loc_nodelay;
3435  sctp_rr_response->so_rcvavoid = loc_rcvavoid;
3436  sctp_rr_response->so_sndavoid = loc_sndavoid;
3437  sctp_rr_response->test_length = sctp_rr_request->test_length;
3438  send_response();
3439
3440  addrlen = sizeof(peeraddr_in);
3441
3442  if ((s_data = accept(s_listen,
3443		       (struct sockaddr *)&peeraddr_in,
3444		       &addrlen)) == -1) {
3445    /* Let's just punt. The remote will be given some information */
3446    close(s_listen);
3447
3448    exit(1);
3449  }
3450
3451  /* we do not need events on a 1-to-1 RR test.  The test will finish
3452   * once all transactions are done.
3453   */
3454
3455  /* now that we are connected, mark the socket as non-blocking */
3456  if (non_block) {
3457    if (!set_nonblock(s_data)) {
3458      perror("netperf: set_nonblock");
3459	exit(1);
3460    }
3461  }
3462
3463#ifdef KLUDGE_SOCKET_OPTIONS
3464  /* this is for those systems which *INCORRECTLY* fail to pass */
3465  /* attributes across an accept() call. Including this goes against */
3466  /* my better judgement :( raj 11/95 */
3467
3468  kludge_socket_options(s_data);
3469
3470#endif /* KLUDGE_SOCKET_OPTIONS */
3471
3472  if (debug) {
3473    fprintf(where,"recv_sctp_rr: accept completes on the data connection.\n");
3474    fflush(where);
3475  }
3476
3477  /* Now it's time to start receiving data on the connection. We will */
3478  /* first grab the apropriate counters and then start grabbing. */
3479
3480  cpu_start(sctp_rr_request->measure_cpu);
3481
3482  /* The loop will exit when we hit the end of the test time, or when */
3483  /* we have exchanged the requested number of transactions. */
3484
3485  if (sctp_rr_request->test_length > 0) {
3486    times_up = 0;
3487    trans_remaining = 0;
3488    start_timer(sctp_rr_request->test_length + PAD_TIME);
3489  }
3490  else {
3491    times_up = 1;
3492    trans_remaining = sctp_rr_request->test_length * -1;
3493  }
3494
3495  trans_received = 0;
3496
3497  while ((!times_up) || (trans_remaining > 0)) {
3498    int msg_flags = 0;
3499
3500    temp_message_ptr = recv_ring->buffer_ptr;
3501    request_bytes_remaining = sctp_rr_request->request_size;
3502    while(!(msg_flags & MSG_EOR)) {
3503      if((request_bytes_recvd=sctp_recvmsg(s_data,
3504					temp_message_ptr,
3505					request_bytes_remaining,
3506					NULL, 0,
3507					NULL, &msg_flags)) < 0) {
3508	if (errno == EINTR) {
3509	  /* the timer popped */
3510	  timed_out = 1;
3511	  break;
3512	} else if (non_block && errno == EAGAIN) {
3513	    continue;  /* while request_bytes_remaining */
3514	}
3515	netperf_response.content.serv_errno = errno;
3516	send_response();
3517	exit(1);
3518      }
3519      request_bytes_remaining -= request_bytes_recvd;
3520      temp_message_ptr += request_bytes_recvd;
3521    }
3522
3523    recv_ring = recv_ring->next;
3524
3525    if (timed_out) {
3526      /* we hit the end of the test based on time - lets */
3527      /* bail out of here now... */
3528      if (debug) {
3529	fprintf(where,"yo55\n");
3530	fflush(where);
3531      }
3532      break;
3533    }
3534
3535
3536    /* Now, send the response to the remote
3537     * In 1-to-1 API destination addr is not needed.
3538     */
3539    while ((bytes_sent=sctp_sendmsg(s_data,
3540				    send_ring->buffer_ptr,
3541				    sctp_rr_request->response_size,
3542				    NULL, 0,
3543				    0, 0, 0, 0, 0)) == -1) {
3544      if (errno == EINTR) {
3545	/* the test timer has popped */
3546	timed_out = 1;
3547	break;
3548      } else if (non_block && errno == EAGAIN) {
3549	 continue;
3550      }
3551
3552      netperf_response.content.serv_errno = 982;
3553      send_response();
3554      exit(1);
3555    }
3556
3557    if (timed_out) {
3558      /* we hit the end of the test based on time - lets */
3559      /* bail out of here now... */
3560      if (debug) {
3561	fprintf(where,"yo6\n");
3562	fflush(where);
3563      }
3564      break;
3565    }
3566
3567    send_ring = send_ring->next;
3568
3569    trans_received++;
3570    if (trans_remaining) {
3571      trans_remaining--;
3572    }
3573  }
3574
3575
3576  /* The loop now exits due to timeout or transaction count being */
3577  /* reached */
3578
3579  cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time);
3580
3581  stop_timer();
3582
3583  if (timed_out) {
3584    /* we ended the test by time, which was at least 2 seconds */
3585    /* longer than we wanted to run. so, we want to subtract */
3586    /* PAD_TIME from the elapsed_time. */
3587    elapsed_time -= PAD_TIME;
3588  }
3589
3590  /* send the results to the sender			*/
3591
3592  if (debug) {
3593    fprintf(where,
3594	    "recv_sctp_rr: got %d transactions\n",
3595	    trans_received);
3596    fflush(where);
3597  }
3598
3599  sctp_rr_results->bytes_received = (trans_received *
3600				    (sctp_rr_request->request_size +
3601				     sctp_rr_request->response_size));
3602  sctp_rr_results->trans_received = trans_received;
3603  sctp_rr_results->elapsed_time   = elapsed_time;
3604  sctp_rr_results->cpu_method     = cpu_method;
3605  sctp_rr_results->num_cpus       = lib_num_loc_cpus;
3606  if (sctp_rr_request->measure_cpu) {
3607    sctp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
3608  }
3609
3610  if (debug) {
3611    fprintf(where,
3612	    "recv_sctp_rr: test complete, sending results.\n");
3613    fflush(where);
3614  }
3615
3616  /* we are now done with the sockets */
3617  send_response();
3618
3619  close(s_data);
3620  close(s_listen);
3621
3622}
3623
3624
3625
3626/* this routine implements the sending (netperf) side of the
3627   SCTP_RR_1TOMANY test */
3628
3629void
3630send_sctp_rr_1toMany(remote_host)
3631     char	remote_host[];
3632{
3633
3634  char *tput_title = "\
3635Local /Remote\n\
3636Socket Size   Request  Resp.   Elapsed  Trans.\n\
3637Send   Recv   Size     Size    Time     Rate         \n\
3638bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
3639
3640  char *tput_fmt_0 =
3641    "%7.2f\n";
3642
3643  char *tput_fmt_1_line_1 = "\
3644%-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
3645  char *tput_fmt_1_line_2 = "\
3646%-6d %-6d\n";
3647
3648  char *cpu_title = "\
3649Local /Remote\n\
3650Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
3651Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
3652bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
3653
3654  char *cpu_fmt_0 =
3655    "%6.3f %c\n";
3656
3657  char *cpu_fmt_1_line_1 = "\
3658%-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f\n";
3659
3660  char *cpu_fmt_1_line_2 = "\
3661%-6d %-6d\n";
3662
3663  char *ksink_fmt = "\
3664Alignment      Offset\n\
3665Local  Remote  Local  Remote\n\
3666Send   Recv    Send   Recv\n\
3667%5d  %5d   %5d  %5d\n";
3668
3669
3670  int			timed_out = 0;
3671  float			elapsed_time;
3672
3673  int	len, j = 0;
3674  char	*temp_message_ptr;
3675  int	nummessages;
3676  int	*send_socket;
3677  int	trans_remaining;
3678  double	bytes_xferd;
3679  int   msg_flags = 0;
3680
3681  struct ring_elt *send_ring;
3682  struct ring_elt *recv_ring;
3683
3684  int	rsp_bytes_left;
3685  int	rsp_bytes_recvd;
3686
3687  float	local_cpu_utilization;
3688  float	local_service_demand;
3689  float	remote_cpu_utilization;
3690  float	remote_service_demand;
3691  double	thruput;
3692
3693  struct sockaddr_storage peer;
3694  struct addrinfo *local_res;
3695  struct addrinfo *remote_res;
3696
3697  struct	sctp_rr_request_struct	*sctp_rr_request;
3698  struct	sctp_rr_response_struct	*sctp_rr_response;
3699  struct	sctp_rr_results_struct	*sctp_rr_result;
3700
3701#ifdef WANT_INTERVALS
3702  int	interval_count;
3703  sigset_t signal_set;
3704#endif /* WANT_INTERVALS */
3705
3706  sctp_rr_request =
3707    (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
3708  sctp_rr_response =
3709    (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
3710  sctp_rr_result =
3711    (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
3712
3713#ifdef WANT_HISTOGRAM
3714  time_hist = HIST_new();
3715#endif /* WANT_HISTOGRAM */
3716
3717  /* since we are now disconnected from the code that established the */
3718  /* control socket, and since we want to be able to use different */
3719  /* protocols and such, we are passed the name of the remote host and */
3720  /* must turn that into the test specific addressing information. */
3721
3722  complete_addrinfos(&remote_res,
3723		     &local_res,
3724		     remote_host,
3725		     SOCK_SEQPACKET,
3726		     IPPROTO_SCTP,
3727		     0);
3728
3729  if ( print_headers ) {
3730    print_top_test_header("SCTP 1-TO-MANY REQUEST/RESPONSE TEST",local_res,remote_res);
3731  }
3732
3733  /* initialize a few counters */
3734
3735  send_ring = NULL;
3736  recv_ring = NULL;
3737  confidence_iteration = 1;
3738  init_stat();
3739
3740  send_socket = malloc(sizeof(int) * num_associations);
3741  if (send_socket == NULL) {
3742      fprintf(where,
3743	      "Could not create the socket array for %d associations",
3744	      num_associations);
3745      fflush(where);
3746      exit(1);
3747  }
3748
3749  /* we have a great-big while loop which controls the number of times */
3750  /* we run a particular test. this is for the calculation of a */
3751  /* confidence interval (I really should have stayed awake during */
3752  /* probstats :). If the user did not request confidence measurement */
3753  /* (no confidence is the default) then we will only go though the */
3754  /* loop once. the confidence stuff originates from the folks at IBM */
3755
3756  while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
3757	 (confidence_iteration <= iteration_min)) {
3758
3759    /* initialize a few counters. we have to remember that we might be */
3760    /* going through the loop more than once. */
3761
3762    nummessages     = 0;
3763    bytes_xferd     = 0.0;
3764    times_up        = 0;
3765    timed_out       = 0;
3766    trans_remaining = 0;
3767
3768    /* set-up the data buffers with the requested alignment and offset. */
3769    /* since this is a request/response test, default the send_width and */
3770    /* recv_width to 1 and not two raj 7/94 */
3771
3772    if (send_width == 0) send_width = 1;
3773    if (recv_width == 0) recv_width = 1;
3774
3775    if (send_ring == NULL) {
3776      send_ring = allocate_buffer_ring(send_width,
3777				       req_size,
3778				       local_send_align,
3779				       local_send_offset);
3780    }
3781
3782    if (recv_ring == NULL) {
3783      recv_ring = allocate_buffer_ring(recv_width,
3784				       rsp_size,
3785				       local_recv_align,
3786				       local_recv_offset);
3787    }
3788
3789    /* If the user has requested cpu utilization measurements, we must */
3790    /* calibrate the cpu(s). We will perform this task within the tests */
3791    /* themselves. If the user has specified the cpu rate, then */
3792    /* calibrate_local_cpu will return rather quickly as it will have */
3793    /* nothing to do. If local_cpu_rate is zero, then we will go through */
3794    /* all the "normal" calibration stuff and return the rate back.*/
3795
3796    if (local_cpu_usage) {
3797      local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3798    }
3799
3800    /* Tell the remote end to do a listen. The server alters the socket */
3801    /* paramters on the other side at this point, hence the reason for */
3802    /* all the values being passed in the setup message. If the user did */
3803    /* not specify any of the parameters, they will be passed as 0, which */
3804    /* will indicate to the remote that no changes beyond the system's */
3805    /* default should be used. Alignment is the exception, it will */
3806    /* default to 8, which will be no alignment alterations. */
3807
3808    netperf_request.content.request_type =	DO_SCTP_RR_MANY;
3809    sctp_rr_request->recv_buf_size     =	rsr_size_req;
3810    sctp_rr_request->send_buf_size     =	rss_size_req;
3811    sctp_rr_request->recv_alignment    =	remote_recv_align;
3812    sctp_rr_request->recv_offset       =	remote_recv_offset;
3813    sctp_rr_request->send_alignment    =	remote_send_align;
3814    sctp_rr_request->send_offset       =	remote_send_offset;
3815    sctp_rr_request->request_size      =	req_size;
3816    sctp_rr_request->response_size     =	rsp_size;
3817    sctp_rr_request->no_delay	       =	rem_nodelay;
3818    sctp_rr_request->measure_cpu       =	remote_cpu_usage;
3819    sctp_rr_request->cpu_rate	       =	remote_cpu_rate;
3820    sctp_rr_request->so_rcvavoid       =	rem_rcvavoid;
3821    sctp_rr_request->so_sndavoid       =	rem_sndavoid;
3822    if (test_time) {
3823      sctp_rr_request->test_length     =	test_time;
3824    }
3825    else {
3826      sctp_rr_request->test_length     =	test_trans * num_associations
3827						* -1;
3828    }
3829    sctp_rr_request->non_blocking      = 	non_block;
3830    sctp_rr_request->port              =       atoi(remote_data_port);
3831    sctp_rr_request->ipfamily          =       af_to_nf(remote_res->ai_family);
3832    if (debug > 1) {
3833      fprintf(where,"netperf: send_sctp_rr_1toMany: requesting SCTP rr test\n");
3834    }
3835
3836    send_request();
3837
3838    /* The response from the remote will contain all of the relevant 	*/
3839    /* socket parameters for this test type. We will put them back into */
3840    /* the variables here so they can be displayed if desired.  The	*/
3841    /* remote will have calibrated CPU if necessary, and will have done	*/
3842    /* all the needed set-up we will have calibrated the cpu locally	*/
3843    /* before sending the request, and will grab the counter value right*/
3844    /* after the connect returns. The remote will grab the counter right*/
3845    /* after the accept call. This saves the hassle of extra messages	*/
3846    /* being sent for the sctp tests.					*/
3847
3848    recv_response();
3849
3850    if (!netperf_response.content.serv_errno) {
3851      rsr_size          = sctp_rr_response->recv_buf_size;
3852      rss_size          = sctp_rr_response->send_buf_size;
3853      rem_nodelay       = sctp_rr_response->no_delay;
3854      remote_cpu_usage  = sctp_rr_response->measure_cpu;
3855      remote_cpu_rate   = sctp_rr_response->cpu_rate;
3856      /* make sure that port numbers are in network order */
3857      set_port_number(remote_res,
3858		      (unsigned short)sctp_rr_response->data_port_number);
3859    }
3860    else {
3861      Set_errno(netperf_response.content.serv_errno);
3862      fprintf(where,
3863	      "netperf: remote error %d",
3864	      netperf_response.content.serv_errno);
3865      perror("");
3866      fflush(where);
3867
3868      exit(1);
3869    }
3870
3871    /*set up the data socket list  */
3872    for (j = 0; j < num_associations; j++) {
3873      send_socket[j] = create_data_socket(local_res);
3874
3875      if (send_socket < 0){
3876	perror("netperf: send_sctp_rr_1toMany: sctp stream data socket");
3877	exit(1);
3878      }
3879
3880      /*Connect up to the remote port on the data socket  */
3881      if (connect(send_socket[j],
3882		  remote_res->ai_addr,
3883		  remote_res->ai_addrlen) < 0){
3884	perror("netperf: data socket connect failed");
3885
3886	exit(1);
3887      }
3888
3889      /* The client end of the 1-to-Many test uses 1-to-1 sockets.
3890       * it doesn't need events.
3891       */
3892      sctp_enable_events(send_socket[j], 0);
3893
3894      if (non_block) {
3895        if (!set_nonblock(send_socket[j])) {
3896	  close(send_socket[j]);
3897	  exit(1);
3898	}
3899      }
3900    }
3901
3902    /* Data Socket set-up is finished. If there were problems, either the */
3903    /* connect would have failed, or the previous response would have */
3904    /* indicated a problem. I failed to see the value of the extra */
3905    /* message after the accept on the remote. If it failed, we'll see it */
3906    /* here. If it didn't, we might as well start pumping data. */
3907
3908    /* Set-up the test end conditions. For a request/response test, they */
3909    /* can be either time or transaction based. */
3910
3911    if (test_time) {
3912      /* The user wanted to end the test after a period of time. */
3913      times_up = 0;
3914      trans_remaining = 0;
3915      start_timer(test_time);
3916    }
3917    else {
3918      /* The tester wanted to send a number of bytes. */
3919      trans_remaining = test_bytes * num_associations;
3920      times_up = 1;
3921    }
3922
3923    /* The cpu_start routine will grab the current time and possibly */
3924    /* value of the idle counter for later use in measuring cpu */
3925    /* utilization and/or service demand and thruput. */
3926
3927    cpu_start(local_cpu_usage);
3928
3929#ifdef WANT_INTERVALS
3930    if ((interval_burst) || (demo_mode)) {
3931      /* zero means that we never pause, so we never should need the */
3932      /* interval timer, unless we are in demo_mode */
3933      start_itimer(interval_wate);
3934    }
3935    interval_count = interval_burst;
3936    /* get the signal set for the call to sigsuspend */
3937    if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) {
3938      fprintf(where,
3939	      "send_sctp_rr_1toMany: unable to get sigmask errno %d\n",
3940	      errno);
3941      fflush(where);
3942      exit(1);
3943    }
3944#endif /* WANT_INTERVALS */
3945
3946    /* We use an "OR" to control test execution. When the test is */
3947    /* controlled by time, the byte count check will always return false. */
3948    /* When the test is controlled by byte count, the time test will */
3949    /* always return false. When the test is finished, the whole */
3950    /* expression will go false and we will stop sending data. I think I */
3951    /* just arbitrarily decrement trans_remaining for the timed test, but */
3952    /* will not do that just yet... One other question is whether or not */
3953    /* the send buffer and the receive buffer should be the same buffer. */
3954
3955#ifdef WANT_FIRST_BURST
3956    {
3957      int i;
3958      for (j = 0; j < num_associations; j++) {
3959	  for (i = 0; i < first_burst_size; i++) {
3960	    if((len=sctp_sendmsg(send_socket[j],
3961			 send_ring->buffer_ptr, send_size,
3962			 remote_res->ai_addr,
3963			 remote_res->ai_addrlen,
3964			 0, 0, 0, 0, 0)) != req_size) {
3965	      /* we should never hit the end of the test in the first burst */
3966	      perror("send_sctp_rr_1toMany: initial burst data send error");
3967	      exit(1);
3968	    }
3969	  }
3970      }
3971    }
3972#endif /* WANT_FIRST_BURST */
3973
3974    while ((!times_up) || (trans_remaining > 0)) {
3975      /* send the request. we assume that if we use a blocking socket, */
3976      /* the request will be sent at one shot. */
3977
3978      /* this is a fairly poor way of testing 1toMany connections.
3979       * For each association we measure round trip time to account for
3980       * any delay in lookups and delivery.  To stress the server a bit
3981       * more we would need a distributed client test, or at least multiple
3982       * processes.  I want to force as much paralellism as possible, but
3983       * this will do for the fist take. vlad
3984       */
3985      for (j = 0; j < num_associations; j++) {
3986#ifdef WANT_HISTOGRAM
3987	/* timestamp just before our call to send, and then again just */
3988	/* after the receive raj 8/94 */
3989	gettimeofday(&time_one,NULL);
3990#endif /* WANT_HISTOGRAM */
3991
3992	while ((len=sctp_sendmsg(send_socket[j],
3993				 send_ring->buffer_ptr, send_size,
3994				 remote_res->ai_addr,
3995				 remote_res->ai_addrlen,
3996				 0, 0, 0, 0, 0)) != req_size) {
3997	  if (non_block && errno == EAGAIN) {
3998	    /* try sending again */
3999	    continue;
4000	  } else if ((errno == EINTR) || (errno == 0)) {
4001	    /* we hit the end of a */
4002	    /* timed test. */
4003	    timed_out = 1;
4004	    break;
4005	  }
4006	  perror("send_sctp_rr_1toMany: data send error");
4007	  exit(1);
4008	}
4009
4010	if (timed_out) {
4011	  /* we may have been in a nested while loop - we need */
4012	  /* another call to break. */
4013	  break;
4014	}
4015
4016	/* setup for the next time */
4017	send_ring = send_ring->next;
4018
4019	rsp_bytes_left = rsp_size;
4020	temp_message_ptr  = recv_ring->buffer_ptr;
4021	while (!(msg_flags & MSG_EOR)) {
4022	  if((rsp_bytes_recvd = sctp_recvmsg(send_socket[j],
4023					     temp_message_ptr,
4024					     rsp_bytes_left,
4025					     NULL, 0,
4026					     NULL, &msg_flags)) < 0) {
4027	    if (errno == EINTR) {
4028	      /* We hit the end of a timed test. */
4029	      timed_out = 1;
4030	      break;
4031	    } else if (non_block && errno == EAGAIN) {
4032	      continue;
4033	    }
4034	    perror("send_sctp_rr_1toMany: data recv error");
4035	    exit(1);
4036	  }
4037	  rsp_bytes_left -= rsp_bytes_recvd;
4038	  temp_message_ptr  += rsp_bytes_recvd;
4039	}
4040	recv_ring = recv_ring->next;
4041
4042	if (timed_out) {
4043	  /* we may have been in a nested while loop - we need */
4044	  /* another call to break. */
4045	  break;
4046	}
4047
4048#ifdef WANT_HISTOGRAM
4049	gettimeofday(&time_two,NULL);
4050	HIST_add(time_hist,delta_micro(&time_one,&time_two));
4051#endif /* WANT_HISTOGRAM */
4052
4053	nummessages++;
4054	if (trans_remaining) {
4055	  trans_remaining--;
4056	}
4057
4058	if (debug > 3) {
4059	  if ((nummessages % 100) == 0) {
4060	    fprintf(where,
4061		    "Transaction %d completed\n",
4062		    nummessages);
4063	    fflush(where);
4064	  }
4065	}
4066      }
4067    }
4068
4069    /* At this point we used to call shutdown on the data socket to be */
4070    /* sure all the data was delivered, but this was not germane in a */
4071    /* request/response test, and it was causing the tests to "hang" when */
4072    /* they were being controlled by time. So, I have replaced this */
4073    /* shutdown call with a call to close that can be found later in the */
4074    /* procedure. */
4075
4076    /* this call will always give us the elapsed time for the test, and */
4077    /* will also store-away the necessaries for cpu utilization */
4078
4079    cpu_stop(local_cpu_usage,&elapsed_time);	/* was cpu being */
4080						/* measured? how long */
4081						/* did we really run? */
4082
4083    /* Get the statistics from the remote end. The remote will have */
4084    /* calculated CPU utilization. If it wasn't supposed to care, it */
4085    /* will return obvious values. */
4086
4087    recv_response();
4088    if (!netperf_response.content.serv_errno) {
4089      if (debug)
4090	fprintf(where,"remote results obtained\n");
4091    }
4092    else {
4093      Set_errno(netperf_response.content.serv_errno);
4094      fprintf(where,"netperf: remote error %d",
4095	      netperf_response.content.serv_errno);
4096      perror("");
4097      fflush(where);
4098      exit(1);
4099    }
4100
4101    /* We now calculate what our throughput was for the test. */
4102
4103    bytes_xferd	= (req_size * nummessages) + (rsp_size * nummessages);
4104    thruput	= nummessages/elapsed_time;
4105
4106    if (local_cpu_usage || remote_cpu_usage) {
4107      /* We must now do a little math for service demand and cpu */
4108      /* utilization for the system(s) */
4109      /* Of course, some of the information might be bogus because */
4110      /* there was no idle counter in the kernel(s). We need to make */
4111      /* a note of this for the user's benefit...*/
4112      if (local_cpu_usage) {
4113	local_cpu_utilization = calc_cpu_util(0.0);
4114	/* since calc_service demand is doing ms/Kunit we will */
4115	/* multiply the number of transaction by 1024 to get */
4116	/* "good" numbers */
4117	local_service_demand  = calc_service_demand((double) nummessages*1024,
4118						    0.0,
4119						    0.0,
4120						    0);
4121      }
4122      else {
4123	local_cpu_utilization	= (float) -1.0;
4124	local_service_demand	= (float) -1.0;
4125      }
4126
4127      if (remote_cpu_usage) {
4128	remote_cpu_utilization = sctp_rr_result->cpu_util;
4129	/* since calc_service demand is doing ms/Kunit we will */
4130	/* multiply the number of transaction by 1024 to get */
4131	/* "good" numbers */
4132	remote_service_demand = calc_service_demand((double) nummessages*1024,
4133						    0.0,
4134						    remote_cpu_utilization,
4135						    sctp_rr_result->num_cpus);
4136      }
4137      else {
4138	remote_cpu_utilization = (float) -1.0;
4139	remote_service_demand  = (float) -1.0;
4140      }
4141
4142    }
4143    else {
4144      /* we were not measuring cpu, for the confidence stuff, we */
4145      /* should make it -1.0 */
4146      local_cpu_utilization	= (float) -1.0;
4147      local_service_demand	= (float) -1.0;
4148      remote_cpu_utilization = (float) -1.0;
4149      remote_service_demand  = (float) -1.0;
4150    }
4151
4152    /* at this point, we want to calculate the confidence information. */
4153    /* if debugging is on, calculate_confidence will print-out the */
4154    /* parameters we pass it */
4155
4156    calculate_confidence(confidence_iteration,
4157			 elapsed_time,
4158			 thruput,
4159			 local_cpu_utilization,
4160			 remote_cpu_utilization,
4161			 local_service_demand,
4162			 remote_service_demand);
4163
4164
4165    confidence_iteration++;
4166
4167    /* we are now done with the socket, so close it */
4168    for (j = 0; j < num_associations; j++)
4169	close(send_socket[j]);
4170  }
4171
4172  retrieve_confident_values(&elapsed_time,
4173			    &thruput,
4174			    &local_cpu_utilization,
4175			    &remote_cpu_utilization,
4176			    &local_service_demand,
4177			    &remote_service_demand);
4178
4179  /* We are now ready to print all the information. If the user */
4180  /* has specified zero-level verbosity, we will just print the */
4181  /* local service demand, or the remote service demand. If the */
4182  /* user has requested verbosity level 1, he will get the basic */
4183  /* "streamperf" numbers. If the user has specified a verbosity */
4184  /* of greater than 1, we will display a veritable plethora of */
4185  /* background information from outside of this block as it it */
4186  /* not cpu_measurement specific...  */
4187
4188  if (confidence < 0) {
4189    /* we did not hit confidence, but were we asked to look for it? */
4190    if (iteration_max > 1) {
4191      display_confidence();
4192    }
4193  }
4194
4195  if (local_cpu_usage || remote_cpu_usage) {
4196    local_cpu_method = format_cpu_method(cpu_method);
4197    remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method);
4198
4199    switch (verbosity) {
4200    case 0:
4201      if (local_cpu_usage) {
4202	fprintf(where,
4203		cpu_fmt_0,
4204		local_service_demand,
4205		local_cpu_method);
4206      }
4207      else {
4208	fprintf(where,
4209		cpu_fmt_0,
4210		remote_service_demand,
4211		remote_cpu_method);
4212      }
4213      break;
4214    case 1:
4215    case 2:
4216      if (print_headers) {
4217	fprintf(where,
4218		cpu_title,
4219		local_cpu_method,
4220		remote_cpu_method);
4221      }
4222
4223      fprintf(where,
4224	      cpu_fmt_1_line_1,		/* the format string */
4225	      lss_size,		/* local sendbuf size */
4226	      lsr_size,
4227	      req_size,		/* how large were the requests */
4228	      rsp_size,		/* guess */
4229	      elapsed_time,		/* how long was the test */
4230	      thruput,
4231	      local_cpu_utilization,	/* local cpu */
4232	      remote_cpu_utilization,	/* remote cpu */
4233	      local_service_demand,	/* local service demand */
4234	      remote_service_demand);	/* remote service demand */
4235      fprintf(where,
4236	      cpu_fmt_1_line_2,
4237	      rss_size,
4238	      rsr_size);
4239      break;
4240    }
4241  }
4242  else {
4243    /* The tester did not wish to measure service demand. */
4244
4245    switch (verbosity) {
4246    case 0:
4247      fprintf(where,
4248	      tput_fmt_0,
4249	      thruput);
4250      break;
4251    case 1:
4252    case 2:
4253      if (print_headers) {
4254	fprintf(where,tput_title,format_units());
4255      }
4256
4257      fprintf(where,
4258	      tput_fmt_1_line_1,	/* the format string */
4259	      lss_size,
4260	      lsr_size,
4261	      req_size,		/* how large were the requests */
4262	      rsp_size,		/* how large were the responses */
4263	      elapsed_time, 		/* how long did it take */
4264	      thruput);
4265      fprintf(where,
4266	      tput_fmt_1_line_2,
4267	      rss_size, 		/* remote recvbuf size */
4268	      rsr_size);
4269
4270      break;
4271    }
4272  }
4273
4274  /* it would be a good thing to include information about some of the */
4275  /* other parameters that may have been set for this test, but at the */
4276  /* moment, I do not wish to figure-out all the  formatting, so I will */
4277  /* just put this comment here to help remind me that it is something */
4278  /* that should be done at a later time. */
4279
4280  /* how to handle the verbose information in the presence of */
4281  /* confidence intervals is yet to be determined... raj 11/94 */
4282  if (verbosity > 1) {
4283    /* The user wanted to know it all, so we will give it to him. */
4284    /* This information will include as much as we can find about */
4285    /* TCP statistics, the alignments of the sends and receives */
4286    /* and all that sort of rot... */
4287
4288    fprintf(where,
4289	    ksink_fmt,
4290	    local_send_align,
4291	    remote_recv_offset,
4292	    local_send_offset,
4293	    remote_recv_offset);
4294
4295#ifdef WANT_HISTOGRAM
4296    fprintf(where,"\nHistogram of request/response times\n");
4297    fflush(where);
4298    HIST_report(time_hist);
4299#endif /* WANT_HISTOGRAM */
4300
4301  }
4302
4303}
4304
4305
4306 /* this routine implements the receive (netserver) side of a TCP_RR */
4307 /* test */
4308void
4309recv_sctp_rr_1toMany()
4310{
4311
4312  struct ring_elt *send_ring;
4313  struct ring_elt *recv_ring;
4314
4315
4316  struct sockaddr_in        myaddr_in; 	/* needed to get the port number */
4317  struct sockaddr_storage   peeraddr;   /* to communicate with peer */
4318  struct addrinfo *local_res;
4319  char   local_name[BUFSIZ];
4320  char   port_buffer[PORTBUFSIZE];
4321  int    msg_flags;
4322
4323  int	s_rcv;
4324  int 	addrlen;
4325  char	*temp_message_ptr;
4326  int	trans_received;
4327  int	trans_remaining;
4328  int	bytes_sent;
4329  int	bytes_recvd;
4330  int	recv_buf_size;
4331  int	timed_out = 0;
4332  float	elapsed_time;
4333
4334  struct	sctp_rr_request_struct	*sctp_rr_request;
4335  struct	sctp_rr_response_struct	*sctp_rr_response;
4336  struct	sctp_rr_results_struct	*sctp_rr_results;
4337
4338  sctp_rr_request =
4339    (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data;
4340  sctp_rr_response =
4341    (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data;
4342  sctp_rr_results =
4343    (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data;
4344
4345  if (debug) {
4346    fprintf(where,"netserver: recv_sctp_rr_1toMany: entered...\n");
4347    fflush(where);
4348  }
4349
4350  /* We want to set-up the listen socket with all the desired */
4351  /* parameters and then let the initiator know that all is ready. If */
4352  /* socket size defaults are to be used, then the initiator will have */
4353  /* sent us 0's. If the socket sizes cannot be changed, then we will */
4354  /* send-back what they are. If that information cannot be determined, */
4355  /* then we send-back -1's for the sizes. If things go wrong for any */
4356  /* reason, we will drop back ten yards and punt. */
4357
4358  /* If anything goes wrong, we want the remote to know about it. It */
4359  /* would be best if the error that the remote reports to the user is */
4360  /* the actual error we encountered, rather than some bogus unexpected */
4361  /* response type message. */
4362
4363  if (debug) {
4364    fprintf(where,"recv_sctp_rr_1toMany: setting the response type...\n");
4365    fflush(where);
4366  }
4367
4368  netperf_response.content.response_type = SCTP_RR_MANY_RESPONSE;
4369
4370  if (debug) {
4371    fprintf(where,"recv_sctp_rr_1toMany: the response type is set...\n");
4372    fflush(where);
4373  }
4374
4375  /* allocate the recv and send rings with the requested alignments */
4376  /* and offsets. raj 7/94 */
4377  if (debug) {
4378    fprintf(where,"recv_sctp_rr_1toMany: requested recv alignment of %d offset %d\n",
4379	    sctp_rr_request->recv_alignment,
4380	    sctp_rr_request->recv_offset);
4381    fprintf(where,"recv_sctp_rr_1toMany: requested send alignment of %d offset %d\n",
4382	    sctp_rr_request->send_alignment,
4383	    sctp_rr_request->send_offset);
4384    fflush(where);
4385  }
4386
4387  /* at some point, these need to come to us from the remote system */
4388  if (send_width == 0) send_width = 1;
4389  if (recv_width == 0) recv_width = 1;
4390
4391  send_ring = allocate_buffer_ring(send_width,
4392				   sctp_rr_request->response_size,
4393				   sctp_rr_request->send_alignment,
4394				   sctp_rr_request->send_offset);
4395
4396  recv_ring = allocate_buffer_ring(recv_width,
4397				   sctp_rr_request->request_size,
4398				   sctp_rr_request->recv_alignment,
4399				   sctp_rr_request->recv_offset);
4400
4401
4402  /* create_data_socket expects to find some things in the global */
4403  /* variables, so set the globals based on the values in the request. */
4404  /* once the socket has been created, we will set the response values */
4405  /* based on the updated value of those globals. raj 7/94 */
4406  lss_size_req = sctp_rr_request->send_buf_size;
4407  lsr_size_req = sctp_rr_request->recv_buf_size;
4408  loc_nodelay = sctp_rr_request->no_delay;
4409  loc_rcvavoid = sctp_rr_request->so_rcvavoid;
4410  loc_sndavoid = sctp_rr_request->so_sndavoid;
4411  non_block = sctp_rr_request->non_blocking;
4412
4413  set_hostname_and_port(local_name,
4414		        port_buffer,
4415			nf_to_af(sctp_rr_request->ipfamily),
4416			sctp_rr_request->port);
4417
4418  local_res = complete_addrinfo(local_name,
4419				local_name,
4420				port_buffer,
4421				nf_to_af(sctp_rr_request->ipfamily),
4422				SOCK_SEQPACKET,
4423				IPPROTO_SCTP,
4424				0);
4425
4426  /* Grab a socket to listen on, and then listen on it. */
4427  if (debug) {
4428    fprintf(where,"recv_sctp_rr_1toMany: grabbing a socket...\n");
4429    fflush(where);
4430  }
4431
4432  s_rcv = create_data_socket(local_res);
4433
4434  if (s_rcv < 0) {
4435    netperf_response.content.serv_errno = errno;
4436    send_response();
4437
4438    exit(1);
4439  }
4440
4441  /* Now, let's set-up the socket to listen for connections */
4442  if (listen(s_rcv, 5) == -1) {
4443    netperf_response.content.serv_errno = errno;
4444    close(s_rcv);
4445    send_response();
4446
4447    exit(1);
4448  }
4449
4450
4451  /* now get the port number assigned by the system  */
4452  addrlen = sizeof(myaddr_in);
4453  if (getsockname(s_rcv,
4454		  (struct sockaddr *)&myaddr_in, &addrlen) == -1){
4455    netperf_response.content.serv_errno = errno;
4456    close(s_rcv);
4457    send_response();
4458
4459    exit(1);
4460  }
4461
4462  /* Now myaddr_in contains the port and the internet address this is */
4463  /* returned to the sender also implicitly telling the sender that the */
4464  /* socket buffer sizing has been done. */
4465
4466  sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
4467  netperf_response.content.serv_errno   = 0;
4468
4469  /* But wait, there's more. If the initiator wanted cpu measurements, */
4470  /* then we must call the calibrate routine, which will return the max */
4471  /* rate back to the initiator. If the CPU was not to be measured, or */
4472  /* something went wrong with the calibration, we will return a 0.0 to */
4473  /* the initiator. */
4474
4475  sctp_rr_response->cpu_rate = (float)0.0; 	/* assume no cpu */
4476  sctp_rr_response->measure_cpu = 0;
4477
4478  if (sctp_rr_request->measure_cpu) {
4479    sctp_rr_response->measure_cpu = 1;
4480    sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate);
4481  }
4482
4483
4484  /* before we send the response back to the initiator, pull some of */
4485  /* the socket parms from the globals */
4486  sctp_rr_response->send_buf_size = lss_size;
4487  sctp_rr_response->recv_buf_size = lsr_size;
4488  sctp_rr_response->no_delay = loc_nodelay;
4489  sctp_rr_response->so_rcvavoid = loc_rcvavoid;
4490  sctp_rr_response->so_sndavoid = loc_sndavoid;
4491  sctp_rr_response->test_length = sctp_rr_request->test_length;
4492  send_response();
4493
4494  /* Don't need events */
4495  sctp_enable_events(s_rcv, 0);
4496
4497  /* now that we are connected, mark the socket as non-blocking */
4498  if (non_block) {
4499    if (!set_nonblock(s_rcv)) {
4500      perror("netperf: set_nonblock");
4501	exit(1);
4502    }
4503  }
4504
4505  /* FIXME:  The way 1-to-Many test operates right now, we are including
4506   * association setup time into our measurements.  The reason for this
4507   * is that the client creates multiple endpoints and connects each
4508   * endpoint to us using the connect call.  On this end we simply call
4509   * recvmsg() to get data becuase there is no equivalen of accept() for
4510   * 1-to-Many API.
4511   * I think this is OK, but if it were to be fixed, the server side
4512   * would need to know how many associations are being setup and
4513   * have a recvmsg() loop with SCTP_ASSOC_CHANGE events waiting for
4514   * all the associations to be be established.
4515   * I am punting on this for now.
4516   */
4517
4518
4519  addrlen = sizeof(peeraddr);
4520
4521  /* Now it's time to start receiving data on the connection. We will */
4522  /* first grab the apropriate counters and then start grabbing. */
4523
4524  cpu_start(sctp_rr_request->measure_cpu);
4525
4526  /* The loop will exit when we hit the end of the test time, or when */
4527  /* we have exchanged the requested number of transactions. */
4528
4529  if (sctp_rr_request->test_length > 0) {
4530    times_up = 0;
4531    trans_remaining = 0;
4532    start_timer(sctp_rr_request->test_length + PAD_TIME);
4533  }
4534  else {
4535    times_up = 1;
4536    trans_remaining = sctp_rr_request->test_length * -1;
4537  }
4538
4539  trans_received = 0;
4540
4541  while ((!times_up) || (trans_remaining > 0)) {
4542
4543    recv_buf_size = sctp_rr_request->request_size;
4544
4545    /* Receive the data.  We don't particularly care which association
4546     * the data came in on.  We'll simply be doing a receive untill
4547     * we get and MSG_EOR flag (meaning that a single transmission was
4548     * received) and a send to the same address, so the RR would be for
4549     * the same associations.
4550     * We can get away with this because the client will establish all
4551     * the associations before transmitting any data.  Any partial data
4552     * will not have EOR thus will we will not send a response untill
4553     * we get everything.
4554     */
4555
4556    do {
4557      msg_flags = 0;
4558      if((bytes_recvd = sctp_recvmsg(s_rcv,
4559				     recv_ring->buffer_ptr,
4560				     recv_buf_size,
4561				     (struct sockaddr *)&peeraddr, &addrlen,
4562				     0, &msg_flags)) == SOCKET_ERROR) {
4563	if (SOCKET_EINTR(bytes_recvd)) {
4564	  /* the timer popped */
4565	  timed_out = 1;
4566	  break;
4567	} else if (non_block & errno == EAGAIN) {
4568	    /* do recvmsg again */
4569	    continue;
4570	}
4571	netperf_response.content.serv_errno = errno;
4572	send_response();
4573	exit(1);
4574      }
4575    } while(!(msg_flags & MSG_EOR));
4576
4577    recv_ring = recv_ring->next;
4578
4579    if (timed_out) {
4580      /* we hit the end of the test based on time - lets */
4581      /* bail out of here now... */
4582      if (debug) {
4583	fprintf(where,"yo5\n");
4584	fflush(where);
4585      }
4586      break;
4587    }
4588
4589    /* Now, send the response to the remote */
4590    while ((bytes_sent=sctp_sendmsg(s_rcv,
4591			      send_ring->buffer_ptr,
4592			      sctp_rr_request->response_size,
4593			      (struct sockaddr *)&peeraddr, addrlen,
4594			      0, 0, 0, 0, 0)) == SOCKET_ERROR) {
4595      if (SOCKET_EINTR(bytes_sent)) {
4596	/* the test timer has popped */
4597	timed_out = 1;
4598	break;
4599      } else if (non_block && errno == EAGAIN) {
4600	 continue;
4601      }
4602
4603      netperf_response.content.serv_errno = 992;
4604      send_response();
4605      exit(1);
4606    }
4607
4608    if (timed_out) {
4609      if (debug) {
4610	fprintf(where,"yo6\n");
4611	fflush(where);
4612      }
4613      /* we hit the end of the test based on time - lets */
4614      /* bail out of here now... */
4615      break;
4616    }
4617
4618    send_ring = send_ring->next;
4619
4620    trans_received++;
4621    if (trans_remaining) {
4622      trans_remaining--;
4623    }
4624  }
4625
4626
4627  /* The loop now exits due to timeout or transaction count being */
4628  /* reached */
4629
4630  cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time);
4631
4632  stop_timer();
4633
4634  if (timed_out) {
4635    /* we ended the test by time, which was at least 2 seconds */
4636    /* longer than we wanted to run. so, we want to subtract */
4637    /* PAD_TIME from the elapsed_time. */
4638    elapsed_time -= PAD_TIME;
4639  }
4640
4641  /* send the results to the sender			*/
4642
4643  if (debug) {
4644    fprintf(where,
4645	    "recv_sctp_rr: got %d transactions\n",
4646	    trans_received);
4647    fflush(where);
4648  }
4649
4650  sctp_rr_results->bytes_received = (trans_received *
4651				    (sctp_rr_request->request_size +
4652				     sctp_rr_request->response_size));
4653  sctp_rr_results->trans_received = trans_received;
4654  sctp_rr_results->elapsed_time   = elapsed_time;
4655  sctp_rr_results->cpu_method     = cpu_method;
4656  sctp_rr_results->num_cpus       = lib_num_loc_cpus;
4657  if (sctp_rr_request->measure_cpu) {
4658    sctp_rr_results->cpu_util	= calc_cpu_util(elapsed_time);
4659  }
4660
4661  if (debug) {
4662    fprintf(where,
4663	    "recv_sctp_rr: test complete, sending results.\n");
4664    fflush(where);
4665  }
4666
4667  /* we are now done with the sockets */
4668  close(s_rcv);
4669
4670  send_response();
4671
4672}
4673
4674
4675void
4676print_sctp_usage()
4677{
4678
4679  printf("%s",sctp_usage);
4680  exit(1);
4681
4682}
4683void
4684scan_sctp_args(argc, argv)
4685     int	argc;
4686     char	*argv[];
4687
4688{
4689
4690#define SOCKETS_ARGS "BDhH:I:L:m:M:P:r:s:S:VN:T:46"
4691
4692  extern char	*optarg;	  /* pointer to option string	*/
4693
4694  int		c;
4695
4696  char
4697    arg1[BUFSIZ],  /* argument holders		*/
4698    arg2[BUFSIZ];
4699
4700  if (no_control) {
4701    fprintf(where,
4702	    "The SCTP tests do not know how to deal with no control tests\n");
4703    exit(-1);
4704  }
4705
4706  strncpy(local_data_port,"0",sizeof(local_data_port));
4707  strncpy(remote_data_port,"0",sizeof(remote_data_port));
4708
4709  /* Go through all the command line arguments and break them */
4710  /* out. For those options that take two parms, specifying only */
4711  /* the first will set both to that value. Specifying only the */
4712  /* second will leave the first untouched. To change only the */
4713  /* first, use the form "first," (see the routine break_args.. */
4714
4715  while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
4716    switch (c) {
4717    case '?':
4718    case '4':
4719      remote_data_family = AF_INET;
4720      local_data_family = AF_INET;
4721      break;
4722    case '6':
4723#if defined(AF_INET6)
4724      remote_data_family = AF_INET6;
4725      local_data_family = AF_INET6;
4726#else
4727      fprintf(stderr,
4728	      "This netperf was not compiled on an IPv6 capable host!\n");
4729      fflush(stderr);
4730      exit(-1);
4731#endif
4732      break;
4733    case 'h':
4734      print_sctp_usage();
4735      exit(1);
4736    case 'b':
4737#ifdef WANT_FIRST_BURST
4738      first_burst_size = atoi(optarg);
4739#else /* WANT_FIRST_BURST */
4740      printf("Initial request burst functionality not compiled-in!\n");
4741#endif /* WANT_FIRST_BURST */
4742      break;
4743    case 'D':
4744      /* set the nodelay flag */
4745      loc_nodelay = 1;
4746      rem_nodelay = 1;
4747      break;
4748    case 'H':
4749      break_args_explicit(optarg,arg1,arg2);
4750      if (arg1[0]) {
4751	/* make sure we leave room for the NULL termination boys and
4752	   girls. raj 2005-02-82 */
4753	remote_data_address = malloc(strlen(arg1)+1);
4754	strncpy(remote_data_address,arg1,strlen(arg1));
4755      }
4756      if (arg2[0])
4757	remote_data_family = parse_address_family(arg2);
4758      break;
4759    case 'L':
4760      break_args_explicit(optarg,arg1,arg2);
4761      if (arg1[0]) {
4762	/* make sure we leave room for the NULL termination boys and
4763	   girls. raj 2005-02-82 */
4764	local_data_address = malloc(strlen(arg1)+1);
4765	strncpy(local_data_address,arg1,strlen(arg1));
4766      }
4767      if (arg2[0])
4768	local_data_family = parse_address_family(arg2);
4769      break;
4770    case 'P':
4771      /* set the local and remote data port numbers for the tests to
4772	 allow them to run through those blankety blank end-to-end
4773	 breaking firewalls. raj 2004-06-15 */
4774      break_args(optarg,arg1,arg2);
4775      if (arg1[0])
4776	strncpy(local_data_port,arg1,sizeof(local_data_port));
4777      if (arg2[0])
4778	strncpy(remote_data_port,arg2,sizeof(remote_data_port));
4779      break;
4780    case 's':
4781      /* set local socket sizes */
4782      break_args(optarg,arg1,arg2);
4783      if (arg1[0])
4784	lss_size_req = convert(arg1);
4785      if (arg2[0])
4786	lsr_size_req = convert(arg2);
4787      break;
4788    case 'S':
4789      /* set remote socket sizes */
4790      break_args(optarg,arg1,arg2);
4791      if (arg1[0])
4792	rss_size_req = convert(arg1);
4793      if (arg2[0])
4794	rsr_size_req = convert(arg2);
4795      break;
4796    case 'r':
4797      /* set the request/response sizes */
4798      break_args(optarg,arg1,arg2);
4799      if (arg1[0])
4800	req_size = convert(arg1);
4801      if (arg2[0])
4802	rsp_size = convert(arg2);
4803      break;
4804    case 'm':
4805      /* set size of the buffer for each sent message */
4806      send_size = convert(optarg);
4807      break;
4808    case 'M':
4809      /* set the size of the buffer for each received message */
4810      recv_size = convert(optarg);
4811      break;
4812    case 't':
4813      /* set the test name */
4814      strcpy(test_name,optarg);
4815      break;
4816    case 'W':
4817	/* set the "width" of the user space data */
4818	/* buffer. This will be the number of */
4819	/* send_size buffers malloc'd in the */
4820	/* *_STREAM test. It may be enhanced to set */
4821	/* both send and receive "widths" but for now */
4822	/* it is just the sending *_STREAM. */
4823	send_width = convert(optarg);
4824	break;
4825    case 'V':
4826      /* we want to do copy avoidance and will set */
4827      /* it for everything, everywhere, if we really */
4828      /* can. of course, we don't know anything */
4829      /* about the remote... */
4830#ifdef SO_SND_COPYAVOID
4831      loc_sndavoid = 1;
4832#else
4833      loc_sndavoid = 0;
4834      printf("Local send copy avoidance not available.\n");
4835#endif
4836#ifdef SO_RCV_COPYAVOID
4837      loc_rcvavoid = 1;
4838#else
4839      loc_rcvavoid = 0;
4840      printf("Local recv copy avoidance not available.\n");
4841#endif
4842      rem_sndavoid = 1;
4843      rem_rcvavoid = 1;
4844      break;
4845    case 'N':
4846      /* this opton allows the user to set the number of
4847       * messages to send.  This in effect modifies the test
4848       * time.  If we know the message size, then the we can
4849       * express the test time as message_size * number_messages
4850       */
4851      msg_count = convert (optarg);
4852      if (msg_count > 0)
4853	  test_time = 0;
4854      break;
4855    case 'B':
4856      non_block = 1;
4857      break;
4858    case 'T':
4859      num_associations = atoi(optarg);
4860      if (num_associations <= 1) {
4861	  printf("Number of SCTP associations must be >= 1\n");
4862	  exit(1);
4863      }
4864      break;
4865    };
4866  }
4867}
4868
4869#endif  /* WANT_SCTP */
4870