1 #include "netperf_version.h"
2
3 char netsh_id[]="\
4 @(#)netsh.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3pre";
5
6
7 /****************************************************************/
8 /* */
9 /* Global include files */
10 /* */
11 /****************************************************************/
12
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
17 #include <sys/types.h>
18 #ifndef WIN32
19 #include <unistd.h>
20 #ifndef __VMS
21 #include <sys/ipc.h>
22 #endif /* __VMS */
23 #endif /* WIN32 */
24 #include <fcntl.h>
25 #ifndef WIN32
26 #include <errno.h>
27 #include <signal.h>
28 #endif /* !WIN32 */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 /* the following four includes should not be needed ?*/
33 #ifndef WIN32
34 #include <sys/time.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <netdb.h>
38 #else
39 #include <time.h>
40 #include <winsock2.h>
41 #define netperf_socklen_t socklen_t
42 #endif
43
44 #ifndef STRINGS
45 #include <string.h>
46 #else /* STRINGS */
47 #include <strings.h>
48 #endif /* STRINGS */
49
50 #ifdef WIN32
51 extern int getopt(int , char **, char *) ;
52 #else
53 double atof(const char *);
54 #endif /* WIN32 */
55
56 /**********************************************************************/
57 /* */
58 /* Local Include Files */
59 /* */
60 /**********************************************************************/
61
62 #define NETSH
63 #include "netsh.h"
64 #include "netlib.h"
65 #include "nettest_bsd.h"
66
67 #ifdef WANT_UNIX
68 #include "nettest_unix.h"
69 #ifndef WIN32
70 #include "sys/socket.h"
71 #endif /* !WIN32 */
72 #endif /* WANT_UNIX */
73
74 #ifdef WANT_XTI
75 #include "nettest_xti.h"
76 #endif /* WANT_XTI */
77
78 #ifdef WANT_DLPI
79 #include "nettest_dlpi.h"
80 #endif /* WANT_DLPI */
81
82 #ifdef WANT_SCTP
83 #include "nettest_sctp.h"
84 #endif
85
86
87 /************************************************************************/
88 /* */
89 /* Global constants and macros */
90 /* */
91 /************************************************************************/
92
93 /* Some of the args take optional parameters. Since we are using */
94 /* getopt to parse the command line, we will tell getopt that they do */
95 /* not take parms, and then look for them ourselves */
96 #define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdDf:F:H:hi:I:k:K:l:L:n:NO:o:P:p:rt:T:v:VW:w:46"
97
98 /************************************************************************/
99 /* */
100 /* Extern variables */
101 /* */
102 /************************************************************************/
103
104 /*
105 extern int errno;
106 extern char *sys_errlist[ ];
107 extern int sys_nerr;
108 */
109
110 /************************************************************************/
111 /* */
112 /* Global variables */
113 /* */
114 /************************************************************************/
115
116 /* some names and such */
117 char *program; /* program invocation name */
118 char username[BUFSIZ]; /* login name of user */
119 char cmd_file[BUFSIZ]; /* name of the commands file */
120
121 /* stuff to say where this test is going */
122 char host_name[HOSTNAMESIZE]; /* remote host name or ip addr */
123 char local_host_name[HOSTNAMESIZE]; /* local hostname or ip */
124 char test_name[BUFSIZ]; /* which test to run */
125 char test_port[PORTBUFSIZE]; /* where is the test waiting */
126 char local_test_port[PORTBUFSIZE]; /* from whence we should start */
127 int address_family; /* which address family remote */
128 int local_address_family; /* which address family local */
129
130 /* the source of data for filling the buffers */
131 char fill_file[BUFSIZ];
132
133 /* output controlling variables */
134 int
135 debug, /* debugging level */
136 print_headers, /* do/don't display headers */
137 verbosity; /* verbosity level */
138
139 /* When specified with -B, this will be displayed at the end of the line
140 for output that does not include the test header. mostly this is
141 to help identify a specific netperf result when concurrent netperfs
142 are run. raj 2006-02-01 */
143 char *result_brand = NULL;
144
145 /* cpu variables */
146 int
147 local_cpu_usage, /* you guessed it */
148 remote_cpu_usage; /* still right ! */
149
150 float
151 local_cpu_rate,
152 remote_cpu_rate;
153
154 int
155 shell_num_cpus=1;
156
157 /* the end-test conditions for the tests - either transactions, bytes, */
158 /* or time. different vars used for clarity - space is cheap ;-) */
159 int
160 test_time, /* test ends by time */
161 test_len_ticks, /* how many times will the timer go off before */
162 /* the test is over? */
163 test_bytes, /* test ends on byte count */
164 test_trans; /* test ends on tran count */
165
166 /* the alignment conditions for the tests */
167 int
168 local_recv_align, /* alignment for local receives */
169 local_send_align, /* alignment for local sends */
170 local_send_offset = 0,
171 local_recv_offset = 0,
172 remote_recv_align, /* alignment for remote receives */
173 remote_send_align, /* alignment for remote sends */
174 remote_send_offset = 0,
175 remote_recv_offset = 0;
176
177 #if defined(WANT_INTERVALS) || defined(WANT_DEMO)
178 int
179 interval_usecs,
180 interval_wate,
181 interval_burst;
182
183 int demo_mode; /* are we actually in demo mode? */
184 double demo_interval = 1000000.0; /* what is the desired interval to
185 display interval results. default
186 is one second in units of
187 microseconds */
188 double demo_units = 0.0; /* what is our current best guess as
189 to how many work units must be
190 done to be near the desired
191 reporting interval? */
192
193 double units_this_tick;
194 #endif
195
196 #ifdef DIRTY
197 int loc_dirty_count;
198 int loc_clean_count;
199 int rem_dirty_count;
200 int rem_clean_count;
201 #endif /* DIRTY */
202
203 /* some of the vairables for confidence intervals... */
204
205 int confidence_level;
206 int iteration_min;
207 int iteration_max;
208 int result_confidence_only = 0;
209
210 double interval;
211
212 /* stuff to control the "width" of the buffer rings for sending and */
213 /* receiving data */
214 int send_width;
215 int recv_width;
216
217 /* address family */
218 int af = AF_INET;
219
220 /* did someone request processor affinity? */
221 int cpu_binding_requested = 0;
222
223 /* are we not establishing a control connection? */
224 int no_control = 0;
225
226 char netserver_usage[] = "\n\
227 Usage: netserver [options] \n\
228 \n\
229 Options:\n\
230 -h Display this text\n\
231 -d Increase debugging output\n\
232 -L name,family Use name to pick listen address and family for family\n\
233 -p portnum Listen for connect requests on portnum.\n\
234 -4 Do IPv4\n\
235 -6 Do IPv6\n\
236 -v verbosity Specify the verbosity level\n\
237 -V Display version information and exit\n\
238 \n";
239
240 /* netperf_usage done as two concatenated strings to make the MS
241 compiler happy when compiling for x86_32. fix from Spencer
242 Frink. */
243
244 char netperf_usage1[] = "\n\
245 Usage: netperf [global options] -- [test options] \n\
246 \n\
247 Global options:\n\
248 -a send,recv Set the local send,recv buffer alignment\n\
249 -A send,recv Set the remote send,recv buffer alignment\n\
250 -B brandstr Specify a string to be emitted with brief output\n\
251 -c [cpu_rate] Report local CPU usage\n\
252 -C [cpu_rate] Report remote CPU usage\n\
253 -d Increase debugging output\n\
254 -D [secs,units] * Display interim results at least every secs seconds\n\
255 using units as the initial guess for units per second\n\
256 -f G|M|K|g|m|k Set the output units\n\
257 -F fill_file Pre-fill buffers with data from fill_file\n\
258 -h Display this text\n\
259 -H name|ip,fam * Specify the target machine and/or local ip and family\n\
260 -i max,min Specify the max and min number of iterations (15,1)\n\
261 -I lvl[,intvl] Specify confidence level (95 or 99) (99) \n\
262 and confidence interval in percentage (10)\n\
263 -l testlen Specify test duration (>0 secs) (<0 bytes|trans)\n\
264 -L name|ip,fam * Specify the local ip|name and address family\n\
265 -o send,recv Set the local send,recv buffer offsets\n\
266 -O send,recv Set the remote send,recv buffer offset\n\
267 -n numcpu Set the number of processors for CPU util\n\
268 -N Establish no control connection, do 'send' side only\n\
269 -p port,lport* Specify netserver port number and/or local port\n\
270 -P 0|1 Don't/Do display test headers\n\
271 -r Allow confidence to be hit on result only\n\
272 -t testname Specify test to perform\n\
273 -T lcpu,rcpu Request netperf/netserver be bound to local/remote cpu\n\
274 -v verbosity Specify the verbosity level\n\
275 -W send,recv Set the number of send,recv buffers\n\
276 -v level Set the verbosity level (default 1, min 0)\n\
277 -V Display the netperf version and exit\n";
278
279 char netperf_usage2[] = "\n\
280 For those options taking two parms, at least one must be specified;\n\
281 specifying one value without a comma will set both parms to that\n\
282 value, specifying a value with a leading comma will set just the second\n\
283 parm, a value with a trailing comma will set just the first. To set\n\
284 each parm to unique values, specify both and separate them with a\n\
285 comma.\n\
286 \n"
287 "* For these options taking two parms, specifying one value with no comma\n\
288 will only set the first parms and will leave the second at the default\n\
289 value. To set the second value it must be preceded with a comma or be a\n\
290 comma-separated pair. This is to retain previous netperf behaviour.\n";
291
292
293 /* This routine will return the two arguments to the calling routine. */
294 /* If the second argument is not specified, and there is no comma, */
295 /* then the value of the second argument will be the same as the */
296 /* value of the first. If there is a comma, then the value of the */
297 /* second argument will be the value of the second argument ;-) */
298 void
break_args(char * s,char * arg1,char * arg2)299 break_args(char *s, char *arg1, char *arg2)
300
301 {
302 char *ns;
303 ns = strchr(s,',');
304 if (ns) {
305 /* there was a comma arg2 should be the second arg*/
306 *ns++ = '\0';
307 while ((*arg2++ = *ns++) != '\0');
308 }
309 else {
310 /* there was not a comma, we can use ns as a temp s */
311 /* and arg2 should be the same value as arg1 */
312 ns = s;
313 while ((*arg2++ = *ns++) != '\0');
314 };
315 while ((*arg1++ = *s++) != '\0');
316 }
317
318 /* break_args_explicit
319
320 this routine is somewhat like break_args in that it will separate a
321 pair of comma-separated values. however, if there is no comma,
322 this version will not ass-u-me that arg2 should be the same as
323 arg1. raj 2005-02-04 */
324 void
break_args_explicit(char * s,char * arg1,char * arg2)325 break_args_explicit(char *s, char *arg1, char *arg2)
326
327 {
328 char *ns;
329 ns = strchr(s,',');
330 if (ns) {
331 /* there was a comma arg2 should be the second arg*/
332 *ns++ = '\0';
333 while ((*arg2++ = *ns++) != '\0');
334 }
335 else {
336 /* there was not a comma, so we should make sure that arg2 is \0
337 lest something become confused. raj 2005-02-04 */
338 *arg2 = '\0';
339 };
340 while ((*arg1++ = *s++) != '\0');
341
342 }
343
344 /* given a string with possible values for setting an address family,
345 convert that into one of the AF_mumble values - AF_INET, AF_INET6,
346 AF_UNSPEC as apropriate. the family_string is compared in a
347 case-insensitive manner */
348
349 int
parse_address_family(char family_string[])350 parse_address_family(char family_string[])
351 {
352
353 char temp[10]; /* gotta love magic constants :) */
354
355 strncpy(temp,family_string,10);
356
357 if (debug) {
358 fprintf(where,
359 "Attempting to parse address family from %s derived from %s\n",
360 temp,
361 family_string);
362 }
363 #if defined(AF_INET6)
364 if (strstr(temp,"6")) {
365 return(AF_INET6);
366 }
367 #endif
368 if (strstr(temp,"inet") ||
369 strstr(temp,"4")) {
370 return(AF_INET);
371 }
372 if (strstr(temp,"unspec") ||
373 strstr(temp,"0")) {
374 return(AF_UNSPEC);
375 }
376 fprintf(where,
377 "WARNING! %s not recognized as an address family, using AF_UNPSEC\n",
378 family_string);
379 fprintf(where,
380 "Are you sure netperf was configured for that address family?\n");
381 fflush(where);
382 return(AF_UNSPEC);
383 }
384
385
386 void
set_defaults()387 set_defaults()
388 {
389
390 /* stuff to say where this test is going */
391 strcpy(host_name,""); /* remote host name or ip addr */
392 strcpy(local_host_name,""); /* we want it to be INADDR_ANY */
393 strcpy(test_name,"TCP_STREAM"); /* which test to run */
394 strncpy(test_port,"12865",PORTBUFSIZE); /* where is the test waiting */
395 strncpy(local_test_port,"0",PORTBUFSIZE);/* INPORT_ANY as it were */
396 address_family = AF_UNSPEC;
397 local_address_family = AF_UNSPEC;
398
399 /* output controlling variables */
400 debug = 0;/* debugging level */
401 print_headers = 1;/* do print test headers */
402 verbosity = 1;/* verbosity level */
403 /* cpu variables */
404 local_cpu_usage = 0;/* measure local cpu */
405 remote_cpu_usage = 0;/* what do you think ;-) */
406
407 local_cpu_rate = (float)0.0;
408 remote_cpu_rate = (float)0.0;
409
410 /* the end-test conditions for the tests - either transactions, bytes, */
411 /* or time. different vars used for clarity - space is cheap ;-) */
412 test_time = 10; /* test ends by time */
413 test_bytes = 0; /* test ends on byte count */
414 test_trans = 0; /* test ends on tran count */
415
416 /* the alignment conditions for the tests */
417 local_recv_align = 8; /* alignment for local receives */
418 local_send_align = 8; /* alignment for local sends */
419 remote_recv_align = 8; /* alignment for remote receives*/
420 remote_send_align = 8; /* alignment for remote sends */
421
422 #ifdef WANT_INTERVALS
423 /* rate controlling stuff */
424 interval_usecs = 0;
425 interval_wate = 1;
426 interval_burst = 0;
427 #endif /* WANT_INTERVALS */
428
429 #ifdef DIRTY
430 /* dirty and clean cache stuff */
431 loc_dirty_count = 0;
432 loc_clean_count = 0;
433 rem_dirty_count = 0;
434 rem_clean_count = 0;
435 #endif /* DIRTY */
436
437 /* some of the vairables for confidence intervals... */
438
439 confidence_level = 99;
440 iteration_min = 1;
441 iteration_max = 1;
442 interval = 0.05; /* five percent? */
443
444 no_control = 0;
445 strcpy(fill_file,"");
446 }
447
448
449 void
print_netserver_usage()450 print_netserver_usage()
451 {
452 fwrite(netserver_usage, sizeof(char), strlen(netserver_usage), stderr);
453 }
454
455
456 void
print_netperf_usage()457 print_netperf_usage()
458 {
459 fwrite(netperf_usage1, sizeof(char), strlen(netperf_usage1), stderr);
460 fwrite(netperf_usage2, sizeof(char), strlen(netperf_usage2), stderr);
461 }
462
463 void
scan_cmd_line(int argc,char * argv[])464 scan_cmd_line(int argc, char *argv[])
465 {
466 extern int optind; /* index of first unused arg */
467 extern char *optarg; /* pointer to option string */
468
469 int c;
470
471 char arg1[BUFSIZ], /* argument holders */
472 arg2[BUFSIZ];
473
474 program = (char *)malloc(strlen(argv[0]) + 1);
475 if (program == NULL) {
476 printf("malloc(%zu) failed!\n", strlen(argv[0]) + 1);
477 exit(1);
478 }
479 strcpy(program, argv[0]);
480
481 /* Go through all the command line arguments and break them */
482 /* out. For those options that take two parms, specifying only */
483 /* the first will set both to that value. Specifying only the */
484 /* second will leave the first untouched. To change only the */
485 /* first, use the form first, (see the routine break_args.. */
486
487 while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
488 switch (c) {
489 case '?':
490 case 'h':
491 print_netperf_usage();
492 exit(1);
493 case 'a':
494 /* set local alignments */
495 break_args(optarg,arg1,arg2);
496 if (arg1[0]) {
497 local_send_align = convert(arg1);
498 }
499 if (arg2[0])
500 local_recv_align = convert(arg2);
501 break;
502 case 'A':
503 /* set remote alignments */
504 break_args(optarg,arg1,arg2);
505 if (arg1[0]) {
506 remote_send_align = convert(arg1);
507 }
508 if (arg2[0])
509 remote_recv_align = convert(arg2);
510 break;
511 case 'c':
512 /* measure local cpu usage please. the user */
513 /* may have specified the cpu rate as an */
514 /* optional parm */
515 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
516 /* there was an optional parm */
517 local_cpu_rate = (float)atof(argv[optind]);
518 optind++;
519 }
520 local_cpu_usage++;
521 break;
522 case 'C':
523 /* measure remote cpu usage please */
524 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
525 /* there was an optional parm */
526 remote_cpu_rate = (float)atof(argv[optind]);
527 optind++;
528 }
529 remote_cpu_usage++;
530 break;
531 case 'd':
532 debug++;
533 break;
534 case 'D':
535 #if (defined WANT_DEMO)
536 demo_mode++;
537 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
538 /* there was an optional parm */
539 break_args_explicit(argv[optind],arg1,arg2);
540 optind++;
541 if (arg1[0]) {
542 demo_interval = atof(arg1) * 1000000.0;
543 }
544 if (arg2[0]) {
545 demo_units = convert(arg2);
546 }
547 }
548 #else
549 printf("Sorry, Demo Mode not configured into this netperf.\n");
550 printf("please consider reconfiguring netperf with\n");
551 printf("--enable-demo=yes and recompiling\n");
552 #endif
553 break;
554 case 'f':
555 /* set the thruput formatting */
556 libfmt = *optarg;
557 break;
558 case 'F':
559 /* set the fill_file variable for pre-filling buffers */
560 strcpy(fill_file,optarg);
561 break;
562 case 'i':
563 /* set the iterations min and max for confidence intervals */
564 break_args(optarg,arg1,arg2);
565 if (arg1[0]) {
566 iteration_max = convert(arg1);
567 }
568 if (arg2[0] ) {
569 iteration_min = convert(arg2);
570 }
571 /* if the iteration_max is < iteration_min make iteration_max
572 equal iteration_min */
573 if (iteration_max < iteration_min) iteration_max = iteration_min;
574 /* limit minimum to 3 iterations */
575 if (iteration_max < 3) iteration_max = 3;
576 if (iteration_min < 3) iteration_min = 3;
577 /* limit maximum to 30 iterations */
578 if (iteration_max > 30) iteration_max = 30;
579 if (iteration_min > 30) iteration_min = 30;
580 break;
581 case 'I':
582 /* set the confidence level (95 or 99) and width */
583 break_args(optarg,arg1,arg2);
584 if (arg1[0]) {
585 confidence_level = convert(arg1);
586 }
587 if((confidence_level != 95) && (confidence_level != 99)){
588 printf("Only 95%% and 99%% confidence level is supported\n");
589 exit(1);
590 }
591 if (arg2[0] ) {
592 interval = (double) convert(arg2)/100;
593 }
594 /* make sure that iteration_min and iteration_max are at least
595 at a reasonable default value. if a -i option has previously
596 been parsed, these will no longer be 1, so we can check
597 against 1 */
598 if (iteration_min == 1) iteration_min = 3;
599 if (iteration_max == 1) iteration_max = 10;
600
601 break;
602 case 'k':
603 /* local dirty and clean counts */
604 #ifdef DIRTY
605 break_args(optarg,arg1,arg2);
606 if (arg1[0]) {
607 loc_dirty_count = convert(arg1);
608 }
609 if (arg2[0] ) {
610 loc_clean_count = convert(arg2);
611 }
612 #else
613 printf("I don't know how to get dirty.\n");
614 #endif /* DIRTY */
615 break;
616 case 'K':
617 /* remote dirty and clean counts */
618 #ifdef DIRTY
619 break_args(optarg,arg1,arg2);
620 if (arg1[0]) {
621 rem_dirty_count = convert(arg1);
622 }
623 if (arg2[0] ) {
624 rem_clean_count = convert(arg2);
625 }
626 #else
627 printf("I don't know how to get dirty.\n");
628 #endif /* DIRTY */
629 break;
630 case 'n':
631 shell_num_cpus = atoi(optarg);
632 break;
633 case 'N':
634 no_control = 1;
635 break;
636 case 'o':
637 /* set the local offsets */
638 break_args(optarg,arg1,arg2);
639 if (arg1[0])
640 local_send_offset = convert(arg1);
641 if (arg2[0])
642 local_recv_offset = convert(arg2);
643 break;
644 case 'O':
645 /* set the remote offsets */
646 break_args(optarg,arg1,arg2);
647 if (arg1[0])
648 remote_send_offset = convert(arg1);
649 if (arg2[0])
650 remote_recv_offset = convert(arg2);
651 break;
652 case 'P':
653 /* to print or not to print, that is */
654 /* the header question */
655 print_headers = convert(optarg);
656 break;
657 case 'r':
658 /* the user wishes that we declare confidence when hit on the
659 result even if not yet reached on CPU utilization. only
660 meaningful if cpu util is enabled */
661 result_confidence_only = 1;
662 break;
663 case 't':
664 /* set the test name */
665 strcpy(test_name,optarg);
666 break;
667 case 'T':
668 /* We want to set the processor on which netserver or netperf */
669 /* will run */
670 break_args(optarg,arg1,arg2);
671 if (arg1[0]) {
672 local_proc_affinity = convert(arg1);
673 bind_to_specific_processor(local_proc_affinity,0);
674 }
675 if (arg2[0]) {
676 remote_proc_affinity = convert(arg2);
677 }
678 cpu_binding_requested = 1;
679 break;
680 case 'W':
681 /* set the "width" of the user space data buffer ring. This will */
682 /* be the number of send_size buffers malloc'd in the tests */
683 break_args(optarg,arg1,arg2);
684 if (arg1[0])
685 send_width = convert(arg1);
686 if (arg2[0])
687 recv_width = convert(arg2);
688 break;
689 case 'l':
690 /* determine test end conditions */
691 /* assume a timed test */
692 test_time = convert(optarg);
693 test_bytes = test_trans = 0;
694 if (test_time < 0) {
695 test_bytes = -1 * test_time;
696 test_trans = test_bytes;
697 test_time = 0;
698 }
699 break;
700 case 'v':
701 /* say how much to say */
702 verbosity = convert(optarg);
703 break;
704 case 'p':
705 /* specify an alternate port number we use break_args_explicit
706 here to maintain backwards compatibility with previous
707 generations of netperf where having a single value did not
708 set both remote _and_ local port number. raj 2005-02-04 */
709 break_args_explicit(optarg,arg1,arg2);
710 if (arg1[0])
711 strncpy(test_port,arg1,PORTBUFSIZE);
712 if (arg2[0])
713 strncpy(local_test_port,arg2,PORTBUFSIZE);
714 break;
715 case 'H':
716 /* save-off the host identifying information, use
717 break_args_explicit since passing just one value should not
718 set both */
719 break_args_explicit(optarg,arg1,arg2);
720 if (arg1[0])
721 strncpy(host_name,arg1,sizeof(host_name));
722 if (arg2[0])
723 address_family = parse_address_family(arg2);
724 break;
725 case 'L':
726 /* save-off the local control socket addressing information. use
727 break_args_explicit since passing just one value should not
728 set both */
729 break_args_explicit(optarg,arg1,arg2);
730 if (arg1[0])
731 strncpy(local_host_name,arg1,sizeof(local_host_name));
732 if (arg2[0])
733 local_address_family = parse_address_family(arg2);
734 break;
735 case 'w':
736 /* We want to send requests at a certain wate. */
737 /* Remember that there are 1000000 usecs in a */
738 /* second, and that the packet rate is */
739 /* expressed in packets per millisecond. */
740 #ifdef WANT_INTERVALS
741 interval_usecs = convert_timespec(optarg);
742 interval_wate = interval_usecs / 1000;
743 #else
744 fprintf(where,
745 "Packet rate control is not compiled in.\n");
746 #endif
747 break;
748 case 'b':
749 /* we want to have a burst so many packets per */
750 /* interval. */
751 #ifdef WANT_INTERVALS
752 interval_burst = convert(optarg);
753 #else
754 fprintf(where,
755 "Packet burst size is not compiled in. \n");
756 #endif /* WANT_INTERVALS */
757 break;
758 case 'B':
759 result_brand = malloc(strlen(optarg)+1);
760 if (NULL != result_brand) {
761 strcpy(result_brand,optarg);
762 }
763 else {
764 fprintf(where,
765 "Unable to malloc space for result brand\n");
766 }
767 break;
768 case '4':
769 address_family = AF_INET;
770 local_address_family = AF_INET;
771 break;
772 case '6':
773 #if defined(AF_INET6)
774 address_family = AF_INET6;
775 local_address_family = AF_INET6;
776 #else
777 printf("This netperf was not compiled on an IPv6 capable system!\n");
778 exit(-1);
779 #endif
780 break;
781 case 'V':
782 printf("Netperf version %s\n",NETPERF_VERSION);
783 exit(0);
784 break;
785 };
786 }
787 /* ok, what should our default hostname and local binding info be?
788 */
789 if ('\0' == host_name[0]) {
790 /* host_name was not set */
791 switch (address_family) {
792 case AF_INET:
793 strcpy(host_name,"localhost");
794 break;
795 case AF_UNSPEC:
796 /* what to do here? case it off the local_address_family I
797 suppose */
798 switch (local_address_family) {
799 case AF_INET:
800 case AF_UNSPEC:
801 strcpy(host_name,"localhost");
802 break;
803 #if defined(AF_INET6)
804 case AF_INET6:
805 strcpy(host_name,"::1");
806 break;
807 #endif
808 default:
809 printf("Netperf does not understand %d as an address family\n",
810 address_family);
811 exit(-1);
812 }
813 break;
814 #if defined(AF_INET6)
815 case AF_INET6:
816 strcpy(host_name,"::1");
817 break;
818 #endif
819 default:
820 printf("Netperf does not understand %d as an address family\n",
821 address_family);
822 exit(-1);
823 }
824 }
825
826 /* now, having established the name to which the control will
827 connect, from what should it come? */
828 if ('\0' == local_host_name[0]) {
829 switch (local_address_family) {
830 case AF_INET:
831 strcpy(local_host_name,"0.0.0.0");
832 break;
833 case AF_UNSPEC:
834 switch (address_family) {
835 case AF_INET:
836 case AF_UNSPEC:
837 strcpy(local_host_name,"0.0.0.0");
838 break;
839 #if defined(AF_INET6)
840 case AF_INET6:
841 strcpy(local_host_name,"::0");
842 break;
843 #endif
844 default:
845 printf("Netperf does not understand %d as an address family\n",
846 address_family);
847 exit(-1);
848 }
849 break;
850 #if defined(AF_INET6)
851 case AF_INET6:
852 strcpy(local_host_name,"::0");
853 break;
854 #endif
855 default:
856 printf("Netperf does not understand %d as an address family\n",
857 address_family);
858 exit(-1);
859 }
860 }
861
862 /* so, if we aren't even going to establish a control connection we
863 should set certain "remote" settings to reflect this, regardless
864 of what else may have been set on the command line */
865 if (no_control) {
866 remote_recv_align = -1;
867 remote_send_align = -1;
868 remote_send_offset = -1;
869 remote_recv_offset = -1;
870 remote_cpu_rate = (float)-1.0;
871 remote_cpu_usage = 0;
872 }
873
874 /* parsing test-specific options used to be conditional on there
875 being a "--" in the option stream. however, some of the tests
876 have other initialization happening in their "scan" routines so we
877 want to call them regardless. raj 2005-02-08 */
878 if ((strcasecmp(test_name,"TCP_STREAM") == 0) ||
879 #ifdef HAVE_ICSC_EXS
880 (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
881 #endif /* HAVE_ICSC_EXS */
882 #ifdef HAVE_SENDFILE
883 (strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
884 #endif /* HAVE_SENDFILE */
885 (strcasecmp(test_name,"TCP_MAERTS") == 0) ||
886 (strcasecmp(test_name,"TCP_RR") == 0) ||
887 (strcasecmp(test_name,"TCP_CRR") == 0) ||
888 (strcasecmp(test_name,"TCP_CC") == 0) ||
889 #ifdef DO_1644
890 (strcasecmp(test_name,"TCP_TRR") == 0) ||
891 #endif /* DO_1644 */
892 #ifdef DO_NBRR
893 (strcasecmp(test_name,"TCP_TRR") == 0) ||
894 #endif /* DO_NBRR */
895 (strcasecmp(test_name,"UDP_STREAM") == 0) ||
896 (strcasecmp(test_name,"UDP_RR") == 0))
897 {
898 scan_sockets_args(argc, argv);
899 }
900
901 #ifdef WANT_DLPI
902 else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
903 (strcasecmp(test_name,"DLCL_RR") == 0) ||
904 (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
905 (strcasecmp(test_name,"DLCL_STREAM") == 0))
906 {
907 scan_dlpi_args(argc, argv);
908 }
909 #endif /* WANT_DLPI */
910
911 #ifdef WANT_UNIX
912 else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
913 (strcasecmp(test_name,"DG_RR") == 0) ||
914 (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
915 (strcasecmp(test_name,"DG_STREAM") == 0))
916 {
917 scan_unix_args(argc, argv);
918 }
919 #endif /* WANT_UNIX */
920
921 #ifdef WANT_XTI
922 else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
923 (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
924 (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
925 (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
926 {
927 scan_xti_args(argc, argv);
928 }
929 #endif /* WANT_XTI */
930
931 #ifdef WANT_SCTP
932 else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
933 (strcasecmp(test_name,"SCTP_RR") == 0) ||
934 (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
935 (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
936 {
937 scan_sctp_args(argc, argv);
938 }
939 #endif
940
941 #ifdef WANT_SDP
942 else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
943 (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
944 (strcasecmp(test_name,"SDP_RR") == 0))
945 {
946 scan_sdp_args(argc, argv);
947 }
948 #endif
949
950 /* what is our default value for the output units? if the test
951 name contains "RR" or "rr" or "Rr" or "rR" then the default is
952 'x' for transactions. otherwise it is 'm' for megabits
953 (10^6) */
954
955 if ('?' == libfmt) {
956 /* we use a series of strstr's here because not everyone has
957 strcasestr and I don't feel like up or downshifting text */
958 if ((strstr(test_name,"RR")) ||
959 (strstr(test_name,"rr")) ||
960 (strstr(test_name,"Rr")) ||
961 (strstr(test_name,"rR"))) {
962 libfmt = 'x';
963 }
964 else {
965 libfmt = 'm';
966 }
967 }
968 else if ('x' == libfmt) {
969 /* now, a format of 'x' makes no sense for anything other than
970 an RR test. if someone has been silly enough to try to set
971 that, we will reset it silently to default - namely 'm' */
972 if ((strstr(test_name,"RR") == NULL) &&
973 (strstr(test_name,"rr") == NULL) &&
974 (strstr(test_name,"Rr") == NULL) &&
975 (strstr(test_name,"rR") == NULL)) {
976 libfmt = 'm';
977 }
978 }
979 }
980
981
982 void
dump_globals()983 dump_globals()
984 {
985 printf("Program name: %s\n", program);
986 printf("Local send alignment: %d\n",local_send_align);
987 printf("Local recv alignment: %d\n",local_recv_align);
988 printf("Remote send alignment: %d\n",remote_send_align);
989 printf("Remote recv alignment: %d\n",remote_recv_align);
990 printf("Report local CPU %d\n",local_cpu_usage);
991 printf("Report remote CPU %d\n",remote_cpu_usage);
992 printf("Verbosity: %d\n",verbosity);
993 printf("Debug: %d\n",debug);
994 printf("Port: %s\n",test_port);
995 printf("Test name: %s\n",test_name);
996 printf("Test bytes: %d Test time: %d Test trans: %d\n",
997 test_bytes,
998 test_time,
999 test_trans);
1000 printf("Host name: %s\n",host_name);
1001 printf("\n");
1002 }
1003