• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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