Home | History | Annotate | Download | only in netperf
      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. */
    295 /* If the second argument is not specified, and there is no comma, */
    296 /* then the value of the second argument will be the same as the */
    297 /* value of the first. If there is a comma, then the value of the */
    298 /* second argument will be the value of the second argument ;-) */
    299 void
    300 break_args(char *s, char *arg1, char *arg2)
    301 
    302 {
    303   char *ns;
    304   ns = strchr(s,',');
    305   if (ns) {
    306     /* there was a comma arg2 should be the second arg*/
    307     *ns++ = '\0';
    308     while ((*arg2++ = *ns++) != '\0');
    309   }
    310   else {
    311     /* there was not a comma, we can use ns as a temp s */
    312     /* and arg2 should be the same value as arg1 */
    313     ns = s;
    314     while ((*arg2++ = *ns++) != '\0');
    315   };
    316   while ((*arg1++ = *s++) != '\0');
    317 }
    318 
    319 /* break_args_explicit
    320 
    321    this routine is somewhat like break_args in that it will separate a
    322    pair of comma-separated values.  however, if there is no comma,
    323    this version will not ass-u-me that arg2 should be the same as
    324    arg1. raj 2005-02-04 */
    325 void
    326 break_args_explicit(char *s, char *arg1, char *arg2)
    327 
    328 {
    329   char *ns;
    330   ns = strchr(s,',');
    331   if (ns) {
    332     /* there was a comma arg2 should be the second arg*/
    333     *ns++ = '\0';
    334     while ((*arg2++ = *ns++) != '\0');
    335   }
    336   else {
    337     /* there was not a comma, so we should make sure that arg2 is \0
    338        lest something become confused. raj 2005-02-04 */
    339     *arg2 = '\0';
    340   };
    341   while ((*arg1++ = *s++) != '\0');
    342 
    343 }
    344 
    345 /* given a string with possible values for setting an address family,
    346    convert that into one of the AF_mumble values - AF_INET, AF_INET6,
    347    AF_UNSPEC as apropriate. the family_string is compared in a
    348    case-insensitive manner */
    349 
    350 int
    351 parse_address_family(char family_string[])
    352 {
    353 
    354   char temp[10];  /* gotta love magic constants :) */
    355 
    356   strncpy(temp,family_string,10);
    357 
    358   if (debug) {
    359     fprintf(where,
    360 	    "Attempting to parse address family from %s derived from %s\n",
    361 	    temp,
    362 	    family_string);
    363   }
    364 #if defined(AF_INET6)
    365   if (strstr(temp,"6")) {
    366     return(AF_INET6);
    367   }
    368 #endif
    369   if (strstr(temp,"inet") ||
    370       strstr(temp,"4")) {
    371     return(AF_INET);
    372   }
    373   if (strstr(temp,"unspec") ||
    374       strstr(temp,"0")) {
    375     return(AF_UNSPEC);
    376   }
    377   fprintf(where,
    378 	  "WARNING! %s not recognized as an address family, using AF_UNPSEC\n",
    379 	  family_string);
    380   fprintf(where,
    381 	  "Are you sure netperf was configured for that address family?\n");
    382   fflush(where);
    383   return(AF_UNSPEC);
    384 }
    385 
    386 
    387 void
    389 set_defaults()
    390 {
    391 
    392   /* stuff to say where this test is going                              */
    393   strcpy(host_name,"");	      /* remote host name or ip addr  */
    394   strcpy(local_host_name,""); /* we want it to be INADDR_ANY */
    395   strcpy(test_name,"TCP_STREAM");	/* which test to run 		*/
    396   strncpy(test_port,"12865",PORTBUFSIZE); /* where is the test waiting    */
    397   strncpy(local_test_port,"0",PORTBUFSIZE);/* INPORT_ANY as it were */
    398   address_family = AF_UNSPEC;
    399   local_address_family = AF_UNSPEC;
    400 
    401   /* output controlling variables                               */
    402   debug			= 0;/* debugging level			*/
    403   print_headers		= 1;/* do print test headers		*/
    404   verbosity		= 1;/* verbosity level			*/
    405   /* cpu variables */
    406   local_cpu_usage	= 0;/* measure local cpu		*/
    407   remote_cpu_usage	= 0;/* what do you think ;-)		*/
    408 
    409   local_cpu_rate	= (float)0.0;
    410   remote_cpu_rate	= (float)0.0;
    411 
    412   /* the end-test conditions for the tests - either transactions, bytes,  */
    413   /* or time. different vars used for clarity - space is cheap ;-)        */
    414   test_time	= 10;	/* test ends by time			*/
    415   test_bytes	= 0;	/* test ends on byte count		*/
    416   test_trans	= 0;	/* test ends on tran count		*/
    417 
    418   /* the alignment conditions for the tests				*/
    419   local_recv_align	= 8;	/* alignment for local receives	*/
    420   local_send_align	= 8;	/* alignment for local sends	*/
    421   remote_recv_align	= 8;	/* alignment for remote receives*/
    422   remote_send_align	= 8;	/* alignment for remote sends	*/
    423 
    424 #ifdef WANT_INTERVALS
    425   /* rate controlling stuff */
    426   interval_usecs  = 0;
    427   interval_wate   = 1;
    428   interval_burst  = 0;
    429 #endif /* WANT_INTERVALS */
    430 
    431 #ifdef DIRTY
    432   /* dirty and clean cache stuff */
    433   loc_dirty_count = 0;
    434   loc_clean_count = 0;
    435   rem_dirty_count = 0;
    436   rem_clean_count = 0;
    437 #endif /* DIRTY */
    438 
    439  /* some of the vairables for confidence intervals... */
    440 
    441   confidence_level = 99;
    442   iteration_min = 1;
    443   iteration_max = 1;
    444   interval = 0.05; /* five percent? */
    445 
    446   no_control = 0;
    447   strcpy(fill_file,"");
    448 }
    449 
    450 
    451 void
    453 print_netserver_usage()
    454 {
    455   fwrite(netserver_usage, sizeof(char), strlen(netserver_usage), stderr);
    456 }
    457 
    458 
    459 void
    461 print_netperf_usage()
    462 {
    463   fwrite(netperf_usage1, sizeof(char), strlen(netperf_usage1),  stderr);
    464   fwrite(netperf_usage2, sizeof(char), strlen(netperf_usage2),  stderr);
    465 }
    466 
    467 void
    468 scan_cmd_line(int argc, char *argv[])
    469 {
    470   extern int	optind;           /* index of first unused arg 	*/
    471   extern char	*optarg;	  /* pointer to option string	*/
    472 
    473   int		c;
    474 
    475   char	arg1[BUFSIZ],  /* argument holders		*/
    476     arg2[BUFSIZ];
    477 
    478   program = (char *)malloc(strlen(argv[0]) + 1);
    479   if (program == NULL) {
    480     printf("malloc(%d) failed!\n", strlen(argv[0]) + 1);
    481     exit(1);
    482   }
    483   strcpy(program, argv[0]);
    484 
    485   /* Go through all the command line arguments and break them */
    486   /* out. For those options that take two parms, specifying only */
    487   /* the first will set both to that value. Specifying only the */
    488   /* second will leave the first untouched. To change only the */
    489   /* first, use the form first, (see the routine break_args.. */
    490 
    491   while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
    492     switch (c) {
    493     case '?':
    494     case 'h':
    495       print_netperf_usage();
    496       exit(1);
    497     case 'a':
    498       /* set local alignments */
    499       break_args(optarg,arg1,arg2);
    500       if (arg1[0]) {
    501 	local_send_align = convert(arg1);
    502       }
    503       if (arg2[0])
    504 	local_recv_align = convert(arg2);
    505       break;
    506     case 'A':
    507       /* set remote alignments */
    508       break_args(optarg,arg1,arg2);
    509       if (arg1[0]) {
    510 	remote_send_align = convert(arg1);
    511       }
    512       if (arg2[0])
    513 	remote_recv_align = convert(arg2);
    514       break;
    515     case 'c':
    516       /* measure local cpu usage please. the user */
    517       /* may have specified the cpu rate as an */
    518       /* optional parm */
    519       if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
    520 	/* there was an optional parm */
    521 	local_cpu_rate = (float)atof(argv[optind]);
    522 	optind++;
    523       }
    524       local_cpu_usage++;
    525       break;
    526     case 'C':
    527       /* measure remote cpu usage please */
    528       if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
    529 	/* there was an optional parm */
    530 	remote_cpu_rate = (float)atof(argv[optind]);
    531 	optind++;
    532       }
    533       remote_cpu_usage++;
    534       break;
    535     case 'd':
    536       debug++;
    537       break;
    538     case 'D':
    539 #if (defined WANT_DEMO)
    540       demo_mode++;
    541       if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
    542 	/* there was an optional parm */
    543 	break_args_explicit(argv[optind],arg1,arg2);
    544 	optind++;
    545 	if (arg1[0]) {
    546 	  demo_interval = atof(arg1) * 1000000.0;
    547 	}
    548 	if (arg2[0]) {
    549 	  demo_units = convert(arg2);
    550 	}
    551       }
    552 #else
    553       printf("Sorry, Demo Mode not configured into this netperf.\n");
    554       printf("please consider reconfiguring netperf with\n");
    555       printf("--enable-demo=yes and recompiling\n");
    556 #endif
    557       break;
    558     case 'f':
    559       /* set the thruput formatting */
    560       libfmt = *optarg;
    561       break;
    562     case 'F':
    563       /* set the fill_file variable for pre-filling buffers */
    564       strcpy(fill_file,optarg);
    565       break;
    566     case 'i':
    567       /* set the iterations min and max for confidence intervals */
    568       break_args(optarg,arg1,arg2);
    569       if (arg1[0]) {
    570 	iteration_max = convert(arg1);
    571       }
    572       if (arg2[0] ) {
    573 	iteration_min = convert(arg2);
    574       }
    575       /* if the iteration_max is < iteration_min make iteration_max
    576 	 equal iteration_min */
    577       if (iteration_max < iteration_min) iteration_max = iteration_min;
    578       /* limit minimum to 3 iterations */
    579       if (iteration_max < 3) iteration_max = 3;
    580       if (iteration_min < 3) iteration_min = 3;
    581       /* limit maximum to 30 iterations */
    582       if (iteration_max > 30) iteration_max = 30;
    583       if (iteration_min > 30) iteration_min = 30;
    584       break;
    585     case 'I':
    586       /* set the confidence level (95 or 99) and width */
    587       break_args(optarg,arg1,arg2);
    588       if (arg1[0]) {
    589 	confidence_level = convert(arg1);
    590       }
    591       if((confidence_level != 95) && (confidence_level != 99)){
    592 	printf("Only 95%% and 99%% confidence level is supported\n");
    593 	exit(1);
    594       }
    595       if (arg2[0] ) {
    596 	interval = (double) convert(arg2)/100;
    597       }
    598       /* make sure that iteration_min and iteration_max are at least
    599 	 at a reasonable default value.  if a -i option has previously
    600 	 been parsed, these will no longer be 1, so we can check
    601 	 against 1 */
    602       if (iteration_min == 1) iteration_min = 3;
    603       if (iteration_max == 1) iteration_max = 10;
    604 
    605       break;
    606     case 'k':
    607       /* local dirty and clean counts */
    608 #ifdef DIRTY
    609       break_args(optarg,arg1,arg2);
    610       if (arg1[0]) {
    611 	loc_dirty_count = convert(arg1);
    612       }
    613       if (arg2[0] ) {
    614 	loc_clean_count = convert(arg2);
    615       }
    616 #else
    617       printf("I don't know how to get dirty.\n");
    618 #endif /* DIRTY */
    619       break;
    620     case 'K':
    621       /* remote dirty and clean counts */
    622 #ifdef DIRTY
    623       break_args(optarg,arg1,arg2);
    624       if (arg1[0]) {
    625 	rem_dirty_count = convert(arg1);
    626       }
    627       if (arg2[0] ) {
    628 	rem_clean_count = convert(arg2);
    629       }
    630 #else
    631       printf("I don't know how to get dirty.\n");
    632 #endif /* DIRTY */
    633       break;
    634     case 'n':
    635       shell_num_cpus = atoi(optarg);
    636       break;
    637     case 'N':
    638       no_control = 1;
    639       break;
    640     case 'o':
    641       /* set the local offsets */
    642       break_args(optarg,arg1,arg2);
    643       if (arg1[0])
    644 	local_send_offset = convert(arg1);
    645       if (arg2[0])
    646 	local_recv_offset = convert(arg2);
    647       break;
    648     case 'O':
    649       /* set the remote offsets */
    650       break_args(optarg,arg1,arg2);
    651       if (arg1[0])
    652 	remote_send_offset = convert(arg1);
    653       if (arg2[0])
    654 	remote_recv_offset = convert(arg2);
    655       break;
    656     case 'P':
    657       /* to print or not to print, that is */
    658       /* the header question */
    659       print_headers = convert(optarg);
    660       break;
    661     case 'r':
    662       /* the user wishes that we declare confidence when hit on the
    663 	 result even if not yet reached on CPU utilization.  only
    664 	 meaningful if cpu util is enabled */
    665       result_confidence_only = 1;
    666       break;
    667     case 't':
    668       /* set the test name */
    669       strcpy(test_name,optarg);
    670       break;
    671     case 'T':
    672       /* We want to set the processor on which netserver or netperf */
    673       /* will run */
    674       break_args(optarg,arg1,arg2);
    675       if (arg1[0]) {
    676 	local_proc_affinity = convert(arg1);
    677 	bind_to_specific_processor(local_proc_affinity,0);
    678       }
    679       if (arg2[0]) {
    680 	remote_proc_affinity = convert(arg2);
    681       }
    682       cpu_binding_requested = 1;
    683       break;
    684     case 'W':
    685       /* set the "width" of the user space data buffer ring. This will */
    686       /* be the number of send_size buffers malloc'd in the tests */
    687       break_args(optarg,arg1,arg2);
    688       if (arg1[0])
    689 	send_width = convert(arg1);
    690       if (arg2[0])
    691 	recv_width = convert(arg2);
    692       break;
    693     case 'l':
    694       /* determine test end conditions */
    695       /* assume a timed test */
    696       test_time = convert(optarg);
    697       test_bytes = test_trans = 0;
    698       if (test_time < 0) {
    699 	test_bytes = -1 * test_time;
    700 	test_trans = test_bytes;
    701 	test_time = 0;
    702       }
    703       break;
    704     case 'v':
    705       /* say how much to say */
    706       verbosity = convert(optarg);
    707       break;
    708     case 'p':
    709       /* specify an alternate port number we use break_args_explicit
    710 	 here to maintain backwards compatibility with previous
    711 	 generations of netperf where having a single value did not
    712 	 set both remote _and_ local port number. raj 2005-02-04 */
    713       break_args_explicit(optarg,arg1,arg2);
    714       if (arg1[0])
    715 	strncpy(test_port,arg1,PORTBUFSIZE);
    716       if (arg2[0])
    717 	strncpy(local_test_port,arg2,PORTBUFSIZE);
    718       break;
    719     case 'H':
    720       /* save-off the host identifying information, use
    721 	 break_args_explicit since passing just one value should not
    722 	 set both */
    723       break_args_explicit(optarg,arg1,arg2);
    724       if (arg1[0])
    725 	strncpy(host_name,arg1,sizeof(host_name));
    726       if (arg2[0])
    727 	address_family = parse_address_family(arg2);
    728       break;
    729     case 'L':
    730       /* save-off the local control socket addressing information. use
    731 	 break_args_explicit since passing just one value should not
    732 	 set both */
    733       break_args_explicit(optarg,arg1,arg2);
    734       if (arg1[0])
    735 	strncpy(local_host_name,arg1,sizeof(local_host_name));
    736       if (arg2[0])
    737 	local_address_family = parse_address_family(arg2);
    738       break;
    739     case 'w':
    740       /* We want to send requests at a certain wate. */
    741       /* Remember that there are 1000000 usecs in a */
    742       /* second, and that the packet rate is */
    743       /* expressed in packets per millisecond. */
    744 #ifdef WANT_INTERVALS
    745       interval_usecs = convert_timespec(optarg);
    746       interval_wate  = interval_usecs / 1000;
    747 #else
    748       fprintf(where,
    749 	      "Packet rate control is not compiled in.\n");
    750 #endif
    751       break;
    752     case 'b':
    753       /* we want to have a burst so many packets per */
    754       /* interval. */
    755 #ifdef WANT_INTERVALS
    756       interval_burst = convert(optarg);
    757 #else
    758       fprintf(where,
    759 	      "Packet burst size is not compiled in. \n");
    760 #endif /* WANT_INTERVALS */
    761       break;
    762     case 'B':
    763       result_brand = malloc(strlen(optarg)+1);
    764       if (NULL != result_brand) {
    765 	strcpy(result_brand,optarg);
    766       }
    767       else {
    768 	fprintf(where,
    769 		"Unable to malloc space for result brand\n");
    770       }
    771       break;
    772     case '4':
    773       address_family = AF_INET;
    774       local_address_family = AF_INET;
    775       break;
    776     case '6':
    777 #if defined(AF_INET6)
    778       address_family = AF_INET6;
    779       local_address_family = AF_INET6;
    780 #else
    781       printf("This netperf was not compiled on an IPv6 capable system!\n");
    782       exit(-1);
    783 #endif
    784       break;
    785     case 'V':
    786       printf("Netperf version %s\n",NETPERF_VERSION);
    787       exit(0);
    788       break;
    789     };
    790   }
    791   /* ok, what should our default hostname and local binding info be?
    792    */
    793   if ('\0' == host_name[0]) {
    794     /* host_name was not set */
    795     switch (address_family) {
    796     case AF_INET:
    797       strcpy(host_name,"localhost");
    798       break;
    799     case AF_UNSPEC:
    800       /* what to do here? case it off the local_address_family I
    801 	 suppose */
    802       switch (local_address_family) {
    803       case AF_INET:
    804       case AF_UNSPEC:
    805 	strcpy(host_name,"localhost");
    806 	break;
    807 #if defined(AF_INET6)
    808       case AF_INET6:
    809 	strcpy(host_name,"::1");
    810 	break;
    811 #endif
    812       default:
    813 	printf("Netperf does not understand %d as an address family\n",
    814 	       address_family);
    815 	exit(-1);
    816       }
    817       break;
    818 #if defined(AF_INET6)
    819     case AF_INET6:
    820       strcpy(host_name,"::1");
    821       break;
    822 #endif
    823     default:
    824       printf("Netperf does not understand %d as an address family\n",
    825 	     address_family);
    826       exit(-1);
    827     }
    828   }
    829 
    830   /* now, having established the name to which the control will
    831      connect, from what should it come? */
    832   if ('\0' == local_host_name[0]) {
    833     switch (local_address_family) {
    834     case AF_INET:
    835       strcpy(local_host_name,"0.0.0.0");
    836       break;
    837     case AF_UNSPEC:
    838       switch (address_family) {
    839       case AF_INET:
    840       case AF_UNSPEC:
    841 	strcpy(local_host_name,"0.0.0.0");
    842 	break;
    843 #if defined(AF_INET6)
    844       case AF_INET6:
    845 	strcpy(local_host_name,"::0");
    846 	break;
    847 #endif
    848       default:
    849 	printf("Netperf does not understand %d as an address family\n",
    850 	       address_family);
    851 	exit(-1);
    852       }
    853       break;
    854 #if defined(AF_INET6)
    855     case AF_INET6:
    856       strcpy(local_host_name,"::0");
    857       break;
    858 #endif
    859     default:
    860       printf("Netperf does not understand %d as an address family\n",
    861 	     address_family);
    862       exit(-1);
    863     }
    864   }
    865 
    866   /* so, if we aren't even going to establish a control connection we
    867      should set certain "remote" settings to reflect this, regardless
    868      of what else may have been set on the command line */
    869   if (no_control) {
    870     remote_recv_align = -1;
    871     remote_send_align = -1;
    872     remote_send_offset = -1;
    873     remote_recv_offset = -1;
    874     remote_cpu_rate = (float)-1.0;
    875     remote_cpu_usage = 0;
    876   }
    877 
    878   /* parsing test-specific options used to be conditional on there
    879     being a "--" in the option stream.  however, some of the tests
    880     have other initialization happening in their "scan" routines so we
    881     want to call them regardless. raj 2005-02-08 */
    882     if ((strcasecmp(test_name,"TCP_STREAM") == 0) ||
    883 #ifdef HAVE_ICSC_EXS
    884     (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
    885 #endif /* HAVE_ICSC_EXS */
    886 #ifdef HAVE_SENDFILE
    887 	(strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
    888 #endif /* HAVE_SENDFILE */
    889 	(strcasecmp(test_name,"TCP_MAERTS") == 0) ||
    890 	(strcasecmp(test_name,"TCP_RR") == 0) ||
    891 	(strcasecmp(test_name,"TCP_CRR") == 0) ||
    892 	(strcasecmp(test_name,"TCP_CC") == 0) ||
    893 #ifdef DO_1644
    894 	(strcasecmp(test_name,"TCP_TRR") == 0) ||
    895 #endif /* DO_1644 */
    896 #ifdef DO_NBRR
    897 	(strcasecmp(test_name,"TCP_TRR") == 0) ||
    898 #endif /* DO_NBRR */
    899 	(strcasecmp(test_name,"UDP_STREAM") == 0) ||
    900 	(strcasecmp(test_name,"UDP_RR") == 0))
    901       {
    902 	scan_sockets_args(argc, argv);
    903       }
    904 
    905 #ifdef WANT_DLPI
    906     else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
    907 	     (strcasecmp(test_name,"DLCL_RR") == 0) ||
    908 	     (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
    909 	     (strcasecmp(test_name,"DLCL_STREAM") == 0))
    910       {
    911 	scan_dlpi_args(argc, argv);
    912       }
    913 #endif /* WANT_DLPI */
    914 
    915 #ifdef WANT_UNIX
    916     else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
    917 	     (strcasecmp(test_name,"DG_RR") == 0) ||
    918 	     (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
    919 	     (strcasecmp(test_name,"DG_STREAM") == 0))
    920       {
    921 	scan_unix_args(argc, argv);
    922       }
    923 #endif /* WANT_UNIX */
    924 
    925 #ifdef WANT_XTI
    926     else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
    927 	     (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
    928 	     (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
    929 	     (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
    930       {
    931 	scan_xti_args(argc, argv);
    932       }
    933 #endif /* WANT_XTI */
    934 
    935 #ifdef WANT_SCTP
    936     else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
    937 	     (strcasecmp(test_name,"SCTP_RR") == 0) ||
    938 	     (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
    939 	     (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
    940     {
    941       scan_sctp_args(argc, argv);
    942     }
    943 #endif
    944 
    945 #ifdef WANT_SDP
    946     else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
    947 	    (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
    948 	    (strcasecmp(test_name,"SDP_RR") == 0))
    949       {
    950 	scan_sdp_args(argc, argv);
    951       }
    952 #endif
    953 
    954     /* what is our default value for the output units?  if the test
    955        name contains "RR" or "rr" or "Rr" or "rR" then the default is
    956        'x' for transactions. otherwise it is 'm' for megabits
    957        (10^6) */
    958 
    959     if ('?' == libfmt) {
    960       /* we use a series of strstr's here because not everyone has
    961 	 strcasestr and I don't feel like up or downshifting text */
    962       if ((strstr(test_name,"RR")) ||
    963 	  (strstr(test_name,"rr")) ||
    964 	  (strstr(test_name,"Rr")) ||
    965 	  (strstr(test_name,"rR"))) {
    966 	libfmt = 'x';
    967       }
    968       else {
    969 	libfmt = 'm';
    970       }
    971     }
    972     else if ('x' == libfmt) {
    973       /* now, a format of 'x' makes no sense for anything other than
    974 	 an RR test. if someone has been silly enough to try to set
    975 	 that, we will reset it silently to default - namely 'm' */
    976       if ((strstr(test_name,"RR") == NULL) &&
    977 	  (strstr(test_name,"rr") == NULL) &&
    978 	  (strstr(test_name,"Rr") == NULL) &&
    979 	  (strstr(test_name,"rR") == NULL)) {
    980 	libfmt = 'm';
    981       }
    982     }
    983 }
    984 
    985 
    986 void
    988 dump_globals()
    989 {
    990   printf("Program name: %s\n", program);
    991   printf("Local send alignment: %d\n",local_send_align);
    992   printf("Local recv alignment: %d\n",local_recv_align);
    993   printf("Remote send alignment: %d\n",remote_send_align);
    994   printf("Remote recv alignment: %d\n",remote_recv_align);
    995   printf("Report local CPU %d\n",local_cpu_usage);
    996   printf("Report remote CPU %d\n",remote_cpu_usage);
    997   printf("Verbosity: %d\n",verbosity);
    998   printf("Debug: %d\n",debug);
    999   printf("Port: %s\n",test_port);
   1000   printf("Test name: %s\n",test_name);
   1001   printf("Test bytes: %d Test time: %d Test trans: %d\n",
   1002 	 test_bytes,
   1003 	 test_time,
   1004 	 test_trans);
   1005   printf("Host name: %s\n",host_name);
   1006   printf("\n");
   1007 }
   1008