• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "netperf_version.h"
2 
3 char	netsh_id[]="\
4 @(#)netsh.c (c) Copyright 1993-2012 Hewlett-Packard Company. Version 2.6.0";
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 <stdio.h>
18 #include <stdlib.h>
19 #include <ctype.h>
20 #include <sys/types.h>
21 #include <fcntl.h>
22 
23 #ifndef WIN32
24 #include <unistd.h>
25 #include <errno.h>
26 #include <signal.h>
27 #include <sys/time.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <netdb.h>
32 #else
33 #include <time.h>
34 #include <winsock2.h>
35 #include "missing\stdint.h"
36 /* while it is unlikely that anyone running Windows 2000 or NT 4 is
37    going to be trying to compile this, if they are they will want to
38    define DONT_IPV6 in the sources file */
39 #ifndef DONT_IPV6
40 #include <ws2tcpip.h>
41 #endif
42 #define netperf_socklen_t socklen_t
43 extern	int	getopt(int , char **, char *) ;
44 #endif
45 
46 
47 #ifndef STRINGS
48 #include <string.h>
49 #else /* STRINGS */
50 #include <strings.h>
51 #endif /* STRINGS */
52 
53 /**********************************************************************/
54 /*                                                                    */
55 /*          Local Include Files                                       */
56 /*                                                                    */
57 /**********************************************************************/
58 
59 #define  NETSH
60 #include "netsh.h"
61 #include "netlib.h"
62 #include "nettest_bsd.h"
63 
64 #ifdef WANT_UNIX
65 #include "nettest_unix.h"
66 #endif /* WANT_UNIX */
67 
68 #ifdef WANT_XTI
69 #include "nettest_xti.h"
70 #endif /* WANT_XTI */
71 
72 #ifdef WANT_DLPI
73 #include "nettest_dlpi.h"
74 #endif /* WANT_DLPI */
75 
76 #ifdef WANT_SCTP
77 #include "nettest_sctp.h"
78 #endif
79 
80 /************************************************************************/
81 /*									*/
82 /*	Global constants  and macros					*/
83 /*									*/
84 /************************************************************************/
85 
86 /* Some of the args take optional parameters. Since we are using
87    getopt to parse the command line, we will tell getopt that they do
88    not take parms, and then look for them ourselves */
89 
90 #define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdD:f:F:H:hi:I:jk:K:l:L:n:NO:o:P:p:rSs:t:T:v:VW:w:y:Y:Z:46"
91 
92 /************************************************************************/
93 /*									*/
94 /*	Global variables 						*/
95 /*									*/
96 /************************************************************************/
97 
98 /* some names and such */
99 char *program;		/* program invocation name */
100 char *command_line;     /* a copy of the entire command line */
101 
102 /* stuff to say where this test is going */
103 char
104   host_name[HOSTNAMESIZE] = "",	      /* remote host name or ip addr */
105   local_host_name[HOSTNAMESIZE] = "", /* local hostname or ip */
106   test_name[BUFSIZ] = "TCP_STREAM",   /* which test to run */
107   test_port[PORTBUFSIZE] = "12865",   /* where is the test waiting */
108   local_test_port[PORTBUFSIZE] = "0"; /* from whence we should start */
109 
110 int
111   address_family = AF_UNSPEC,       /* which address family remote */
112   local_address_family = AF_UNSPEC; /* which address family local */
113 
114 /* the source of data for filling the buffers */
115 char    local_fill_file[BUFSIZ] = "";
116 char    remote_fill_file[32] = ""; /* size limited for control message */
117 
118 /* output controlling variables */
119 int
120   debug = 0,			/* debugging level */
121   print_headers = 1,		/* do/don't display headers */
122   verbosity = 1,		/* verbosity level */
123   keep_histogram = 0,
124   keep_statistics = 0;
125 
126 /* When specified with -B, this will be displayed at the end of the line
127    for output that does not include the test header.  mostly this is
128    to help identify a specific netperf result when concurrent netperfs
129    are run. raj 2006-02-01 */
130 char *result_brand = NULL;
131 
132 /* cpu variables */
133 int
134   local_cpu_usage = 0,	/* you guessed it */
135   remote_cpu_usage = 0;	/* still right ! */
136 
137 float
138   local_cpu_rate = 0.0F,
139   remote_cpu_rate = 0.0F;
140 
141 int
142   shell_num_cpus=1;
143 
144 /* the end-test conditions for the tests - either transactions, bytes,
145    or time. different vars used for clarity - space is cheap ;-) */
146 
147 int
148   test_time = 10, /* test ends by time */
149   test_len_ticks, /* how many times will the timer go off before the
150 		     test is over? */
151   test_bytes = 0, /* test ends on byte count */
152   test_trans = 0; /* test ends on tran count */
153 
154 /* the alignment conditions for the tests */
155 int
156   local_recv_align = 8,	/* alignment for local receives */
157   local_send_align = 8,	/* alignment for local sends */
158   local_send_offset = 0,
159   local_recv_offset = 0,
160   remote_recv_align = 8, /* alignment for remote receives */
161   remote_send_align = 8, /* alignment for remote sends */
162   remote_send_offset = 0,
163   remote_recv_offset = 0,
164   remote_send_width = 0,
165   remote_recv_width = 0;
166 
167 /* hoist above the if for omni */
168 int
169   interval_usecs = 0,
170   interval_wate = 0,
171   interval_burst = 0,
172   remote_interval_usecs = 0,
173   remote_interval_burst = 0;
174 
175 /* wait time between control/data connection establishment and start
176    of data traffic */
177 int wait_time_secs = 0;
178 
179 
180 #ifdef DIRTY
181 int loc_dirty_count = 0,
182     loc_clean_count = 0,
183     rem_dirty_count = 0,
184     rem_clean_count = 0;
185 #else
186 int loc_dirty_count = -1,
187     loc_clean_count = -1,
188     rem_dirty_count = -1,
189     rem_clean_count = -1;
190 #endif /* DIRTY */
191 
192  /* some of the vairables for confidence intervals... */
193 
194 int  confidence_level = 0;
195 int  iteration_min = 1;
196 int  iteration_max = 1;
197 int  result_confidence_only = 0;
198 double interval = 0.0;
199 
200  /* stuff to control the "width" of the buffer rings for sending and
201     receiving data */
202 int	send_width;
203 int     recv_width;
204 
205 /* address family */
206 int	af = AF_INET;
207 
208 /* socket priority via SO_PRIORITY */
209 int local_socket_prio = -1;
210 int remote_socket_prio = -1;
211 
212 /* and IP_TOS */
213 int local_socket_tos = -1;
214 int remote_socket_tos = -1;
215 
216 /* did someone request processor affinity? */
217 int cpu_binding_requested = 0;
218 
219 /* are we not establishing a control connection? */
220 int no_control = 0;
221 
222 /* what is the passphrase? */
223 char *passphrase = NULL;
224 
225 char netserver_usage[] = "\n\
226 Usage: netserver [options] \n\
227 \n\
228 Options:\n\
229     -h                Display this text\n\
230     -D                Do not daemonize\n\
231     -d                Increase debugging output\n\
232     -f                Do not spawn chilren for each test, run serially\n\
233     -L name,family    Use name to pick listen address and family for family\n\
234     -N                No debugging output, even if netperf asks\n\
235     -p portnum        Listen for connect requests on portnum.\n\
236     -4                Do IPv4\n\
237     -6                Do IPv6\n\
238     -v verbosity      Specify the verbosity level\n\
239     -V                Display version information and exit\n\
240     -Z passphrase     Expect passphrase as the first thing received\n\
241 \n";
242 
243 /* netperf_usage done as two concatenated strings to make the MS
244    compiler happy when compiling for x86_32.  fix from Spencer
245    Frink. */
246 
247 char netperf_usage1[] = "\n\
248 Usage: netperf [global options] -- [test options] \n\
249 \n\
250 Global options:\n\
251     -a send,recv      Set the local send,recv buffer alignment\n\
252     -A send,recv      Set the remote send,recv buffer alignment\n\
253     -B brandstr       Specify a string to be emitted with brief output\n\
254     -c [cpu_rate]     Report local CPU usage\n\
255     -C [cpu_rate]     Report remote CPU usage\n\
256     -d                Increase debugging output\n\
257     -D time,[units] * Display interim results at least every time interval\n\
258                       using units as the initial guess for units per second\n\
259                       A negative value for time will make heavy use of the\n\
260                       system's timestamping functionality\n\
261     -f G|M|K|g|m|k    Set the output units\n\
262     -F lfill[,rfill]* Pre-fill buffers with data from specified file\n\
263     -h                Display this text\n\
264     -H name|ip,fam *  Specify the target machine and/or local ip and family\n\
265     -i max,min        Specify the max and min number of iterations (15,1)\n\
266     -I lvl[,intvl]    Specify confidence level (95 or 99) (99) \n\
267                       and confidence interval in percentage (10)\n\
268     -j                Keep additional timing statistics\n\
269     -l testlen        Specify test duration (>0 secs) (<0 bytes|trans)\n\
270     -L name|ip,fam *  Specify the local ip|name and address family\n\
271     -o send,recv      Set the local send,recv buffer offsets\n\
272     -O send,recv      Set the remote send,recv buffer offset\n\
273     -n numcpu         Set the number of processors for CPU util\n\
274     -N                Establish no control connection, do 'send' side only\n\
275     -p port,lport*    Specify netserver port number and/or local port\n\
276     -P 0|1            Don't/Do display test headers\n\
277     -r                Allow confidence to be hit on result only\n\
278     -s seconds        Wait seconds between test setup and test start\n\
279     -S                Set SO_KEEPALIVE on the data connection\n\
280     -t testname       Specify test to perform\n\
281     -T lcpu,rcpu      Request netperf/netserver be bound to local/remote cpu\n\
282     -v verbosity      Specify the verbosity level\n\
283     -W send,recv      Set the number of send,recv buffers\n\
284     -v level          Set the verbosity level (default 1, min 0)\n\
285     -V                Display the netperf version and exit\n\
286     -y local,remote   Set the socket priority\n\
287     -Y local,remote   Set the IP_TOS. Use hexadecimal.\n\
288     -Z passphrase     Set and pass to netserver a passphrase\n";
289 
290 char netperf_usage2[] = "\n\
291 For those options taking two parms, at least one must be specified;\n\
292 specifying one value without a comma will set both parms to that\n\
293 value, specifying a value with a leading comma will set just the second\n\
294 parm, a value with a trailing comma will set just the first. To set\n\
295 each parm to unique values, specify both and separate them with a\n\
296 comma.\n\
297 \n"
298 "* For these options taking two parms, specifying one value with no comma\n\
299 will only set the first parms and will leave the second at the default\n\
300 value. To set the second value it must be preceded with a comma or be a\n\
301 comma-separated pair. This is to retain previous netperf behaviour.\n";
302 
303 
304 /* This routine will return the two arguments to the calling routine.
305    If the second argument is not specified, and there is no comma,
306    then the value of the second argument will be the same as the value
307    of the first. If there is a comma, then the value of the second
308    argument will be the value of the second argument ;-) */
309 void
break_args(char * s,char * arg1,char * arg2)310 break_args(char *s, char *arg1, char *arg2)
311 
312 {
313   char *ns;
314   ns = strchr(s,',');
315   if (ns) {
316     /* there was a comma arg2 should be the second arg*/
317     *ns++ = '\0';
318     while ((*arg2++ = *ns++) != '\0');
319   }
320   else {
321     /* there was not a comma, we can use ns as a temp s */
322     /* and arg2 should be the same value as arg1 */
323     ns = s;
324     while ((*arg2++ = *ns++) != '\0');
325   };
326   while ((*arg1++ = *s++) != '\0');
327 }
328 
329 /* break_args_explicit_sep
330 
331    this routine is somewhat like break_args in that it will separate a
332    pair of values using the given separator.  however, if there is no
333    separator this version will not ass-u-me that arg2 should be the
334    same as arg1. raj 20101129 */
335 
336 void
break_args_explicit_sep(char * s,int sep,char * arg1,char * arg2)337 break_args_explicit_sep(char *s, int sep, char *arg1, char *arg2)
338 
339 {
340   char *ns;
341   ns = strchr(s,sep);
342   if (ns) {
343     /* there was a separator arg2 should be the second arg*/
344     *ns++ = '\0';
345     while ((*arg2++ = *ns++) != '\0');
346   }
347   else {
348     /* there was no separator, so we should make sure that arg2 is \0
349        lest something become confused. raj 2005-02-04 */
350     *arg2 = '\0';
351   };
352   while ((*arg1++ = *s++) != '\0');
353 
354 }
355 
356 /* break_args_explicit - now just a wrapper around a call to
357    break_args_explicit_sep passing-in a ',' as the separator. raj
358    20101129 */
359 
360 void
break_args_explicit(char * s,char * arg1,char * arg2)361 break_args_explicit(char *s, char *arg1, char *arg2)
362 
363 {
364   break_args_explicit_sep(s, ',', arg1, arg2);
365 }
366 
367 
368 /* given a string with possible values for setting an address family,
369    convert that into one of the AF_mumble values - AF_INET, AF_INET6,
370    AF_UNSPEC as apropriate. the family_string is compared in a
371    case-insensitive manner */
372 
373 int
parse_address_family(char family_string[])374 parse_address_family(char family_string[])
375 {
376 
377   char temp[10];  /* gotta love magic constants :) */
378 
379   strncpy(temp,family_string,10);
380 
381   if (debug) {
382     fprintf(where,
383 	    "Attempting to parse address family from %s derived from %s\n",
384 	    temp,
385 	    family_string);
386   }
387 #if defined(AF_INET6)
388   if (strstr(temp,"6")) {
389     return(AF_INET6);
390   }
391 #endif
392   if (strstr(temp,"inet") ||
393       strstr(temp,"4")) {
394     return(AF_INET);
395   }
396 #if defined(AF_RDS)
397   if (strstr(temp,"af_rds") ||
398       strstr(temp,"32")) {
399     return(AF_RDS);
400   }
401 #endif
402   if (strstr(temp,"unspec") ||
403       strstr(temp,"0")) {
404     return(AF_UNSPEC);
405   }
406   fprintf(where,
407 	  "WARNING! %s not recognized as an address family, using AF_UNPSEC\n"
408 	  "Are you sure netperf was configured for that address family?\n",
409 	  family_string);
410   fflush(where);
411   return(AF_UNSPEC);
412 }
413 
414 int
parse_socket_type(char socket_string[])415 parse_socket_type(char socket_string[]) {
416 
417   char temp[10];
418 
419   strncpy(temp,socket_string,10);
420 
421   if (debug) {
422     fprintf(where,
423 	    "Attempting to parse socket type from %s derived from %s\n",
424 	    temp,
425 	    socket_string);
426   }
427 
428 #ifdef SOCK_STREAM
429   if (strstr(temp,"stream"))
430     return SOCK_STREAM;
431 #endif
432 #ifdef SOCK_DGRAM
433   if (strstr(temp,"dgram"))
434     return SOCK_DGRAM;
435 #endif
436   return NST_UNKN;
437 
438 }
439 
440 int
parse_direction(char direction_string[])441 parse_direction(char direction_string[])
442 {
443   char arg1[BUFSIZ],arg2[BUFSIZ];
444   int left, right;
445 
446   if (NULL == direction_string) {
447     return 0;
448   }
449 
450   if (direction_string[0] == '\0') {
451     return 0;
452   }
453 
454   /* allow someone to "or" break_args_explicit will split at the first
455      '|' in the string so we know that arg1 has no '|' in it and arg2
456      might */
457   break_args_explicit_sep(direction_string,'|',arg1,arg2);
458 
459   /* at this point only arg2 could contain a '|' so recurse on that */
460   right = parse_direction(arg2);
461 
462   /* now we parse the "left side" or arg1 */
463   if (arg1[0] == '\0') {
464     left = 0;
465   }
466   else if ((strcasecmp(arg1,"xmit") == 0) ||
467 	   (strcasecmp(arg1,"send") == 0) ||
468 	   (strcasecmp(arg1,"stream") == 0) ||
469 	   (strcasecmp(arg1,"transmit") == 0)) {
470     left = NETPERF_XMIT;
471   }
472   else if ((strcasecmp(arg1,"recv") == 0) ||
473 	   (strcasecmp(arg1,"receive") == 0) ||
474 	   (strcasecmp(arg1,"maerts") == 0)) {
475     /* yes, another magic number... */
476     left =  NETPERF_RECV;
477   }
478   else  if (strcasecmp(arg1,"rr") == 0) {
479     left = NETPERF_XMIT|NETPERF_RECV;
480   }
481   else {
482     /* we now "ass-u-me" it is a number that can be parsed by strtol()
483  */
484     left = strtol(arg1,NULL,0);
485   }
486 
487   return (left | right);
488 
489 }
490 
491 int
parse_protocol(char protocol_string[])492 parse_protocol(char protocol_string[])
493 {
494   char temp[10];
495 
496   strncpy(temp,protocol_string,10);
497 
498   if (debug) {
499     fprintf(where,
500 	    "Attempting to parse protocol from %s derived from %s\n",
501 	    temp,
502 	    protocol_string);
503   }
504 
505   /* we ass-u-me that everyone has IPPROTO_TCP elsewhere so might as
506      well here, and avoid issues with windows using an enum.  Kudos to
507      Jonathan Cook. */
508   if (!strcasecmp(temp,"tcp")){
509     socket_type = SOCK_STREAM;
510     return IPPROTO_TCP;
511   }
512 
513   if (!strcasecmp(temp,"udp")) {
514     socket_type = SOCK_DGRAM;
515     return IPPROTO_UDP;
516   }
517 
518   /* we keep the rest of the #idefs though because these may not be as
519      universal as TCP and UDP... */
520 #ifdef IPPROTO_SCTP
521   if (!strcasecmp(temp,"sctp")) {
522     /* it can be more than one socket type */
523     return IPPROTO_SCTP;
524   }
525 #endif
526 #ifdef IPPROTO_SDP
527   if (!strcasecmp(temp,"sdp")) {
528     socket_type = SOCK_STREAM;
529     return IPPROTO_SDP;
530   }
531 #endif
532 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
533   if (!strcasecmp(temp,"dccp")) {
534     socket_type = SOCK_DCCP;
535     return IPPROTO_DCCP;
536   }
537 #endif
538 #ifdef IPPROTO_UDPLITE
539   if (!strcasecmp(temp,"udplite")) {
540     socket_type = SOCK_DGRAM;
541     return IPPROTO_UDPLITE;
542   }
543 #endif
544   return IPPROTO_IP;
545 }
546 
547 
548 void
print_netserver_usage()549 print_netserver_usage()
550 {
551   fprintf(stderr, "%s", netserver_usage);
552 }
553 
554 
555 void
print_netperf_usage()556 print_netperf_usage()
557 {
558   fprintf(stderr, "%s%s", netperf_usage1, netperf_usage2);
559 }
560 
561 /* convert the specified string to upper case if we know how */
562 static void
convert_to_upper(char * source)563 convert_to_upper(char *source)
564 {
565 #if defined(HAVE_TOUPPER)
566   int i,length;
567 
568   length = strlen(source);
569 
570   for (i=0; i < length; i++) {
571     source[i] = toupper(source[i]);
572   }
573 #endif
574   return;
575 
576 }
577 
578 void
scan_cmd_line(int argc,char * argv[])579 scan_cmd_line(int argc, char *argv[])
580 {
581   extern int	optind;           /* index of first unused arg 	*/
582   extern char	*optarg;	  /* pointer to option string	*/
583 
584   int           cmnd_len;
585   char          *p;
586 
587   int		c;
588 
589   char	arg1[BUFSIZ],  /* argument holders		*/
590     arg2[BUFSIZ];
591 
592   program = (char *)malloc(strlen(argv[0]) + 1);
593   if (program == NULL) {
594     printf("malloc() to store program name failed!\n");
595     exit(-1);
596   }
597   strcpy(program, argv[0]);
598 
599   /* brute force, but effective */
600   command_line = NULL;
601   cmnd_len = 0;
602   for (c = 0; c < argc; c++) {
603     cmnd_len += strlen(argv[c]);
604   }
605   cmnd_len += argc;  /* forget thee not the spaces */
606   command_line = malloc(cmnd_len+1);
607 
608   if (command_line == NULL) {
609     printf("malloc(%d) failed!\n",cmnd_len);
610     exit(-1);
611   }
612   p = command_line;
613   for (c = 0; c < argc; c++) {
614     memcpy(p,argv[c],strlen(argv[c]));
615     p += strlen(argv[c]);
616     *p = ' ';
617     p += 1;
618   }
619   *--p = 0;
620 
621   /* Go through all the command line arguments and break them out. For
622      those options that take two parms, specifying only the first will
623      set both to that value. Specifying only the second will leave the
624      first untouched. To change only the first, use the form first,
625      (see the routine break_args.. */
626 
627   while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
628     switch (c) {
629     case '?':
630     case 'h':
631       print_netperf_usage();
632       exit(1);
633     case 'a':
634       /* set local alignments */
635       break_args(optarg,arg1,arg2);
636       if (arg1[0]) {
637 	local_send_align = convert(arg1);
638       }
639       if (arg2[0])
640 	local_recv_align = convert(arg2);
641       break;
642     case 'A':
643       /* set remote alignments */
644       break_args(optarg,arg1,arg2);
645       if (arg1[0]) {
646 	remote_send_align = convert(arg1);
647       }
648       if (arg2[0])
649 	remote_recv_align = convert(arg2);
650       break;
651     case 'c':
652       /* measure local cpu usage please. the user may have specified
653          the cpu rate as an optional parm */
654       if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
655 	/* there was an optional parm */
656 	local_cpu_rate = (float)atof(argv[optind]);
657 	optind++;
658       }
659       local_cpu_usage++;
660       break;
661     case 'C':
662       /* measure remote cpu usage please */
663       if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
664 	/* there was an optional parm */
665 	remote_cpu_rate = (float)atof(argv[optind]);
666 	optind++;
667       }
668       remote_cpu_usage++;
669       break;
670     case 'd':
671       debug++;
672       break;
673     case 'D':
674 #if (defined WANT_DEMO)
675       demo_mode = 1; /* 1 == use units; 2 == always timestamp */
676       break_args_explicit(optarg,arg1,arg2);
677       if (arg1[0]) {
678 	demo_interval = atof(arg1) * 1000000.0;
679 	if (demo_interval < 0.0) {
680 	  demo_interval = demo_interval * -1.0;
681 	  demo_mode = 2;
682 	}
683       }
684       if (arg2[0]) {
685 	demo_units = convert(arg2);
686       }
687 #else
688       printf("Sorry, Demo Mode not configured into this netperf.\n"
689 	     "Please consider reconfiguring netperf with\n"
690 	     "--enable-demo=yes and recompiling\n");
691 #endif
692       break;
693     case 'f':
694       /* set the thruput formatting */
695       libfmt = *optarg;
696       break;
697     case 'F':
698       /* set the fill_file variables for pre-filling buffers. check
699 	 the remote fill file name length against our limit as we will
700 	 not hear from the remote on errors opening the fill
701 	 file. Props to Jonathan Cook for the remote name check */
702       break_args_explicit(optarg,arg1,arg2);
703       if (arg1[0]) {
704 	strncpy(local_fill_file,arg1,sizeof(local_fill_file));
705 	local_fill_file[sizeof(local_fill_file) - 1] = '\0';
706       }
707       if (arg2[0]) {
708 	if (strlen(arg2)>(sizeof(remote_fill_file) - 1)){
709 	  fprintf(stderr,
710 		  "Remote fill file name must be less than %d characters\n",
711 		  (int) sizeof(remote_fill_file));
712 	  fflush(stderr);
713 	  exit(-1);
714 	}
715 
716 	strncpy(remote_fill_file,arg2,sizeof(remote_fill_file));
717 	remote_fill_file[sizeof(remote_fill_file) - 1] = '\0';
718       }
719       break;
720     case 'i':
721       /* set the iterations min and max for confidence intervals */
722       break_args(optarg,arg1,arg2);
723       if (arg1[0]) {
724 	iteration_max = convert(arg1);
725       }
726       if (arg2[0] ) {
727 	iteration_min = convert(arg2);
728       }
729       /* if the iteration_max is < iteration_min make iteration_max
730 	 equal iteration_min */
731       if (iteration_max < iteration_min) iteration_max = iteration_min;
732       /* limit minimum to 3 iterations */
733       if (iteration_max < 3) iteration_max = 3;
734       if (iteration_min < 3) iteration_min = 3;
735       /* limit maximum to 30 iterations */
736       if (iteration_max > 30) iteration_max = 30;
737       if (iteration_min > 30) iteration_min = 30;
738       if (confidence_level == 0) confidence_level = 99;
739       if (interval == 0.0) interval = 0.05; /* five percent */
740       break;
741     case 'I':
742       /* set the confidence level (95 or 99) and width */
743       break_args(optarg,arg1,arg2);
744       if (arg1[0]) {
745 	confidence_level = convert(arg1);
746       }
747       if((confidence_level != 95) && (confidence_level != 99)){
748 	printf("Only 95%% and 99%% confidence level is supported\n");
749 	exit(-1);
750       }
751       if (arg2[0] ) {
752 	/* it doesn't make much sense to use convert() here so just
753 	   use strtod() instead. raj 2007-10-24 */
754 	interval = strtod(arg2,NULL)/100.0;
755       }
756       /* make sure that iteration_min and iteration_max are at least
757 	 at a reasonable default value.  if a -i option has previously
758 	 been parsed, these will no longer be 1, so we can check
759 	 against 1 */
760       if (iteration_min == 1) iteration_min = 3;
761       if (iteration_max == 1) iteration_max = 10;
762       /* make sure that the interval is set if it isn't at its default
763 	 value */
764       if (interval == 0.0) interval = 0.05; /* five percent */
765       break;
766     case 'j':
767       keep_histogram = 1;
768       keep_statistics = 1;
769       break;
770     case 'k':
771       /* local dirty and clean counts */
772 #ifdef DIRTY
773       break_args(optarg,arg1,arg2);
774       if (arg1[0]) {
775 	loc_dirty_count = convert(arg1);
776       }
777       if (arg2[0] ) {
778 	loc_clean_count = convert(arg2);
779       }
780 #else
781       printf("I don't know how to get dirty.\n");
782 #endif /* DIRTY */
783       break;
784     case 'K':
785       /* remote dirty and clean counts */
786 #ifdef DIRTY
787       break_args(optarg,arg1,arg2);
788       if (arg1[0]) {
789 	rem_dirty_count = convert(arg1);
790       }
791       if (arg2[0] ) {
792 	rem_clean_count = convert(arg2);
793       }
794 #else
795       printf("I don't know how to get dirty.\n");
796 #endif /* DIRTY */
797       break;
798     case 'n':
799       shell_num_cpus = atoi(optarg);
800       break;
801     case 'N':
802       no_control = 1;
803       break;
804     case 'o':
805       /* set the local offsets */
806       break_args(optarg,arg1,arg2);
807       if (arg1[0])
808 	local_send_offset = convert(arg1);
809       if (arg2[0])
810 	local_recv_offset = convert(arg2);
811       break;
812     case 'O':
813       /* set the remote offsets */
814       break_args(optarg,arg1,arg2);
815       if (arg1[0])
816 	remote_send_offset = convert(arg1);
817       if (arg2[0])
818 	remote_recv_offset = convert(arg2);
819       break;
820     case 'P':
821       /* to print or not to print, that is */
822       /* the header question */
823       print_headers = convert(optarg);
824       break;
825     case 'r':
826       /* the user wishes that we declare confidence when hit on the
827 	 result even if not yet reached on CPU utilization.  only
828 	 meaningful if cpu util is enabled */
829       result_confidence_only = 1;
830       break;
831     case 'S':
832       /* the user wishes us to set SO_KEEPALIVE */
833       want_keepalive = 1;
834       break;
835     case 's':
836       /* the user wishes us to sleep/pause some length of time before
837 	 actually starting the test */
838       wait_time_secs = convert(optarg);
839       break;
840     case 't':
841       /* set the test name and shift it to upper case so we don't have
842 	 to worry about compares on things like substrings */
843       strncpy(test_name,optarg,sizeof(test_name)-1);
844       convert_to_upper(test_name);
845       break;
846     case 'T':
847       /* We want to set the processor on which netserver or netperf
848          will run */
849       break_args(optarg,arg1,arg2);
850       if (arg1[0]) {
851 	local_proc_affinity = convert(arg1);
852 	bind_to_specific_processor(local_proc_affinity,0);
853       }
854       if (arg2[0]) {
855 	remote_proc_affinity = convert(arg2);
856       }
857       cpu_binding_requested = 1;
858       break;
859     case 'W':
860       /* set the "width" of the user space data buffer ring. This will
861 	 be the number of send_size buffers malloc'd in the tests */
862       break_args(optarg,arg1,arg2);
863       if (arg1[0])
864 	send_width = convert(arg1);
865       if (arg2[0])
866 	recv_width = convert(arg2);
867       break;
868     case 'y':
869       break_args(optarg, arg1, arg2);
870 #if defined(SO_PRIORITY)
871       if (arg1[0])
872 	local_socket_prio = convert(arg1);
873 #else
874       if (debug) {
875 	fprintf(where,
876 		"Setting SO_PRIORITY is not supported on this platform, request to set SO_PRIORITY locally ignored.\n");
877 	fflush(where);
878       }
879       local_socket_prio = -3;
880 #endif
881       if (arg2[0])
882 	remote_socket_prio = convert(arg2);
883       break;
884     case 'Y':
885       break_args(optarg, arg1, arg2);
886 #if defined(IP_TOS) || defined(IPV6_TCLASS)
887       if (arg1[0])
888 	local_socket_tos = parse_ipqos(arg1);
889 #else
890       if (debug) {
891 	fprintf(where,
892 		"Setting IP type-of-service is not supported on this platform, request to set it locally ignored.\n");
893 	fflush(where);
894       }
895       local_socket_tos = -1;
896 #endif
897       if (arg2[0]) {
898 	remote_socket_tos = parse_ipqos(arg2);
899 	if (debug) {
900 	  fprintf(where,
901 		  "Setting remote_socket_tos to 0x%x\n",
902 		  remote_socket_tos);
903 	  fflush(where);
904 	}
905       }
906       break;
907     case 'Z':
908       /* only copy as much of the passphrase as could fit in the
909 	 test-specific portion of a control message. Windows does not
910 	 seem to have a strndup() so just malloc and strncpy it.  we
911 	 weren't checking the strndup() return so won't bother with
912 	 checking malloc(). we will though make certain we only
913 	 allocated it once in the event that someone puts -Z on the
914 	 command line more than once */
915       if (passphrase == NULL)
916 	passphrase = malloc(sizeof(netperf_request.content.test_specific_data));
917       strncpy(passphrase,
918 	      optarg,
919 	      sizeof(netperf_request.content.test_specific_data));
920       passphrase[sizeof(netperf_request.content.test_specific_data) - 1] = '\0';
921       break;
922     case 'l':
923       /* determine test end conditions */
924       /* assume a timed test */
925       test_time = convert(optarg);
926       test_bytes = test_trans = 0;
927       if (test_time < 0) {
928 	test_bytes = -1 * test_time;
929 	test_trans = test_bytes;
930 	test_time = 0;
931       }
932       break;
933     case 'v':
934       /* say how much to say */
935       verbosity = convert(optarg);
936       break;
937     case 'p':
938       /* specify an alternate port number we use break_args_explicit
939 	 here to maintain backwards compatibility with previous
940 	 generations of netperf where having a single value did not
941 	 set both remote _and_ local port number. raj 2005-02-04 */
942       break_args_explicit(optarg,arg1,arg2);
943       if (arg1[0])
944 	strncpy(test_port,arg1,PORTBUFSIZE);
945       if (arg2[0])
946 	strncpy(local_test_port,arg2,PORTBUFSIZE);
947       break;
948     case 'H':
949       /* save-off the host identifying information, use
950 	 break_args_explicit since passing just one value should not
951 	 set both */
952       break_args_explicit(optarg,arg1,arg2);
953       if (arg1[0])
954 	strncpy(host_name,arg1,sizeof(host_name));
955       if (arg2[0])
956 	address_family = parse_address_family(arg2);
957       break;
958     case 'L':
959       /* save-off the local control socket addressing information. use
960 	 break_args_explicit since passing just one value should not
961 	 set both */
962       break_args_explicit(optarg,arg1,arg2);
963       if (arg1[0])
964 	strncpy(local_host_name,arg1,sizeof(local_host_name));
965       if (arg2[0])
966 	local_address_family = parse_address_family(arg2);
967       break;
968     case 'w':
969       /* We want to send requests at a certain wate.  Remember that
970          there are 1000000 usecs in a second, and that the packet rate
971          is expressed in packets per millisecond. shuffle the #ifdef
972          around a bit to deal with both netperf and netserver possibly
973          doing intervals with omni tests */
974       break_args_explicit(optarg,arg1,arg2);
975       if (arg1[0]) {
976 #ifdef WANT_INTERVALS
977 	interval_usecs = convert_timespec(arg1);
978 	interval_wate  = interval_usecs / 1000;
979 #else
980 	fprintf(where,
981 		"Packet rate control is not compiled in.\n");
982 #endif
983       }
984       if (arg2[0]) {
985 	/* we pass usecs to the remote and let it deal to cover both
986 	   intervals and spin methods. if he wasn't intervals enabled
987 	   he will return a suitable value back to us */
988 	remote_interval_usecs = convert_timespec(arg2);
989       }
990       break;
991     case 'b':
992       /* we want to have a burst so many packets per */
993       /* interval. */
994       break_args_explicit(optarg,arg1,arg2);
995       if (arg1[0]) {
996 #ifdef WANT_INTERVALS
997 	interval_burst = convert(arg1);
998 	/* set a default in case the user does not include the -w
999 	   option */
1000 	if (interval_usecs == 0) {
1001 	  interval_wate = 1;
1002 	  interval_usecs = 1000;
1003 	}
1004 #else
1005 	fprintf(where,
1006 		"Packet burst size is not compiled in. \n");
1007 #endif /* WANT_INTERVALS */
1008       }
1009       /* there is no ifdef here because we are sending this value to
1010 	 the remote, which may or may not have been compiled for
1011 	 intervals and we don't have a way of knowing on this side
1012 	 until we try */
1013       if (arg2[0]) {
1014 	remote_interval_burst = convert(arg2);
1015 	if (remote_interval_usecs == 0) {
1016 	  remote_interval_usecs = 1000;
1017 	}
1018       }
1019       break;
1020     case 'B':
1021       result_brand = malloc(strlen(optarg)+1);
1022       if (NULL != result_brand) {
1023 	strcpy(result_brand,optarg);
1024       }
1025       else {
1026 	fprintf(where,
1027 		"Unable to malloc space for result brand\n");
1028       }
1029       break;
1030     case '4':
1031       address_family = AF_INET;
1032       local_address_family = AF_INET;
1033       break;
1034     case '6':
1035 #if defined(AF_INET6)
1036       address_family = AF_INET6;
1037       local_address_family = AF_INET6;
1038 #else
1039       printf("This netperf was not compiled on an IPv6 capable system!\n");
1040       exit(-1);
1041 #endif
1042       break;
1043     case 'V':
1044       printf("Netperf version %s\n",NETPERF_VERSION);
1045       exit(0);
1046       break;
1047     };
1048   }
1049   /* ok, what should our default hostname and local binding info be?
1050    */
1051 
1052   if ('\0' == host_name[0]) {
1053     /* host_name was not set */
1054     switch (address_family) {
1055     case AF_INET:
1056 #if defined(AF_RDS)
1057     case AF_RDS:
1058 #endif
1059       strcpy(host_name,"localhost");
1060       break;
1061     case AF_UNSPEC:
1062       /* what to do here? case it off the local_address_family I
1063 	 suppose */
1064       switch (local_address_family) {
1065       case AF_INET:
1066       case AF_UNSPEC:
1067 #if defined(AF_RDS)
1068       case AF_RDS:
1069 #endif
1070 	strcpy(host_name,"localhost");
1071 	break;
1072 #if defined(AF_INET6)
1073       case AF_INET6:
1074 	strcpy(host_name,"::1");
1075 	break;
1076 #endif
1077       default:
1078 	printf("Netperf does not understand %d as an address family\n",
1079 	       address_family);
1080 	exit(-1);
1081       }
1082       break;
1083 #if defined(AF_INET6)
1084     case AF_INET6:
1085       strcpy(host_name,"::1");
1086       break;
1087 #endif
1088     default:
1089       printf("Netperf does not understand %d as an address family\n",
1090 	     address_family);
1091       exit(-1);
1092     }
1093   } else {
1094     /* resolve the hostname and pull the address family from the
1095        addrinfo */
1096     struct addrinfo *ai;
1097 
1098     ai = resolve_host(host_name, NULL, address_family);
1099     if (!ai) {
1100       printf("Netperf could not resolve %s as a host name\n", host_name);
1101       exit(-1);
1102     }
1103     address_family = ai->ai_family;
1104     freeaddrinfo(ai);
1105   }
1106 
1107 
1108   /* now, having established the name to which the control will
1109      connect, from what should it come? */
1110   if ('\0' == local_host_name[0]) {
1111     switch (local_address_family) {
1112     case AF_INET:
1113 #if defined(AF_RDS)
1114     case AF_RDS:
1115 #endif
1116       strcpy(local_host_name,"0.0.0.0");
1117       break;
1118     case AF_UNSPEC:
1119       switch (address_family) {
1120       case AF_INET:
1121       case AF_UNSPEC:
1122 #if defined(AF_RDS)
1123     case AF_RDS:
1124 #endif
1125 	strcpy(local_host_name,"0.0.0.0");
1126 	break;
1127 #if defined(AF_INET6)
1128       case AF_INET6:
1129 	strcpy(local_host_name,"::0");
1130 	break;
1131 #endif
1132       default:
1133 	printf("Netperf does not understand %d as an address family\n",
1134 	       address_family);
1135 	exit(-1);
1136       }
1137       break;
1138 #if defined(AF_INET6)
1139     case AF_INET6:
1140       strcpy(local_host_name,"::0");
1141       break;
1142 #endif
1143     default:
1144       printf("Netperf does not understand %d as an address family\n",
1145 	     address_family);
1146       exit(-1);
1147     }
1148   }
1149 
1150   /* so, if we aren't even going to establish a control connection we
1151      should set certain "remote" settings to reflect this, regardless
1152      of what else may have been set on the command line */
1153   if (no_control) {
1154     remote_socket_prio = -1;
1155     remote_socket_tos = -1;
1156     remote_recv_align = -1;
1157     remote_send_align = -1;
1158     remote_send_offset = -1;
1159     remote_recv_offset = -1;
1160     remote_cpu_rate = (float)-1.0;
1161     remote_cpu_usage = 0;
1162   }
1163 
1164   /* parsing test-specific options used to be conditional on there
1165      being a "--" in the option stream.  however, some of the tests
1166      have other initialization happening in their "scan" routines so
1167      we want to call them regardless. raj 2005-02-08 */
1168   /* while the parsing of the command line will upshift the test name,
1169      since we don't know that there will always be a way to do so? we
1170      will retain for now the strcasecmp calls rather than switch to
1171      strcmp. raj 20101220 */
1172     if (
1173 #ifndef WANT_MIGRATION
1174 	(strcasecmp(test_name,"TCP_STREAM") == 0) ||
1175 	(strcasecmp(test_name,"TCP_MAERTS") == 0) ||
1176 	(strcasecmp(test_name,"TCP_RR") == 0) ||
1177 	(strcasecmp(test_name,"TCP_CRR") == 0) ||
1178 	(strcasecmp(test_name,"UDP_STREAM") == 0) ||
1179 	(strcasecmp(test_name,"UDP_RR") == 0) ||
1180 #endif
1181 #ifdef HAVE_ICSC_EXS
1182 	(strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
1183 #endif /* HAVE_ICSC_EXS */
1184 #ifdef HAVE_SENDFILE
1185 	(strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
1186 #endif /* HAVE_SENDFILE */
1187 	(strcasecmp(test_name,"TCP_CC") == 0) ||
1188 	(strcasecmp(test_name,"TCP_MSS") == 0) ||
1189 #ifdef DO_1644
1190 	(strcasecmp(test_name,"TCP_TRR") == 0) ||
1191 #endif /* DO_1644 */
1192 #ifdef DO_NBRR
1193 	(strcasecmp(test_name,"TCP_TRR") == 0) ||
1194 #endif /* DO_NBRR */
1195 	(0))
1196       {
1197 	scan_sockets_args(argc, argv);
1198       }
1199 
1200 #ifdef WANT_DLPI
1201     else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
1202 	     (strcasecmp(test_name,"DLCL_RR") == 0) ||
1203 	     (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
1204 	     (strcasecmp(test_name,"DLCL_STREAM") == 0))
1205       {
1206 	scan_dlpi_args(argc, argv);
1207       }
1208 #endif /* WANT_DLPI */
1209 
1210 #ifdef WANT_UNIX
1211     else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
1212 	     (strcasecmp(test_name,"DG_RR") == 0) ||
1213 	     (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
1214 	     (strcasecmp(test_name,"DG_STREAM") == 0))
1215       {
1216 	scan_unix_args(argc, argv);
1217       }
1218 #endif /* WANT_UNIX */
1219 
1220 #ifdef WANT_XTI
1221     else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
1222 	     (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
1223 	     (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
1224 	     (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
1225       {
1226 	scan_xti_args(argc, argv);
1227       }
1228 #endif /* WANT_XTI */
1229 
1230 #ifdef WANT_SCTP
1231     else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
1232 	     (strcasecmp(test_name,"SCTP_RR") == 0) ||
1233 	     (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
1234 	     (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
1235     {
1236       scan_sctp_args(argc, argv);
1237     }
1238 #endif
1239 
1240 #ifdef WANT_SDP
1241     else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
1242 	    (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
1243 	    (strcasecmp(test_name,"SDP_RR") == 0))
1244       {
1245 	scan_sdp_args(argc, argv);
1246       }
1247 #endif
1248 
1249 #ifdef WANT_OMNI
1250     else if ((strcasecmp(test_name,"OMNI") == 0) ||
1251 #ifdef WANT_MIGRATION
1252 	     (strcasecmp(test_name,"TCP_STREAM") == 0) ||
1253 	     (strcasecmp(test_name,"TCP_MAERTS") == 0) ||
1254 	     (strcasecmp(test_name,"TCP_RR") == 0) ||
1255 	     (strcasecmp(test_name,"TCP_CRR") == 0) ||
1256 	     (strcasecmp(test_name,"UDP_STREAM") == 0) ||
1257 	     (strcasecmp(test_name,"UDP_RR") == 0) ||
1258 #endif
1259 	     (strcasecmp(test_name,"UUID") == 0)) {
1260       scan_omni_args(argc, argv);
1261     }
1262 #endif
1263 
1264     /* what is our default value for the output units?  if the test
1265        name contains "RR" or "rr" or "Rr" or "rR" then the default is
1266        'x' for transactions. otherwise it is 'm' for megabits (10^6)
1267        however...  if this is an "omni" test then we want to defer
1268        this decision to scan_omni_args */
1269 
1270     if (strcasecmp(test_name,"omni")) {
1271       if ('?' == libfmt) {
1272 	/* we use a series of strstr's here because not everyone has
1273 	   strcasestr and I don't feel like up or downshifting text */
1274 	if ((strstr(test_name,"RR")) ||
1275 	    (strstr(test_name,"rr")) ||
1276 	    (strstr(test_name,"Rr")) ||
1277 	    (strstr(test_name,"rR"))) {
1278 	  libfmt = 'x';
1279 	}
1280 	else {
1281 	  libfmt = 'm';
1282 	}
1283       }
1284       else if ('x' == libfmt) {
1285 	/* now, a format of 'x' makes no sense for anything other than
1286 	   an RR test. if someone has been silly enough to try to set
1287 	   that, we will reset it silently to default - namely 'm' */
1288 	if ((strstr(test_name,"RR") == NULL) &&
1289 	    (strstr(test_name,"rr") == NULL) &&
1290 	    (strstr(test_name,"Rr") == NULL) &&
1291 	    (strstr(test_name,"rR") == NULL)) {
1292 	  libfmt = 'm';
1293 	}
1294       }
1295     }
1296 }
1297 
1298 
1299 void
dump_globals()1300 dump_globals()
1301 {
1302   printf("Program name: %s\n", program);
1303   printf("Local send alignment: %d\n",local_send_align);
1304   printf("Local recv alignment: %d\n",local_recv_align);
1305   printf("Remote send alignment: %d\n",remote_send_align);
1306   printf("Remote recv alignment: %d\n",remote_recv_align);
1307   printf("Local socket priority: %d\n", local_socket_prio);
1308   printf("Remote socket priority: %d\n", remote_socket_prio);
1309   printf("Local socket TOS: %s\n", iptos2str(local_socket_tos));
1310   printf("Remote socket TOS: %s\n", iptos2str(remote_socket_tos));
1311   printf("Report local CPU %d\n",local_cpu_usage);
1312   printf("Report remote CPU %d\n",remote_cpu_usage);
1313   printf("Verbosity: %d\n",verbosity);
1314   printf("Debug: %d\n",debug);
1315   printf("Port: %s\n",test_port);
1316   printf("Test name: %s\n",test_name);
1317   printf("Test bytes: %d Test time: %d Test trans: %d\n",
1318 	 test_bytes,
1319 	 test_time,
1320 	 test_trans);
1321   printf("Host name: %s\n",host_name);
1322   printf("\n");
1323 }
1324