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