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