blob: 696fd3e7e30a02adcd3ea1bfe8a25084b4462a85 [file] [log] [blame]
The Android Open Source Project02fb0ac2009-03-03 19:30:07 -08001#ifndef lint
2char nettest_sdp[]="\
3@(#)nettest_sdp.c (c) Copyright 2007 Hewlett-Packard Co. Version 2.4.4";
4#else
5#define DIRTY
6#define WANT_HISTOGRAM
7#define WANT_INTERVALS
8#endif /* lint */
9
10/****************************************************************/
11/* */
12/* nettest_sdp.c */
13/* */
14/* */
15/* scan_sdp_args() get the sdp command line args */
16/* */
17/* the actual test routines... */
18/* */
19/* send_sdp_stream() perform a sdp stream test */
20/* recv_sdp_stream() */
21/* send_sdp_rr() perform a sdp request/response */
22/* recv_sdp_rr() */
23/* */
24/* relies on create_data_socket in nettest_bsd.c */
25/****************************************************************/
26
27#if HAVE_CONFIG_H
28# include <config.h>
29#endif
30
31#if defined(WANT_SDP)
32
33#include <sys/types.h>
34#include <fcntl.h>
35#include <errno.h>
36#include <signal.h>
37#include <stdio.h>
38#include <string.h>
39#include <time.h>
40#ifdef NOSTDLIBH
41#include <malloc.h>
42#else /* NOSTDLIBH */
43#include <stdlib.h>
44#endif /* NOSTDLIBH */
45
46#if !defined(__VMS)
47#include <sys/ipc.h>
48#endif /* !defined(__VMS) */
49#include <unistd.h>
50#include <sys/types.h>
51#include <sys/socket.h>
52#include <netinet/in.h>
53#include <netinet/tcp.h>
54#include <arpa/inet.h>
55#include <netdb.h>
56
57/* would seem that not all sdp.h files define a MSG_EOF, but that
58 MSG_EOF can be the same as MSG_FIN so lets work with that
59 assumption. initial find by Jon Pedersen. raj 2006-02-01 */
60#ifndef MSG_EOF
61#ifdef MSG_FIN
62#define MSG_EOF MSG_FIN
63#else
64#error Must have either MSG_EOF or MSG_FIN defined
65#endif
66#endif
67
68#include "netlib.h"
69#include "netsh.h"
70/* get some of the functions from nettest_bsd.c */
71#include "nettest_bsd.h"
72#include "nettest_sdp.h"
73
74#ifdef WANT_HISTOGRAM
75#ifdef __sgi
76#include <sys/time.h>
77#endif /* __sgi */
78#include "hist.h"
79#endif /* WANT_HISTOGRAM */
80
81#ifdef WANT_FIRST_BURST
82extern int first_burst_size;
83#endif /* WANT_FIRST_BURST */
84
85
86
87/* these variables are specific to SDP tests. declare */
88/* them static to make them global only to this file. */
89
90static int
91 msg_count = 0, /* number of messages to transmit on association */
92 non_block = 0, /* default to blocking sockets */
93 num_associations = 1; /* number of associations on the endpoint */
94
95static int confidence_iteration;
96static char local_cpu_method;
97static char remote_cpu_method;
98
99#ifdef WANT_HISTOGRAM
100static struct timeval time_one;
101static struct timeval time_two;
102static HIST time_hist;
103#endif /* WANT_HISTOGRAM */
104
105
106char sdp_usage[] = "\n\
107Usage: netperf [global options] -- [test options] \n\
108\n\
109SDP Sockets Test Options:\n\
110 -b number Send number requests at the start of _RR tests\n\
111 -D [L][,R] Set SDP_NODELAY locally and/or remotely\n\
112 -h Display this text\n\
113 -H name,fam Use name (or IP) and family as target of data connection\n\
114 -L name,fam Use name (or IP) and family as source of data connextion\n\
115 -m bytes Set the size of each sent message\n\
116 -M bytes Set the size of each received messages\n\
117 -P local[,remote] Set the local/remote port for the data socket\n\
118 -r req,[rsp] Set request/response sizes (_RR tests)\n\
119 -s send[,recv] Set local socket send/recv buffer sizes\n\
120 -S send[,recv] Set remote socket send/recv buffer sizes\n\
121 -V Enable copy avoidance if supported\n\
122 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
123 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
124\n\
125For those options taking two parms, at least one must be specified;\n\
126specifying one value without a comma will set both parms to that\n\
127value, specifying a value with a leading comma will set just the second\n\
128parm, a value with a trailing comma will set just the first. To set\n\
129each parm to unique values, specify both and separate them with a\n\
130comma.\n";
131
132
133 /* This routine is intended to retrieve interesting aspects of sdp */
134 /* for the data connection. at first, it attempts to retrieve the */
135 /* maximum segment size. later, it might be modified to retrieve */
136 /* other information, but it must be information that can be */
137 /* retrieved quickly as it is called during the timing of the test. */
138 /* for that reason, a second routine may be created that can be */
139 /* called outside of the timing loop */
140static
141void
142get_sdp_info(int socket, int * mss)
143{
144
145#ifdef TCP_MAXSEG
146 netperf_socklen_t sock_opt_len;
147
148 sock_opt_len = sizeof(netperf_socklen_t);
149 if (getsockopt(socket,
150 getprotobyname("tcp")->p_proto,
151 TCP_MAXSEG,
152 (char *)mss,
153 &sock_opt_len) == SOCKET_ERROR) {
154 fprintf(where,
155 "netperf: get_sdp_info: getsockopt TCP_MAXSEG: errno %d\n",
156 errno);
157 fflush(where);
158 *mss = -1;
159 }
160#else
161 *mss = -1;
162#endif /* TCP_MAXSEG */
163
164}
165
166void
167send_sdp_stream(char remote_host[])
168{
169
170 char *tput_title = "\
171Recv Send Send \n\
172Socket Socket Message Elapsed \n\
173Size Size Size Time Throughput \n\
174bytes bytes bytes secs. %s/sec \n\n";
175
176 char *tput_fmt_0 =
177 "%7.2f %s\n";
178
179 char *tput_fmt_1 =
180 "%6d %6d %6d %-6.2f %7.2f %s\n";
181
182 char *cpu_title = "\
183Recv Send Send Utilization Service Demand\n\
184Socket Socket Message Elapsed Send Recv Send Recv\n\
185Size Size Size Time Throughput local remote local remote\n\
186bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
187
188 char *cpu_fmt_0 =
189 "%6.3f %c %s\n";
190
191 char *cpu_fmt_1 =
192 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
193
194 char *ksink_fmt = "\n\
195Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
196Local Remote Local Remote Xfered Per Per\n\
197Send Recv Send Recv Send (avg) Recv (avg)\n\
198%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
199
200 char *ksink_fmt2 = "\n\
201Maximum\n\
202Segment\n\
203Size (bytes)\n\
204%6d\n";
205
206
207 float elapsed_time;
208
209 /* what we want is to have a buffer space that is at least one */
210 /* send-size greater than our send window. this will insure that we */
211 /* are never trying to re-use a buffer that may still be in the hands */
212 /* of the transport. This buffer will be malloc'd after we have found */
213 /* the size of the local senc socket buffer. We will want to deal */
214 /* with alignment and offset concerns as well. */
215
216 struct ring_elt *send_ring;
217
218 int len;
219 unsigned int nummessages = 0;
220 SOCKET send_socket;
221 int bytes_remaining;
222 int sdp_mss = -1; /* possibly uninitialized on printf far below */
223
224 /* with links like fddi, one can send > 32 bits worth of bytes */
225 /* during a test... ;-) at some point, this should probably become a */
226 /* 64bit integral type, but those are not entirely common yet */
227
228 unsigned long long local_bytes_sent = 0;
229 double bytes_sent = 0.0;
230
231 float local_cpu_utilization;
232 float local_service_demand;
233 float remote_cpu_utilization;
234 float remote_service_demand;
235
236 double thruput;
237
238 struct addrinfo *remote_res;
239 struct addrinfo *local_res;
240
241 struct sdp_stream_request_struct *sdp_stream_request;
242 struct sdp_stream_response_struct *sdp_stream_response;
243 struct sdp_stream_results_struct *sdp_stream_result;
244
245 sdp_stream_request =
246 (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data;
247 sdp_stream_response =
248 (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data;
249 sdp_stream_result =
250 (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data;
251
252#ifdef WANT_HISTOGRAM
253 if (verbosity > 1) {
254 time_hist = HIST_new();
255 }
256#endif /* WANT_HISTOGRAM */
257 /* since we are now disconnected from the code that established the */
258 /* control socket, and since we want to be able to use different */
259 /* protocols and such, we are passed the name of the remote host and */
260 /* must turn that into the test specific addressing information. */
261
262 /* complete_addrinfos will either succede or exit the process */
263 complete_addrinfos(&remote_res,
264 &local_res,
265 remote_host,
266 SOCK_STREAM,
267 IPPROTO_TCP,
268 0);
269
270 if ( print_headers ) {
271 print_top_test_header("SDP STREAM TEST",local_res,remote_res);
272 }
273
274 send_ring = NULL;
275 confidence_iteration = 1;
276 init_stat();
277
278 /* we have a great-big while loop which controls the number of times */
279 /* we run a particular test. this is for the calculation of a */
280 /* confidence interval (I really should have stayed awake during */
281 /* probstats :). If the user did not request confidence measurement */
282 /* (no confidence is the default) then we will only go though the */
283 /* loop once. the confidence stuff originates from the folks at IBM */
284
285 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
286 (confidence_iteration <= iteration_min)) {
287
288 /* initialize a few counters. we have to remember that we might be */
289 /* going through the loop more than once. */
290
291 nummessages = 0;
292 bytes_sent = 0.0;
293 times_up = 0;
294
295 /*set up the data socket */
296 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
297 local_res->ai_family = AF_INET_SDP;
298 local_res->ai_protocol = 0;
299 send_socket = create_data_socket(local_res);
300
301 if (send_socket == INVALID_SOCKET){
302 perror("netperf: send_sdp_stream: sdp stream data socket");
303 exit(1);
304 }
305
306 if (debug) {
307 fprintf(where,"send_sdp_stream: send_socket obtained...\n");
308 }
309
310 /* at this point, we have either retrieved the socket buffer sizes, */
311 /* or have tried to set them, so now, we may want to set the send */
312 /* size based on that (because the user either did not use a -m */
313 /* option, or used one with an argument of 0). If the socket buffer */
314 /* size is not available, we will set the send size to 4KB - no */
315 /* particular reason, just arbitrary... */
316 if (send_size == 0) {
317 if (lss_size > 0) {
318 send_size = lss_size;
319 }
320 else {
321 send_size = 4096;
322 }
323 }
324
325 /* set-up the data buffer ring with the requested alignment and offset. */
326 /* note also that we have allocated a quantity */
327 /* of memory that is at least one send-size greater than our socket */
328 /* buffer size. We want to be sure that there are at least two */
329 /* buffers allocated - this can be a bit of a problem when the */
330 /* send_size is bigger than the socket size, so we must check... the */
331 /* user may have wanted to explicitly set the "width" of our send */
332 /* buffers, we should respect that wish... */
333 if (send_width == 0) {
334 send_width = (lss_size/send_size) + 1;
335 if (send_width == 1) send_width++;
336 }
337
338 if (send_ring == NULL) {
339 /* only allocate the send ring once. this is a networking test, */
340 /* not a memory allocation test. this way, we do not need a */
341 /* deallocate_buffer_ring() routine, and I don't feel like */
342 /* writing one anyway :) raj 11/94 */
343 send_ring = allocate_buffer_ring(send_width,
344 send_size,
345 local_send_align,
346 local_send_offset);
347 }
348
349 /* If the user has requested cpu utilization measurements, we must */
350 /* calibrate the cpu(s). We will perform this task within the tests */
351 /* themselves. If the user has specified the cpu rate, then */
352 /* calibrate_local_cpu will return rather quickly as it will have */
353 /* nothing to do. If local_cpu_rate is zero, then we will go through */
354 /* all the "normal" calibration stuff and return the rate back. */
355
356 if (local_cpu_usage) {
357 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
358 }
359
360 if (!no_control) {
361 /* Tell the remote end to do a listen. The server alters the
362 socket paramters on the other side at this point, hence the
363 reason for all the values being passed in the setup
364 message. If the user did not specify any of the parameters,
365 they will be passed as 0, which will indicate to the remote
366 that no changes beyond the system's default should be
367 used. Alignment is the exception, it will default to 1, which
368 will be no alignment alterations. */
369
370 netperf_request.content.request_type = DO_SDP_STREAM;
371 sdp_stream_request->send_buf_size = rss_size_req;
372 sdp_stream_request->recv_buf_size = rsr_size_req;
373 sdp_stream_request->receive_size = recv_size;
374 sdp_stream_request->no_delay = rem_nodelay;
375 sdp_stream_request->recv_alignment = remote_recv_align;
376 sdp_stream_request->recv_offset = remote_recv_offset;
377 sdp_stream_request->measure_cpu = remote_cpu_usage;
378 sdp_stream_request->cpu_rate = remote_cpu_rate;
379 if (test_time) {
380 sdp_stream_request->test_length = test_time;
381 }
382 else {
383 sdp_stream_request->test_length = test_bytes;
384 }
385 sdp_stream_request->so_rcvavoid = rem_rcvavoid;
386 sdp_stream_request->so_sndavoid = rem_sndavoid;
387#ifdef DIRTY
388 sdp_stream_request->dirty_count = rem_dirty_count;
389 sdp_stream_request->clean_count = rem_clean_count;
390#endif /* DIRTY */
391 sdp_stream_request->port = atoi(remote_data_port);
392 sdp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
393 if (debug > 1) {
394 fprintf(where,
395 "netperf: send_sdp_stream: requesting SDP stream test\n");
396 }
397
398 send_request();
399
400 /* The response from the remote will contain all of the relevant
401 socket parameters for this test type. We will put them back
402 into the variables here so they can be displayed if desired.
403 The remote will have calibrated CPU if necessary, and will
404 have done all the needed set-up we will have calibrated the
405 cpu locally before sending the request, and will grab the
406 counter value right after the connect returns. The remote
407 will grab the counter right after the accept call. This saves
408 the hassle of extra messages being sent for the SDP
409 tests. */
410
411 recv_response();
412
413 if (!netperf_response.content.serv_errno) {
414 if (debug)
415 fprintf(where,"remote listen done.\n");
416 rsr_size = sdp_stream_response->recv_buf_size;
417 rss_size = sdp_stream_response->send_buf_size;
418 rem_nodelay = sdp_stream_response->no_delay;
419 remote_cpu_usage= sdp_stream_response->measure_cpu;
420 remote_cpu_rate = sdp_stream_response->cpu_rate;
421
422 /* we have to make sure that the server port number is in
423 network order */
424 set_port_number(remote_res,
425 (short)sdp_stream_response->data_port_number);
426
427 rem_rcvavoid = sdp_stream_response->so_rcvavoid;
428 rem_sndavoid = sdp_stream_response->so_sndavoid;
429 }
430 else {
431 Set_errno(netperf_response.content.serv_errno);
432 fprintf(where,
433 "netperf: remote error %d",
434 netperf_response.content.serv_errno);
435 perror("");
436 fflush(where);
437
438 exit(1);
439 }
440 }
441
442#ifdef WANT_DEMO
443 DEMO_STREAM_SETUP(lss_size,rsr_size)
444#endif
445
446 /*Connect up to the remote port on the data socket */
447 if (connect(send_socket,
448 remote_res->ai_addr,
449 remote_res->ai_addrlen) == INVALID_SOCKET){
450 perror("netperf: send_sdp_stream: data socket connect failed");
451 exit(1);
452 }
453
454 /* Data Socket set-up is finished. If there were problems, either */
455 /* the connect would have failed, or the previous response would */
456 /* have indicated a problem. I failed to see the value of the */
457 /* extra message after the accept on the remote. If it failed, */
458 /* we'll see it here. If it didn't, we might as well start pumping */
459 /* data. */
460
461 /* Set-up the test end conditions. For a stream test, they can be */
462 /* either time or byte-count based. */
463
464 if (test_time) {
465 /* The user wanted to end the test after a period of time. */
466 times_up = 0;
467 bytes_remaining = 0;
468 /* in previous revisions, we had the same code repeated throught */
469 /* all the test suites. this was unnecessary, and meant more */
470 /* work for me when I wanted to switch to POSIX signals, so I */
471 /* have abstracted this out into a routine in netlib.c. if you */
472 /* are experiencing signal problems, you might want to look */
473 /* there. raj 11/94 */
474 start_timer(test_time);
475 }
476 else {
477 /* The tester wanted to send a number of bytes. */
478 bytes_remaining = test_bytes;
479 times_up = 1;
480 }
481
482 /* The cpu_start routine will grab the current time and possibly */
483 /* value of the idle counter for later use in measuring cpu */
484 /* utilization and/or service demand and thruput. */
485
486 cpu_start(local_cpu_usage);
487
488 /* we only start the interval timer if we are using the
489 timer-timed intervals rather than the sit and spin ones. raj
490 2006-02-06 */
491#if defined(WANT_INTERVALS)
492 INTERVALS_INIT();
493#endif /* WANT_INTERVALS */
494
495 /* before we start, initialize a few variables */
496
497#ifdef WANT_DEMO
498 if (demo_mode) {
499 HIST_timestamp(demo_one_ptr);
500 }
501#endif
502
503
504 /* We use an "OR" to control test execution. When the test is */
505 /* controlled by time, the byte count check will always return false. */
506 /* When the test is controlled by byte count, the time test will */
507 /* always return false. When the test is finished, the whole */
508 /* expression will go false and we will stop sending data. */
509
510 while ((!times_up) || (bytes_remaining > 0)) {
511
512#ifdef DIRTY
513 access_buffer(send_ring->buffer_ptr,
514 send_size,
515 loc_dirty_count,
516 loc_clean_count);
517#endif /* DIRTY */
518
519#ifdef WANT_HISTOGRAM
520 if (verbosity > 1) {
521 /* timestamp just before we go into send and then again just
522 after we come out raj 8/94 */
523 /* but lets only do this if there is going to be a histogram
524 displayed */
525 HIST_timestamp(&time_one);
526 }
527#endif /* WANT_HISTOGRAM */
528
529 if((len=send(send_socket,
530 send_ring->buffer_ptr,
531 send_size,
532 0)) != send_size) {
533 if ((len >=0) || SOCKET_EINTR(len)) {
534 /* the test was interrupted, must be the end of test */
535 break;
536 }
537 perror("netperf: data send error");
538 printf("len was %d\n",len);
539 exit(1);
540 }
541
542 local_bytes_sent += send_size;
543
544#ifdef WANT_HISTOGRAM
545 if (verbosity > 1) {
546 /* timestamp the exit from the send call and update the histogram */
547 HIST_timestamp(&time_two);
548 HIST_add(time_hist,delta_micro(&time_one,&time_two));
549 }
550#endif /* WANT_HISTOGRAM */
551
552#ifdef WANT_DEMO
553 DEMO_STREAM_INTERVAL(send_size)
554#endif
555
556#if defined(WANT_INTERVALS)
557 INTERVALS_WAIT();
558#endif /* WANT_INTERVALS */
559
560 /* now we want to move our pointer to the next position in the */
561 /* data buffer...we may also want to wrap back to the "beginning" */
562 /* of the bufferspace, so we will mod the number of messages sent */
563 /* by the send width, and use that to calculate the offset to add */
564 /* to the base pointer. */
565 nummessages++;
566 send_ring = send_ring->next;
567 if (bytes_remaining) {
568 bytes_remaining -= send_size;
569 }
570 }
571
572 /* The test is over. Flush the buffers to the remote end. We do a */
573 /* graceful release to insure that all data has been taken by the */
574 /* remote. */
575
576 /* but first, if the verbosity is greater than 1, find-out what */
577 /* the SDP maximum segment_size was (if possible) */
578 if (verbosity > 1) {
579 sdp_mss = -1;
580 get_sdp_info(send_socket,&sdp_mss);
581 }
582
583 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
584 perror("netperf: cannot shutdown sdp stream socket");
585 exit(1);
586 }
587
588 /* hang a recv() off the socket to block until the remote has */
589 /* brought all the data up into the application. it will do a */
590 /* shutdown to cause a FIN to be sent our way. We will assume that */
591 /* any exit from the recv() call is good... raj 4/93 */
592
593 recv(send_socket, send_ring->buffer_ptr, send_size, 0);
594
595 /* this call will always give us the elapsed time for the test, and */
596 /* will also store-away the necessaries for cpu utilization */
597
598 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
599 /* measured and how */
600 /* long did we really */
601 /* run? */
602
603 /* we are finished with the socket, so close it to prevent hitting */
604 /* the limit on maximum open files. */
605
606 close(send_socket);
607
608 if (!no_control) {
609 /* Get the statistics from the remote end. The remote will have
610 calculated service demand and all those interesting
611 things. If it wasn't supposed to care, it will return obvious
612 values. */
613
614 recv_response();
615 if (!netperf_response.content.serv_errno) {
616 if (debug)
617 fprintf(where,"remote results obtained\n");
618 }
619 else {
620 Set_errno(netperf_response.content.serv_errno);
621 fprintf(where,
622 "netperf: remote error %d",
623 netperf_response.content.serv_errno);
624 perror("");
625 fflush(where);
626
627 exit(1);
628 }
629
630 /* We now calculate what our thruput was for the test. In the
631 future, we may want to include a calculation of the thruput
632 measured by the remote, but it should be the case that for a
633 SDP stream test, that the two numbers should be *very*
634 close... We calculate bytes_sent regardless of the way the
635 test length was controlled. If it was time, we needed to,
636 and if it was by bytes, the user may have specified a number
637 of bytes that wasn't a multiple of the send_size, so we
638 really didn't send what he asked for ;-) */
639
640 bytes_sent = ntohd(sdp_stream_result->bytes_received);
641 }
642 else {
643 bytes_sent = (double)local_bytes_sent;
644 }
645
646 thruput = calc_thruput(bytes_sent);
647
648 if (local_cpu_usage || remote_cpu_usage) {
649 /* We must now do a little math for service demand and cpu */
650 /* utilization for the system(s) */
651 /* Of course, some of the information might be bogus because */
652 /* there was no idle counter in the kernel(s). We need to make */
653 /* a note of this for the user's benefit...*/
654 if (local_cpu_usage) {
655
656 local_cpu_utilization = calc_cpu_util(0.0);
657 local_service_demand = calc_service_demand(bytes_sent,
658 0.0,
659 0.0,
660 0);
661 }
662 else {
663 local_cpu_utilization = (float) -1.0;
664 local_service_demand = (float) -1.0;
665 }
666
667 if (remote_cpu_usage) {
668
669 remote_cpu_utilization = sdp_stream_result->cpu_util;
670 remote_service_demand = calc_service_demand(bytes_sent,
671 0.0,
672 remote_cpu_utilization,
673 sdp_stream_result->num_cpus);
674 }
675 else {
676 remote_cpu_utilization = (float) -1.0;
677 remote_service_demand = (float) -1.0;
678 }
679 }
680 else {
681 /* we were not measuring cpu, for the confidence stuff, we */
682 /* should make it -1.0 */
683 local_cpu_utilization = (float) -1.0;
684 local_service_demand = (float) -1.0;
685 remote_cpu_utilization = (float) -1.0;
686 remote_service_demand = (float) -1.0;
687 }
688
689 /* at this point, we want to calculate the confidence information. */
690 /* if debugging is on, calculate_confidence will print-out the */
691 /* parameters we pass it */
692
693 calculate_confidence(confidence_iteration,
694 elapsed_time,
695 thruput,
696 local_cpu_utilization,
697 remote_cpu_utilization,
698 local_service_demand,
699 remote_service_demand);
700
701
702 confidence_iteration++;
703 }
704
705 /* at this point, we have finished making all the runs that we */
706 /* will be making. so, we should extract what the calcuated values */
707 /* are for all the confidence stuff. we could make the values */
708 /* global, but that seemed a little messy, and it did not seem worth */
709 /* all the mucking with header files. so, we create a routine much */
710 /* like calcualte_confidence, which just returns the mean values. */
711 /* raj 11/94 */
712
713 retrieve_confident_values(&elapsed_time,
714 &thruput,
715 &local_cpu_utilization,
716 &remote_cpu_utilization,
717 &local_service_demand,
718 &remote_service_demand);
719
720 /* We are now ready to print all the information. If the user */
721 /* has specified zero-level verbosity, we will just print the */
722 /* local service demand, or the remote service demand. If the */
723 /* user has requested verbosity level 1, he will get the basic */
724 /* "streamperf" numbers. If the user has specified a verbosity */
725 /* of greater than 1, we will display a veritable plethora of */
726 /* background information from outside of this block as it it */
727 /* not cpu_measurement specific... */
728
729 if (confidence < 0) {
730 /* we did not hit confidence, but were we asked to look for it? */
731 if (iteration_max > 1) {
732 display_confidence();
733 }
734 }
735
736 if (local_cpu_usage || remote_cpu_usage) {
737 local_cpu_method = format_cpu_method(cpu_method);
738 remote_cpu_method = format_cpu_method(sdp_stream_result->cpu_method);
739
740 switch (verbosity) {
741 case 0:
742 if (local_cpu_usage) {
743 fprintf(where,
744 cpu_fmt_0,
745 local_service_demand,
746 local_cpu_method,
747 ((print_headers) ||
748 (result_brand == NULL)) ? "" : result_brand);
749 }
750 else {
751 fprintf(where,
752 cpu_fmt_0,
753 remote_service_demand,
754 remote_cpu_method,
755 ((print_headers) ||
756 (result_brand == NULL)) ? "" : result_brand);
757 }
758 break;
759 case 1:
760 case 2:
761 if (print_headers) {
762 fprintf(where,
763 cpu_title,
764 format_units(),
765 local_cpu_method,
766 remote_cpu_method);
767 }
768
769 fprintf(where,
770 cpu_fmt_1, /* the format string */
771 rsr_size, /* remote recvbuf size */
772 lss_size, /* local sendbuf size */
773 send_size, /* how large were the sends */
774 elapsed_time, /* how long was the test */
775 thruput, /* what was the xfer rate */
776 local_cpu_utilization, /* local cpu */
777 remote_cpu_utilization, /* remote cpu */
778 local_service_demand, /* local service demand */
779 remote_service_demand, /* remote service demand */
780 ((print_headers) ||
781 (result_brand == NULL)) ? "" : result_brand);
782 break;
783 }
784 }
785 else {
786 /* The tester did not wish to measure service demand. */
787
788 switch (verbosity) {
789 case 0:
790 fprintf(where,
791 tput_fmt_0,
792 thruput,
793 ((print_headers) ||
794 (result_brand == NULL)) ? "" : result_brand);
795 break;
796 case 1:
797 case 2:
798 if (print_headers) {
799 fprintf(where,tput_title,format_units());
800 }
801 fprintf(where,
802 tput_fmt_1, /* the format string */
803 rsr_size, /* remote recvbuf size */
804 lss_size, /* local sendbuf size */
805 send_size, /* how large were the sends */
806 elapsed_time, /* how long did it take */
807 thruput, /* how fast did it go */
808 ((print_headers) ||
809 (result_brand == NULL)) ? "" : result_brand);
810 break;
811 }
812 }
813
814 /* it would be a good thing to include information about some of the */
815 /* other parameters that may have been set for this test, but at the */
816 /* moment, I do not wish to figure-out all the formatting, so I will */
817 /* just put this comment here to help remind me that it is something */
818 /* that should be done at a later time. */
819
820 if (verbosity > 1) {
821 /* The user wanted to know it all, so we will give it to him. */
822 /* This information will include as much as we can find about */
823 /* SDP statistics, the alignments of the sends and receives */
824 /* and all that sort of rot... */
825
826 /* this stuff needs to be worked-out in the presence of confidence */
827 /* intervals and multiple iterations of the test... raj 11/94 */
828
829 fprintf(where,
830 ksink_fmt,
831 "Bytes",
832 "Bytes",
833 "Bytes",
834 local_send_align,
835 remote_recv_align,
836 local_send_offset,
837 remote_recv_offset,
838 bytes_sent,
839 bytes_sent / (double)nummessages,
840 nummessages,
841 bytes_sent / (double)sdp_stream_result->recv_calls,
842 sdp_stream_result->recv_calls);
843 fprintf(where,
844 ksink_fmt2,
845 sdp_mss);
846 fflush(where);
847#ifdef WANT_HISTOGRAM
848 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
849 fflush(where);
850 HIST_report(time_hist);
851#endif /* WANT_HISTOGRAM */
852 }
853
854}
855
856
857
858/* This routine implements the netperf-side SDP unidirectional data
859 transfer test (a.k.a. stream) for the sockets interface where the
860 data flow is from the netserver to the netperf. It receives its
861 parameters via global variables from the shell and writes its
862 output to the standard output. */
863
864
865void
866send_sdp_maerts(char remote_host[])
867{
868
869 char *tput_title = "\
870Recv Send Send \n\
871Socket Socket Message Elapsed \n\
872Size Size Size Time Throughput \n\
873bytes bytes bytes secs. %s/sec \n\n";
874
875 char *tput_fmt_0 =
876 "%7.2f %s\n";
877
878 char *tput_fmt_1 =
879 "%6d %6d %6d %-6.2f %7.2f \n %s";
880
881 char *cpu_title = "\
882Recv Send Send Utilization Service Demand\n\
883Socket Socket Message Elapsed Send Recv Send Recv\n\
884Size Size Size Time Throughput local remote local remote\n\
885bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
886
887 char *cpu_fmt_0 =
888 "%6.3f %c %s\n";
889
890 char *cpu_fmt_1 =
891 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
892
893 char *ksink_fmt = "\n\
894Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\
895Local Remote Local Remote Xfered Per Per\n\
896Recv Send Recv Send Recv (avg) Send (avg)\n\
897%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
898
899 char *ksink_fmt2 = "\n\
900Maximum\n\
901Segment\n\
902Size (bytes)\n\
903%6d\n";
904
905
906 float elapsed_time;
907
908 /* what we want is to have a buffer space that is at least one */
909 /* recv-size greater than our recv window. this will insure that we */
910 /* are never trying to re-use a buffer that may still be in the hands */
911 /* of the transport. This buffer will be malloc'd after we have found */
912 /* the size of the local senc socket buffer. We will want to deal */
913 /* with alignment and offset concerns as well. */
914
915 struct ring_elt *recv_ring;
916
917 int len;
918 unsigned int nummessages = 0;
919 SOCKET recv_socket;
920 int bytes_remaining;
921 int sdp_mss = -1; /* possibly uninitialized on printf far below */
922
923 /* with links like fddi, one can recv > 32 bits worth of bytes */
924 /* during a test... ;-) at some point, this should probably become a */
925 /* 64bit integral type, but those are not entirely common yet */
926 double bytes_sent = 0.0;
927 unsigned long long local_bytes_recvd = 0;
928
929 float local_cpu_utilization;
930 float local_service_demand;
931 float remote_cpu_utilization;
932 float remote_service_demand;
933
934 double thruput;
935
936 struct addrinfo *remote_res;
937 struct addrinfo *local_res;
938
939 struct sdp_maerts_request_struct *sdp_maerts_request;
940 struct sdp_maerts_response_struct *sdp_maerts_response;
941 struct sdp_maerts_results_struct *sdp_maerts_result;
942
943 sdp_maerts_request =
944 (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data;
945 sdp_maerts_response =
946 (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data;
947 sdp_maerts_result =
948 (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data;
949
950#ifdef WANT_HISTOGRAM
951 if (verbosity > 1) {
952 time_hist = HIST_new();
953 }
954#endif /* WANT_HISTOGRAM */
955 /* since we are now disconnected from the code that established the */
956 /* control socket, and since we want to be able to use different */
957 /* protocols and such, we are passed the name of the remote host and */
958 /* must turn that into the test specific addressing information. */
959
960 complete_addrinfos(&remote_res,
961 &local_res,
962 remote_host,
963 SOCK_STREAM,
964 IPPROTO_TCP,
965 0);
966
967 if ( print_headers ) {
968 print_top_test_header("SDP MAERTS TEST",local_res,remote_res);
969 }
970
971 recv_ring = NULL;
972 confidence_iteration = 1;
973 init_stat();
974
975 /* we have a great-big while loop which controls the number of times */
976 /* we run a particular test. this is for the calculation of a */
977 /* confidence interval (I really should have stayed awake during */
978 /* probstats :). If the user did not request confidence measurement */
979 /* (no confidence is the default) then we will only go though the */
980 /* loop once. the confidence stuff originates from the folks at IBM */
981
982 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
983 (confidence_iteration <= iteration_min)) {
984
985 /* initialize a few counters. we have to remember that we might be */
986 /* going through the loop more than once. */
987
988 nummessages = 0;
989 bytes_sent = 0.0;
990 times_up = 0;
991
992 /*set up the data socket */
993 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
994 local_res->ai_family = AF_INET_SDP;
995 local_res->ai_protocol = 0;
996 recv_socket = create_data_socket(local_res);
997
998 if (recv_socket == INVALID_SOCKET){
999 perror("netperf: send_sdp_maerts: sdp stream data socket");
1000 exit(1);
1001 }
1002
1003 if (debug) {
1004 fprintf(where,"send_sdp_maerts: recv_socket obtained...\n");
1005 }
1006
1007 /* at this point, we have either retrieved the socket buffer sizes, */
1008 /* or have tried to set them, so now, we may want to set the recv */
1009 /* size based on that (because the user either did not use a -m */
1010 /* option, or used one with an argument of 0). If the socket buffer */
1011 /* size is not available, we will set the recv size to 4KB - no */
1012 /* particular reason, just arbitrary... */
1013 if (recv_size == 0) {
1014 if (lsr_size > 0) {
1015 recv_size = lsr_size;
1016 }
1017 else {
1018 recv_size = 4096;
1019 }
1020 }
1021
1022 /* set-up the data buffer ring with the requested alignment and offset. */
1023 /* note also that we have allocated a quantity */
1024 /* of memory that is at least one recv-size greater than our socket */
1025 /* buffer size. We want to be sure that there are at least two */
1026 /* buffers allocated - this can be a bit of a problem when the */
1027 /* recv_size is bigger than the socket size, so we must check... the */
1028 /* user may have wanted to explicitly set the "width" of our recv */
1029 /* buffers, we should respect that wish... */
1030 if (recv_width == 0) {
1031 recv_width = (lsr_size/recv_size) + 1;
1032 if (recv_width == 1) recv_width++;
1033 }
1034
1035 if (recv_ring == NULL) {
1036 /* only allocate the recv ring once. this is a networking test, */
1037 /* not a memory allocation test. this way, we do not need a */
1038 /* deallocate_buffer_ring() routine, and I don't feel like */
1039 /* writing one anyway :) raj 11/94 */
1040 recv_ring = allocate_buffer_ring(recv_width,
1041 recv_size,
1042 local_recv_align,
1043 local_recv_offset);
1044 }
1045
1046 /* If the user has requested cpu utilization measurements, we must */
1047 /* calibrate the cpu(s). We will perform this task within the tests */
1048 /* themselves. If the user has specified the cpu rate, then */
1049 /* calibrate_local_cpu will return rather quickly as it will have */
1050 /* nothing to do. If local_cpu_rate is zero, then we will go through */
1051 /* all the "normal" calibration stuff and return the rate back. */
1052
1053 if (local_cpu_usage) {
1054 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1055 }
1056
1057 if (!no_control) {
1058 /* Tell the remote end to do a listen. The server alters the
1059 socket paramters on the other side at this point, hence the
1060 reason for all the values being passed in the setup
1061 message. If the user did not specify any of the parameters,
1062 they will be passed as 0, which will indicate to the remote
1063 that no changes beyond the system's default should be
1064 used. Alignment is the exception, it will default to 1, which
1065 will be no alignment alterations. */
1066
1067 netperf_request.content.request_type = DO_SDP_MAERTS;
1068 sdp_maerts_request->send_buf_size = rss_size_req;
1069 sdp_maerts_request->recv_buf_size = rsr_size_req;
1070 sdp_maerts_request->send_size = send_size;
1071 sdp_maerts_request->no_delay = rem_nodelay;
1072 sdp_maerts_request->send_alignment = remote_send_align;
1073 sdp_maerts_request->send_offset = remote_send_offset;
1074 sdp_maerts_request->measure_cpu = remote_cpu_usage;
1075 sdp_maerts_request->cpu_rate = remote_cpu_rate;
1076 if (test_time) {
1077 sdp_maerts_request->test_length = test_time;
1078 }
1079 else {
1080 sdp_maerts_request->test_length = test_bytes;
1081 }
1082 sdp_maerts_request->so_rcvavoid = rem_rcvavoid;
1083 sdp_maerts_request->so_sndavoid = rem_sndavoid;
1084#ifdef DIRTY
1085 sdp_maerts_request->dirty_count = rem_dirty_count;
1086 sdp_maerts_request->clean_count = rem_clean_count;
1087#endif /* DIRTY */
1088 sdp_maerts_request->port = atoi(remote_data_port);
1089 sdp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family);
1090 if (debug > 1) {
1091 fprintf(where,
1092 "netperf: send_sdp_maerts: requesting SDP maerts test\n");
1093 }
1094
1095 send_request();
1096
1097 /* The response from the remote will contain all of the relevant
1098 socket parameters for this test type. We will put them back
1099 into the variables here so they can be displayed if desired.
1100 The remote will have calibrated CPU if necessary, and will
1101 have done all the needed set-up we will have calibrated the
1102 cpu locally before sending the request, and will grab the
1103 counter value right after the connect returns. The remote
1104 will grab the counter right after the accept call. This saves
1105 the hassle of extra messages being sent for the SDP
1106 tests. */
1107
1108 recv_response();
1109
1110 if (!netperf_response.content.serv_errno) {
1111 if (debug)
1112 fprintf(where,"remote listen done.\n");
1113 rsr_size = sdp_maerts_response->recv_buf_size;
1114 rss_size = sdp_maerts_response->send_buf_size;
1115 rem_nodelay = sdp_maerts_response->no_delay;
1116 remote_cpu_usage= sdp_maerts_response->measure_cpu;
1117 remote_cpu_rate = sdp_maerts_response->cpu_rate;
1118 send_size = sdp_maerts_response->send_size;
1119
1120 /* we have to make sure that the server port number is in
1121 network order */
1122 set_port_number(remote_res,
1123 (short)sdp_maerts_response->data_port_number);
1124 rem_rcvavoid = sdp_maerts_response->so_rcvavoid;
1125 rem_sndavoid = sdp_maerts_response->so_sndavoid;
1126 }
1127 else {
1128 Set_errno(netperf_response.content.serv_errno);
1129 fprintf(where,
1130 "netperf: remote error %d",
1131 netperf_response.content.serv_errno);
1132 perror("");
1133 fflush(where);
1134
1135 exit(1);
1136 }
1137 }
1138
1139#ifdef WANT_DEMO
1140 DEMO_STREAM_SETUP(lsr_size,rss_size)
1141#endif
1142
1143 /*Connect up to the remote port on the data socket */
1144 if (connect(recv_socket,
1145 remote_res->ai_addr,
1146 remote_res->ai_addrlen) == INVALID_SOCKET){
1147 perror("netperf: send_sdp_maerts: data socket connect failed");
1148 exit(1);
1149 }
1150
1151 /* Data Socket set-up is finished. If there were problems, either */
1152 /* the connect would have failed, or the previous response would */
1153 /* have indicated a problem. I failed to see the value of the */
1154 /* extra message after the accept on the remote. If it failed, */
1155 /* we'll see it here. If it didn't, we might as well start pumping */
1156 /* data. */
1157
1158 /* Set-up the test end conditions. For a maerts test, they can be */
1159 /* either time or byte-count based. */
1160
1161 if (test_time) {
1162 /* The user wanted to end the test after a period of time. */
1163 times_up = 0;
1164 bytes_remaining = 0;
1165 /* in previous revisions, we had the same code repeated throught */
1166 /* all the test suites. this was unnecessary, and meant more */
1167 /* work for me when I wanted to switch to POSIX signals, so I */
1168 /* have abstracted this out into a routine in netlib.c. if you */
1169 /* are experiencing signal problems, you might want to look */
1170 /* there. raj 11/94 */
1171 if (!no_control) {
1172 /* this is a netperf to netserver test, netserver will close
1173 to tell us the test is over, so use PAD_TIME to avoid
1174 causing the netserver fits. */
1175 start_timer(test_time + PAD_TIME);
1176 }
1177 else {
1178 /* this is a netperf to data source test, no PAD_TIME */
1179 start_timer(test_time);
1180 }
1181 }
1182 else {
1183 /* The tester wanted to recv a number of bytes. we don't do that
1184 in a SDP_MAERTS test. sorry. raj 2002-06-21 */
1185 printf("netperf: send_sdp_maerts: test must be timed\n");
1186 exit(1);
1187 }
1188
1189 /* The cpu_start routine will grab the current time and possibly */
1190 /* value of the idle counter for later use in measuring cpu */
1191 /* utilization and/or service demand and thruput. */
1192
1193 cpu_start(local_cpu_usage);
1194
1195#ifdef WANT_INTERVALS
1196 INTERVALS_INIT();
1197#endif /* WANT_INTERVALS */
1198
1199 /* before we start, initialize a few variables */
1200
1201#ifdef WANT_DEMO
1202 if (demo_mode) {
1203 HIST_timestamp(demo_one_ptr);
1204 }
1205#endif
1206
1207 /* the test will continue until we either get a zero-byte recv()
1208 on the socket or our failsafe timer expires. most of the time
1209 we trust that we get a zero-byte recieve from the socket. raj
1210 2002-06-21 */
1211
1212#ifdef WANT_HISTOGRAM
1213 if (verbosity > 1) {
1214 /* timestamp just before we go into recv and then again just
1215 after we come out raj 8/94 */
1216 /* but only if we are actually going to display a histogram. raj
1217 2006-02-07 */
1218 HIST_timestamp(&time_one);
1219 }
1220#endif /* WANT_HISTOGRAM */
1221
1222 while ((!times_up) && (len=recv(recv_socket,
1223 recv_ring->buffer_ptr,
1224 recv_size,
1225 0)) > 0 ) {
1226
1227#ifdef WANT_HISTOGRAM
1228 if (verbosity > 1) {
1229 /* timestamp the exit from the recv call and update the histogram */
1230 HIST_timestamp(&time_two);
1231 HIST_add(time_hist,delta_micro(&time_one,&time_two));
1232 }
1233#endif /* WANT_HISTOGRAM */
1234
1235#ifdef DIRTY
1236 access_buffer(recv_ring->buffer_ptr,
1237 recv_size,
1238 loc_dirty_count,
1239 loc_clean_count);
1240#endif /* DIRTY */
1241
1242#ifdef WANT_DEMO
1243 DEMO_STREAM_INTERVAL(len);
1244#endif
1245
1246#ifdef WANT_INTERVALS
1247 INTERVALS_WAIT();
1248#endif /* WANT_INTERVALS */
1249
1250 /* now we want to move our pointer to the next position in the */
1251 /* data buffer...we may also want to wrap back to the "beginning" */
1252 /* of the bufferspace, so we will mod the number of messages sent */
1253 /* by the recv width, and use that to calculate the offset to add */
1254 /* to the base pointer. */
1255 nummessages++;
1256 recv_ring = recv_ring->next;
1257 if (bytes_remaining) {
1258 bytes_remaining -= len;
1259 }
1260
1261 local_bytes_recvd += len;
1262
1263#ifdef WANT_HISTOGRAM
1264 if (verbosity > 1) {
1265 /* make sure we timestamp just before we go into recv */
1266 /* raj 2004-06-15 */
1267 HIST_timestamp(&time_one);
1268 }
1269#endif /* WANT_HISTOGRAM */
1270
1271 }
1272
1273 /* an EINTR is to be expected when this is a no_control test */
1274 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
1275 perror("send_sdp_maerts: data recv error");
1276 printf("len was %d\n",len);
1277 exit(1);
1278 }
1279
1280 /* if we get here, it must mean we had a recv return of 0 before
1281 the watchdog timer expired, or the watchdog timer expired and
1282 this was a no_control test */
1283
1284 /* The test is over. Flush the buffers to the remote end. We do a
1285 graceful release to tell the remote we have all the data. */
1286
1287 /* but first, if the verbosity is greater than 1, find-out what */
1288 /* the SDP maximum segment_size was (if possible) */
1289 if (verbosity > 1) {
1290 sdp_mss = -1;
1291 get_sdp_info(recv_socket,&sdp_mss);
1292 }
1293
1294 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
1295 perror("netperf: cannot shutdown sdp maerts socket");
1296 exit(1);
1297 }
1298
1299 stop_timer();
1300
1301 /* this call will always give us the local elapsed time for the
1302 test, and will also store-away the necessaries for cpu
1303 utilization */
1304
1305 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
1306 /* measured and how */
1307 /* long did we really */
1308 /* run? */
1309
1310 /* we are finished with the socket, so close it to prevent hitting */
1311 /* the limit on maximum open files. */
1312
1313 close(recv_socket);
1314
1315 if (!no_control) {
1316 /* Get the statistics from the remote end. The remote will have
1317 calculated service demand and all those interesting
1318 things. If it wasn't supposed to care, it will return obvious
1319 values. */
1320
1321 recv_response();
1322 if (!netperf_response.content.serv_errno) {
1323 if (debug)
1324 fprintf(where,"remote results obtained\n");
1325 }
1326 else {
1327 Set_errno(netperf_response.content.serv_errno);
1328 fprintf(where,
1329 "netperf: remote error %d",
1330 netperf_response.content.serv_errno);
1331 perror("");
1332 fflush(where);
1333
1334 exit(1);
1335 }
1336
1337 /* We now calculate what our thruput was for the test. In the
1338 future, we may want to include a calculation of the thruput
1339 measured by the remote, but it should be the case that for a
1340 SDP maerts test, that the two numbers should be *very*
1341 close... We calculate bytes_sent regardless of the way the
1342 test length was controlled. If it was time, we needed to,
1343 and if it was by bytes, the user may have specified a number
1344 of bytes that wasn't a multiple of the recv_size, so we
1345 really didn't recv what he asked for ;-) */
1346
1347 bytes_sent = ntohd(sdp_maerts_result->bytes_sent);
1348 }
1349 else {
1350 bytes_sent = (double)local_bytes_recvd;
1351 }
1352
1353
1354 thruput = calc_thruput(bytes_sent);
1355
1356 if (local_cpu_usage || remote_cpu_usage) {
1357 /* We must now do a little math for service demand and cpu */
1358 /* utilization for the system(s) */
1359 /* Of course, some of the information might be bogus because */
1360 /* there was no idle counter in the kernel(s). We need to make */
1361 /* a note of this for the user's benefit...*/
1362 if (local_cpu_usage) {
1363
1364 local_cpu_utilization = calc_cpu_util(0.0);
1365 local_service_demand = calc_service_demand(bytes_sent,
1366 0.0,
1367 0.0,
1368 0);
1369 }
1370 else {
1371 local_cpu_utilization = (float) -1.0;
1372 local_service_demand = (float) -1.0;
1373 }
1374
1375 if (remote_cpu_usage) {
1376
1377 remote_cpu_utilization = sdp_maerts_result->cpu_util;
1378 remote_service_demand = calc_service_demand(bytes_sent,
1379 0.0,
1380 remote_cpu_utilization,
1381 sdp_maerts_result->num_cpus);
1382 }
1383 else {
1384 remote_cpu_utilization = (float) -1.0;
1385 remote_service_demand = (float) -1.0;
1386 }
1387 }
1388 else {
1389 /* we were not measuring cpu, for the confidence stuff, we */
1390 /* should make it -1.0 */
1391 local_cpu_utilization = (float) -1.0;
1392 local_service_demand = (float) -1.0;
1393 remote_cpu_utilization = (float) -1.0;
1394 remote_service_demand = (float) -1.0;
1395 }
1396
1397 /* at this point, we want to calculate the confidence information. */
1398 /* if debugging is on, calculate_confidence will print-out the */
1399 /* parameters we pass it */
1400
1401 calculate_confidence(confidence_iteration,
1402 elapsed_time,
1403 thruput,
1404 local_cpu_utilization,
1405 remote_cpu_utilization,
1406 local_service_demand,
1407 remote_service_demand);
1408
1409
1410 confidence_iteration++;
1411 }
1412
1413 /* at this point, we have finished making all the runs that we */
1414 /* will be making. so, we should extract what the calcuated values */
1415 /* are for all the confidence stuff. we could make the values */
1416 /* global, but that seemed a little messy, and it did not seem worth */
1417 /* all the mucking with header files. so, we create a routine much */
1418 /* like calcualte_confidence, which just returns the mean values. */
1419 /* raj 11/94 */
1420
1421 retrieve_confident_values(&elapsed_time,
1422 &thruput,
1423 &local_cpu_utilization,
1424 &remote_cpu_utilization,
1425 &local_service_demand,
1426 &remote_service_demand);
1427
1428 /* We are now ready to print all the information. If the user */
1429 /* has specified zero-level verbosity, we will just print the */
1430 /* local service demand, or the remote service demand. If the */
1431 /* user has requested verbosity level 1, he will get the basic */
1432 /* "streamperf" numbers. If the user has specified a verbosity */
1433 /* of greater than 1, we will display a veritable plethora of */
1434 /* background information from outside of this block as it it */
1435 /* not cpu_measurement specific... */
1436
1437 if (confidence < 0) {
1438 /* we did not hit confidence, but were we asked to look for it? */
1439 if (iteration_max > 1) {
1440 display_confidence();
1441 }
1442 }
1443
1444 if (local_cpu_usage || remote_cpu_usage) {
1445 local_cpu_method = format_cpu_method(cpu_method);
1446 remote_cpu_method = format_cpu_method(sdp_maerts_result->cpu_method);
1447
1448 switch (verbosity) {
1449 case 0:
1450 if (local_cpu_usage) {
1451 fprintf(where,
1452 cpu_fmt_0,
1453 local_service_demand,
1454 local_cpu_method,
1455 ((print_headers) ||
1456 (result_brand == NULL)) ? "" : result_brand);
1457 }
1458 else {
1459 fprintf(where,
1460 cpu_fmt_0,
1461 remote_service_demand,
1462 remote_cpu_method,
1463 ((print_headers) ||
1464 (result_brand == NULL)) ? "" : result_brand);
1465 }
1466 break;
1467 case 1:
1468 case 2:
1469 if (print_headers) {
1470 fprintf(where,
1471 cpu_title,
1472 format_units(),
1473 local_cpu_method,
1474 remote_cpu_method);
1475 }
1476
1477 fprintf(where,
1478 cpu_fmt_1, /* the format string */
1479 rsr_size, /* remote recvbuf size */
1480 lss_size, /* local sendbuf size */
1481 send_size, /* how large were the recvs */
1482 elapsed_time, /* how long was the test */
1483 thruput, /* what was the xfer rate */
1484 local_cpu_utilization, /* local cpu */
1485 remote_cpu_utilization, /* remote cpu */
1486 local_service_demand, /* local service demand */
1487 remote_service_demand, /* remote service demand */
1488 ((print_headers) ||
1489 (result_brand == NULL)) ? "" : result_brand);
1490 break;
1491 }
1492 }
1493 else {
1494 /* The tester did not wish to measure service demand. */
1495
1496 switch (verbosity) {
1497 case 0:
1498 fprintf(where,
1499 tput_fmt_0,
1500 thruput,
1501 ((print_headers) ||
1502 (result_brand == NULL)) ? "" : result_brand);
1503 break;
1504 case 1:
1505 case 2:
1506 if (print_headers) {
1507 fprintf(where,tput_title,format_units());
1508 }
1509 fprintf(where,
1510 tput_fmt_1, /* the format string */
1511 lsr_size, /* local recvbuf size */
1512 rss_size, /* remot sendbuf size */
1513 send_size, /* how large were the recvs */
1514 elapsed_time, /* how long did it take */
1515 thruput, /* how fast did it go */
1516 ((print_headers) ||
1517 (result_brand == NULL)) ? "" : result_brand);
1518 break;
1519 }
1520 }
1521
1522 /* it would be a good thing to include information about some of the */
1523 /* other parameters that may have been set for this test, but at the */
1524 /* moment, I do not wish to figure-out all the formatting, so I will */
1525 /* just put this comment here to help remind me that it is something */
1526 /* that should be done at a later time. */
1527
1528 if (verbosity > 1) {
1529 /* The user wanted to know it all, so we will give it to him. */
1530 /* This information will include as much as we can find about */
1531 /* SDP statistics, the alignments of the sends and receives */
1532 /* and all that sort of rot... */
1533
1534 /* this stuff needs to be worked-out in the presence of confidence */
1535 /* intervals and multiple iterations of the test... raj 11/94 */
1536
1537 fprintf(where,
1538 ksink_fmt,
1539 "Bytes",
1540 "Bytes",
1541 "Bytes",
1542 local_recv_align,
1543 remote_recv_align,
1544 local_recv_offset,
1545 remote_recv_offset,
1546 bytes_sent,
1547 bytes_sent / (double)nummessages,
1548 nummessages,
1549 bytes_sent / (double)sdp_maerts_result->send_calls,
1550 sdp_maerts_result->send_calls);
1551 fprintf(where,
1552 ksink_fmt2,
1553 sdp_mss);
1554 fflush(where);
1555#ifdef WANT_HISTOGRAM
1556 fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
1557 fflush(where);
1558 HIST_report(time_hist);
1559#endif /* WANT_HISTOGRAM */
1560 }
1561
1562}
1563/* This is the server-side routine for the sdp stream test. It is */
1564/* implemented as one routine. I could break things-out somewhat, but */
1565/* didn't feel it was necessary. */
1566
1567void
1568recv_sdp_stream()
1569{
1570
1571 struct sockaddr_in myaddr_in, peeraddr_in;
1572 SOCKET s_listen,s_data;
1573 netperf_socklen_t addrlen;
1574 int len;
1575 unsigned int receive_calls;
1576 float elapsed_time;
1577 double bytes_received;
1578
1579 struct ring_elt *recv_ring;
1580
1581 struct addrinfo *local_res;
1582 char local_name[BUFSIZ];
1583 char port_buffer[PORTBUFSIZE];
1584
1585#ifdef DO_SELECT
1586 fd_set readfds;
1587 struct timeval timeout;
1588#endif /* DO_SELECT */
1589
1590 struct sdp_stream_request_struct *sdp_stream_request;
1591 struct sdp_stream_response_struct *sdp_stream_response;
1592 struct sdp_stream_results_struct *sdp_stream_results;
1593
1594#ifdef DO_SELECT
1595 FD_ZERO(&readfds);
1596 timeout.tv_sec = 1;
1597 timeout.tv_usec = 0;
1598#endif /* DO_SELECT */
1599
1600 sdp_stream_request =
1601 (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data;
1602 sdp_stream_response =
1603 (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data;
1604 sdp_stream_results =
1605 (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data;
1606
1607 if (debug) {
1608 fprintf(where,"netserver: recv_sdp_stream: entered...\n");
1609 fflush(where);
1610 }
1611
1612 /* We want to set-up the listen socket with all the desired */
1613 /* parameters and then let the initiator know that all is ready. If */
1614 /* socket size defaults are to be used, then the initiator will have */
1615 /* sent us 0's. If the socket sizes cannot be changed, then we will */
1616 /* send-back what they are. If that information cannot be determined, */
1617 /* then we send-back -1's for the sizes. If things go wrong for any */
1618 /* reason, we will drop back ten yards and punt. */
1619
1620 /* If anything goes wrong, we want the remote to know about it. It */
1621 /* would be best if the error that the remote reports to the user is */
1622 /* the actual error we encountered, rather than some bogus unexpected */
1623 /* response type message. */
1624
1625 if (debug) {
1626 fprintf(where,"recv_sdp_stream: setting the response type...\n");
1627 fflush(where);
1628 }
1629
1630 netperf_response.content.response_type = SDP_STREAM_RESPONSE;
1631
1632 if (debug) {
1633 fprintf(where,"recv_sdp_stream: the response type is set...\n");
1634 fflush(where);
1635 }
1636
1637 /* We now alter the message_ptr variable to be at the desired */
1638 /* alignment with the desired offset. */
1639
1640 if (debug) {
1641 fprintf(where,"recv_sdp_stream: requested alignment of %d\n",
1642 sdp_stream_request->recv_alignment);
1643 fflush(where);
1644 }
1645
1646 /* create_data_socket expects to find some things in the global */
1647 /* variables, so set the globals based on the values in the request. */
1648 /* once the socket has been created, we will set the response values */
1649 /* based on the updated value of those globals. raj 7/94 */
1650 lss_size_req = sdp_stream_request->send_buf_size;
1651 lsr_size_req = sdp_stream_request->recv_buf_size;
1652 loc_nodelay = sdp_stream_request->no_delay;
1653 loc_rcvavoid = sdp_stream_request->so_rcvavoid;
1654 loc_sndavoid = sdp_stream_request->so_sndavoid;
1655
1656 set_hostname_and_port(local_name,
1657 port_buffer,
1658 nf_to_af(sdp_stream_request->ipfamily),
1659 sdp_stream_request->port);
1660
1661 local_res = complete_addrinfo(local_name,
1662 local_name,
1663 port_buffer,
1664 nf_to_af(sdp_stream_request->ipfamily),
1665 SOCK_STREAM,
1666 IPPROTO_TCP,
1667 0);
1668
1669 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
1670 local_res->ai_family = AF_INET_SDP;
1671 local_res->ai_protocol = 0;
1672 s_listen = create_data_socket(local_res);
1673
1674 if (s_listen == INVALID_SOCKET) {
1675 netperf_response.content.serv_errno = errno;
1676 send_response();
1677 exit(1);
1678 }
1679
1680#ifdef WIN32
1681 /* The test timer can fire during operations on the listening socket,
1682 so to make the start_timer below work we have to move
1683 it to close s_listen while we are blocked on accept. */
1684 win_kludge_socket2 = s_listen;
1685#endif
1686
1687 /* what sort of sizes did we end-up with? */
1688 if (sdp_stream_request->receive_size == 0) {
1689 if (lsr_size > 0) {
1690 recv_size = lsr_size;
1691 }
1692 else {
1693 recv_size = 4096;
1694 }
1695 }
1696 else {
1697 recv_size = sdp_stream_request->receive_size;
1698 }
1699
1700 /* we want to set-up our recv_ring in a manner analagous to what we */
1701 /* do on the sending side. this is more for the sake of symmetry */
1702 /* than for the needs of say copy avoidance, but it might also be */
1703 /* more realistic - this way one could conceivably go with a */
1704 /* double-buffering scheme when taking the data an putting it into */
1705 /* the filesystem or something like that. raj 7/94 */
1706
1707 if (recv_width == 0) {
1708 recv_width = (lsr_size/recv_size) + 1;
1709 if (recv_width == 1) recv_width++;
1710 }
1711
1712 recv_ring = allocate_buffer_ring(recv_width,
1713 recv_size,
1714 sdp_stream_request->recv_alignment,
1715 sdp_stream_request->recv_offset);
1716
1717 if (debug) {
1718 fprintf(where,"recv_sdp_stream: receive alignment and offset set...\n");
1719 fflush(where);
1720 }
1721
1722 /* Now, let's set-up the socket to listen for connections */
1723 if (listen(s_listen, 5) == SOCKET_ERROR) {
1724 netperf_response.content.serv_errno = errno;
1725 close(s_listen);
1726 send_response();
1727
1728 exit(1);
1729 }
1730
1731
1732 /* now get the port number assigned by the system */
1733 addrlen = sizeof(myaddr_in);
1734 if (getsockname(s_listen,
1735 (struct sockaddr *)&myaddr_in,
1736 &addrlen) == SOCKET_ERROR){
1737 netperf_response.content.serv_errno = errno;
1738 close(s_listen);
1739 send_response();
1740
1741 exit(1);
1742 }
1743
1744 /* Now myaddr_in contains the port and the internet address this is */
1745 /* returned to the sender also implicitly telling the sender that the */
1746 /* socket buffer sizing has been done. */
1747
1748 sdp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
1749 netperf_response.content.serv_errno = 0;
1750
1751 /* But wait, there's more. If the initiator wanted cpu measurements, */
1752 /* then we must call the calibrate routine, which will return the max */
1753 /* rate back to the initiator. If the CPU was not to be measured, or */
1754 /* something went wrong with the calibration, we will return a -1 to */
1755 /* the initiator. */
1756
1757 sdp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
1758 if (sdp_stream_request->measure_cpu) {
1759 sdp_stream_response->measure_cpu = 1;
1760 sdp_stream_response->cpu_rate =
1761 calibrate_local_cpu(sdp_stream_request->cpu_rate);
1762 }
1763 else {
1764 sdp_stream_response->measure_cpu = 0;
1765 }
1766
1767 /* before we send the response back to the initiator, pull some of */
1768 /* the socket parms from the globals */
1769 sdp_stream_response->send_buf_size = lss_size;
1770 sdp_stream_response->recv_buf_size = lsr_size;
1771 sdp_stream_response->no_delay = loc_nodelay;
1772 sdp_stream_response->so_rcvavoid = loc_rcvavoid;
1773 sdp_stream_response->so_sndavoid = loc_sndavoid;
1774 sdp_stream_response->receive_size = recv_size;
1775
1776 send_response();
1777
1778 addrlen = sizeof(peeraddr_in);
1779
1780 if ((s_data=accept(s_listen,
1781 (struct sockaddr *)&peeraddr_in,
1782 &addrlen)) == INVALID_SOCKET) {
1783 /* Let's just punt. The remote will be given some information */
1784 close(s_listen);
1785 exit(1);
1786 }
1787
1788#ifdef KLUDGE_SOCKET_OPTIONS
1789 /* this is for those systems which *INCORRECTLY* fail to pass */
1790 /* attributes across an accept() call. Including this goes against */
1791 /* my better judgement :( raj 11/95 */
1792
1793 kludge_socket_options(s_data);
1794
1795#endif /* KLUDGE_SOCKET_OPTIONS */
1796
1797 /* Now it's time to start receiving data on the connection. We will */
1798 /* first grab the apropriate counters and then start grabbing. */
1799
1800 cpu_start(sdp_stream_request->measure_cpu);
1801
1802 /* The loop will exit when the sender does a shutdown, which will */
1803 /* return a length of zero */
1804
1805 /* there used to be an #ifdef DIRTY call to access_buffer() here,
1806 but we have switched from accessing the buffer before the recv()
1807 call to accessing the buffer after the recv() call. The
1808 accessing before was, IIRC, related to having dirty data when
1809 doing page-flipping copy avoidance. */
1810
1811 bytes_received = 0;
1812 receive_calls = 0;
1813
1814 while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) {
1815 if (len == SOCKET_ERROR )
1816 {
1817 netperf_response.content.serv_errno = errno;
1818 send_response();
1819 exit(1);
1820 }
1821 bytes_received += len;
1822 receive_calls++;
1823
1824#ifdef DIRTY
1825 /* we access the buffer after the recv() call now, rather than before */
1826 access_buffer(recv_ring->buffer_ptr,
1827 recv_size,
1828 sdp_stream_request->dirty_count,
1829 sdp_stream_request->clean_count);
1830#endif /* DIRTY */
1831
1832
1833 /* move to the next buffer in the recv_ring */
1834 recv_ring = recv_ring->next;
1835
1836#ifdef PAUSE
1837 sleep(1);
1838#endif /* PAUSE */
1839
1840#ifdef DO_SELECT
1841 FD_SET(s_data,&readfds);
1842 select(s_data+1,&readfds,NULL,NULL,&timeout);
1843#endif /* DO_SELECT */
1844
1845 }
1846
1847 /* perform a shutdown to signal the sender that */
1848 /* we have received all the data sent. raj 4/93 */
1849
1850 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
1851 netperf_response.content.serv_errno = errno;
1852 send_response();
1853 exit(1);
1854 }
1855
1856 cpu_stop(sdp_stream_request->measure_cpu,&elapsed_time);
1857
1858 /* send the results to the sender */
1859
1860 if (debug) {
1861 fprintf(where,
1862 "recv_sdp_stream: got %g bytes\n",
1863 bytes_received);
1864 fprintf(where,
1865 "recv_sdp_stream: got %d recvs\n",
1866 receive_calls);
1867 fflush(where);
1868 }
1869
1870 sdp_stream_results->bytes_received = htond(bytes_received);
1871 sdp_stream_results->elapsed_time = elapsed_time;
1872 sdp_stream_results->recv_calls = receive_calls;
1873
1874 sdp_stream_results->cpu_method = cpu_method;
1875 sdp_stream_results->num_cpus = lib_num_loc_cpus;
1876
1877 if (sdp_stream_request->measure_cpu) {
1878 sdp_stream_results->cpu_util = calc_cpu_util(0.0);
1879 };
1880
1881 if (debug) {
1882 fprintf(where,
1883 "recv_sdp_stream: test complete, sending results.\n");
1884 fprintf(where,
1885 " bytes_received %g receive_calls %d\n",
1886 bytes_received,
1887 receive_calls);
1888 fprintf(where,
1889 " len %d\n",
1890 len);
1891 fflush(where);
1892 }
1893
1894 send_response();
1895
1896 /* we are now done with the sockets */
1897 close(s_data);
1898 close(s_listen);
1899
1900 }
1901
1902/* This is the server-side routine for the sdp maerts test. It is
1903 implemented as one routine. I could break things-out somewhat, but
1904 didn't feel it was necessary. */
1905
1906void
1907recv_sdp_maerts()
1908{
1909
1910 struct sockaddr_in myaddr_in, peeraddr_in;
1911 struct addrinfo *local_res;
1912 char local_name[BUFSIZ];
1913 char port_buffer[PORTBUFSIZE];
1914
1915 SOCKET s_listen,s_data;
1916 netperf_socklen_t addrlen;
1917 int len;
1918 unsigned int send_calls;
1919 float elapsed_time;
1920 double bytes_sent = 0.0 ;
1921
1922 struct ring_elt *send_ring;
1923
1924 struct sdp_maerts_request_struct *sdp_maerts_request;
1925 struct sdp_maerts_response_struct *sdp_maerts_response;
1926 struct sdp_maerts_results_struct *sdp_maerts_results;
1927
1928 sdp_maerts_request =
1929 (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data;
1930 sdp_maerts_response =
1931 (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data;
1932 sdp_maerts_results =
1933 (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data;
1934
1935 if (debug) {
1936 fprintf(where,"netserver: recv_sdp_maerts: entered...\n");
1937 fflush(where);
1938 }
1939
1940 /* We want to set-up the listen socket with all the desired
1941 parameters and then let the initiator know that all is ready. If
1942 socket size defaults are to be used, then the initiator will have
1943 sent us 0's. If the socket sizes cannot be changed, then we will
1944 send-back what they are. If that information cannot be
1945 determined, then we send-back -1's for the sizes. If things go
1946 wrong for any reason, we will drop back ten yards and punt. */
1947
1948 /* If anything goes wrong, we want the remote to know about it. It
1949 would be best if the error that the remote reports to the user is
1950 the actual error we encountered, rather than some bogus
1951 unexpected response type message. */
1952
1953 if (debug) {
1954 fprintf(where,"recv_sdp_maerts: setting the response type...\n");
1955 fflush(where);
1956 }
1957
1958 netperf_response.content.response_type = SDP_MAERTS_RESPONSE;
1959
1960 if (debug) {
1961 fprintf(where,"recv_sdp_maerts: the response type is set...\n");
1962 fflush(where);
1963 }
1964
1965 /* We now alter the message_ptr variable to be at the desired */
1966 /* alignment with the desired offset. */
1967
1968 if (debug) {
1969 fprintf(where,"recv_sdp_maerts: requested alignment of %d\n",
1970 sdp_maerts_request->send_alignment);
1971 fflush(where);
1972 }
1973
1974 /* Grab a socket to listen on, and then listen on it. */
1975
1976 if (debug) {
1977 fprintf(where,"recv_sdp_maerts: grabbing a socket...\n");
1978 fflush(where);
1979 }
1980
1981 /* create_data_socket expects to find some things in the global */
1982 /* variables, so set the globals based on the values in the request. */
1983 /* once the socket has been created, we will set the response values */
1984 /* based on the updated value of those globals. raj 7/94 */
1985 lss_size_req = sdp_maerts_request->send_buf_size;
1986 lsr_size_req = sdp_maerts_request->recv_buf_size;
1987 loc_nodelay = sdp_maerts_request->no_delay;
1988 loc_rcvavoid = sdp_maerts_request->so_rcvavoid;
1989 loc_sndavoid = sdp_maerts_request->so_sndavoid;
1990
1991 set_hostname_and_port(local_name,
1992 port_buffer,
1993 nf_to_af(sdp_maerts_request->ipfamily),
1994 sdp_maerts_request->port);
1995
1996 local_res = complete_addrinfo(local_name,
1997 local_name,
1998 port_buffer,
1999 nf_to_af(sdp_maerts_request->ipfamily),
2000 SOCK_STREAM,
2001 IPPROTO_TCP,
2002 0);
2003
2004 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
2005 local_res->ai_family = AF_INET_SDP;
2006 local_res->ai_protocol = 0;
2007 s_listen = create_data_socket(local_res);
2008
2009 if (s_listen == INVALID_SOCKET) {
2010 netperf_response.content.serv_errno = errno;
2011 send_response();
2012 exit(1);
2013 }
2014
2015#ifdef WIN32
2016 /* The test timer can fire during operations on the listening socket,
2017 so to make the start_timer below work we have to move
2018 it to close s_listen while we are blocked on accept. */
2019 win_kludge_socket2 = s_listen;
2020#endif
2021
2022
2023 /* what sort of sizes did we end-up with? */
2024 if (sdp_maerts_request->send_size == 0) {
2025 if (lss_size > 0) {
2026 send_size = lss_size;
2027 }
2028 else {
2029 send_size = 4096;
2030 }
2031 }
2032 else {
2033 send_size = sdp_maerts_request->send_size;
2034 }
2035
2036 /* we want to set-up our recv_ring in a manner analagous to what we */
2037 /* do on the recving side. this is more for the sake of symmetry */
2038 /* than for the needs of say copy avoidance, but it might also be */
2039 /* more realistic - this way one could conceivably go with a */
2040 /* double-buffering scheme when taking the data an putting it into */
2041 /* the filesystem or something like that. raj 7/94 */
2042
2043 if (send_width == 0) {
2044 send_width = (lsr_size/send_size) + 1;
2045 if (send_width == 1) send_width++;
2046 }
2047
2048 send_ring = allocate_buffer_ring(send_width,
2049 send_size,
2050 sdp_maerts_request->send_alignment,
2051 sdp_maerts_request->send_offset);
2052
2053 if (debug) {
2054 fprintf(where,"recv_sdp_maerts: receive alignment and offset set...\n");
2055 fflush(where);
2056 }
2057
2058 /* Now, let's set-up the socket to listen for connections */
2059 if (listen(s_listen, 5) == SOCKET_ERROR) {
2060 netperf_response.content.serv_errno = errno;
2061 close(s_listen);
2062 send_response();
2063
2064 exit(1);
2065 }
2066
2067
2068 /* now get the port number assigned by the system */
2069 addrlen = sizeof(myaddr_in);
2070 if (getsockname(s_listen,
2071 (struct sockaddr *)&myaddr_in,
2072 &addrlen) == SOCKET_ERROR){
2073 netperf_response.content.serv_errno = errno;
2074 close(s_listen);
2075 send_response();
2076
2077 exit(1);
2078 }
2079
2080 /* Now myaddr_in contains the port and the internet address this is */
2081 /* returned to the sender also implicitly telling the sender that the */
2082 /* socket buffer sizing has been done. */
2083
2084 sdp_maerts_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
2085 netperf_response.content.serv_errno = 0;
2086
2087 /* But wait, there's more. If the initiator wanted cpu measurements, */
2088 /* then we must call the calibrate routine, which will return the max */
2089 /* rate back to the initiator. If the CPU was not to be measured, or */
2090 /* something went wrong with the calibration, we will return a -1 to */
2091 /* the initiator. */
2092
2093 sdp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */
2094 if (sdp_maerts_request->measure_cpu) {
2095 sdp_maerts_response->measure_cpu = 1;
2096 sdp_maerts_response->cpu_rate =
2097 calibrate_local_cpu(sdp_maerts_request->cpu_rate);
2098 }
2099 else {
2100 sdp_maerts_response->measure_cpu = 0;
2101 }
2102
2103 /* before we send the response back to the initiator, pull some of */
2104 /* the socket parms from the globals */
2105 sdp_maerts_response->send_buf_size = lss_size;
2106 sdp_maerts_response->recv_buf_size = lsr_size;
2107 sdp_maerts_response->no_delay = loc_nodelay;
2108 sdp_maerts_response->so_rcvavoid = loc_rcvavoid;
2109 sdp_maerts_response->so_sndavoid = loc_sndavoid;
2110 sdp_maerts_response->send_size = send_size;
2111
2112 send_response();
2113
2114 addrlen = sizeof(peeraddr_in);
2115
2116 /* we will start the timer before the accept() to be somewhat
2117 analagous to the starting of the timer before the connect() call
2118 in the SDP_STREAM test. raj 2002-06-21 */
2119
2120 start_timer(sdp_maerts_request->test_length);
2121
2122 /* Now it's time to start receiving data on the connection. We will
2123 first grab the apropriate counters and then start grabbing. */
2124
2125 cpu_start(sdp_maerts_request->measure_cpu);
2126
2127
2128 if ((s_data=accept(s_listen,
2129 (struct sockaddr *)&peeraddr_in,
2130 &addrlen)) == INVALID_SOCKET) {
2131 /* Let's just punt. The remote will be given some information */
2132 close(s_listen);
2133 exit(1);
2134 }
2135
2136#ifdef KLUDGE_SOCKET_OPTIONS
2137
2138 /* this is for those systems which *INCORRECTLY* fail to pass
2139 attributes across an accept() call. Including this goes against
2140 my better judgement :( raj 11/95 */
2141
2142 kludge_socket_options(s_data);
2143
2144#endif /* KLUDGE_SOCKET_OPTIONS */
2145
2146 /* The loop will exit when the sender does a shutdown, which will */
2147 /* return a length of zero */
2148
2149 bytes_sent = 0.0;
2150 send_calls = 0;
2151
2152 len = 0; /* nt-lint; len is not initialized (printf far below) if
2153 times_up initially true.*/
2154 times_up = 0; /* must remember to initialize this little beauty */
2155 while (!times_up) {
2156
2157#ifdef DIRTY
2158 /* we want to dirty some number of consecutive integers in the buffer */
2159 /* we are about to send. we may also want to bring some number of */
2160 /* them cleanly into the cache. The clean ones will follow any dirty */
2161 /* ones into the cache. */
2162
2163 access_buffer(send_ring->buffer_ptr,
2164 send_size,
2165 sdp_maerts_request->dirty_count,
2166 sdp_maerts_request->clean_count);
2167
2168#endif /* DIRTY */
2169
2170 if((len=send(s_data,
2171 send_ring->buffer_ptr,
2172 send_size,
2173 0)) != send_size) {
2174 if ((len >=0) || SOCKET_EINTR(len)) {
2175 /* the test was interrupted, must be the end of test */
2176 break;
2177 }
2178 netperf_response.content.serv_errno = errno;
2179 send_response();
2180 exit(1);
2181 }
2182
2183 bytes_sent += len;
2184 send_calls++;
2185
2186 /* more to the next buffer in the send_ring */
2187 send_ring = send_ring->next;
2188
2189 }
2190
2191 /* perform a shutdown to signal the sender that */
2192 /* we have received all the data sent. raj 4/93 */
2193
2194 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
2195 netperf_response.content.serv_errno = errno;
2196 send_response();
2197 exit(1);
2198 }
2199
2200 /* hang a recv() off the socket to block until the remote has
2201 brought all the data up into the application. it will do a
2202 shutdown to cause a FIN to be sent our way. We will assume that
2203 any exit from the recv() call is good... raj 4/93 */
2204
2205 recv(s_data, send_ring->buffer_ptr, send_size, 0);
2206
2207
2208 cpu_stop(sdp_maerts_request->measure_cpu,&elapsed_time);
2209
2210 /* send the results to the sender */
2211
2212 if (debug) {
2213 fprintf(where,
2214 "recv_sdp_maerts: got %g bytes\n",
2215 bytes_sent);
2216 fprintf(where,
2217 "recv_sdp_maerts: got %d sends\n",
2218 send_calls);
2219 fflush(where);
2220 }
2221
2222 sdp_maerts_results->bytes_sent = htond(bytes_sent);
2223 sdp_maerts_results->elapsed_time = elapsed_time;
2224 sdp_maerts_results->send_calls = send_calls;
2225
2226 if (sdp_maerts_request->measure_cpu) {
2227 sdp_maerts_results->cpu_util = calc_cpu_util(0.0);
2228 };
2229
2230 if (debug) {
2231 fprintf(where,
2232 "recv_sdp_maerts: test complete, sending results.\n");
2233 fprintf(where,
2234 " bytes_sent %g send_calls %d\n",
2235 bytes_sent,
2236 send_calls);
2237 fprintf(where,
2238 " len %d\n",
2239 len);
2240 fflush(where);
2241 }
2242
2243 sdp_maerts_results->cpu_method = cpu_method;
2244 sdp_maerts_results->num_cpus = lib_num_loc_cpus;
2245 send_response();
2246
2247 /* we are now done with the sockets */
2248 close(s_data);
2249 close(s_listen);
2250
2251 }
2252
2253
2254 /* this routine implements the sending (netperf) side of the SDP_RR */
2255 /* test. */
2256
2257void
2258send_sdp_rr(char remote_host[])
2259{
2260
2261 char *tput_title = "\
2262Local /Remote\n\
2263Socket Size Request Resp. Elapsed Trans.\n\
2264Send Recv Size Size Time Rate \n\
2265bytes Bytes bytes bytes secs. per sec \n\n";
2266
2267 char *tput_fmt_0 =
2268 "%7.2f %s\n";
2269
2270 char *tput_fmt_1_line_1 = "\
2271%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
2272 char *tput_fmt_1_line_2 = "\
2273%-6d %-6d\n";
2274
2275 char *cpu_title = "\
2276Local /Remote\n\
2277Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
2278Send Recv Size Size Time Rate local remote local remote\n\
2279bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
2280
2281 char *cpu_fmt_0 =
2282 "%6.3f %c %s\n";
2283
2284 char *cpu_fmt_1_line_1 = "\
2285%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
2286
2287 char *cpu_fmt_1_line_2 = "\
2288%-6d %-6d\n";
2289
2290 char *ksink_fmt = "\
2291Alignment Offset\n\
2292Local Remote Local Remote\n\
2293Send Recv Send Recv\n\
2294%5d %5d %5d %5d\n";
2295
2296
2297 int timed_out = 0;
2298 float elapsed_time;
2299
2300 int len;
2301 char *temp_message_ptr;
2302 int nummessages;
2303 SOCKET send_socket;
2304 int trans_remaining;
2305 double bytes_xferd;
2306
2307 struct ring_elt *send_ring;
2308 struct ring_elt *recv_ring;
2309
2310 int rsp_bytes_left;
2311 int rsp_bytes_recvd;
2312
2313 float local_cpu_utilization;
2314 float local_service_demand;
2315 float remote_cpu_utilization;
2316 float remote_service_demand;
2317 double thruput;
2318
2319 struct addrinfo *local_res;
2320 struct addrinfo *remote_res;
2321
2322 struct sdp_rr_request_struct *sdp_rr_request;
2323 struct sdp_rr_response_struct *sdp_rr_response;
2324 struct sdp_rr_results_struct *sdp_rr_result;
2325
2326#ifdef WANT_FIRST_BURST
2327#define REQUEST_CWND_INITIAL 2
2328 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
2329 Unix and the state of New Jersey - both were simple an unspoiled.
2330 then it was realized that some stacks are quite picky about
2331 initial congestion windows and a non-trivial initial burst of
2332 requests would not be individual segments even with TCP_NODELAY
2333 set. so, we have to start tracking a poor-man's congestion window
2334 up here in window space because we want to try to make something
2335 happen that frankly, we cannot guarantee with the specification
2336 of SDP. ain't that grand?-) raj 2006-01-30 */
2337 int requests_outstanding = 0;
2338 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having
2339 three requests
2340 outstanding at the
2341 beginning of the test
2342 is ok with SDP stacks
2343 of interest. the first
2344 two will come from our
2345 first_burst loop, and
2346 the third from our
2347 regularly scheduled
2348 send */
2349#endif
2350
2351 sdp_rr_request =
2352 (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data;
2353 sdp_rr_response=
2354 (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data;
2355 sdp_rr_result =
2356 (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data;
2357
2358#ifdef WANT_HISTOGRAM
2359 if (verbosity > 1) {
2360 time_hist = HIST_new();
2361 }
2362#endif /* WANT_HISTOGRAM */
2363
2364 /* since we are now disconnected from the code that established the */
2365 /* control socket, and since we want to be able to use different */
2366 /* protocols and such, we are passed the name of the remote host and */
2367 /* must turn that into the test specific addressing information. */
2368
2369 complete_addrinfos(&remote_res,
2370 &local_res,
2371 remote_host,
2372 SOCK_STREAM,
2373 IPPROTO_TCP,
2374 0);
2375
2376 if ( print_headers ) {
2377 print_top_test_header("SDP REQUEST/RESPONSE TEST",local_res,remote_res);
2378 }
2379
2380 /* initialize a few counters */
2381
2382 send_ring = NULL;
2383 recv_ring = NULL;
2384 confidence_iteration = 1;
2385 init_stat();
2386
2387 /* we have a great-big while loop which controls the number of times */
2388 /* we run a particular test. this is for the calculation of a */
2389 /* confidence interval (I really should have stayed awake during */
2390 /* probstats :). If the user did not request confidence measurement */
2391 /* (no confidence is the default) then we will only go though the */
2392 /* loop once. the confidence stuff originates from the folks at IBM */
2393
2394 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2395 (confidence_iteration <= iteration_min)) {
2396
2397 /* initialize a few counters. we have to remember that we might be */
2398 /* going through the loop more than once. */
2399
2400 nummessages = 0;
2401 bytes_xferd = 0.0;
2402 times_up = 0;
2403 timed_out = 0;
2404 trans_remaining = 0;
2405
2406#ifdef WANT_FIRST_BURST
2407 /* we have to remember to reset the number of transactions
2408 outstanding and the "congestion window for each new
2409 iteration. raj 2006-01-31 */
2410 requests_outstanding = 0;
2411 request_cwnd = REQUEST_CWND_INITIAL;
2412#endif
2413
2414
2415 /* set-up the data buffers with the requested alignment and offset. */
2416 /* since this is a request/response test, default the send_width and */
2417 /* recv_width to 1 and not two raj 7/94 */
2418
2419 if (send_width == 0) send_width = 1;
2420 if (recv_width == 0) recv_width = 1;
2421
2422 if (send_ring == NULL) {
2423 send_ring = allocate_buffer_ring(send_width,
2424 req_size,
2425 local_send_align,
2426 local_send_offset);
2427 }
2428
2429 if (recv_ring == NULL) {
2430 recv_ring = allocate_buffer_ring(recv_width,
2431 rsp_size,
2432 local_recv_align,
2433 local_recv_offset);
2434 }
2435
2436 /*set up the data socket */
2437 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
2438 local_res->ai_family = AF_INET_SDP;
2439 local_res->ai_protocol = 0;
2440 send_socket = create_data_socket(local_res);
2441
2442 if (send_socket == INVALID_SOCKET){
2443 perror("netperf: send_sdp_rr: sdp stream data socket");
2444 exit(1);
2445 }
2446
2447 if (debug) {
2448 fprintf(where,"send_sdp_rr: send_socket obtained...\n");
2449 }
2450
2451 /* If the user has requested cpu utilization measurements, we must */
2452 /* calibrate the cpu(s). We will perform this task within the tests */
2453 /* themselves. If the user has specified the cpu rate, then */
2454 /* calibrate_local_cpu will return rather quickly as it will have */
2455 /* nothing to do. If local_cpu_rate is zero, then we will go through */
2456 /* all the "normal" calibration stuff and return the rate back.*/
2457
2458 if (local_cpu_usage) {
2459 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2460 }
2461
2462 if (!no_control) {
2463 /* Tell the remote end to do a listen. The server alters the
2464 socket paramters on the other side at this point, hence the
2465 reason for all the values being passed in the setup
2466 message. If the user did not specify any of the parameters,
2467 they will be passed as 0, which will indicate to the remote
2468 that no changes beyond the system's default should be
2469 used. Alignment is the exception, it will default to 8, which
2470 will be no alignment alterations. */
2471
2472 netperf_request.content.request_type = DO_SDP_RR;
2473 sdp_rr_request->recv_buf_size = rsr_size_req;
2474 sdp_rr_request->send_buf_size = rss_size_req;
2475 sdp_rr_request->recv_alignment = remote_recv_align;
2476 sdp_rr_request->recv_offset = remote_recv_offset;
2477 sdp_rr_request->send_alignment = remote_send_align;
2478 sdp_rr_request->send_offset = remote_send_offset;
2479 sdp_rr_request->request_size = req_size;
2480 sdp_rr_request->response_size = rsp_size;
2481 sdp_rr_request->no_delay = rem_nodelay;
2482 sdp_rr_request->measure_cpu = remote_cpu_usage;
2483 sdp_rr_request->cpu_rate = remote_cpu_rate;
2484 sdp_rr_request->so_rcvavoid = rem_rcvavoid;
2485 sdp_rr_request->so_sndavoid = rem_sndavoid;
2486 if (test_time) {
2487 sdp_rr_request->test_length = test_time;
2488 }
2489 else {
2490 sdp_rr_request->test_length = test_trans * -1;
2491 }
2492 sdp_rr_request->port = atoi(remote_data_port);
2493 sdp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
2494
2495 if (debug > 1) {
2496 fprintf(where,"netperf: send_sdp_rr: requesting SDP rr test\n");
2497 }
2498
2499 send_request();
2500
2501 /* The response from the remote will contain all of the relevant
2502 socket parameters for this test type. We will put them back
2503 into the variables here so they can be displayed if desired.
2504 The remote will have calibrated CPU if necessary, and will
2505 have done all the needed set-up we will have calibrated the
2506 cpu locally before sending the request, and will grab the
2507 counter value right after the connect returns. The remote
2508 will grab the counter right after the accept call. This saves
2509 the hassle of extra messages being sent for the SDP
2510 tests. */
2511
2512 recv_response();
2513
2514 if (!netperf_response.content.serv_errno) {
2515 if (debug)
2516 fprintf(where,"remote listen done.\n");
2517 rsr_size = sdp_rr_response->recv_buf_size;
2518 rss_size = sdp_rr_response->send_buf_size;
2519 rem_nodelay = sdp_rr_response->no_delay;
2520 remote_cpu_usage = sdp_rr_response->measure_cpu;
2521 remote_cpu_rate = sdp_rr_response->cpu_rate;
2522 /* make sure that port numbers are in network order */
2523 set_port_number(remote_res,(short)sdp_rr_response->data_port_number);
2524 }
2525 else {
2526 Set_errno(netperf_response.content.serv_errno);
2527 fprintf(where,
2528 "netperf: remote error %d",
2529 netperf_response.content.serv_errno);
2530 perror("");
2531 fflush(where);
2532
2533 exit(1);
2534 }
2535 }
2536
2537#ifdef WANT_DEMO
2538 DEMO_RR_SETUP(1000)
2539#endif
2540
2541 /*Connect up to the remote port on the data socket */
2542 if (connect(send_socket,
2543 remote_res->ai_addr,
2544 remote_res->ai_addrlen) == INVALID_SOCKET){
2545 perror("netperf: data socket connect failed");
2546
2547 exit(1);
2548 }
2549
2550 /* Data Socket set-up is finished. If there were problems, either the */
2551 /* connect would have failed, or the previous response would have */
2552 /* indicated a problem. I failed to see the value of the extra */
2553 /* message after the accept on the remote. If it failed, we'll see it */
2554 /* here. If it didn't, we might as well start pumping data. */
2555
2556 /* Set-up the test end conditions. For a request/response test, they */
2557 /* can be either time or transaction based. */
2558
2559 if (test_time) {
2560 /* The user wanted to end the test after a period of time. */
2561 times_up = 0;
2562 trans_remaining = 0;
2563 start_timer(test_time);
2564 }
2565 else {
2566 /* The tester wanted to send a number of bytes. */
2567 trans_remaining = test_bytes;
2568 times_up = 1;
2569 }
2570
2571 /* The cpu_start routine will grab the current time and possibly */
2572 /* value of the idle counter for later use in measuring cpu */
2573 /* utilization and/or service demand and thruput. */
2574
2575 cpu_start(local_cpu_usage);
2576
2577#ifdef WANT_INTERVALS
2578 INTERVALS_INIT();
2579#endif /* WANT_INTERVALS */
2580
2581 /* We use an "OR" to control test execution. When the test is */
2582 /* controlled by time, the byte count check will always return false. */
2583 /* When the test is controlled by byte count, the time test will */
2584 /* always return false. When the test is finished, the whole */
2585 /* expression will go false and we will stop sending data. I think I */
2586 /* just arbitrarily decrement trans_remaining for the timed test, but */
2587 /* will not do that just yet... One other question is whether or not */
2588 /* the send buffer and the receive buffer should be the same buffer. */
2589
2590#ifdef WANT_DEMO
2591 if (demo_mode) {
2592 HIST_timestamp(demo_one_ptr);
2593 }
2594#endif
2595
2596 while ((!times_up) || (trans_remaining > 0)) {
2597 /* send the request. we assume that if we use a blocking socket, */
2598 /* the request will be sent at one shot. */
2599
2600#ifdef WANT_FIRST_BURST
2601 /* we can inject no more than request_cwnd, which will grow with
2602 time, and no more than first_burst_size. we don't use <= to
2603 account for the "regularly scheduled" send call. of course
2604 that makes it more a "max_outstanding_ than a
2605 "first_burst_size" but for now we won't fix the names. also,
2606 I suspect the extra check against < first_burst_size is
2607 redundant since later I expect to make sure that request_cwnd
2608 can never get larger than first_burst_size, but just at the
2609 moment I'm feeling like a belt and suspenders kind of
2610 programmer. raj 2006-01-30 */
2611 while ((first_burst_size > 0) &&
2612 (requests_outstanding < request_cwnd) &&
2613 (requests_outstanding < first_burst_size)) {
2614 if (debug) {
2615 fprintf(where,
2616 "injecting, req_outstndng %d req_cwnd %d burst %d\n",
2617 requests_outstanding,
2618 request_cwnd,
2619 first_burst_size);
2620 }
2621 if ((len = send(send_socket,
2622 send_ring->buffer_ptr,
2623 req_size,
2624 0)) != req_size) {
2625 /* we should never hit the end of the test in the first burst */
2626 perror("send_sdp_rr: initial burst data send error");
2627 exit(-1);
2628 }
2629 requests_outstanding += 1;
2630 }
2631
2632#endif /* WANT_FIRST_BURST */
2633
2634#ifdef WANT_HISTOGRAM
2635 if (verbosity > 1) {
2636 /* timestamp just before our call to send, and then again just
2637 after the receive raj 8/94 */
2638 /* but only if we are actually going to display one. raj
2639 2007-02-07 */
2640
2641 HIST_timestamp(&time_one);
2642 }
2643#endif /* WANT_HISTOGRAM */
2644
2645 if ((len = send(send_socket,
2646 send_ring->buffer_ptr,
2647 req_size,
2648 0)) != req_size) {
2649 if (SOCKET_EINTR(len) || (errno == 0)) {
2650 /* we hit the end of a */
2651 /* timed test. */
2652 timed_out = 1;
2653 break;
2654 }
2655 perror("send_sdp_rr: data send error");
2656 exit(1);
2657 }
2658 send_ring = send_ring->next;
2659
2660#ifdef WANT_FIRST_BURST
2661 requests_outstanding += 1;
2662#endif
2663
2664 /* receive the response */
2665 rsp_bytes_left = rsp_size;
2666 temp_message_ptr = recv_ring->buffer_ptr;
2667 while(rsp_bytes_left > 0) {
2668 if((rsp_bytes_recvd=recv(send_socket,
2669 temp_message_ptr,
2670 rsp_bytes_left,
2671 0)) == SOCKET_ERROR) {
2672 if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
2673 /* We hit the end of a timed test. */
2674 timed_out = 1;
2675 break;
2676 }
2677 perror("send_sdp_rr: data recv error");
2678 exit(1);
2679 }
2680 rsp_bytes_left -= rsp_bytes_recvd;
2681 temp_message_ptr += rsp_bytes_recvd;
2682 }
2683 recv_ring = recv_ring->next;
2684
2685#ifdef WANT_FIRST_BURST
2686 /* so, since we've gotten a response back, update the
2687 bookkeeping accordingly. there is one less request
2688 outstanding and we can put one more out there than before. */
2689 requests_outstanding -= 1;
2690 if (request_cwnd < first_burst_size) {
2691 request_cwnd += 1;
2692 if (debug) {
2693 fprintf(where,
2694 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
2695 request_cwnd,
2696 first_burst_size,
2697 requests_outstanding);
2698 }
2699 }
2700#endif
2701 if (timed_out) {
2702 /* we may have been in a nested while loop - we need */
2703 /* another call to break. */
2704 break;
2705 }
2706
2707#ifdef WANT_HISTOGRAM
2708 if (verbosity > 1) {
2709 HIST_timestamp(&time_two);
2710 HIST_add(time_hist,delta_micro(&time_one,&time_two));
2711 }
2712#endif /* WANT_HISTOGRAM */
2713
2714#ifdef WANT_DEMO
2715 DEMO_RR_INTERVAL(1);
2716#endif
2717
2718#ifdef WANT_INTERVALS
2719 INTERVALS_WAIT();
2720#endif /* WANT_INTERVALS */
2721
2722 nummessages++;
2723 if (trans_remaining) {
2724 trans_remaining--;
2725 }
2726
2727 if (debug > 3) {
2728 if ((nummessages % 100) == 0) {
2729 fprintf(where,
2730 "Transaction %d completed\n",
2731 nummessages);
2732 fflush(where);
2733 }
2734 }
2735 }
2736
2737 /* At this point we used to call shutdown on the data socket to be
2738 sure all the data was delivered, but this was not germane in a
2739 request/response test, and it was causing the tests to "hang"
2740 when they were being controlled by time. So, I have replaced
2741 this shutdown call with a call to close that can be found later
2742 in the procedure. */
2743
2744 /* this call will always give us the elapsed time for the test,
2745 and will also store-away the necessaries for cpu utilization */
2746
2747 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
2748 /* measured? how long */
2749 /* did we really run? */
2750
2751 if (!no_control) {
2752 /* Get the statistics from the remote end. The remote will have
2753 calculated CPU utilization. If it wasn't supposed to care, it
2754 will return obvious values. */
2755
2756 recv_response();
2757 if (!netperf_response.content.serv_errno) {
2758 if (debug)
2759 fprintf(where,"remote results obtained\n");
2760 }
2761 else {
2762 Set_errno(netperf_response.content.serv_errno);
2763 fprintf(where,"netperf: remote error %d",
2764 netperf_response.content.serv_errno);
2765 perror("");
2766 fflush(where);
2767 exit(1);
2768 }
2769 }
2770
2771 /* We now calculate what our throughput was for the test. */
2772
2773 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
2774 thruput = nummessages/elapsed_time;
2775
2776 if (local_cpu_usage || remote_cpu_usage) {
2777 /* We must now do a little math for service demand and cpu
2778 utilization for the system(s) Of course, some of the
2779 information might be bogus because there was no idle counter in
2780 the kernel(s). We need to make a note of this for the user's
2781 benefit... */
2782 if (local_cpu_usage) {
2783 local_cpu_utilization = calc_cpu_util(0.0);
2784 /* since calc_service demand is doing ms/Kunit we will
2785 multiply the number of transaction by 1024 to get "good"
2786 numbers */
2787 local_service_demand = calc_service_demand((double) nummessages*1024,
2788 0.0,
2789 0.0,
2790 0);
2791 }
2792 else {
2793 local_cpu_utilization = (float) -1.0;
2794 local_service_demand = (float) -1.0;
2795 }
2796
2797 if (remote_cpu_usage) {
2798 remote_cpu_utilization = sdp_rr_result->cpu_util;
2799 /* since calc_service demand is doing ms/Kunit we will
2800 multiply the number of transaction by 1024 to get "good"
2801 numbers */
2802 remote_service_demand = calc_service_demand((double) nummessages*1024,
2803 0.0,
2804 remote_cpu_utilization,
2805 sdp_rr_result->num_cpus);
2806 }
2807 else {
2808 remote_cpu_utilization = (float) -1.0;
2809 remote_service_demand = (float) -1.0;
2810 }
2811
2812 }
2813 else {
2814 /* we were not measuring cpu, for the confidence stuff, we */
2815 /* should make it -1.0 */
2816 local_cpu_utilization = (float) -1.0;
2817 local_service_demand = (float) -1.0;
2818 remote_cpu_utilization = (float) -1.0;
2819 remote_service_demand = (float) -1.0;
2820 }
2821
2822 /* at this point, we want to calculate the confidence information.
2823 if debugging is on, calculate_confidence will print-out the
2824 parameters we pass it */
2825
2826 calculate_confidence(confidence_iteration,
2827 elapsed_time,
2828 thruput,
2829 local_cpu_utilization,
2830 remote_cpu_utilization,
2831 local_service_demand,
2832 remote_service_demand);
2833
2834
2835 confidence_iteration++;
2836
2837 /* we are now done with the socket, so close it */
2838 close(send_socket);
2839
2840 }
2841
2842 retrieve_confident_values(&elapsed_time,
2843 &thruput,
2844 &local_cpu_utilization,
2845 &remote_cpu_utilization,
2846 &local_service_demand,
2847 &remote_service_demand);
2848
2849 /* We are now ready to print all the information. If the user has
2850 specified zero-level verbosity, we will just print the local
2851 service demand, or the remote service demand. If the user has
2852 requested verbosity level 1, he will get the basic "streamperf"
2853 numbers. If the user has specified a verbosity of greater than 1,
2854 we will display a veritable plethora of background information
2855 from outside of this block as it it not cpu_measurement
2856 specific... */
2857
2858 if (confidence < 0) {
2859 /* we did not hit confidence, but were we asked to look for it? */
2860 if (iteration_max > 1) {
2861 display_confidence();
2862 }
2863 }
2864
2865 if (local_cpu_usage || remote_cpu_usage) {
2866 local_cpu_method = format_cpu_method(cpu_method);
2867 remote_cpu_method = format_cpu_method(sdp_rr_result->cpu_method);
2868
2869 switch (verbosity) {
2870 case 0:
2871 if (local_cpu_usage) {
2872 fprintf(where,
2873 cpu_fmt_0,
2874 local_service_demand,
2875 local_cpu_method,
2876 ((print_headers) ||
2877 (result_brand == NULL)) ? "" : result_brand);
2878 }
2879 else {
2880 fprintf(where,
2881 cpu_fmt_0,
2882 remote_service_demand,
2883 remote_cpu_method,
2884 ((print_headers) ||
2885 (result_brand == NULL)) ? "" : result_brand);
2886 }
2887 break;
2888 case 1:
2889 case 2:
2890 if (print_headers) {
2891 fprintf(where,
2892 cpu_title,
2893 local_cpu_method,
2894 remote_cpu_method);
2895 }
2896
2897 fprintf(where,
2898 cpu_fmt_1_line_1, /* the format string */
2899 lss_size, /* local sendbuf size */
2900 lsr_size,
2901 req_size, /* how large were the requests */
2902 rsp_size, /* guess */
2903 elapsed_time, /* how long was the test */
2904 thruput,
2905 local_cpu_utilization, /* local cpu */
2906 remote_cpu_utilization, /* remote cpu */
2907 local_service_demand, /* local service demand */
2908 remote_service_demand, /* remote service demand */
2909 ((print_headers) ||
2910 (result_brand == NULL)) ? "" : result_brand);
2911 fprintf(where,
2912 cpu_fmt_1_line_2,
2913 rss_size,
2914 rsr_size);
2915 break;
2916 }
2917 }
2918 else {
2919 /* The tester did not wish to measure service demand. */
2920
2921 switch (verbosity) {
2922 case 0:
2923 fprintf(where,
2924 tput_fmt_0,
2925 thruput,
2926 ((print_headers) ||
2927 (result_brand == NULL)) ? "" : result_brand);
2928 break;
2929 case 1:
2930 case 2:
2931 if (print_headers) {
2932 fprintf(where,tput_title,format_units());
2933 }
2934
2935 fprintf(where,
2936 tput_fmt_1_line_1, /* the format string */
2937 lss_size,
2938 lsr_size,
2939 req_size, /* how large were the requests */
2940 rsp_size, /* how large were the responses */
2941 elapsed_time, /* how long did it take */
2942 thruput,
2943 ((print_headers) ||
2944 (result_brand == NULL)) ? "" : result_brand);
2945 fprintf(where,
2946 tput_fmt_1_line_2,
2947 rss_size, /* remote recvbuf size */
2948 rsr_size);
2949
2950 break;
2951 }
2952 }
2953
2954 /* it would be a good thing to include information about some of the */
2955 /* other parameters that may have been set for this test, but at the */
2956 /* moment, I do not wish to figure-out all the formatting, so I will */
2957 /* just put this comment here to help remind me that it is something */
2958 /* that should be done at a later time. */
2959
2960 /* how to handle the verbose information in the presence of */
2961 /* confidence intervals is yet to be determined... raj 11/94 */
2962 if (verbosity > 1) {
2963 /* The user wanted to know it all, so we will give it to him. */
2964 /* This information will include as much as we can find about */
2965 /* SDP statistics, the alignments of the sends and receives */
2966 /* and all that sort of rot... */
2967
2968 fprintf(where,
2969 ksink_fmt,
2970 local_send_align,
2971 remote_recv_offset,
2972 local_send_offset,
2973 remote_recv_offset);
2974
2975#ifdef WANT_HISTOGRAM
2976 fprintf(where,"\nHistogram of request/response times\n");
2977 fflush(where);
2978 HIST_report(time_hist);
2979#endif /* WANT_HISTOGRAM */
2980
2981 }
2982
2983}
2984 /* this routine implements the receive (netserver) side of a SDP_RR */
2985 /* test */
2986void
2987recv_sdp_rr()
2988{
2989
2990 struct ring_elt *send_ring;
2991 struct ring_elt *recv_ring;
2992
2993 struct addrinfo *local_res;
2994 char local_name[BUFSIZ];
2995 char port_buffer[PORTBUFSIZE];
2996
2997 struct sockaddr_in myaddr_in,
2998 peeraddr_in;
2999 SOCKET s_listen,s_data;
3000 netperf_socklen_t addrlen;
3001 char *temp_message_ptr;
3002 int trans_received;
3003 int trans_remaining;
3004 int bytes_sent;
3005 int request_bytes_recvd;
3006 int request_bytes_remaining;
3007 int timed_out = 0;
3008 int sock_closed = 0;
3009 float elapsed_time;
3010
3011 struct sdp_rr_request_struct *sdp_rr_request;
3012 struct sdp_rr_response_struct *sdp_rr_response;
3013 struct sdp_rr_results_struct *sdp_rr_results;
3014
3015 sdp_rr_request =
3016 (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data;
3017 sdp_rr_response =
3018 (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data;
3019 sdp_rr_results =
3020 (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data;
3021
3022 if (debug) {
3023 fprintf(where,"netserver: recv_sdp_rr: entered...\n");
3024 fflush(where);
3025 }
3026
3027 /* We want to set-up the listen socket with all the desired */
3028 /* parameters and then let the initiator know that all is ready. If */
3029 /* socket size defaults are to be used, then the initiator will have */
3030 /* sent us 0's. If the socket sizes cannot be changed, then we will */
3031 /* send-back what they are. If that information cannot be determined, */
3032 /* then we send-back -1's for the sizes. If things go wrong for any */
3033 /* reason, we will drop back ten yards and punt. */
3034
3035 /* If anything goes wrong, we want the remote to know about it. It */
3036 /* would be best if the error that the remote reports to the user is */
3037 /* the actual error we encountered, rather than some bogus unexpected */
3038 /* response type message. */
3039
3040 if (debug) {
3041 fprintf(where,"recv_sdp_rr: setting the response type...\n");
3042 fflush(where);
3043 }
3044
3045 netperf_response.content.response_type = SDP_RR_RESPONSE;
3046
3047 if (debug) {
3048 fprintf(where,"recv_sdp_rr: the response type is set...\n");
3049 fflush(where);
3050 }
3051
3052 /* allocate the recv and send rings with the requested alignments */
3053 /* and offsets. raj 7/94 */
3054 if (debug) {
3055 fprintf(where,"recv_sdp_rr: requested recv alignment of %d offset %d\n",
3056 sdp_rr_request->recv_alignment,
3057 sdp_rr_request->recv_offset);
3058 fprintf(where,"recv_sdp_rr: requested send alignment of %d offset %d\n",
3059 sdp_rr_request->send_alignment,
3060 sdp_rr_request->send_offset);
3061 fflush(where);
3062 }
3063
3064 /* at some point, these need to come to us from the remote system */
3065 if (send_width == 0) send_width = 1;
3066 if (recv_width == 0) recv_width = 1;
3067
3068 send_ring = allocate_buffer_ring(send_width,
3069 sdp_rr_request->response_size,
3070 sdp_rr_request->send_alignment,
3071 sdp_rr_request->send_offset);
3072
3073 recv_ring = allocate_buffer_ring(recv_width,
3074 sdp_rr_request->request_size,
3075 sdp_rr_request->recv_alignment,
3076 sdp_rr_request->recv_offset);
3077
3078
3079 /* Grab a socket to listen on, and then listen on it. */
3080
3081 if (debug) {
3082 fprintf(where,"recv_sdp_rr: grabbing a socket...\n");
3083 fflush(where);
3084 }
3085
3086 /* create_data_socket expects to find some things in the global */
3087 /* variables, so set the globals based on the values in the request. */
3088 /* once the socket has been created, we will set the response values */
3089 /* based on the updated value of those globals. raj 7/94 */
3090 lss_size_req = sdp_rr_request->send_buf_size;
3091 lsr_size_req = sdp_rr_request->recv_buf_size;
3092 loc_nodelay = sdp_rr_request->no_delay;
3093 loc_rcvavoid = sdp_rr_request->so_rcvavoid;
3094 loc_sndavoid = sdp_rr_request->so_sndavoid;
3095
3096 set_hostname_and_port(local_name,
3097 port_buffer,
3098 nf_to_af(sdp_rr_request->ipfamily),
3099 sdp_rr_request->port);
3100
3101 local_res = complete_addrinfo(local_name,
3102 local_name,
3103 port_buffer,
3104 nf_to_af(sdp_rr_request->ipfamily),
3105 SOCK_STREAM,
3106 IPPROTO_TCP,
3107 0);
3108
3109 /* fake things out by changing local_res->ai_family to AF_INET_SDP */
3110 local_res->ai_family = AF_INET_SDP;
3111 local_res->ai_protocol = 0;
3112 s_listen = create_data_socket(local_res);
3113
3114 if (s_listen == INVALID_SOCKET) {
3115 netperf_response.content.serv_errno = errno;
3116 send_response();
3117
3118 exit(1);
3119 }
3120
3121
3122#ifdef WIN32
3123 /* The test timer can fire during operations on the listening socket,
3124 so to make the start_timer below work we have to move
3125 it to close s_listen while we are blocked on accept. */
3126 win_kludge_socket2 = s_listen;
3127#endif
3128
3129
3130 /* Now, let's set-up the socket to listen for connections */
3131 if (listen(s_listen, 5) == SOCKET_ERROR) {
3132 netperf_response.content.serv_errno = errno;
3133 close(s_listen);
3134 send_response();
3135
3136 exit(1);
3137 }
3138
3139
3140 /* now get the port number assigned by the system */
3141 addrlen = sizeof(myaddr_in);
3142 if (getsockname(s_listen,
3143 (struct sockaddr *)&myaddr_in,
3144 &addrlen) == SOCKET_ERROR) {
3145 netperf_response.content.serv_errno = errno;
3146 close(s_listen);
3147 send_response();
3148
3149 exit(1);
3150 }
3151
3152 /* Now myaddr_in contains the port and the internet address this is */
3153 /* returned to the sender also implicitly telling the sender that the */
3154 /* socket buffer sizing has been done. */
3155
3156 sdp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
3157 netperf_response.content.serv_errno = 0;
3158
3159 /* But wait, there's more. If the initiator wanted cpu measurements, */
3160 /* then we must call the calibrate routine, which will return the max */
3161 /* rate back to the initiator. If the CPU was not to be measured, or */
3162 /* something went wrong with the calibration, we will return a 0.0 to */
3163 /* the initiator. */
3164
3165 sdp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
3166 sdp_rr_response->measure_cpu = 0;
3167
3168 if (sdp_rr_request->measure_cpu) {
3169 sdp_rr_response->measure_cpu = 1;
3170 sdp_rr_response->cpu_rate = calibrate_local_cpu(sdp_rr_request->cpu_rate);
3171 }
3172
3173
3174 /* before we send the response back to the initiator, pull some of */
3175 /* the socket parms from the globals */
3176 sdp_rr_response->send_buf_size = lss_size;
3177 sdp_rr_response->recv_buf_size = lsr_size;
3178 sdp_rr_response->no_delay = loc_nodelay;
3179 sdp_rr_response->so_rcvavoid = loc_rcvavoid;
3180 sdp_rr_response->so_sndavoid = loc_sndavoid;
3181 sdp_rr_response->test_length = sdp_rr_request->test_length;
3182 send_response();
3183
3184 addrlen = sizeof(peeraddr_in);
3185
3186 if ((s_data = accept(s_listen,
3187 (struct sockaddr *)&peeraddr_in,
3188 &addrlen)) == INVALID_SOCKET) {
3189 /* Let's just punt. The remote will be given some information */
3190 close(s_listen);
3191
3192 exit(1);
3193 }
3194
3195#ifdef KLUDGE_SOCKET_OPTIONS
3196 /* this is for those systems which *INCORRECTLY* fail to pass */
3197 /* attributes across an accept() call. Including this goes against */
3198 /* my better judgement :( raj 11/95 */
3199
3200 kludge_socket_options(s_data);
3201
3202#endif /* KLUDGE_SOCKET_OPTIONS */
3203
3204#ifdef WIN32
3205 /* this is used so the timer thread can close the socket out from */
3206 /* under us, which to date is the easiest/cleanest/least */
3207 /* Windows-specific way I can find to force the winsock calls to */
3208 /* return WSAEINTR with the test is over. anything that will run on */
3209 /* 95 and NT and is closer to what netperf expects from Unix signals */
3210 /* and such would be appreciated raj 1/96 */
3211 win_kludge_socket = s_data;
3212#endif /* WIN32 */
3213
3214 if (debug) {
3215 fprintf(where,"recv_sdp_rr: accept completes on the data connection.\n");
3216 fflush(where);
3217 }
3218
3219 /* Now it's time to start receiving data on the connection. We will */
3220 /* first grab the apropriate counters and then start grabbing. */
3221
3222 cpu_start(sdp_rr_request->measure_cpu);
3223
3224 /* The loop will exit when we hit the end of the test time, or when */
3225 /* we have exchanged the requested number of transactions. */
3226
3227 if (sdp_rr_request->test_length > 0) {
3228 times_up = 0;
3229 trans_remaining = 0;
3230 start_timer(sdp_rr_request->test_length + PAD_TIME);
3231 }
3232 else {
3233 times_up = 1;
3234 trans_remaining = sdp_rr_request->test_length * -1;
3235 }
3236
3237 trans_received = 0;
3238
3239 while ((!times_up) || (trans_remaining > 0)) {
3240 temp_message_ptr = recv_ring->buffer_ptr;
3241 request_bytes_remaining = sdp_rr_request->request_size;
3242 while(request_bytes_remaining > 0) {
3243 if((request_bytes_recvd=recv(s_data,
3244 temp_message_ptr,
3245 request_bytes_remaining,
3246 0)) == SOCKET_ERROR) {
3247 if (SOCKET_EINTR(request_bytes_recvd))
3248 {
3249 timed_out = 1;
3250 break;
3251 }
3252
3253 netperf_response.content.serv_errno = errno;
3254 send_response();
3255 exit(1);
3256 }
3257 else if( request_bytes_recvd == 0 ) {
3258 if (debug) {
3259 fprintf(where,"zero is my hero\n");
3260 fflush(where);
3261 }
3262 sock_closed = 1;
3263 break;
3264 }
3265 else {
3266 request_bytes_remaining -= request_bytes_recvd;
3267 temp_message_ptr += request_bytes_recvd;
3268 }
3269 }
3270
3271 recv_ring = recv_ring->next;
3272
3273 if ((timed_out) || (sock_closed)) {
3274 /* we hit the end of the test based on time - or the socket
3275 closed on us along the way. bail out of here now... */
3276 if (debug) {
3277 fprintf(where,"yo5\n");
3278 fflush(where);
3279 }
3280 break;
3281 }
3282
3283 /* Now, send the response to the remote */
3284 if((bytes_sent=send(s_data,
3285 send_ring->buffer_ptr,
3286 sdp_rr_request->response_size,
3287 0)) == SOCKET_ERROR) {
3288 if (SOCKET_EINTR(bytes_sent)) {
3289 /* the test timer has popped */
3290 timed_out = 1;
3291 fprintf(where,"yo6\n");
3292 fflush(where);
3293 break;
3294 }
3295 netperf_response.content.serv_errno = 992;
3296 send_response();
3297 exit(1);
3298 }
3299
3300 send_ring = send_ring->next;
3301
3302 trans_received++;
3303 if (trans_remaining) {
3304 trans_remaining--;
3305 }
3306 }
3307
3308
3309 /* The loop now exits due to timeout or transaction count being */
3310 /* reached */
3311
3312 cpu_stop(sdp_rr_request->measure_cpu,&elapsed_time);
3313
3314 stop_timer();
3315
3316 if (timed_out) {
3317 /* we ended the test by time, which was at least 2 seconds */
3318 /* longer than we wanted to run. so, we want to subtract */
3319 /* PAD_TIME from the elapsed_time. */
3320 elapsed_time -= PAD_TIME;
3321 }
3322
3323 /* send the results to the sender */
3324
3325 if (debug) {
3326 fprintf(where,
3327 "recv_sdp_rr: got %d transactions\n",
3328 trans_received);
3329 fflush(where);
3330 }
3331
3332 sdp_rr_results->bytes_received = (trans_received *
3333 (sdp_rr_request->request_size +
3334 sdp_rr_request->response_size));
3335 sdp_rr_results->trans_received = trans_received;
3336 sdp_rr_results->elapsed_time = elapsed_time;
3337 sdp_rr_results->cpu_method = cpu_method;
3338 sdp_rr_results->num_cpus = lib_num_loc_cpus;
3339 if (sdp_rr_request->measure_cpu) {
3340 sdp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
3341 }
3342
3343 if (debug) {
3344 fprintf(where,
3345 "recv_sdp_rr: test complete, sending results.\n");
3346 fflush(where);
3347 }
3348
3349 /* we are now done with the sockets */
3350 close(s_data);
3351 close(s_listen);
3352
3353 send_response();
3354
3355}
3356
3357
3358
3359void
3360print_sdp_usage()
3361{
3362
3363 printf("%s",sdp_usage);
3364 exit(1);
3365
3366}
3367void
3368scan_sdp_args(argc, argv)
3369 int argc;
3370 char *argv[];
3371
3372{
3373
3374#define SOCKETS_ARGS "b:DhH:I:L:m:M:P:r:s:S:V46"
3375
3376 extern char *optarg; /* pointer to option string */
3377
3378 int c;
3379
3380 char
3381 arg1[BUFSIZ], /* argument holders */
3382 arg2[BUFSIZ];
3383
3384 if (no_control) {
3385 fprintf(where,
3386 "The SDP tests do not know how to deal with no control tests\n");
3387 exit(-1);
3388 }
3389
3390 strncpy(local_data_port,"0",sizeof(local_data_port));
3391 strncpy(remote_data_port,"0",sizeof(remote_data_port));
3392
3393 /* Go through all the command line arguments and break them */
3394 /* out. For those options that take two parms, specifying only */
3395 /* the first will set both to that value. Specifying only the */
3396 /* second will leave the first untouched. To change only the */
3397 /* first, use the form "first," (see the routine break_args.. */
3398
3399 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
3400 switch (c) {
3401 case '?':
3402 case '4':
3403 remote_data_family = AF_INET;
3404 local_data_family = AF_INET;
3405 break;
3406 case '6':
3407#if defined(AF_INET6)
3408 remote_data_family = AF_INET6;
3409 local_data_family = AF_INET6;
3410#else
3411 fprintf(stderr,
3412 "This netperf was not compiled on an IPv6 capable host!\n");
3413 fflush(stderr);
3414 exit(-1);
3415#endif
3416 break;
3417 case 'h':
3418 print_sdp_usage();
3419 exit(1);
3420 case 'b':
3421#ifdef WANT_FIRST_BURST
3422 first_burst_size = atoi(optarg);
3423#else /* WANT_FIRST_BURST */
3424 printf("Initial request burst functionality not compiled-in!\n");
3425#endif /* WANT_FIRST_BURST */
3426 break;
3427 case 'D':
3428 /* set the nodelay flag */
3429 loc_nodelay = 1;
3430 rem_nodelay = 1;
3431 break;
3432 case 'H':
3433 break_args_explicit(optarg,arg1,arg2);
3434 if (arg1[0]) {
3435 /* make sure we leave room for the NULL termination boys and
3436 girls. raj 2005-02-82 */
3437 remote_data_address = malloc(strlen(arg1)+1);
3438 strncpy(remote_data_address,arg1,strlen(arg1));
3439 }
3440 if (arg2[0])
3441 remote_data_family = parse_address_family(arg2);
3442 break;
3443 case 'L':
3444 break_args_explicit(optarg,arg1,arg2);
3445 if (arg1[0]) {
3446 /* make sure we leave room for the NULL termination boys and
3447 girls. raj 2005-02-82 */
3448 local_data_address = malloc(strlen(arg1)+1);
3449 strncpy(local_data_address,arg1,strlen(arg1));
3450 }
3451 if (arg2[0])
3452 local_data_family = parse_address_family(arg2);
3453 break;
3454 case 'P':
3455 /* set the local and remote data port numbers for the tests to
3456 allow them to run through those blankety blank end-to-end
3457 breaking firewalls. raj 2004-06-15 */
3458 break_args(optarg,arg1,arg2);
3459 if (arg1[0])
3460 strncpy(local_data_port,arg1,sizeof(local_data_port));
3461 if (arg2[0])
3462 strncpy(remote_data_port,arg2,sizeof(remote_data_port));
3463 break;
3464 case 's':
3465 /* set local socket sizes */
3466 break_args(optarg,arg1,arg2);
3467 if (arg1[0])
3468 lss_size_req = convert(arg1);
3469 if (arg2[0])
3470 lsr_size_req = convert(arg2);
3471 break;
3472 case 'S':
3473 /* set remote socket sizes */
3474 break_args(optarg,arg1,arg2);
3475 if (arg1[0])
3476 rss_size_req = convert(arg1);
3477 if (arg2[0])
3478 rsr_size_req = convert(arg2);
3479 break;
3480 case 'r':
3481 /* set the request/response sizes */
3482 break_args(optarg,arg1,arg2);
3483 if (arg1[0])
3484 req_size = convert(arg1);
3485 if (arg2[0])
3486 rsp_size = convert(arg2);
3487 break;
3488 case 'm':
3489 /* set size of the buffer for each sent message */
3490 send_size = convert(optarg);
3491 break;
3492 case 'M':
3493 /* set the size of the buffer for each received message */
3494 recv_size = convert(optarg);
3495 break;
3496 case 't':
3497 /* set the test name */
3498 strcpy(test_name,optarg);
3499 break;
3500 case 'W':
3501 /* set the "width" of the user space data */
3502 /* buffer. This will be the number of */
3503 /* send_size buffers malloc'd in the */
3504 /* *_STREAM test. It may be enhanced to set */
3505 /* both send and receive "widths" but for now */
3506 /* it is just the sending *_STREAM. */
3507 send_width = convert(optarg);
3508 break;
3509 case 'V':
3510 /* we want to do copy avoidance and will set */
3511 /* it for everything, everywhere, if we really */
3512 /* can. of course, we don't know anything */
3513 /* about the remote... */
3514#ifdef SO_SND_COPYAVOID
3515 loc_sndavoid = 1;
3516#else
3517 loc_sndavoid = 0;
3518 printf("Local send copy avoidance not available.\n");
3519#endif
3520#ifdef SO_RCV_COPYAVOID
3521 loc_rcvavoid = 1;
3522#else
3523 loc_rcvavoid = 0;
3524 printf("Local recv copy avoidance not available.\n");
3525#endif
3526 rem_sndavoid = 1;
3527 rem_rcvavoid = 1;
3528 break;
3529 case 'N':
3530 /* this opton allows the user to set the number of
3531 * messages to send. This in effect modifies the test
3532 * time. If we know the message size, then the we can
3533 * express the test time as message_size * number_messages
3534 */
3535 msg_count = convert (optarg);
3536 if (msg_count > 0)
3537 test_time = 0;
3538 break;
3539 case 'B':
3540 non_block = 1;
3541 break;
3542 case 'T':
3543 num_associations = atoi(optarg);
3544 if (num_associations <= 1) {
3545 printf("Number of SDP associations must be >= 1\n");
3546 exit(1);
3547 }
3548 break;
3549 };
3550 }
3551}
3552
3553#endif /* WANT_SDP */