The Android Open Source Project | 02fb0ac | 2009-03-03 19:30:07 -0800 | [diff] [blame] | 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 |
| 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 |
| 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 |
| 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 |
| 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 |
| 450 | print_netserver_usage() |
| 451 | { |
| 452 | fwrite(netserver_usage, sizeof(char), strlen(netserver_usage), stderr); |
| 453 | } |
| 454 | |
| 455 | |
| 456 | void |
| 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 |
| 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) { |
Mark Salyzyn | 1a75dd0 | 2014-04-25 14:43:58 -0700 | [diff] [blame] | 476 | printf("malloc(%zu) failed!\n", strlen(argv[0]) + 1); |
The Android Open Source Project | 02fb0ac | 2009-03-03 19:30:07 -0800 | [diff] [blame] | 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 |
| 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 | } |