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