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