1 #ifdef HAVE_CONFIG_H 2 #include <config.h> 3 #endif 4 5 #ifdef WANT_OMNI 6 char nettest_omni_id[]="\ 7 @(#)nettest_omni.c (c) Copyright 2008-2012 Hewlett-Packard Co. Version 2.6.0"; 8 9 #include <stdio.h> 10 #if HAVE_SYS_TYPES_H 11 # include <sys/types.h> 12 #endif 13 #if HAVE_SYS_STAT_H 14 # include <sys/stat.h> 15 #endif 16 #if STDC_HEADERS 17 # include <stdlib.h> 18 # include <stddef.h> 19 #else 20 # if HAVE_STDLIB_H 21 # include <stdlib.h> 22 # endif 23 #endif 24 #if HAVE_STRING_H 25 # if !STDC_HEADERS && HAVE_MEMORY_H 26 # include <memory.h> 27 # endif 28 # include <string.h> 29 #endif 30 #if HAVE_STRINGS_H 31 # include <strings.h> 32 #endif 33 #if HAVE_INTTYPES_H 34 # include <inttypes.h> 35 #else 36 # if HAVE_STDINT_H 37 # include <stdint.h> 38 # endif 39 #endif 40 #if HAVE_UNISTD_H 41 # include <unistd.h> 42 #endif 43 #if HAVE_SYS_IOCTL_H 44 # include <sys/ioctl.h> 45 #endif 46 #if HAVE_SCHED_H 47 # include <sched.h> 48 #endif 49 50 #include <fcntl.h> 51 #ifndef WIN32 52 #include <errno.h> 53 #include <signal.h> 54 #endif 55 56 #if TIME_WITH_SYS_TIME 57 # include <sys/time.h> 58 # include <time.h> 59 #else 60 # if HAVE_SYS_TIME_H 61 # include <sys/time.h> 62 # else 63 # include <time.h> 64 # endif 65 #endif 66 67 #include <ctype.h> 68 69 #ifdef NOSTDLIBH 70 #include <malloc.h> 71 #endif /* NOSTDLIBH */ 72 73 #include <assert.h> 74 75 #ifndef WIN32 76 #include <sys/socket.h> 77 #include <netinet/in.h> 78 79 /* it would seem that including both <netinet/tcp.h> and <linux/tcp.h> 80 is not a path to happiness and joy when one wishes to grab tcp_info 81 stats and not get something like the compiler complaining about 82 either redefinitions, or missing tcpi_total_retrans. */ 83 #ifdef HAVE_LINUX_TCP_H 84 #include <linux/tcp.h> 85 #else 86 #include <netinet/tcp.h> 87 #endif 88 89 /* this is to get us the definition of MSG_FASTOPEN. we may need to 90 cheat just a litle at first */ 91 #ifdef HAVE_LINUX_SOCKET_H 92 # include <linux/socket.h> 93 # ifndef MSG_FASTOPEN 94 # warning Using our own value for MSG_FASTOPEN 95 # define MSG_FASTOPEN 0x20000000 /* Send data in TCP SYN */ 96 # endif 97 # ifndef TCP_FASTOPEN 98 # warning Using our own value for TCP_FASTOPEN 99 # define TCP_FASTOPEN 23 100 # endif 101 #endif 102 103 #ifdef HAVE_NETINET_SCTP_H 104 #include <netinet/sctp.h> 105 #endif 106 107 #include <arpa/inet.h> 108 #include <netdb.h> 109 #else /* WIN32 */ 110 #include <process.h> 111 #define netperf_socklen_t socklen_t 112 #include <winsock2.h> 113 /* while it is unlikely that anyone running Windows 2000 or NT 4 is 114 going to be trying to compile this, if they are they will want to 115 define DONT_IPV6 in the sources file */ 116 #ifndef DONT_IPV6 117 #include <ws2tcpip.h> 118 #endif 119 #include <windows.h> 120 121 #define sleep(x) Sleep((x)*1000) 122 123 #include "missing\stdint.h" 124 #endif /* WIN32 */ 125 126 /* We don't want to use bare constants in the shutdown() call. In the 127 extremely unlikely event that SHUT_WR isn't defined, we will define 128 it to the value we used to be passing to shutdown() anyway. raj 129 2007-02-08 */ 130 #if !defined(SHUT_WR) 131 #define SHUT_WR 1 132 #endif 133 134 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) 135 # include "missing/getaddrinfo.h" 136 #endif 137 138 #include "netlib.h" 139 #include "netsh.h" 140 #include "nettest_bsd.h" 141 142 /* we only really use this once, but the initial patch to 143 src/nettest_bsd.c used it in several places. keep it as a macro 144 just for kicks and just in case we do end-up needing to use it 145 multiple times. */ 146 147 #define WAIT_BEFORE_DATA_TRAFFIC() \ 148 { \ 149 if (wait_time_secs) \ 150 sleep(wait_time_secs); \ 151 } \ 152 153 154 /* since someone can ask for latency stats, we will always include 155 this and do the other other things */ 156 #include "hist.h" 157 158 static HIST time_hist; 159 160 161 162 #ifdef WANT_INTERVALS 163 int interval_count; 164 unsigned int interval_wait_microseconds; 165 166 /* hoist the timestamps up here so we can use them to factor-out the 167 time spent "waiting" */ 168 /* first out timestamp */ 169 #ifdef HAVE_GETHRTIME 170 static hrtime_t intvl_one; 171 static hrtime_t intvl_two; 172 static hrtime_t intvl_wait_start; 173 static hrtime_t *intvl_one_ptr = &intvl_one; 174 static hrtime_t *intvl_two_ptr = &intvl_two; 175 static hrtime_t *temp_intvl_ptr = &intvl_one; 176 #elif defined(WIN32) 177 static LARGE_INTEGER intvl_one; 178 static LARGE_INTEGER intvl_two; 179 static LARGE_INTEGER intvl_wait_start; 180 static LARGE_INTEGER *intvl_one_ptr = &intvl_one; 181 static LARGE_INTEGER *intvl_two_ptr = &intvl_two; 182 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one; 183 #else 184 static struct timeval intvl_one; 185 static struct timeval intvl_two; 186 static struct timeval intvl_wait_start; 187 static struct timeval *intvl_one_ptr = &intvl_one; 188 static struct timeval *intvl_two_ptr = &intvl_two; 189 static struct timeval *temp_intvl_ptr = &intvl_one; 190 #endif 191 192 #ifndef WANT_SPIN 193 #ifdef WIN32 194 #define INTERVALS_INIT() \ 195 if (interval_burst) { \ 196 /* zero means that we never pause, so we never should need the \ 197 interval timer. we used to use it for demo mode, but we deal \ 198 with that with a variant on watching the clock rather than \ 199 waiting for a timer. raj 2006-02-06 */ \ 200 start_itimer(interval_wate); \ 201 } \ 202 interval_count = interval_burst; \ 203 interval_wait_microseconds = 0; 204 #else 205 sigset_t signal_set; 206 #define INTERVALS_INIT() \ 207 if (interval_burst) { \ 208 /* zero means that we never pause, so we never should need the \ 209 interval timer. we used to use it for demo mode, but we deal \ 210 with that with a variant on watching the clock rather than \ 211 waiting for a timer. raj 2006-02-06 */ \ 212 start_itimer(interval_wate); \ 213 } \ 214 interval_count = interval_burst; \ 215 interval_wait_microseconds = 0; \ 216 /* get the signal set for the call to sigsuspend */ \ 217 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \ 218 fprintf(where, \ 219 "%s: unable to get sigmask errno %d\n", \ 220 __FUNCTION__, \ 221 errno); \ 222 fflush(where); \ 223 exit(1); \ 224 } 225 #endif /* WIN32 */ 226 227 #ifdef WIN32 228 #define INTERVALS_WAIT() \ 229 /* in this case, the interval count is the count-down counter \ 230 to decide to sleep for a little bit */ \ 231 if ((interval_burst) && (--interval_count == 0)) { \ 232 /* call WaitForSingleObject and wait for the interval timer to get us \ 233 out */ \ 234 if (debug > 1) { \ 235 fprintf(where,"about to suspend\n"); \ 236 fflush(where); \ 237 } \ 238 HIST_timestamp(&intvl_wait_start); \ 239 if (WaitForSingleObject(WinTimer, INFINITE) != WAIT_OBJECT_0) { \ 240 fprintf(where, "WaitForSingleObject failed (%d)\n", GetLastError()); \ 241 fflush(where); \ 242 exit(1); \ 243 } \ 244 HIST_timestamp(&intvl_two); \ 245 interval_wait_microseconds += \ 246 delta_micro(&intvl_wait_start,&intvl_two); \ 247 interval_count = interval_burst; \ 248 } 249 #else 250 #define INTERVALS_WAIT() \ 251 /* in this case, the interval count is the count-down couter \ 252 to decide to sleep for a little bit */ \ 253 if ((interval_burst) && (--interval_count == 0)) { \ 254 /* call sigsuspend and wait for the interval timer to get us \ 255 out */ \ 256 if (debug > 1) { \ 257 fprintf(where,"about to suspend\n"); \ 258 fflush(where); \ 259 } \ 260 HIST_timestamp(&intvl_wait_start); \ 261 if (sigsuspend(&signal_set) == EFAULT) { \ 262 fprintf(where, \ 263 "%s: fault with sigsuspend.\n", \ 264 __FUNCTION__); \ 265 fflush(where); \ 266 exit(1); \ 267 } \ 268 HIST_timestamp(&intvl_two); \ 269 interval_wait_microseconds += \ 270 delta_micro(&intvl_wait_start,&intvl_two); \ 271 interval_count = interval_burst; \ 272 } 273 #endif /* WIN32 */ 274 #else 275 276 #define INTERVALS_INIT() \ 277 if (interval_burst) { \ 278 HIST_timestamp(intvl_one_ptr); \ 279 } \ 280 interval_wait_microseconds = 0; \ 281 interval_count = interval_burst; \ 282 283 #define INTERVALS_WAIT() \ 284 /* in this case, the interval count is the count-down couter \ 285 to decide to sleep for a little bit */ \ 286 if ((interval_burst) && (--interval_count == 0)) { \ 287 /* spin and wait for the interval timer to get us \ 288 out */ \ 289 if (debug > 1) { \ 290 fprintf(where,"about to spin suspend\n"); \ 291 fflush(where); \ 292 } \ 293 \ 294 HIST_timestamp(&intvl_wait_start); \ 295 do { \ 296 HIST_timestamp(intvl_two_ptr); } \ 297 while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs); \ 298 interval_wait_microseconds += \ 299 delta_micro(&intvl_wait_start,&intvl_two); \ 300 temp_intvl_ptr = intvl_one_ptr; \ 301 intvl_one_ptr = intvl_two_ptr; \ 302 intvl_two_ptr = temp_intvl_ptr; \ 303 interval_count = interval_burst; \ 304 } 305 #endif 306 #endif 307 308 #define NETPERF_WAITALL 0x1 309 310 extern void get_uuid_string(char *string, size_t size); 311 312 /* a boatload of globals while I settle things out */ 313 char *output_selection_spec = NULL; 314 315 char test_uuid[38]; 316 317 double result_confid_pct = -1.0; 318 double loc_cpu_confid_pct = -1.0; 319 double rem_cpu_confid_pct = -1.0; 320 double interval_pct = -1.0; 321 322 int protocol; 323 int direction; 324 int remote_send_size = -1; 325 int remote_recv_size = -1; 326 int remote_send_size_req = -1; 327 int remote_recv_size_req = -1; 328 int remote_use_sendfile; 329 330 extern int loc_dirty_count; 331 extern int loc_clean_count; 332 extern int rem_dirty_count; 333 extern int rem_clean_count; 334 int remote_checksum_off; 335 int connection_test; 336 int dont_give_up = 0; 337 int use_fastopen = 0; 338 int use_write = 0; 339 int need_to_connect; 340 int need_connection; 341 int bytes_to_send; 342 double bytes_per_send; 343 int failed_sends; 344 int bytes_to_recv; 345 double bytes_per_recv; 346 int null_message_ok = 0; 347 348 int was_legacy = 0; 349 int legacy = 0; 350 int implicit_direction = 0; 351 int explicit_data_address = 0; 352 int want_defer_accept = 0; 353 354 uint64_t trans_completed = 0; 355 int64_t units_remaining; 356 uint64_t bytes_sent = 0; 357 uint64_t bytes_received = 0; 358 uint64_t local_send_calls = 0; 359 uint64_t local_receive_calls = 0; 360 uint64_t remote_bytes_sent; 361 uint64_t remote_bytes_received; 362 uint64_t remote_send_calls; 363 uint64_t remote_receive_calls; 364 double bytes_xferd; 365 double remote_bytes_xferd; 366 double remote_bytes_per_recv; 367 double remote_bytes_per_send; 368 float elapsed_time; 369 float local_cpu_utilization; 370 float local_service_demand; 371 float remote_cpu_utilization; 372 float remote_service_demand; 373 double thruput; 374 double local_send_thruput; 375 double local_recv_thruput; 376 double remote_send_thruput; 377 double remote_recv_thruput; 378 379 /* kludges for omni output */ 380 double elapsed_time_double; 381 double local_service_demand_double; 382 double remote_service_demand_double; 383 double transaction_rate = 1.0; 384 double rtt_latency = -1.0; 385 int32_t transport_mss = -2; 386 int32_t local_transport_retrans = -2; 387 int32_t remote_transport_retrans = -2; 388 char *deprecated_str = "Deprecated"; 389 int remote_interface_vendor = -2; 390 int remote_interface_device = -2; 391 int remote_interface_subvendor = -2; 392 int remote_interface_subdevice = -2; 393 int local_interface_vendor = -2; 394 int local_interface_device = -2; 395 int local_interface_subvendor = -2; 396 int local_interface_subdevice = -2; 397 int local_cpu_frequency = 0; 398 int remote_cpu_frequency = 0; 399 400 int local_security_type_id; 401 int local_security_enabled_num; 402 int remote_security_type_id; 403 int remote_security_enabled_num; 404 405 char local_cong_control[16] = ""; 406 char remote_cong_control[16] = ""; 407 char local_cong_control_req[16] = ""; 408 char remote_cong_control_req[16] = ""; 409 410 int receive_timeout = -1; 411 412 /* new statistics based on code diffs from Google, with raj's own 413 personal twist added to make them compatible with the omni 414 tests... 20100913 */ 415 416 /* min and max "latency" */ 417 int min_latency = -1, max_latency = -1; 418 /* the percentiles */ 419 int p50_latency = -1, p90_latency = -1, p99_latency = -1; 420 /* mean and stddev - while the mean is reduntant with the *_RR test we 421 keep it because it won't be for other tests */ 422 double mean_latency = -1.0, stddev_latency = -1.0; 423 424 /* default to zero to avoid randomizing */ 425 int local_mask_len = 0; 426 int remote_mask_len = 0; 427 428 int printing_initialized = 0; 429 430 char *sd_str; 431 char *thruput_format_str; 432 433 char *socket_type_str; 434 char *protocol_str; 435 char *direction_str; 436 437 extern int first_burst_size; 438 439 int parallel_connections = 1; 440 441 static int socket_debug = 0; 442 443 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun)) 444 #include <sys/sendfile.h> 445 #endif /* HAVE_SENDFILE && (__linux || __sun) */ 446 447 static int confidence_iteration; 448 449 static int local_cpu_method; 450 static int remote_cpu_method; 451 452 /* these will control the width of port numbers we try to use in the */ 453 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */ 454 static int client_port_min = 5000; 455 static int client_port_max = 65535; 456 457 /* different options for the sockets */ 458 459 int 460 loc_nodelay, /* don't/do use NODELAY locally */ 461 rem_nodelay, /* don't/do use NODELAY remotely */ 462 loc_sndavoid, /* avoid send copies locally */ 463 loc_rcvavoid, /* avoid recv copies locally */ 464 rem_sndavoid, /* avoid send copies remotely */ 465 rem_rcvavoid; /* avoid recv_copies remotely */ 466 467 extern int 468 loc_tcpcork, 469 rem_tcpcork, 470 local_connected, 471 remote_connected; 472 473 enum netperf_output_type { 474 NETPERF_TYPE_UNKNOWN, 475 NETPERF_TYPE_UINT32, 476 NETPERF_TYPE_INT32, 477 NETPERF_TYPE_UINT64, 478 NETPERF_TYPE_INT64, 479 NETPERF_TYPE_CHAR, 480 NETPERF_TYPE_FLOAT, 481 NETPERF_TYPE_DOUBLE, 482 }; 483 484 /* you should add to this in the order in which they should appear in 485 the default csv (everything) output */ 486 487 enum netperf_output_name { 488 NETPERF_OUTPUT_UNKNOWN, 489 OUTPUT_NONE, 490 SOCKET_TYPE, 491 PROTOCOL, 492 DIRECTION, 493 ELAPSED_TIME, 494 THROUGHPUT, 495 THROUGHPUT_UNITS, 496 LSS_SIZE_REQ, 497 LSS_SIZE, 498 LSS_SIZE_END, 499 LSR_SIZE_REQ, 500 LSR_SIZE, 501 LSR_SIZE_END, 502 RSS_SIZE_REQ, 503 RSS_SIZE, 504 RSS_SIZE_END, 505 RSR_SIZE_REQ, 506 RSR_SIZE, 507 RSR_SIZE_END, 508 LOCAL_SEND_SIZE, 509 LOCAL_RECV_SIZE, 510 REMOTE_SEND_SIZE, 511 REMOTE_RECV_SIZE, 512 REQUEST_SIZE, 513 RESPONSE_SIZE, 514 LOCAL_CPU_UTIL, 515 LOCAL_CPU_PERCENT_USER, 516 LOCAL_CPU_PERCENT_SYSTEM, 517 LOCAL_CPU_PERCENT_IOWAIT, 518 LOCAL_CPU_PERCENT_IRQ, 519 LOCAL_CPU_PERCENT_SWINTR, 520 LOCAL_CPU_METHOD, 521 LOCAL_SD, 522 REMOTE_CPU_UTIL, 523 REMOTE_CPU_PERCENT_USER, 524 REMOTE_CPU_PERCENT_SYSTEM, 525 REMOTE_CPU_PERCENT_IOWAIT, 526 REMOTE_CPU_PERCENT_IRQ, 527 REMOTE_CPU_PERCENT_SWINTR, 528 REMOTE_CPU_METHOD, 529 REMOTE_SD, 530 SD_UNITS, 531 CONFIDENCE_LEVEL, 532 CONFIDENCE_INTERVAL, 533 CONFIDENCE_ITERATION, 534 THROUGHPUT_CONFID, 535 LOCAL_CPU_CONFID, 536 REMOTE_CPU_CONFID, 537 TRANSACTION_RATE, 538 RT_LATENCY, 539 BURST_SIZE, 540 LOCAL_TRANSPORT_RETRANS, 541 REMOTE_TRANSPORT_RETRANS, 542 TRANSPORT_MSS, 543 LOCAL_SEND_THROUGHPUT, 544 LOCAL_RECV_THROUGHPUT, 545 REMOTE_SEND_THROUGHPUT, 546 REMOTE_RECV_THROUGHPUT, 547 LOCAL_CPU_BIND, 548 LOCAL_CPU_COUNT, 549 LOCAL_CPU_PEAK_UTIL, 550 LOCAL_CPU_PEAK_ID, 551 LOCAL_CPU_MODEL, 552 LOCAL_CPU_FREQUENCY, 553 REMOTE_CPU_BIND, 554 REMOTE_CPU_COUNT, 555 REMOTE_CPU_PEAK_UTIL, 556 REMOTE_CPU_PEAK_ID, 557 REMOTE_CPU_MODEL, 558 REMOTE_CPU_FREQUENCY, 559 SOURCE_PORT, 560 SOURCE_ADDR, 561 SOURCE_FAMILY, 562 DEST_PORT, 563 DEST_ADDR, 564 DEST_FAMILY, 565 LOCAL_SEND_CALLS, 566 LOCAL_RECV_CALLS, 567 LOCAL_BYTES_PER_RECV, 568 LOCAL_BYTES_PER_SEND, 569 LOCAL_BYTES_SENT, 570 LOCAL_BYTES_RECVD, 571 LOCAL_BYTES_XFERD, 572 LOCAL_SEND_OFFSET, 573 LOCAL_RECV_OFFSET, 574 LOCAL_SEND_ALIGN, 575 LOCAL_RECV_ALIGN, 576 LOCAL_SEND_WIDTH, 577 LOCAL_RECV_WIDTH, 578 LOCAL_SEND_DIRTY_COUNT, 579 LOCAL_RECV_DIRTY_COUNT, 580 LOCAL_RECV_CLEAN_COUNT, 581 LOCAL_NODELAY, 582 LOCAL_CORK, 583 REMOTE_SEND_CALLS, 584 REMOTE_RECV_CALLS, 585 REMOTE_BYTES_PER_RECV, 586 REMOTE_BYTES_PER_SEND, 587 REMOTE_BYTES_SENT, 588 REMOTE_BYTES_RECVD, 589 REMOTE_BYTES_XFERD, 590 REMOTE_SEND_OFFSET, 591 REMOTE_RECV_OFFSET, 592 REMOTE_SEND_ALIGN, 593 REMOTE_RECV_ALIGN, 594 REMOTE_SEND_WIDTH, 595 REMOTE_RECV_WIDTH, 596 REMOTE_SEND_DIRTY_COUNT, 597 REMOTE_RECV_DIRTY_COUNT, 598 REMOTE_RECV_CLEAN_COUNT, 599 REMOTE_NODELAY, 600 REMOTE_CORK, 601 LOCAL_SYSNAME, 602 LOCAL_SYSTEM_MODEL, 603 LOCAL_RELEASE, 604 LOCAL_VERSION, 605 LOCAL_MACHINE, 606 REMOTE_SYSNAME, 607 REMOTE_SYSTEM_MODEL, 608 REMOTE_RELEASE, 609 REMOTE_VERSION, 610 REMOTE_MACHINE, 611 LOCAL_INTERFACE_NAME, 612 LOCAL_INTERFACE_VENDOR, 613 LOCAL_INTERFACE_DEVICE, 614 LOCAL_INTERFACE_SUBVENDOR, 615 LOCAL_INTERFACE_SUBDEVICE, 616 LOCAL_DRIVER_NAME, 617 LOCAL_DRIVER_VERSION, 618 LOCAL_DRIVER_FIRMWARE, 619 LOCAL_DRIVER_BUS, 620 LOCAL_INTERFACE_SLOT, 621 REMOTE_INTERFACE_NAME, 622 REMOTE_INTERFACE_VENDOR, 623 REMOTE_INTERFACE_DEVICE, 624 REMOTE_INTERFACE_SUBVENDOR, 625 REMOTE_INTERFACE_SUBDEVICE, 626 REMOTE_DRIVER_NAME, 627 REMOTE_DRIVER_VERSION, 628 REMOTE_DRIVER_FIRMWARE, 629 REMOTE_DRIVER_BUS, 630 REMOTE_INTERFACE_SLOT, 631 LOCAL_INTERVAL_USECS, 632 LOCAL_INTERVAL_BURST, 633 REMOTE_INTERVAL_USECS, 634 REMOTE_INTERVAL_BURST, 635 LOCAL_SECURITY_TYPE_ID, 636 LOCAL_SECURITY_TYPE, 637 LOCAL_SECURITY_ENABLED_NUM, 638 LOCAL_SECURITY_ENABLED, 639 LOCAL_SECURITY_SPECIFIC, 640 REMOTE_SECURITY_TYPE_ID, 641 REMOTE_SECURITY_TYPE, 642 REMOTE_SECURITY_ENABLED_NUM, 643 REMOTE_SECURITY_ENABLED, 644 REMOTE_SECURITY_SPECIFIC, 645 RESULT_BRAND, 646 UUID, 647 MIN_LATENCY, 648 MAX_LATENCY, 649 P50_LATENCY, 650 P90_LATENCY, 651 P99_LATENCY, 652 MEAN_LATENCY, 653 STDDEV_LATENCY, 654 LOCAL_SOCKET_PRIO, 655 REMOTE_SOCKET_PRIO, 656 LOCAL_SOCKET_TOS, 657 REMOTE_SOCKET_TOS, 658 LOCAL_CONG_CONTROL, 659 REMOTE_CONG_CONTROL, 660 LOCAL_FILL_FILE, 661 REMOTE_FILL_FILE, 662 COMMAND_LINE, /* COMMAND_LINE should always be "last" */ 663 OUTPUT_END, 664 NETPERF_OUTPUT_MAX 665 }; 666 667 /* flags for the output groups, lower 16 bits for remote, upper 16 668 bits for local */ 669 670 #define OMNI_WANT_REM_IFNAME 0X00000001 671 #define OMNI_WANT_LOC_IFNAME 0X00010000 672 #define OMNI_WANT_REM_IFSLOT 0X00000002 673 #define OMNI_WANT_LOC_IFSLOT 0X00020000 674 #define OMNI_WANT_REM_IFIDS 0X00000004 675 #define OMNI_WANT_LOC_IFIDS 0X00040000 676 #define OMNI_WANT_REM_DRVINFO 0X00000008 677 #define OMNI_WANT_LOC_DRVINFO 0X00080000 678 #define OMNI_WANT_STATS 0X00100010 679 #define OMNI_WANT_REM_CONG 0X00000020 680 #define OMNI_WANT_LOC_CONG 0X00200000 681 682 unsigned int desired_output_groups = 0; 683 684 typedef struct netperf_output_elt { 685 enum netperf_output_name output_name; /* belt and suspenders */ 686 int max_line_len; /* length of the longest of the "lines" */ 687 int tot_line_len; /* total length of all lines, including spaces */ 688 char *line[4]; 689 char *format; /* format to apply to value */ 690 void *display_value; /* where to find the value */ 691 enum netperf_output_type output_type; /* what type is the value? */ 692 int output_default; /* is it included in the default output */ 693 unsigned int output_group; /* used to avoid some lookups */ 694 } netperf_output_elt_t; 695 696 netperf_output_elt_t netperf_output_source[NETPERF_OUTPUT_MAX]; 697 698 #define NETPERF_MAX_BLOCKS 4 699 700 /* let us simply use one, two-dimensional list, and either use or some 701 of the additional dimension depending on the type of output we are 702 doing. this should help simplify matters. raj 20110120 */ 703 704 enum netperf_output_name output_list[NETPERF_MAX_BLOCKS][NETPERF_OUTPUT_MAX]; 705 706 /* some things for setting the source IP address on outgoing UDP 707 sends. borrows liberally from 708 http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket */ 709 710 int want_use_pktinfo = 0; 711 int use_pktinfo = 0; 712 int have_pktinfo = 0; 713 #ifdef IP_PKTINFO 714 struct in_pktinfo in_pktinfo; 715 #endif 716 717 char *direction_to_str(int direction) { 718 if (NETPERF_RECV_ONLY(direction)) return "Receive"; 719 if (NETPERF_XMIT_ONLY(direction)) return "Send"; 720 if (NETPERF_CC(direction)) return "Connection"; 721 else if (connection_test) { 722 return "Connect|Send|Recv"; 723 } 724 else return "Send|Recv"; 725 } 726 727 static unsigned short 728 get_port_number(struct addrinfo *res) 729 { 730 switch(res->ai_family) { 731 case AF_INET: { 732 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 733 return(ntohs(foo->sin_port)); 734 break; 735 } 736 #if defined(AF_INET6) 737 case AF_INET6: { 738 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 739 return(ntohs(foo->sin6_port)); 740 break; 741 } 742 #endif 743 default: 744 fprintf(where, 745 "Unexpected Address Family %u\n",res->ai_family); 746 fflush(where); 747 exit(-1); 748 } 749 } 750 751 /* does this need to become conditional on the presence of the macros 752 or might we ass-u-me that we will not be compiled on something so 753 old as to not have what we use? raj 20090803 */ 754 static int 755 is_multicast_addr(struct addrinfo *res) { 756 switch(res->ai_family) { 757 case AF_INET: { 758 /* IPv4 multicast runs from 224.0.0.0 to 239.255.255.255 or 759 0xE0000000 to 0xEFFFFFFF. Thankfully though there are macros 760 available to make the checks for one */ 761 struct in_addr bar = ((struct sockaddr_in *)res->ai_addr)->sin_addr; 762 /* and here I thought IN_MULTICAST would operate on things in 763 network byte order??? raj 20100315 */ 764 return IN_MULTICAST(ntohl(bar.s_addr)); 765 } 766 #if defined(AF_INET6) 767 case AF_INET6: { 768 struct in6_addr *bar = &(((struct sockaddr_in6 *)res->ai_addr)->sin6_addr); 769 return IN6_IS_ADDR_MULTICAST(bar); 770 } 771 #endif 772 default: 773 fprintf(where, 774 "Unexpected Address Family for Multicast Check %u\n", 775 res->ai_family); 776 fflush(where); 777 return 0; /* or should we exit? */ 778 } 779 } 780 781 static void 782 set_multicast_ttl(SOCKET sock) { 783 int optlen = sizeof(int); 784 785 /* now set/get the TTL */ 786 if (multicast_ttl >= 0) { 787 if (setsockopt(sock, 788 IPPROTO_IP, 789 #if defined(IP_MULTICAST_TTL) 790 IP_MULTICAST_TTL, 791 #else 792 IP_TTL, 793 #endif 794 (const char *)&multicast_ttl, 795 sizeof(multicast_ttl)) == SOCKET_ERROR) { 796 fprintf(where, 797 "setsockopt(IP_TTL) failed errno %d\n", 798 errno); 799 } 800 } 801 if (getsockopt(sock, 802 IPPROTO_IP, 803 IP_TTL, 804 (char *)&multicast_ttl, 805 (netperf_socklen_t *)&optlen) < 0) { 806 fprintf(where, 807 "getsockopt(IP_TTL) failed errno %d\n", 808 errno); 809 multicast_ttl = -2; 810 } 811 } 812 813 /* we presume we are only called with something which is actually a 814 multicast address. raj 20100315 */ 815 static void 816 join_multicast_addr(SOCKET sock, struct addrinfo *res) { 817 switch(res->ai_family) { 818 case AF_INET: { 819 struct ip_mreq mreq; 820 struct in_addr bar = ((struct sockaddr_in *)res->ai_addr)->sin_addr; 821 int optlen = sizeof(int); 822 int one = 1; 823 824 mreq.imr_multiaddr.s_addr=bar.s_addr; 825 mreq.imr_interface.s_addr=htonl(INADDR_ANY); 826 if (setsockopt(sock, 827 IPPROTO_IP, 828 IP_ADD_MEMBERSHIP, 829 (const char *)&mreq, 830 sizeof(mreq)) == 0) { 831 832 /* let others do the same */ 833 if (setsockopt(sock, 834 SOL_SOCKET, 835 SO_REUSEADDR, 836 (const char *)&one, 837 sizeof(one)) == SOCKET_ERROR) { 838 if (debug) { 839 fprintf(where, 840 "join_multicast_addr SO_REUSADDR failed errno %d\n", 841 errno); 842 fflush(where); 843 } 844 } 845 846 /* now set/get the TTL */ 847 if (multicast_ttl >= 0) { 848 if (setsockopt(sock, 849 IPPROTO_IP, 850 IP_TTL, 851 (const char *)&multicast_ttl, 852 sizeof(multicast_ttl)) == SOCKET_ERROR) { 853 fprintf(where, 854 "setsockopt(IP_TTL) failed errno %d\n", 855 errno); 856 } 857 } 858 if (getsockopt(sock, 859 IPPROTO_IP, 860 IP_TTL, 861 (char *)&multicast_ttl, 862 (netperf_socklen_t *)&optlen) == SOCKET_ERROR) { 863 fprintf(where, 864 "getsockopt(IP_TTL) failed errno %d\n", 865 errno); 866 multicast_ttl = -2; 867 } 868 } 869 else { 870 if (debug) { 871 fprintf(where, 872 "setsockopt(IP_ADD_MEMBERSHIP) failed errno %d\n", 873 errno); 874 fflush(where); 875 } 876 } 877 break; 878 } 879 case AF_INET6: { 880 fprintf(where,"I do not know how to join an IPv6 multicast group\n"); 881 break; 882 } 883 884 } 885 return; 886 } 887 888 static void 889 extract_inet_address_and_port(struct addrinfo *res, void *addr, int len, int *port) 890 { 891 switch(res->ai_family) { 892 case AF_INET: { 893 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 894 *port = foo->sin_port; 895 memcpy(addr,&(foo->sin_addr),min(len,sizeof(foo->sin_addr))); 896 break; 897 } 898 #if defined(AF_INET6) 899 case AF_INET6: { 900 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 901 *port = foo->sin6_port; 902 memcpy(addr,&(foo->sin6_addr),min(len,sizeof(foo->sin6_addr))); 903 break; 904 } 905 #endif 906 default: 907 *port = 0xDEADBEEF; 908 strncpy(addr,"UNKN FAMILY",len); 909 } 910 } 911 912 void 913 pick_next_port_number(struct addrinfo *local_res, struct addrinfo *remote_res) { 914 915 static int myport_init = 0; 916 static unsigned short myport = 0; 917 918 if (0 == myport_init) { 919 /* pick a nice random spot between client_port_min and 920 client_port_max for our initial port number, but only for a 921 connection oriented test. otherwise, we will want to set myport 922 to a specific port provided by the user if they have so provided 923 a specific port :) raj 2008-01-08 */ 924 srand(getpid()); 925 if (client_port_max - client_port_min) { 926 myport = client_port_min + 927 (rand() % (client_port_max - client_port_min)); 928 } 929 else { 930 myport = (unsigned short)client_port_min; 931 } 932 /* there will be a ++ before the first call to bind, so subtract one */ 933 myport--; 934 myport_init = 1; 935 } 936 937 /* newport: */ 938 /* pick a new port number */ 939 myport++; 940 941 /* check to see if we are using the port number on which the 942 server is sitting _before_ we check against the boundaries lest 943 the server sits at the upper boundary. if this happens to be a 944 loopback test, trying to use the same portnumber would lead to 945 unsatisfying results and should be avoided. if this isn't a 946 loopback test, avoiding using the same port number doesn't 947 seriously affect anything anyway */ 948 949 if (myport == get_port_number(remote_res)) myport++; 950 951 /* wrap the port number when we reach the upper bound. for 952 students of networking history, some ancient stacks (1980's and 953 early 1990's perhaps) mistakenly treated these port numbers as 954 signed 16 bit quantities. we make no effort here to support 955 such stacks. raj 2008-01-08 */ 956 if (myport >= client_port_max) { 957 myport = (unsigned short)client_port_min; 958 } 959 960 /* set up the data socket */ 961 set_port_number(local_res, (unsigned short)myport); 962 } 963 964 /* at some point this should become a table lookup... raj 20090813 */ 965 char * 966 netperf_output_enum_to_str(enum netperf_output_name output_name) 967 { 968 switch (output_name) { 969 case OUTPUT_NONE: 970 return "OUTPUT_NONE"; 971 case COMMAND_LINE: 972 return "COMMAND_LINE"; 973 case UUID: 974 return "UUID"; 975 case RESULT_BRAND: 976 return "RESULT_BRAND"; 977 case SOCKET_TYPE: 978 return "SOCKET_TYPE"; 979 case DIRECTION: 980 return "DIRECTION"; 981 case PROTOCOL: 982 return "PROTOCOL"; 983 case ELAPSED_TIME: 984 return "ELAPSED_TIME"; 985 case SOURCE_PORT: 986 return "SOURCE_PORT"; 987 case SOURCE_ADDR: 988 return "SOURCE_ADDR"; 989 case SOURCE_FAMILY: 990 return "SOURCE_FAMILY"; 991 case DEST_PORT: 992 return "DEST_PORT"; 993 case DEST_ADDR: 994 return "DEST_ADDR"; 995 case DEST_FAMILY: 996 return "DEST_FAMILY"; 997 case THROUGHPUT: 998 return "THROUGHPUT"; 999 case LOCAL_SEND_THROUGHPUT: 1000 return "LOCAL_SEND_THROUGHPUT"; 1001 case LOCAL_RECV_THROUGHPUT: 1002 return "LOCAL_RECV_THROUGHPUT"; 1003 case REMOTE_SEND_THROUGHPUT: 1004 return "REMOTE_SEND_THROUGHPUT"; 1005 case REMOTE_RECV_THROUGHPUT: 1006 return "REMOTE_RECV_THROUGHPUT"; 1007 case THROUGHPUT_UNITS: 1008 return "THROUGHPUT_UNITS"; 1009 case CONFIDENCE_LEVEL: 1010 return "CONFIDENCE_LEVEL"; 1011 case CONFIDENCE_INTERVAL: 1012 return "CONFIDENCE_INTERVAL"; 1013 case CONFIDENCE_ITERATION: 1014 return "CONFIDENCE_ITERATION"; 1015 case THROUGHPUT_CONFID: 1016 return "THROUGHPUT_CONFID"; 1017 case LOCAL_CPU_CONFID: 1018 return "LOCAL_CPU_CONFID"; 1019 case REMOTE_CPU_CONFID: 1020 return "REMOTE_CPU_CONFID"; 1021 case RT_LATENCY: 1022 return "RT_LATENCY"; 1023 case TRANSACTION_RATE: 1024 return "TRANSACTION_RATE"; 1025 case BURST_SIZE: 1026 return "BURST_SIZE"; 1027 case LOCAL_TRANSPORT_RETRANS: 1028 return "LOCAL_TRANSPORT_RETRANS"; 1029 case REMOTE_TRANSPORT_RETRANS: 1030 return "REMOTE_TRANSPORT_RETRANS"; 1031 case TRANSPORT_MSS: 1032 return "TRANSPORT_MSS"; 1033 case REQUEST_SIZE: 1034 return "REQUEST_SIZE"; 1035 case RESPONSE_SIZE: 1036 return "RESPONSE_SIZE"; 1037 case LSS_SIZE_REQ: 1038 return "LSS_SIZE_REQ"; 1039 case LSS_SIZE: 1040 return "LSS_SIZE"; 1041 case LSS_SIZE_END: 1042 return "LSS_SIZE_END"; 1043 case LSR_SIZE_REQ: 1044 return "LSR_SIZE_REQ"; 1045 case LSR_SIZE: 1046 return "LSR_SIZE"; 1047 case LSR_SIZE_END: 1048 return "LSR_SIZE_END"; 1049 case LOCAL_SEND_SIZE: 1050 return "LOCAL_SEND_SIZE"; 1051 case LOCAL_RECV_SIZE: 1052 return "LOCAL_RECV_SIZE"; 1053 case LOCAL_SEND_CALLS: 1054 return "LOCAL_SEND_CALLS"; 1055 case LOCAL_RECV_CALLS: 1056 return "LOCAL_RECV_CALLS"; 1057 case LOCAL_BYTES_PER_RECV: 1058 return "LOCAL_BYTES_PER_RECV"; 1059 case LOCAL_BYTES_PER_SEND: 1060 return "LOCAL_BYTES_PER_SEND"; 1061 case LOCAL_BYTES_SENT: 1062 return "LOCAL_BYTES_SENT"; 1063 case LOCAL_BYTES_RECVD: 1064 return "LOCAL_BYTES_RECVD"; 1065 case LOCAL_BYTES_XFERD: 1066 return "LOCAL_BYTES_XFERD"; 1067 case LOCAL_SEND_OFFSET: 1068 return "LOCAL_SEND_OFFSET"; 1069 case LOCAL_RECV_OFFSET: 1070 return "LOCAL_RECV_OFFSET"; 1071 case LOCAL_RECV_ALIGN: 1072 return "LOCAL_RECV_ALIGN"; 1073 case LOCAL_SEND_ALIGN: 1074 return "LOCAL_SEND_ALIGN"; 1075 case LOCAL_SEND_WIDTH: 1076 return "LOCAL_SEND_WIDTH"; 1077 case LOCAL_RECV_WIDTH: 1078 return "LOCAL_RECV_WIDTH"; 1079 case LOCAL_SEND_DIRTY_COUNT: 1080 return "LOCAL_SEND_DIRTY_COUNT"; 1081 case LOCAL_RECV_DIRTY_COUNT: 1082 return "LOCAL_RECV_DIRTY_COUNT"; 1083 case LOCAL_RECV_CLEAN_COUNT: 1084 return "LOCAL_RECV_CLEAN_COUNT"; 1085 case LOCAL_CPU_UTIL: 1086 return "LOCAL_CPU_UTIL"; 1087 case LOCAL_CPU_PERCENT_USER: 1088 return "LOCAL_CPU_PERCENT_USER"; 1089 case LOCAL_CPU_PERCENT_SYSTEM: 1090 return "LOCAL_CPU_PERCENT_SYSTEM"; 1091 case LOCAL_CPU_PERCENT_IOWAIT: 1092 return "LOCAL_CPU_PERCENT_IOWAIT"; 1093 case LOCAL_CPU_PERCENT_IRQ: 1094 return "LOCAL_CPU_PERCENT_IRQ"; 1095 case LOCAL_CPU_PERCENT_SWINTR: 1096 return "LOCAL_CPU_PERCENT_SWINTR"; 1097 case LOCAL_CPU_BIND: 1098 return "LOCAL_CPU_BIND"; 1099 case LOCAL_SD: 1100 return "LOCAL_SD"; 1101 case SD_UNITS: 1102 return "SD_UNITS"; 1103 case LOCAL_CPU_METHOD: 1104 return "LOCAL_CPU_METHOD"; 1105 case LOCAL_CPU_COUNT: 1106 return "LOCAL_CPU_COUNT"; 1107 case LOCAL_CPU_PEAK_UTIL: 1108 return "LOCAL_CPU_PEAK_UTIL"; 1109 case LOCAL_CPU_PEAK_ID: 1110 return "LOCAL_CPU_PEAK_ID"; 1111 case LOCAL_NODELAY: 1112 return "LOCAL_NODELAY"; 1113 case LOCAL_CORK: 1114 return "LOCAL_CORK"; 1115 case RSS_SIZE_REQ: 1116 return "RSS_SIZE_REQ"; 1117 case RSS_SIZE: 1118 return "RSS_SIZE"; 1119 case RSS_SIZE_END: 1120 return "RSS_SIZE_END"; 1121 case RSR_SIZE_REQ: 1122 return "RSR_SIZE_REQ"; 1123 case RSR_SIZE: 1124 return "RSR_SIZE"; 1125 case RSR_SIZE_END: 1126 return "RSR_SIZE_END"; 1127 case REMOTE_SEND_SIZE: 1128 return "REMOTE_SEND_SIZE"; 1129 case REMOTE_RECV_SIZE: 1130 return "REMOTE_RECV_SIZE"; 1131 case REMOTE_SEND_CALLS: 1132 return "REMOTE_SEND_CALLS"; 1133 case REMOTE_RECV_CALLS: 1134 return "REMOTE_RECV_CALLS"; 1135 case REMOTE_BYTES_PER_RECV: 1136 return "REMOTE_BYTES_PER_RECV"; 1137 case REMOTE_BYTES_PER_SEND: 1138 return "REMOTE_BYTES_PER_SEND"; 1139 case REMOTE_BYTES_SENT: 1140 return "REMOTE_BYTES_SENT"; 1141 case REMOTE_BYTES_RECVD: 1142 return "REMOTE_BYTES_RECVD"; 1143 case REMOTE_BYTES_XFERD: 1144 return "REMOTE_BYTES_XFERD"; 1145 case REMOTE_SEND_OFFSET: 1146 return "REMOTE_SEND_OFFSET"; 1147 case REMOTE_RECV_OFFSET: 1148 return "REMOTE_RECV_OFFSET"; 1149 case REMOTE_RECV_ALIGN: 1150 return "REMOTE_RECV_ALIGN"; 1151 case REMOTE_SEND_ALIGN: 1152 return "REMOTE_SEND_ALIGN"; 1153 case REMOTE_SEND_WIDTH: 1154 return "REMOTE_SEND_WIDTH"; 1155 case REMOTE_RECV_WIDTH: 1156 return "REMOTE_RECV_WIDTH"; 1157 case REMOTE_SEND_DIRTY_COUNT: 1158 return "REMOTE_SEND_DIRTY_COUNT"; 1159 case REMOTE_RECV_DIRTY_COUNT: 1160 return "REMOTE_RECV_DIRTY_COUNT"; 1161 case REMOTE_RECV_CLEAN_COUNT: 1162 return "REMOTE_RECV_CLEAN_COUNT"; 1163 case REMOTE_CPU_UTIL: 1164 return "REMOTE_CPU_UTIL"; 1165 case REMOTE_CPU_PERCENT_USER: 1166 return "REMOTE_CPU_PERCENT_USER"; 1167 case REMOTE_CPU_PERCENT_SYSTEM: 1168 return "REMOTE_CPU_PERCENT_SYSTEM"; 1169 case REMOTE_CPU_PERCENT_IOWAIT: 1170 return "REMOTE_CPU_PERCENT_IOWAIT"; 1171 case REMOTE_CPU_PERCENT_IRQ: 1172 return "REMOTE_CPU_PERCENT_IRQ"; 1173 case REMOTE_CPU_PERCENT_SWINTR: 1174 return "REMOTE_CPU_PERCENT_SWINTR"; 1175 case REMOTE_CPU_BIND: 1176 return "REMOTE_CPU_BIND"; 1177 case REMOTE_SD: 1178 return "REMOTE_SD"; 1179 case REMOTE_CPU_METHOD: 1180 return "REMOTE_CPU_METHOD"; 1181 case REMOTE_CPU_COUNT: 1182 return "REMOTE_CPU_COUNT"; 1183 case REMOTE_CPU_PEAK_UTIL: 1184 return "REMOTE_CPU_PEAK_UTIL"; 1185 case REMOTE_CPU_PEAK_ID: 1186 return "REMOTE_CPU_PEAK_ID"; 1187 case REMOTE_NODELAY: 1188 return "REMOTE_NODELAY"; 1189 case REMOTE_CORK: 1190 return "REMOTE_CORK"; 1191 case LOCAL_INTERFACE_SLOT: 1192 return "LOCAL_INTERFACE_SLOT"; 1193 case REMOTE_INTERFACE_SLOT: 1194 return "REMOTE_INTERFACE_SLOT"; 1195 case REMOTE_INTERFACE_SUBDEVICE: 1196 return "REMOTE_INTERFACE_SUBDEVICE"; 1197 case REMOTE_INTERFACE_SUBVENDOR: 1198 return "REMOTE_INTERFACE_SUBVENDOR"; 1199 case REMOTE_INTERFACE_DEVICE: 1200 return "REMOTE_INTERFACE_DEVICE"; 1201 case REMOTE_INTERFACE_VENDOR: 1202 return "REMOTE_INTERFACE_VENDOR"; 1203 case LOCAL_INTERFACE_SUBDEVICE: 1204 return "LOCAL_INTERFACE_SUBDEVICE"; 1205 case LOCAL_INTERFACE_SUBVENDOR: 1206 return "LOCAL_INTERFACE_SUBVENDOR"; 1207 case LOCAL_INTERFACE_DEVICE: 1208 return "LOCAL_INTERFACE_DEVICE"; 1209 case LOCAL_INTERFACE_VENDOR: 1210 return "LOCAL_INTERFACE_VENDOR"; 1211 case LOCAL_INTERFACE_NAME: 1212 return "LOCAL_INTERFACE_NAME"; 1213 case REMOTE_INTERFACE_NAME: 1214 return "REMOTE_INTERFACE_NAME"; 1215 case REMOTE_DRIVER_NAME: 1216 return "REMOTE_DRIVER_NAME"; 1217 case REMOTE_DRIVER_VERSION: 1218 return "REMOTE_DRIVER_VERSION"; 1219 case REMOTE_DRIVER_FIRMWARE: 1220 return "REMOTE_DRIVER_FIRMWARE"; 1221 case REMOTE_DRIVER_BUS: 1222 return "REMOTE_DRIVER_BUS"; 1223 case LOCAL_DRIVER_NAME: 1224 return "LOCAL_DRIVER_NAME"; 1225 case LOCAL_DRIVER_VERSION: 1226 return "LOCAL_DRIVER_VERSION"; 1227 case LOCAL_DRIVER_FIRMWARE: 1228 return "LOCAL_DRIVER_FIRMWARE"; 1229 case LOCAL_INTERVAL_USECS: 1230 return "LOCAL_INTERVAL_USECS"; 1231 case LOCAL_INTERVAL_BURST: 1232 return "LOCAL_INTERVAL_BURST"; 1233 case REMOTE_INTERVAL_USECS: 1234 return "REMOTE_INTERVAL_USECS"; 1235 case REMOTE_INTERVAL_BURST: 1236 return "REMOTE_INTERVAL_BURST"; 1237 case LOCAL_SECURITY_TYPE_ID: 1238 return "LOCAL_SECURITY_TYPE_ID"; 1239 case LOCAL_SECURITY_ENABLED_NUM: 1240 return "LOCAL_SECURITY_ENABLED_NUM"; 1241 case LOCAL_SECURITY_TYPE: 1242 return "LOCAL_SECURITY_TYPE"; 1243 case LOCAL_SECURITY_ENABLED: 1244 return "LOCAL_SECURITY_ENABLED"; 1245 case LOCAL_SECURITY_SPECIFIC: 1246 return "LOCAL_SECURITY_SPECIFIC"; 1247 case REMOTE_SECURITY_TYPE_ID: 1248 return "REMOTE_SECURITY_TYPE_ID"; 1249 case REMOTE_SECURITY_ENABLED_NUM: 1250 return "REMOTE_SECURITY_ENABLED_NUM"; 1251 case REMOTE_SECURITY_TYPE: 1252 return "REMOTE_SECURITY_TYPE"; 1253 case REMOTE_SECURITY_ENABLED: 1254 return "REMOTE_SECURITY_ENABLED"; 1255 case REMOTE_SECURITY_SPECIFIC: 1256 return "REMOTE_SECURITY_SPECIFIC"; 1257 case LOCAL_DRIVER_BUS: 1258 return "LOCAL_DRIVER_BUS"; 1259 case REMOTE_SYSNAME: 1260 return "REMOTE_SYSNAME"; 1261 case REMOTE_MACHINE: 1262 return "REMOTE_MACHINE"; 1263 case REMOTE_VERSION: 1264 return "REMOTE_VERSION"; 1265 case REMOTE_RELEASE: 1266 return "REMOTE_RELEASE"; 1267 case LOCAL_SYSNAME: 1268 return "LOCAL_SYSNAME"; 1269 case LOCAL_MACHINE: 1270 return "LOCAL_MACHINE"; 1271 case LOCAL_VERSION: 1272 return "LOCAL_VERSION"; 1273 case LOCAL_RELEASE: 1274 return "LOCAL_RELEASE"; 1275 case REMOTE_CPU_MODEL: 1276 return "REMOTE_CPU_MODEL"; 1277 case REMOTE_CPU_FREQUENCY: 1278 return "REMOTE_CPU_FREQUENCY"; 1279 case REMOTE_SYSTEM_MODEL: 1280 return "REMOTE_SYSTEM_MODEL"; 1281 case LOCAL_CPU_MODEL: 1282 return "LOCAL_CPU_MODEL"; 1283 case LOCAL_CPU_FREQUENCY: 1284 return "LOCAL_CPU_FREQUENCY"; 1285 case LOCAL_SYSTEM_MODEL: 1286 return "LOCAL_SYSTEM_MODEL"; 1287 case MIN_LATENCY: 1288 return "MIN_LATENCY"; 1289 case MAX_LATENCY: 1290 return "MAX_LATENCY"; 1291 case P50_LATENCY: 1292 return "P50_LATENCY"; 1293 case P90_LATENCY: 1294 return "P90_LATENCY"; 1295 case P99_LATENCY: 1296 return "P99_LATENCY"; 1297 case MEAN_LATENCY: 1298 return "MEAN_LATENCY"; 1299 case STDDEV_LATENCY: 1300 return "STDDEV_LATENCY"; 1301 case LOCAL_SOCKET_PRIO: 1302 return "LOCAL_SOCKET_PRIO"; 1303 case REMOTE_SOCKET_PRIO: 1304 return "REMOTE_SOCKET_PRIO"; 1305 case LOCAL_SOCKET_TOS: 1306 return "LOCAL_SOCKET_TOS"; 1307 case REMOTE_SOCKET_TOS: 1308 return "REMOTE_SOCKET_TOS"; 1309 case LOCAL_CONG_CONTROL: 1310 return "LOCAL_CONG_CONTROL"; 1311 case REMOTE_CONG_CONTROL: 1312 return "REMOTE_CONG_CONTROL"; 1313 case LOCAL_FILL_FILE: 1314 return "LOCAL_FILL_FILE"; 1315 case REMOTE_FILL_FILE: 1316 return "REMOTE_FILL_FILE"; 1317 case OUTPUT_END: 1318 return "OUTPUT_END"; 1319 default: 1320 return "!UNKNOWN OUTPUT SELECTOR!"; 1321 } 1322 } 1323 1324 void 1325 print_netperf_output_entry(FILE *where, enum netperf_output_name what) 1326 { 1327 } 1328 1329 void print_omni_init_list(); 1330 1331 void 1332 dump_netperf_output_list(FILE *where) { 1333 1334 int i,j; 1335 1336 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 1337 fprintf(where,"Output Block %d\n",i + 1); 1338 for (j = 0; j < NETPERF_OUTPUT_MAX; j++) { 1339 fprintf(where,"%s ",netperf_output_enum_to_str(output_list[i][j])); 1340 } 1341 fprintf(where,"\n"); 1342 } 1343 fflush(where); 1344 } 1345 1346 void 1347 dump_netperf_output_choices(FILE *where, int csv) { 1348 int i; 1349 1350 print_omni_init_list(); 1351 1352 for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++){ 1353 if (OUTPUT_NONE != i) { 1354 fprintf(where,"%c",(csv) ? ',' : '\n'); 1355 } 1356 fprintf(where, 1357 "%s", 1358 netperf_output_enum_to_str(netperf_output_source[i].output_name)); 1359 } 1360 fprintf(where,"\n"); 1361 fflush(where); 1362 } 1363 1364 void 1365 dump_netperf_output_source(FILE *where) 1366 { 1367 int i; 1368 1369 /* belts and suspenders everyone... */ 1370 for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++) { 1371 fprintf(where, 1372 "Output Name: %s\n" 1373 "\tmax_line_len %d tot_line_len %d display_value %p\n" 1374 "\tline[0]: |%s|\n" 1375 "\tline[1]: |%s|\n" 1376 "\tline[2]: |%s|\n" 1377 "\tline[3]: |%s|\n" 1378 "\tformat: |%s|\n", 1379 netperf_output_enum_to_str(netperf_output_source[i].output_name), 1380 netperf_output_source[i].max_line_len, 1381 netperf_output_source[i].tot_line_len, 1382 netperf_output_source[i].display_value, 1383 (netperf_output_source[i].line[0] == NULL) ? "" : 1384 netperf_output_source[i].line[0], 1385 (netperf_output_source[i].line[1] == NULL) ? "" : 1386 netperf_output_source[i].line[1], 1387 (netperf_output_source[i].line[2] == NULL) ? "" : 1388 netperf_output_source[i].line[2], 1389 (netperf_output_source[i].line[3] == NULL) ? "" : 1390 netperf_output_source[i].line[3], 1391 (netperf_output_source[i].format == NULL) ? "" : 1392 netperf_output_source[i].format); 1393 } 1394 fflush(where); 1395 } 1396 1397 #define MY_MAX(a,b) ((a > b) ? a : b) 1398 1399 #define NETPERF_LINE_MAX(x) \ 1400 MY_MAX(MY_MAX(MY_MAX(strlen(netperf_output_source[x].line[0]),\ 1401 strlen(netperf_output_source[x].line[1])),\ 1402 strlen(netperf_output_source[x].line[2])),\ 1403 strlen(netperf_output_source[x].line[3])) 1404 1405 #define NETPERF_LINE_TOT(x) \ 1406 strlen(netperf_output_source[x].line[0]) +\ 1407 strlen(netperf_output_source[x].line[1]) +\ 1408 strlen(netperf_output_source[x].line[2]) +\ 1409 strlen(netperf_output_source[x].line[3]) + 4 1410 1411 enum netperf_output_name 1412 match_string_to_output_mnenomic(char *candidate) { 1413 1414 enum netperf_output_name name; 1415 for (name = OUTPUT_NONE; name < NETPERF_OUTPUT_MAX; name++) { 1416 if(!strcasecmp(candidate,netperf_output_enum_to_str(name))) 1417 return name; 1418 } 1419 return NETPERF_OUTPUT_UNKNOWN; 1420 } 1421 1422 enum netperf_output_name 1423 match_string_to_output(char *candidate) 1424 { 1425 char *h1,*temp; 1426 enum netperf_output_name name; 1427 int k,len; 1428 1429 /* at some point we may need/want to worry about leading and 1430 trailing spaces, but for now we will leave that onus on the 1431 user. */ 1432 1433 for (name = OUTPUT_NONE; name < NETPERF_OUTPUT_MAX; name++) { 1434 /* try for a match based on the nmemonic/enum */ 1435 if (!strcasecmp(candidate,netperf_output_enum_to_str(name))) 1436 return name; 1437 1438 /* try for a match on the actual header text */ 1439 temp = malloc(NETPERF_LINE_TOT(name)); 1440 h1 = temp; 1441 if (h1 != NULL) { 1442 for (k = 0; ((k < 4) && 1443 (NULL != netperf_output_source[name].line[k]) && 1444 (strcmp("",netperf_output_source[name].line[k]))); k++) { 1445 len = sprintf(h1, 1446 "%s", 1447 netperf_output_source[name].line[k]); 1448 *(h1 + len) = ' '; 1449 /* now move to the next starting column. for csv we aren't worried 1450 about alignment between the header and the value lines */ 1451 h1 += len + 1; 1452 } 1453 /* this time we want null termination please */ 1454 *(h1 - 1) = 0; 1455 if (!strcasecmp(candidate,temp)) { 1456 free(temp); 1457 return name; 1458 } 1459 else 1460 free(temp); 1461 } 1462 } 1463 /* if we get here it means there was no match */ 1464 return OUTPUT_NONE; 1465 } 1466 1467 1468 void 1469 set_output_list_all() { 1470 1471 int i, j; /* line, column */ 1472 enum netperf_output_name k; 1473 1474 /* Line One SOCKET_TYPE to RESPONSE_SIZE */ 1475 i = 0; 1476 j = 0; 1477 for (k = SOCKET_TYPE; k <= RESPONSE_SIZE; k++) { 1478 output_list[i][j++] = k; 1479 desired_output_groups |= netperf_output_source[k].output_group; 1480 } 1481 1482 /* Line Two LOCAL_CPU_UTIL to TRANSPORT_MSS */ 1483 i = 1; 1484 j = 0; 1485 for (k = LOCAL_CPU_UTIL; k <= TRANSPORT_MSS; k++) { 1486 output_list[i][j++] = k; 1487 desired_output_groups |= netperf_output_source[k].output_group; 1488 } 1489 1490 /* Line Three LOCAL_SEND_THROUGHPUT throught REMOTE_CORK */ 1491 i = 2; 1492 j = 0; 1493 for (k = LOCAL_SEND_THROUGHPUT; k <= REMOTE_CORK; k++) { 1494 output_list[i][j++] = k; 1495 desired_output_groups |= netperf_output_source[k].output_group; 1496 } 1497 1498 /* Line Four LOCAL_SYSNAME through COMMAND_LINE */ 1499 i = 3; 1500 j = 0; 1501 for (k = LOCAL_SYSNAME; k <= COMMAND_LINE; k++) { 1502 output_list[i][j++] = k; 1503 desired_output_groups |= netperf_output_source[k].output_group; 1504 } 1505 1506 } 1507 1508 void 1509 parse_output_selection_file(char *selection_file) { 1510 FILE *selections; 1511 char name[81]; /* best be more than enough */ 1512 int namepos; 1513 int c; 1514 int j; 1515 int line,column; 1516 1517 selections = fopen(selection_file,"r"); 1518 if (!selections) { 1519 fprintf(where, 1520 "Could not open output selection file '%s' errno %d\n", 1521 selection_file, 1522 errno); 1523 fflush(where); 1524 exit(-1); 1525 } 1526 1527 line = 0; 1528 column = 1; 1529 namepos = 0; 1530 name[0] = 0; 1531 name[80] = 0; 1532 j = 0; 1533 while (((c = fgetc(selections)) != EOF) && (line < 4)) { 1534 if (namepos == 80) { 1535 /* too long */ 1536 1537 fprintf(where, 1538 "Output selection starting column %d on line %d is too long\n", 1539 line + 1, 1540 column); 1541 fflush(where); 1542 exit(-1); 1543 } 1544 if (c == ',') { 1545 /* time to check for a match, but only if we won't overflow the 1546 current row of the array */ 1547 if (j == NETPERF_OUTPUT_MAX) { 1548 fprintf(where,"Too many output selectors on line %d\n",line); 1549 fflush(where); 1550 exit(-1); 1551 } 1552 name[namepos] = 0; 1553 output_list[line][j++] = match_string_to_output(name); 1554 namepos = 0; 1555 } 1556 else if (c == '\n') { 1557 /* move to the next line after checking for a match */ 1558 name[namepos] = 0; 1559 output_list[line++][j++] = match_string_to_output(name); 1560 namepos = 0; 1561 j = 0; 1562 } 1563 else if (isprint(c)) { 1564 name[namepos++] = (char)c; 1565 } 1566 column++; 1567 } 1568 1569 /* ok, do we need/want to do anything here? at present we will 1570 silently ignore the rest of the file if we exit the loop on line 1571 count */ 1572 if ((c == EOF) && (namepos > 0)) { 1573 name[namepos] = 0; 1574 output_list[line][j] = match_string_to_output(name); 1575 } 1576 1577 } 1578 1579 void 1580 parse_output_selection_line(int line, char *list) { 1581 1582 char *token; 1583 int j; 1584 enum netperf_output_name name; 1585 1586 /* belt and suspenders */ 1587 if (line < 0) { 1588 fprintf(where, 1589 "parse_output_selection_line called with negative line number %d\n",line); 1590 fflush(where); 1591 exit(-1); 1592 } 1593 1594 /* silently ignore extra lines and only warn if debug is set */ 1595 if (line >= NETPERF_MAX_BLOCKS) { 1596 if (debug) { 1597 fprintf(where, 1598 "There can be no more than %d output selection lines." 1599 " Ignoring output selection line %d |%s|\n", 1600 NETPERF_MAX_BLOCKS, 1601 line + 1, 1602 list); 1603 fflush(where); 1604 } 1605 return; 1606 } 1607 1608 1609 j=0; 1610 token = strtok(list," ,"); 1611 while ((token) && (j < NETPERF_OUTPUT_MAX)) { 1612 1613 name = match_string_to_output_mnenomic(token); 1614 1615 if ((name == NETPERF_OUTPUT_UNKNOWN) && (debug)) { 1616 fprintf(where,"Ignoring unknown output selector %d |%s| on line %d\n", 1617 j + 1, 1618 token, 1619 line +1); 1620 fflush(where); 1621 } 1622 else { 1623 output_list[line][j] = name; 1624 desired_output_groups |= netperf_output_source[name].output_group; 1625 j++; 1626 } 1627 1628 token = strtok(NULL," ,"); 1629 } 1630 if ((token) && (debug)) { 1631 fprintf(where, 1632 "There can be no more than %d output selectors per line. " 1633 "Ignoring remaining selectors on line %d\n", 1634 NETPERF_OUTPUT_MAX,line +1); 1635 fflush(where); 1636 } 1637 } 1638 1639 void 1640 parse_output_selection_direct(char *output_selection) { 1641 1642 char *source,*line,*remainder,*temp; 1643 char *f1, *f2, *f3; 1644 int i,len,done; 1645 1646 len = strlen(output_selection); 1647 1648 source = strdup(output_selection); 1649 line = (char *) malloc(len+1); 1650 remainder = (char *) malloc(len+1); 1651 1652 if ((NULL == source) || 1653 (NULL == line) || 1654 (NULL == remainder)) { 1655 fprintf(where,"Unable to malloc memory for output selection parsing\n"); 1656 fflush(where); 1657 exit(-1); 1658 } 1659 1660 f1 = source; 1661 f2 = line; 1662 f3 = remainder; 1663 1664 i = 0; 1665 done = 0; 1666 do { 1667 break_args_explicit_sep(source,';',line,remainder); 1668 if (line[0]) { 1669 parse_output_selection_line(i,line); 1670 } 1671 if (remainder[0]) { 1672 temp = source; 1673 source = remainder; 1674 remainder = temp; 1675 i++; 1676 /* 1677 if (i == NETPERF_MAX_BLOCKS) { 1678 fprintf(where, 1679 "Too many output blocks requested, maximum is %d\n", 1680 NETPERF_MAX_BLOCKS); 1681 fflush(where); 1682 exit(-1); 1683 } 1684 */ 1685 continue; 1686 } 1687 else { 1688 done = 1; 1689 } 1690 } while (!done); 1691 1692 free(f1); 1693 free(f2); 1694 free(f3); 1695 1696 } 1697 1698 /* building blocks for output selection */ 1699 #define NETPERF_TPUT "ELAPSED_TIME,THROUGHPUT,THROUGHPUT_UNITS" 1700 #define NETPERF_OUTPUT_STREAM "LSS_SIZE_END,RSR_SIZE_END,LOCAL_SEND_SIZE" 1701 #define NETPERF_OUTPUT_MAERTS "RSS_SIZE_END,LSR_SIZE_END,REMOTE_SEND_SIZE" 1702 #define NETPERF_CPU "LOCAL_CPU_UTIL,LOCAL_CPU_PERCENT_USER,LOCAL_CPU_PERCENT_SYSTEM,LOCAL_CPU_PERCENT_IOWAIT,LOCAL_CPU_PERCENT_IRQ,LOCAL_CPU_PERCENT_SWINTR,LOCAL_CPU_METHOD,REMOTE_CPU_UTIL,REMOTE_CPU_PERCENT_USER,REMOTE_CPU_PERCENT_SYSTEM,REMOTE_CPU_PERCENT_IOWAIT,REMOTE_CPU_PERCENT_IRQ,REMOTE_CPU_PERCENT_SWINTR,REMOTE_CPU_METHOD,LOCAL_SD,REMOTE_SD,SD_UNITS" 1703 #define NETPERF_RR "LSS_SIZE_END,LSR_SIZE_END,RSR_SIZE_END,RSS_SIZE_END,REQUEST_SIZE,RESPONSE_SIZE" 1704 1705 void 1706 set_output_list_by_test() { 1707 1708 char *stream_no_cpu = NETPERF_OUTPUT_STREAM "," NETPERF_TPUT; 1709 char *stream_cpu = NETPERF_OUTPUT_STREAM "," NETPERF_TPUT "," NETPERF_CPU; 1710 char *maerts_no_cpu = NETPERF_OUTPUT_MAERTS "," NETPERF_TPUT; 1711 char *maerts_cpu = NETPERF_OUTPUT_MAERTS "," NETPERF_TPUT "," NETPERF_CPU; 1712 char *rr_no_cpu = NETPERF_RR "," NETPERF_TPUT; 1713 char *rr_cpu = NETPERF_RR "," NETPERF_TPUT "," NETPERF_CPU; 1714 1715 if (debug) { 1716 fprintf(where,"%s setting the output list by test\n", 1717 __FUNCTION__); 1718 fflush(where); 1719 } 1720 1721 if (NETPERF_XMIT_ONLY(direction)) { 1722 if (!(local_cpu_usage || remote_cpu_usage)) 1723 parse_output_selection_direct(stream_no_cpu); 1724 else 1725 parse_output_selection_direct(stream_cpu); 1726 } 1727 else if (NETPERF_RECV_ONLY(direction)) { 1728 if (!(local_cpu_usage || remote_cpu_usage)) 1729 parse_output_selection_direct(maerts_no_cpu); 1730 else 1731 parse_output_selection_direct(maerts_cpu); 1732 } 1733 else if (NETPERF_CC(direction)) { 1734 if (!(local_cpu_usage || remote_cpu_usage)) 1735 parse_output_selection_direct(rr_no_cpu); 1736 else 1737 parse_output_selection_direct(rr_cpu); 1738 } 1739 else if (NETPERF_IS_RR(direction)) { 1740 if (!(local_cpu_usage || remote_cpu_usage)) 1741 parse_output_selection_direct(rr_no_cpu); 1742 else 1743 parse_output_selection_direct(rr_cpu); 1744 } 1745 else { 1746 /* no idea */ 1747 if (debug) { 1748 fprintf(where,"Cannot determine default test output, using mins\n"); 1749 fflush(where); 1750 } 1751 parse_output_selection_direct(NETPERF_TPUT "," NETPERF_CPU); 1752 } 1753 } 1754 1755 void 1756 parse_output_selection(char *output_selection) { 1757 1758 if (debug) { 1759 fprintf(where,"%s is parsing the output selection '%s'\n", 1760 __FUNCTION__, 1761 output_selection); 1762 fflush(where); 1763 } 1764 1765 /* is it the magic keyword? */ 1766 if (strcasecmp(output_selection,"all") == 0) { 1767 set_output_list_all(); 1768 } 1769 /* do not forget the case when the output_selection is a single 1770 mnemonic without any separators... */ 1771 else if (strchr(output_selection,',') || 1772 strchr(output_selection,';') || 1773 (match_string_to_output_mnenomic(output_selection) != 1774 NETPERF_OUTPUT_UNKNOWN)) { 1775 parse_output_selection_direct(output_selection); 1776 } 1777 else { 1778 parse_output_selection_file(output_selection); 1779 } 1780 if (debug > 2) { 1781 dump_netperf_output_list(stderr); 1782 } 1783 return; 1784 } 1785 1786 static void 1787 set_output_elt(enum netperf_output_name name, 1788 char *line0, char *line1, char *line2, char *line3, 1789 char *format, 1790 void *value, 1791 unsigned int out_default, 1792 unsigned int group, 1793 enum netperf_output_type type) { 1794 1795 netperf_output_source[name].output_name = name; 1796 netperf_output_source[name].line[0] = line0; 1797 netperf_output_source[name].line[1] = line1; 1798 netperf_output_source[name].line[2] = line2; 1799 netperf_output_source[name].line[3] = line3; 1800 netperf_output_source[name].format = format; 1801 netperf_output_source[name].display_value = value; 1802 netperf_output_source[name].output_default = out_default; 1803 netperf_output_source[name].output_group = group; 1804 netperf_output_source[name].max_line_len = NETPERF_LINE_MAX(name); 1805 netperf_output_source[name].tot_line_len = NETPERF_LINE_TOT(name); 1806 netperf_output_source[name].output_type = type; 1807 } 1808 1809 void 1810 print_omni_init_list() { 1811 1812 int i; 1813 1814 if (debug) { 1815 fprintf(where,"%s called\n", 1816 __FUNCTION__); 1817 } 1818 1819 /* belts and suspenders everyone... */ 1820 for (i = NETPERF_OUTPUT_UNKNOWN; i < NETPERF_OUTPUT_MAX; i++) { 1821 netperf_output_source[i].output_name = i; 1822 netperf_output_source[i].max_line_len = 0; 1823 netperf_output_source[i].tot_line_len = 0; 1824 netperf_output_source[i].line[0] = ""; 1825 netperf_output_source[i].line[1] = ""; 1826 netperf_output_source[i].line[2] = ""; 1827 netperf_output_source[i].line[3] = ""; 1828 netperf_output_source[i].format = ""; 1829 netperf_output_source[i].display_value = NULL; 1830 netperf_output_source[i].output_default = 1; 1831 netperf_output_source[i].output_group = 0; 1832 netperf_output_source[i].output_type = NETPERF_TYPE_UNKNOWN; 1833 } 1834 1835 set_output_elt(OUTPUT_NONE, " ", "", "", "", "%s", &" ",1, 0, 1836 NETPERF_TYPE_CHAR); 1837 1838 set_output_elt(COMMAND_LINE, "Command","Line","","","\"%s\"", 1839 command_line,1, 0, NETPERF_TYPE_CHAR); 1840 1841 set_output_elt(UUID, "Test", "UUID", "", "", "%s", test_uuid, 1, 0, 1842 NETPERF_TYPE_CHAR); 1843 1844 set_output_elt(RESULT_BRAND, "Result", "Tag", "", "", "\"%s\"", 1845 result_brand, 1, 0, NETPERF_TYPE_CHAR); 1846 1847 set_output_elt(SOCKET_TYPE, "Socket", "Type", "", "", "%s", 1848 socket_type_str, 1, 0, NETPERF_TYPE_CHAR); 1849 1850 set_output_elt(DIRECTION, "Direction", "", "", "", "%s", 1851 direction_str, 1, 0, NETPERF_TYPE_CHAR); 1852 1853 set_output_elt(PROTOCOL, "Protocol", "", "", "", "%s", 1854 protocol_str, 1, 0, NETPERF_TYPE_CHAR); 1855 1856 set_output_elt(ELAPSED_TIME, "Elapsed", "Time", "(sec)", "", "%.2f", 1857 &elapsed_time_double, 1, 0, NETPERF_TYPE_DOUBLE); 1858 1859 set_output_elt(SOURCE_PORT, "Source", "Port", "", "", "%s", 1860 local_data_port, 1, 0, NETPERF_TYPE_CHAR); 1861 1862 set_output_elt(SOURCE_ADDR, "Source", "Address", "", "", "%s", 1863 local_data_address, 1, 0, NETPERF_TYPE_CHAR); 1864 1865 set_output_elt(SOURCE_FAMILY, "Source", "Family", "", "", "%d", 1866 &local_data_family, 1, 0, NETPERF_TYPE_INT32); 1867 1868 set_output_elt(DEST_PORT, "Destination", "Port", "", "", "%s", 1869 remote_data_port, 1, 0, NETPERF_TYPE_CHAR); 1870 1871 set_output_elt(DEST_ADDR, "Destination", "Address", "", "", "%s", 1872 remote_data_address, 1, 0, NETPERF_TYPE_CHAR); 1873 1874 set_output_elt(DEST_FAMILY, "Destination", "Family", "", "", "%d", 1875 &remote_data_family, 1, 0, NETPERF_TYPE_INT32); 1876 1877 set_output_elt(THROUGHPUT, "Throughput", "", "", "", "%.2f", 1878 &thruput, 1, 0, NETPERF_TYPE_DOUBLE); 1879 1880 set_output_elt(LOCAL_SEND_THROUGHPUT, "Local", "Send", "Throughput", "", 1881 "%.2f", &local_send_thruput, 1, 0, NETPERF_TYPE_DOUBLE); 1882 1883 set_output_elt(LOCAL_RECV_THROUGHPUT, "Local", "Recv", "Throughput", "", 1884 "%.2f", &local_recv_thruput, 1, 0, NETPERF_TYPE_DOUBLE); 1885 1886 set_output_elt(REMOTE_SEND_THROUGHPUT, "Remote", "Send", "Throughput", "", 1887 "%.2f", &remote_send_thruput, 1, 0, NETPERF_TYPE_DOUBLE); 1888 1889 set_output_elt(REMOTE_RECV_THROUGHPUT, "Remote", "Recv", "Throughput", "", 1890 "%.2f", &remote_recv_thruput, 1, 0, NETPERF_TYPE_DOUBLE); 1891 1892 set_output_elt(THROUGHPUT_UNITS, "Throughput", "Units", "", "", "%s/s", 1893 thruput_format_str, 1, 0, NETPERF_TYPE_CHAR); 1894 1895 set_output_elt(CONFIDENCE_LEVEL, "Confidence", "Level", "Percent", "", "%d", 1896 &confidence_level, 1, 0, NETPERF_TYPE_INT32); 1897 1898 set_output_elt(CONFIDENCE_INTERVAL, "Confidence", "Width", "Target", "", 1899 "%f", &interval_pct, 1, 0, NETPERF_TYPE_DOUBLE); 1900 1901 set_output_elt(CONFIDENCE_ITERATION, "Confidence", "Iterations", "Run", "", 1902 "%d", &confidence_iteration, 1, 0, NETPERF_TYPE_INT32); 1903 1904 set_output_elt(THROUGHPUT_CONFID, "Throughput", "Confidence", "Width (%)", 1905 "", "%.3f", &result_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE); 1906 1907 set_output_elt(LOCAL_CPU_CONFID, "Local", "CPU", "Confidence", "Width (%)", 1908 "%.3f", &loc_cpu_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE); 1909 1910 set_output_elt(REMOTE_CPU_CONFID, "Remote", "CPU", "Confidence", "Width (%)", 1911 "%.3f", &rem_cpu_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE); 1912 1913 set_output_elt(RT_LATENCY, "Round", "Trip", "Latency", "usec/tran", "%.3f", 1914 &rtt_latency, 1, 0, NETPERF_TYPE_DOUBLE); 1915 1916 set_output_elt(TRANSACTION_RATE, "Transaction", "Rate", "Tran/s", "", "%.3f", 1917 &transaction_rate, 1, 0, NETPERF_TYPE_DOUBLE); 1918 1919 set_output_elt(TRANSPORT_MSS, "Transport", "MSS", "bytes", "", "%d", 1920 &transport_mss, 1, 0, NETPERF_TYPE_INT32); 1921 1922 set_output_elt(LOCAL_TRANSPORT_RETRANS, "Local", "Transport", 1923 "Retransmissions", "", "%d", &local_transport_retrans, 1, 0, 1924 NETPERF_TYPE_INT32); 1925 1926 set_output_elt(REMOTE_TRANSPORT_RETRANS, "Remote", "Transport", 1927 "Retransmissions", "", "%d", &remote_transport_retrans, 1, 0, 1928 NETPERF_TYPE_INT32); 1929 1930 set_output_elt(REQUEST_SIZE, "Request", "Size", "Bytes", "", "%d", 1931 &req_size, 1, 0, NETPERF_TYPE_INT32); 1932 1933 set_output_elt(RESPONSE_SIZE, "Response", "Size", "Bytes", "", "%d", 1934 &rsp_size, 1, 0, NETPERF_TYPE_INT32); 1935 1936 set_output_elt(BURST_SIZE, "Initial", "Burst", "Requests", "", "%d", 1937 &first_burst_size, 1, 0, NETPERF_TYPE_INT32); 1938 1939 set_output_elt(LSS_SIZE_REQ, "Local", "Send Socket", "Size", "Requested", 1940 "%d", &lss_size_req, 1, 0, NETPERF_TYPE_INT32); 1941 1942 set_output_elt(LSS_SIZE, "Local", "Send Socket", "Size", "Initial", "%d", 1943 &lss_size, 1, 0, NETPERF_TYPE_INT32); 1944 1945 set_output_elt(LSS_SIZE_END, "Local", "Send Socket", "Size", "Final", "%d", 1946 &lss_size_end, 1, 0, NETPERF_TYPE_INT32); 1947 1948 set_output_elt(LSR_SIZE_REQ, "Local", "Recv Socket", "Size", "Requested", 1949 "%d", &lsr_size_req, 1, 0, NETPERF_TYPE_INT32); 1950 1951 set_output_elt(LSR_SIZE, "Local", "Recv Socket", "Size", "Initial", "%d", 1952 &lsr_size, 1, 0, NETPERF_TYPE_INT32); 1953 1954 set_output_elt(LSR_SIZE_END, "Local", "Recv Socket", "Size", "Final", "%d", 1955 &lsr_size_end, 1, 0, NETPERF_TYPE_INT32); 1956 1957 set_output_elt(LOCAL_SEND_SIZE, "Local", "Send", "Size", "", "%d", 1958 &send_size, 1, 0, NETPERF_TYPE_INT32); 1959 1960 set_output_elt(LOCAL_RECV_SIZE, "Local", "Recv", "Size", "", "%d", 1961 &recv_size, 1, 0, NETPERF_TYPE_INT32); 1962 1963 set_output_elt(LOCAL_SEND_CALLS, "Local", "Send", "Calls", "", "%"PRIu64, 1964 &local_send_calls, 1, 0, NETPERF_TYPE_UINT64); 1965 1966 set_output_elt(LOCAL_RECV_CALLS, "Local", "Recv", "Calls", "", "%"PRIu64, 1967 &local_receive_calls, 1, 0, NETPERF_TYPE_UINT64); 1968 1969 set_output_elt(LOCAL_BYTES_PER_RECV, "Local", "Bytes", "Per", "Recv", "%.2f", 1970 &bytes_per_recv, 1, 0, NETPERF_TYPE_DOUBLE); 1971 1972 set_output_elt(LOCAL_BYTES_PER_SEND, "Local", "Bytes", "Per", "Send", "%.2f", 1973 &bytes_per_send, 1, 0, NETPERF_TYPE_DOUBLE); 1974 1975 set_output_elt(LOCAL_BYTES_RECVD, "Local", "Bytes", "Received", "", "%"PRIu64, 1976 &bytes_received, 1, 0, NETPERF_TYPE_UINT64); 1977 1978 set_output_elt(LOCAL_BYTES_SENT, "Local", "Bytes", "Sent", "", "%"PRIu64, 1979 &bytes_sent, 1, 0, NETPERF_TYPE_UINT64); 1980 1981 set_output_elt(LOCAL_BYTES_XFERD, "Local", "Bytes", "Xferred", "", "%.0f", 1982 &bytes_xferd, 1, 0, NETPERF_TYPE_DOUBLE); 1983 1984 set_output_elt(LOCAL_SEND_WIDTH, "Local", "Send", "Width", "", "%d", 1985 &send_width, 1, 0, NETPERF_TYPE_INT32); 1986 1987 set_output_elt(LOCAL_RECV_WIDTH, "Local", "Recv", "Width", "", "%d", 1988 &recv_width, 1, 0, NETPERF_TYPE_INT32); 1989 1990 set_output_elt(LOCAL_SEND_OFFSET, "Local", "Send", "Offset", "", "%d", 1991 &local_send_offset, 1, 0, NETPERF_TYPE_INT32); 1992 1993 set_output_elt(LOCAL_RECV_OFFSET, "Local", "Recv", "Offset", "", "%d", 1994 &local_recv_offset, 1, 0, NETPERF_TYPE_INT32); 1995 1996 set_output_elt(LOCAL_RECV_ALIGN, "Local", "Recv", "Alignment", "", "%d", 1997 &local_recv_align, 1, 0, NETPERF_TYPE_INT32); 1998 1999 set_output_elt(LOCAL_SEND_ALIGN, "Local", "Send", "Alignment", "", "%d", 2000 &local_send_align, 1, 0, NETPERF_TYPE_INT32); 2001 2002 set_output_elt(LOCAL_SEND_DIRTY_COUNT, "Local", "Send", "Dirty", "Count", 2003 "%d", &loc_dirty_count, 1, 0, NETPERF_TYPE_INT32); 2004 2005 set_output_elt(LOCAL_RECV_DIRTY_COUNT, "Local", "Recv", "Dirty", "Count", 2006 "%d", &loc_dirty_count, 1, 0, NETPERF_TYPE_INT32); 2007 2008 set_output_elt(LOCAL_RECV_CLEAN_COUNT, "Local", "Recv", "Clean", "Count", 2009 "%d", &loc_clean_count, 1, 0, NETPERF_TYPE_INT32); 2010 2011 set_output_elt(LOCAL_CPU_UTIL, "Local", "CPU", "Util", "%", "%.2f", 2012 &local_cpu_utilization, 1, 0, NETPERF_TYPE_FLOAT); 2013 2014 set_output_elt(LOCAL_CPU_PERCENT_USER, "Local", "CPU", "User", "%", "%.2f", 2015 &lib_local_cpu_stats.cpu_user, 1, 0, NETPERF_TYPE_FLOAT); 2016 2017 set_output_elt(LOCAL_CPU_PERCENT_SYSTEM, 2018 "Local", "CPU", "System", "%", "%.2f", 2019 &lib_local_cpu_stats.cpu_system, 1, 0, NETPERF_TYPE_FLOAT); 2020 2021 set_output_elt(LOCAL_CPU_PERCENT_IOWAIT, 2022 "Local", "CPU", "I/O", "%", "%.2f", 2023 &lib_local_cpu_stats.cpu_iowait, 1, 0, NETPERF_TYPE_FLOAT); 2024 2025 set_output_elt(LOCAL_CPU_PERCENT_IRQ, 2026 "Local", "CPU", "IRQ", "%", "%.2f", 2027 &lib_local_cpu_stats.cpu_irq, 1, 0, NETPERF_TYPE_FLOAT); 2028 2029 set_output_elt(LOCAL_CPU_PERCENT_SWINTR, 2030 "Local", "CPU", "swintr", "%", "%.2f", 2031 &lib_local_cpu_stats.cpu_swintr, 1, 0, NETPERF_TYPE_FLOAT); 2032 2033 set_output_elt(LOCAL_CPU_PEAK_UTIL, "Local", "Peak", "Per CPU", "Util %", 2034 "%.2f", &lib_local_cpu_stats.peak_cpu_util, 1, 0, 2035 NETPERF_TYPE_FLOAT); 2036 2037 set_output_elt(LOCAL_CPU_PEAK_ID, "Local", "Peak", "Per CPU", "ID", "%d", 2038 &lib_local_cpu_stats.peak_cpu_id, 1, 0, NETPERF_TYPE_INT32); 2039 2040 set_output_elt(LOCAL_CPU_BIND, "Local", "CPU", "Bind", "", "%d", 2041 &local_proc_affinity, 1, 0, NETPERF_TYPE_INT32); 2042 2043 set_output_elt(LOCAL_SD, "Local", "Service", "Demand", "", "%.3f", 2044 &local_service_demand_double, 1, 0, NETPERF_TYPE_DOUBLE); 2045 2046 set_output_elt(SD_UNITS, "Service", "Demand", "Units", "", "%s", 2047 sd_str, 1, 0, NETPERF_TYPE_CHAR); 2048 2049 set_output_elt(LOCAL_CPU_METHOD, "Local", "CPU", "Util", "Method", "%c", 2050 &local_cpu_method, 1, 0, NETPERF_TYPE_INT32); 2051 2052 set_output_elt(LOCAL_CPU_COUNT, "Local", "CPU", "Count", "", "%d", 2053 &lib_num_loc_cpus, 1, 0, NETPERF_TYPE_INT32); 2054 2055 set_output_elt(LOCAL_NODELAY, "Local", "NODELAY", "", "", "%d", 2056 &loc_nodelay, 1, 0, NETPERF_TYPE_INT32); 2057 2058 set_output_elt(LOCAL_CORK, "Local", "Cork", "", "", "%d", 2059 &loc_tcpcork, 1, 0, NETPERF_TYPE_INT32); 2060 2061 set_output_elt(RSS_SIZE_REQ, "Remote", "Send Socket", "Size", "Requested", 2062 "%d", &rss_size_req, 1, 0, NETPERF_TYPE_INT32); 2063 2064 set_output_elt(RSS_SIZE, "Remote", "Send Socket", "Size", "Initial", "%d", 2065 &rss_size, 1, 0, NETPERF_TYPE_INT32); 2066 2067 set_output_elt(RSS_SIZE_END, "Remote", "Send Socket", "Size", "Final", "%d", 2068 &rss_size_end, 1, 0, NETPERF_TYPE_INT32); 2069 2070 set_output_elt(RSR_SIZE_REQ, "Remote", "Recv Socket", "Size", "Requested", 2071 "%d", &rsr_size_req, 1, 0, NETPERF_TYPE_INT32); 2072 2073 set_output_elt(RSR_SIZE, "Remote", "Recv Socket", "Size", "Initial", "%d", 2074 &rsr_size, 1, 0, NETPERF_TYPE_INT32); 2075 2076 set_output_elt(RSR_SIZE_END, "Remote", "Recv Socket", "Size", "Final", "%d", 2077 &rsr_size_end, 1, 0, NETPERF_TYPE_INT32); 2078 2079 set_output_elt(REMOTE_SEND_SIZE, "Remote", "Send", "Size", "", "%d", 2080 &remote_send_size, 1, 0, NETPERF_TYPE_INT32); 2081 2082 set_output_elt(REMOTE_RECV_SIZE, "Remote", "Recv", "Size", "", "%d", 2083 &remote_recv_size, 1, 0, NETPERF_TYPE_INT32); 2084 2085 set_output_elt(REMOTE_SEND_CALLS, "Remote", "Send", "Calls", "", "%"PRIu64, 2086 &remote_send_calls, 1, 0, NETPERF_TYPE_UINT64); 2087 2088 set_output_elt(REMOTE_RECV_CALLS, "Remote", "Recv", "Calls", "", "%"PRIu64, 2089 &remote_receive_calls, 1, 0, NETPERF_TYPE_UINT64); 2090 2091 set_output_elt(REMOTE_BYTES_PER_RECV, "Remote", "Bytes", "Per", "Recv", 2092 "%.2f", &remote_bytes_per_recv, 1, 0, NETPERF_TYPE_DOUBLE); 2093 2094 set_output_elt(REMOTE_BYTES_PER_SEND, "Remote", "Bytes", "Per", "Send", 2095 "%.2f", &remote_bytes_per_send, 1, 0, NETPERF_TYPE_DOUBLE); 2096 2097 set_output_elt(REMOTE_BYTES_RECVD, "Remote", "Bytes", "Received", "", 2098 "%"PRIu64, &remote_bytes_received, 1, 0, NETPERF_TYPE_UINT64); 2099 2100 set_output_elt(REMOTE_BYTES_SENT, "Remote", "Bytes", "Sent", "", "%"PRIu64, 2101 &remote_bytes_sent, 1, 0, NETPERF_TYPE_UINT64); 2102 2103 set_output_elt(REMOTE_BYTES_XFERD, "Remote", "Bytes", "Xferred", "", "%.0f", 2104 &remote_bytes_xferd, 1, 0, NETPERF_TYPE_DOUBLE); 2105 2106 set_output_elt(REMOTE_SEND_WIDTH, "Remote", "Send", "Width", "", "%d", 2107 &remote_send_width, 1, 0, NETPERF_TYPE_INT32); 2108 2109 set_output_elt(REMOTE_RECV_WIDTH, "Remote", "Recv", "Width", "", "%d", 2110 &remote_recv_width, 1, 0, NETPERF_TYPE_INT32); 2111 2112 set_output_elt(REMOTE_SEND_OFFSET, "Remote", "Send", "Offset", "", "%d", 2113 &remote_send_offset, 1, 0, NETPERF_TYPE_INT32); 2114 2115 set_output_elt(REMOTE_RECV_OFFSET, "Remote", "Recv", "Offset", "", "%d", 2116 &remote_recv_offset, 1, 0, NETPERF_TYPE_INT32); 2117 2118 set_output_elt(REMOTE_RECV_ALIGN, "Remote", "Recv", "Alignment", "", "%d", 2119 &remote_recv_align, 1, 0, NETPERF_TYPE_INT32); 2120 2121 set_output_elt(REMOTE_SEND_ALIGN, "Remote", "Send", "Alignment", "", "%d", 2122 &remote_send_align, 1, 0, NETPERF_TYPE_INT32); 2123 2124 set_output_elt(REMOTE_SEND_DIRTY_COUNT, "Remote", "Send", "Dirty", "Count", 2125 "%d", &rem_dirty_count, 1, 0, NETPERF_TYPE_INT32); 2126 2127 set_output_elt(REMOTE_RECV_DIRTY_COUNT, "Remote", "Recv", "Dirty", "Count", 2128 "%d", &rem_dirty_count, 1, 0, NETPERF_TYPE_INT32); 2129 2130 set_output_elt(REMOTE_RECV_CLEAN_COUNT, "Remote", "Recv", "Clean", "Count", 2131 "%d", &rem_clean_count, 1, 0, NETPERF_TYPE_INT32); 2132 2133 set_output_elt(REMOTE_CPU_UTIL, "Remote", "CPU", "Util", "%", "%.2f", 2134 &remote_cpu_utilization, 1, 0, NETPERF_TYPE_FLOAT); 2135 2136 set_output_elt(REMOTE_CPU_PERCENT_USER, "Remote", "CPU", "User", "%", "%.2f", 2137 &lib_remote_cpu_stats.cpu_user, 1, 0, NETPERF_TYPE_FLOAT); 2138 2139 set_output_elt(REMOTE_CPU_PERCENT_SYSTEM, 2140 "Remote", "CPU", "System", "%", "%.2f", 2141 &lib_remote_cpu_stats.cpu_system, 1, 0, NETPERF_TYPE_FLOAT); 2142 2143 set_output_elt(REMOTE_CPU_PERCENT_IOWAIT, 2144 "Remote", "CPU", "I/O", "%", "%.2f", 2145 &lib_remote_cpu_stats.cpu_iowait, 1, 0, NETPERF_TYPE_FLOAT); 2146 2147 set_output_elt(REMOTE_CPU_PERCENT_IRQ, 2148 "Remote", "CPU", "IRQ", "%", "%.2f", 2149 &lib_remote_cpu_stats.cpu_irq, 1, 0, NETPERF_TYPE_FLOAT); 2150 2151 set_output_elt(REMOTE_CPU_PERCENT_SWINTR, 2152 "Remote", "CPU", "swintr", "%", "%.2f", 2153 &lib_remote_cpu_stats.cpu_swintr, 1, 0, NETPERF_TYPE_FLOAT); 2154 2155 set_output_elt(REMOTE_CPU_PEAK_UTIL, "Remote", "Peak", "Per CPU", "Util %", 2156 "%.2f", &lib_remote_cpu_stats.peak_cpu_util, 1, 0, 2157 NETPERF_TYPE_FLOAT); 2158 2159 set_output_elt(REMOTE_CPU_PEAK_ID, "Remote", "Peak", "Per CPU", "ID", "%d", 2160 &lib_remote_cpu_stats.peak_cpu_id, 1, 0, NETPERF_TYPE_INT32); 2161 2162 set_output_elt(REMOTE_CPU_BIND, "Remote", "CPU", "Bind", "", "%d", 2163 &remote_proc_affinity, 1, 0, NETPERF_TYPE_INT32); 2164 2165 set_output_elt(REMOTE_SD, "Remote", "Service", "Demand", "", "%.3f", 2166 &remote_service_demand_double, 1, 0, NETPERF_TYPE_DOUBLE); 2167 2168 set_output_elt(REMOTE_CPU_METHOD, "Remote", "CPU", "Util", "Method", "%c", 2169 &remote_cpu_method, 1, 0, NETPERF_TYPE_INT32); 2170 2171 set_output_elt(REMOTE_CPU_COUNT, "Remote", "CPU", "Count", "", "%d", 2172 &lib_num_rem_cpus, 1, 0, NETPERF_TYPE_INT32); 2173 2174 set_output_elt(REMOTE_NODELAY, "Remote", "NODELAY", "", "", "%d", 2175 &rem_nodelay, 1, 0, NETPERF_TYPE_INT32); 2176 2177 set_output_elt(REMOTE_CORK, "Remote", "Cork", "", "", "%d", 2178 &rem_tcpcork, 1, 0, NETPERF_TYPE_INT32); 2179 2180 set_output_elt(LOCAL_DRIVER_NAME, "Local", "Driver", "Name", "", "%s", 2181 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO, 2182 NETPERF_TYPE_CHAR); 2183 2184 set_output_elt(LOCAL_DRIVER_VERSION, "Local", "Driver", "Version", "", "%s", 2185 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO, 2186 NETPERF_TYPE_CHAR); 2187 2188 set_output_elt(LOCAL_DRIVER_FIRMWARE, "Local", "Driver", "Firmware", "", 2189 "%s", deprecated_str, 1, OMNI_WANT_LOC_DRVINFO, 2190 NETPERF_TYPE_CHAR); 2191 2192 set_output_elt(LOCAL_DRIVER_BUS, "Local", "Driver", "Bus", "", "%s", 2193 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO, NETPERF_TYPE_CHAR); 2194 2195 set_output_elt(REMOTE_DRIVER_NAME, "Remote", "Driver", "Name", "", "%s", 2196 deprecated_str, 1, OMNI_WANT_REM_DRVINFO, 2197 NETPERF_TYPE_CHAR); 2198 2199 set_output_elt(REMOTE_DRIVER_VERSION, "Remote", "Driver", "Version", "", 2200 "%s", deprecated_str, 1, OMNI_WANT_REM_DRVINFO, 2201 NETPERF_TYPE_CHAR); 2202 2203 set_output_elt(REMOTE_DRIVER_FIRMWARE, "Remote", "Driver", "Firmware", "", 2204 "%s", deprecated_str, 1, OMNI_WANT_REM_DRVINFO, 2205 NETPERF_TYPE_CHAR); 2206 2207 set_output_elt(REMOTE_DRIVER_BUS, "Remote", "Driver", "Bus", "", "%s", 2208 deprecated_str, 1, OMNI_WANT_REM_DRVINFO, 2209 NETPERF_TYPE_CHAR); 2210 2211 set_output_elt(LOCAL_INTERFACE_SUBDEVICE, "Local", "Interface", "Subdevice", 2212 "", "0x%.4x", &local_interface_subdevice, 1, 2213 OMNI_WANT_LOC_IFIDS, NETPERF_TYPE_INT32); 2214 2215 set_output_elt(LOCAL_INTERFACE_DEVICE, "Local", "Interface", "Device", "", 2216 "0x%.4x", &local_interface_device, 1, OMNI_WANT_LOC_IFIDS, 2217 NETPERF_TYPE_INT32); 2218 2219 set_output_elt(LOCAL_INTERFACE_SUBVENDOR, "Local", "Interface", "Subvendor", 2220 "", "0x%.4x", &local_interface_subvendor, 1, 2221 OMNI_WANT_LOC_IFIDS, NETPERF_TYPE_UINT32); 2222 2223 set_output_elt(LOCAL_INTERFACE_VENDOR, "Local", "Interface", "Vendor", "", 2224 "0x%.4x", &local_interface_vendor, 1, OMNI_WANT_LOC_IFIDS, 2225 NETPERF_TYPE_UINT32); 2226 2227 set_output_elt(REMOTE_INTERFACE_SUBDEVICE, "Remote", "Interface", 2228 "Subdevice", "", "0x%.4x", &remote_interface_subdevice, 1, 2229 OMNI_WANT_REM_IFIDS, NETPERF_TYPE_UINT32); 2230 2231 set_output_elt(REMOTE_INTERFACE_DEVICE, "Remote", "Interface", "Device", "", 2232 "0x%.4x", &remote_interface_device, 1, OMNI_WANT_REM_IFIDS, 2233 NETPERF_TYPE_UINT32); 2234 2235 set_output_elt(REMOTE_INTERFACE_SUBVENDOR, "Remote", "Interface", 2236 "Subvendor", "", "0x%.4x", &remote_interface_subvendor, 1, 2237 OMNI_WANT_REM_IFIDS, NETPERF_TYPE_UINT32); 2238 2239 set_output_elt(REMOTE_INTERFACE_VENDOR, "Remote", "Interface", "Vendor", "", 2240 "0x%.4x", &remote_interface_vendor, 1, OMNI_WANT_REM_IFIDS, 2241 NETPERF_TYPE_UINT32); 2242 2243 set_output_elt(LOCAL_INTERFACE_NAME, "Local", "Interface", "Name", "", "%s", 2244 deprecated_str, 1, OMNI_WANT_LOC_IFNAME, 2245 NETPERF_TYPE_CHAR); 2246 2247 set_output_elt(REMOTE_INTERFACE_NAME, "Remote", "Interface", "Name", "", 2248 "%s", deprecated_str, 1, OMNI_WANT_REM_IFNAME, 2249 NETPERF_TYPE_CHAR); 2250 2251 set_output_elt(LOCAL_INTERFACE_SLOT, "Local", "Interface", "Slot", "", "%s", 2252 deprecated_str, 1, OMNI_WANT_LOC_IFSLOT, 2253 NETPERF_TYPE_CHAR); 2254 2255 set_output_elt(REMOTE_INTERFACE_SLOT, "Remote", "Interface", "Slot", "", 2256 "%s", deprecated_str, 1, OMNI_WANT_REM_IFSLOT, 2257 NETPERF_TYPE_CHAR); 2258 2259 set_output_elt(REMOTE_MACHINE, "Remote", "Machine", "", "", "%s", 2260 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2261 2262 set_output_elt(REMOTE_VERSION, "Remote", "Version", "", "", "%s", 2263 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2264 2265 set_output_elt(REMOTE_RELEASE, "Remote", "Release", "", "", "%s", 2266 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2267 2268 set_output_elt(REMOTE_SYSNAME, "Remote", "Sysname", "", "", "%s", 2269 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2270 2271 set_output_elt(LOCAL_MACHINE, "Local", "Machine", "", "", "%s", 2272 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2273 2274 set_output_elt(LOCAL_VERSION, "Local", "Version", "", "", "%s", 2275 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2276 2277 set_output_elt(LOCAL_RELEASE, "Local", "Release", "", "", "%s", 2278 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2279 2280 set_output_elt(LOCAL_SYSNAME, "Local", "Sysname", "", "", "%s", 2281 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2282 2283 set_output_elt(REMOTE_INTERVAL_USECS, "Remote", "Interval", "Usecs", "", 2284 "%d", &remote_interval_usecs, 1, 0, NETPERF_TYPE_INT32); 2285 2286 set_output_elt(REMOTE_INTERVAL_BURST, "Remote", "Interval", "Burst", "", 2287 "%d", &remote_interval_burst, 1, 0, NETPERF_TYPE_INT32); 2288 2289 set_output_elt(LOCAL_SECURITY_ENABLED, "Local", "OS", "Security", "Enabled", 2290 "%s", deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2291 2292 set_output_elt(LOCAL_SECURITY_TYPE, "Local", "OS", "Security", "Type", "%s", 2293 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2294 2295 set_output_elt(LOCAL_SECURITY_SPECIFIC, "Local", "OS", "Security", 2296 "Specific", "%s", deprecated_str, 1, 0, 2297 NETPERF_TYPE_CHAR); 2298 2299 set_output_elt(LOCAL_SECURITY_ENABLED_NUM, "Local", "OS", "Security", 2300 "Enabled Num", "%d", &local_security_enabled_num, 1, 0, 2301 NETPERF_TYPE_INT32); 2302 2303 set_output_elt(LOCAL_SECURITY_TYPE_ID, "Local", "OS", "Security", "Type ID", 2304 "%d", &local_security_type_id, 1, 0, NETPERF_TYPE_INT32); 2305 2306 set_output_elt(REMOTE_SECURITY_ENABLED, "Remote", "OS", "Security", 2307 "Enabled", "%s", deprecated_str, 1, 0, 2308 NETPERF_TYPE_CHAR); 2309 2310 set_output_elt(REMOTE_SECURITY_TYPE, "Remote", "OS", "Security", "Type", 2311 "%s", deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2312 2313 set_output_elt(REMOTE_SECURITY_SPECIFIC, "Remote", "OS", "Security", 2314 "Specific", "%s", deprecated_str, 1, 0, 2315 NETPERF_TYPE_CHAR); 2316 2317 set_output_elt(REMOTE_SECURITY_ENABLED_NUM, "Remote", "OS", "Security", 2318 "Enabled", "%d", &remote_security_enabled_num, 1, 0, 2319 NETPERF_TYPE_INT32); 2320 2321 set_output_elt(REMOTE_SECURITY_TYPE_ID, "Remote", "OS", "Security", "Type", 2322 "%d", &remote_security_type_id, 1, 0, NETPERF_TYPE_INT32); 2323 2324 set_output_elt(LOCAL_INTERVAL_USECS, "Local", "Interval", "Usecs", "", "%d", 2325 &interval_usecs, 1, 0, NETPERF_TYPE_INT32); 2326 2327 set_output_elt(LOCAL_INTERVAL_BURST, "Local", "Interval", "Burst", "", "%d", 2328 &interval_burst, 1, 0, NETPERF_TYPE_INT32); 2329 2330 set_output_elt(REMOTE_SYSTEM_MODEL, "Remote", "System", "Model", "", "%s", 2331 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2332 2333 set_output_elt(REMOTE_CPU_MODEL, "Remote", "CPU", "Model", "", "%s", 2334 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2335 2336 set_output_elt(REMOTE_CPU_FREQUENCY, "Remote", "CPU", "Frequency", "MHz", 2337 "%d", &remote_cpu_frequency, 1, 0, NETPERF_TYPE_INT32); 2338 2339 set_output_elt(LOCAL_SYSTEM_MODEL, "Local", "System", "Model", "", "%s", 2340 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2341 2342 set_output_elt(LOCAL_CPU_MODEL, "Local", "CPU", "Model", "", "%s", 2343 deprecated_str, 1, 0, NETPERF_TYPE_CHAR); 2344 2345 set_output_elt(LOCAL_CPU_FREQUENCY, "Local", "CPU", "Frequency", "MHz", "%d", 2346 &local_cpu_frequency, 1, 0, NETPERF_TYPE_INT32); 2347 2348 set_output_elt(MIN_LATENCY, "Minimum", "Latency", "Microseconds", "", "%d", 2349 &min_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32); 2350 2351 set_output_elt(MAX_LATENCY, "Maximum", "Latency", "Microseconds", "", "%d", 2352 &max_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32); 2353 2354 set_output_elt(P50_LATENCY, "50th", "Percentile", "Latency", "Microseconds", 2355 "%d", &p50_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32); 2356 2357 set_output_elt(P90_LATENCY, "90th", "Percentile", "Latency", "Microseconds", 2358 "%d", &p90_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32); 2359 2360 set_output_elt(P99_LATENCY, "99th", "Percentile", "Latency", "Microseconds", 2361 "%d", &p99_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32); 2362 2363 set_output_elt(MEAN_LATENCY, "Mean", "Latency", "Microseconds", "", "%.2f", 2364 &mean_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_DOUBLE); 2365 2366 set_output_elt(STDDEV_LATENCY, "Stddev", "Latency", "Microseconds", "", 2367 "%.2f", &stddev_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_DOUBLE); 2368 2369 set_output_elt(LOCAL_SOCKET_PRIO, "Local", "Socket", "Priority", "", "%d", 2370 &local_socket_prio, 1, 0, NETPERF_TYPE_INT32); 2371 2372 set_output_elt(REMOTE_SOCKET_PRIO, "Remote", "Socket", "Priority", "", "%d" 2373 , &remote_socket_prio, 1, 0, NETPERF_TYPE_INT32); 2374 2375 set_output_elt(LOCAL_SOCKET_TOS, "Local", "Socket", "TOS", "", "0x%.2x", 2376 &local_socket_tos, 1, 0, NETPERF_TYPE_INT32); 2377 2378 set_output_elt(REMOTE_SOCKET_TOS, "Remote", "Socket", "TOS", "", "0x%.2x", 2379 &remote_socket_tos, 1, 0, NETPERF_TYPE_INT32); 2380 2381 set_output_elt(LOCAL_CONG_CONTROL, "Local", "Congestion", "Control", 2382 "Algorithm", "%s", local_cong_control, 0, 2383 OMNI_WANT_LOC_CONG, NETPERF_TYPE_CHAR); 2384 2385 set_output_elt(REMOTE_CONG_CONTROL, "Remote", "Congestion", "Control", 2386 "Algorithm", "%s", remote_cong_control, 0, 2387 OMNI_WANT_REM_CONG, NETPERF_TYPE_CHAR); 2388 2389 set_output_elt(LOCAL_FILL_FILE, "Local", "Fill", "File", "", "%s", 2390 local_fill_file, 0, 0, NETPERF_TYPE_CHAR); 2391 2392 set_output_elt(REMOTE_FILL_FILE, "Remote", "Fill", "File", "", "%s", 2393 remote_fill_file, 0, 0, NETPERF_TYPE_CHAR); 2394 2395 set_output_elt(OUTPUT_END, "This", "Is", "The", "End", "%s", 2396 NULL, 0, 0, NETPERF_TYPE_CHAR); 2397 2398 } 2399 2400 void 2401 print_omni_init() { 2402 2403 int i,j; 2404 2405 if (debug) { 2406 fprintf(where,"%s entered\n", 2407 __FUNCTION__); 2408 fflush(where); 2409 } 2410 2411 /* why is this before the if you ask? because some of the output 2412 specifiers are char * rather than char[] and when I wanted to 2413 start setting output_group flags I was needing to call 2414 print_omni_init() before the char * 's were malloced, which meant 2415 the netperf_output_source got NULL pointers. there is 2416 undoubtedly a cleaner way to do all this. raj 20110629 */ 2417 2418 print_omni_init_list(); 2419 2420 if (printing_initialized) return; 2421 2422 printing_initialized = 1; 2423 2424 2425 /* belts and suspenders */ 2426 for (j = 0; j < NETPERF_MAX_BLOCKS; j++) 2427 for (i = 0; i < NETPERF_OUTPUT_MAX; i++) 2428 output_list[j][i] = OUTPUT_END; 2429 2430 2431 if (output_selection_spec) { 2432 parse_output_selection(output_selection_spec); 2433 } 2434 else { 2435 set_output_list_by_test(); 2436 } 2437 2438 } 2439 2440 /* why? because one cannot simply pass a pointer to snprintf - well 2441 except when it is expecting one... */ 2442 int 2443 my_snprintf(char *buffer, size_t size, netperf_output_elt_t *output_elt) 2444 { 2445 switch (output_elt->output_type) { 2446 case NETPERF_TYPE_CHAR: 2447 return snprintf(buffer, size, 2448 output_elt->format, 2449 (char *)output_elt->display_value); 2450 break; 2451 case NETPERF_TYPE_INT32: 2452 return snprintf(buffer, size, 2453 output_elt->format, 2454 *(int *)(output_elt->display_value)); 2455 break; 2456 case NETPERF_TYPE_UINT32: 2457 return snprintf(buffer, size, 2458 output_elt->format, 2459 *(unsigned int *)(output_elt->display_value)); 2460 break; 2461 case NETPERF_TYPE_INT64: 2462 return snprintf(buffer, size, 2463 output_elt->format, 2464 *(long long *)(output_elt->display_value)); 2465 break; 2466 case NETPERF_TYPE_UINT64: 2467 return snprintf(buffer, size, 2468 output_elt->format, 2469 *(unsigned long long *)(output_elt->display_value)); 2470 break; 2471 case NETPERF_TYPE_FLOAT: 2472 return snprintf(buffer, size, 2473 output_elt->format, 2474 *(float *)(output_elt->display_value)); 2475 break; 2476 case NETPERF_TYPE_DOUBLE: 2477 return snprintf(buffer, size, 2478 output_elt->format, 2479 *(double *)(output_elt->display_value)); 2480 break; 2481 default: 2482 fprintf(stderr, 2483 "Unknown/unsupported output_elt output_type of %d\n", 2484 output_elt->output_type); 2485 fflush(stderr); 2486 exit(-1); 2487 } 2488 } 2489 2490 void 2491 print_omni_csv() 2492 { 2493 2494 int i,j,k,buflen,vallen; 2495 2496 char *hdr1 = NULL; 2497 char *val1 = NULL; 2498 char *h1 = NULL; 2499 char *v1 = NULL; 2500 char tmpval[1024]; 2501 2502 buflen = 0; 2503 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 2504 for (j = 0; 2505 ((j < NETPERF_OUTPUT_MAX) && 2506 (output_list[i][j] != OUTPUT_END)); 2507 j++) { 2508 if ((netperf_output_source[output_list[i][j]].format != NULL) && 2509 (netperf_output_source[output_list[i][j]].display_value != NULL)) { 2510 vallen = 2511 my_snprintf(tmpval, 2512 1024, 2513 &(netperf_output_source[output_list[i][j]])); 2514 if (vallen == -1) { 2515 fprintf(where,"my_snprintf failed on %s with format %s\n", 2516 netperf_output_enum_to_str(j), 2517 netperf_output_source[output_list[i][j]].format); 2518 fflush(where); 2519 } 2520 vallen += 1; /* forget not the terminator */ 2521 } 2522 else 2523 vallen = 0; 2524 2525 if (vallen > 2526 netperf_output_source[output_list[i][j]].tot_line_len) 2527 netperf_output_source[output_list[i][j]].tot_line_len = vallen; 2528 2529 buflen += 2530 netperf_output_source[output_list[i][j]].tot_line_len; 2531 } 2532 } 2533 2534 if (print_headers) hdr1 = malloc(buflen + 1); 2535 val1 = malloc(buflen + 1); 2536 2537 if (((hdr1 == NULL) && (print_headers)) || 2538 (val1 == NULL)) { 2539 fprintf(where,"unable to allocate output buffers\n"); 2540 fflush(where); 2541 exit(-1); 2542 } 2543 2544 if (print_headers) memset(hdr1,' ',buflen + 1); 2545 memset(val1,' ',buflen + 1); 2546 2547 /* ostensibly, we now "know" that we have enough space in all our 2548 strings, and we have spaces where we want them etc */ 2549 h1 = hdr1; 2550 v1 = val1; 2551 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 2552 for (j = 0; 2553 ((j < NETPERF_OUTPUT_MAX) && 2554 (output_list[i][j] != OUTPUT_END)); 2555 j++) { 2556 int len; 2557 len = 0; 2558 if (print_headers) { 2559 for (k = 0; ((k < 4) && 2560 (NULL != 2561 netperf_output_source[output_list[i][j]].line[k]) && 2562 (strcmp("",netperf_output_source[output_list[i][j]].line[k]))); k++) { 2563 2564 len = sprintf(h1, 2565 "%s", 2566 netperf_output_source[output_list[i][j]].line[k]); 2567 *(h1 + len) = ' '; 2568 /* now move to the next starting column. for csv we aren't worried 2569 about alignment between the header and the value lines */ 2570 h1 += len + 1; 2571 } 2572 *(h1 - 1) = ','; 2573 } 2574 if ((netperf_output_source[output_list[i][j]].format != NULL) && 2575 (netperf_output_source[output_list[i][j]].display_value != NULL)) { 2576 /* tot_line_len is bogus here, but should be "OK" ? */ 2577 len = my_snprintf(v1, 2578 netperf_output_source[output_list[i][j]].tot_line_len, 2579 &(netperf_output_source[output_list[i][j]])); 2580 2581 /* nuke the trailing \n" from the string routine. */ 2582 *(v1 + len) = ','; 2583 v1 += len + 1; 2584 } 2585 else { 2586 /* we need a ',' even if there is no value */ 2587 *v1 = ','; 2588 v1 += 2; 2589 } 2590 } 2591 } 2592 2593 /* ok, _now_ null terminate each line by nuking the last comma. do 2594 we have an OBOB here? */ 2595 if (print_headers) *(h1-1) = 0; 2596 *(v1-1) = 0; 2597 /* and now spit it out, but only if it is going to have something 2598 in it. we don't want a bunch of blank lines or nulls... */ 2599 if (output_list[0][0] != OUTPUT_END) { 2600 if (print_headers) printf("%s\n",hdr1); 2601 printf("%s\n",val1); 2602 } 2603 2604 if (hdr1 != NULL) free(hdr1); 2605 if (val1 != NULL) free(val1); 2606 2607 } 2608 2609 void 2610 print_omni_keyword() 2611 { 2612 /* this one should be the simplest of all - no buffers to allocate, 2613 just spit it all out. raj 20080805 */ 2614 2615 int i,j; 2616 char tmpval[1024]; 2617 int vallen; 2618 2619 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 2620 for (j = 0; 2621 ((j < NETPERF_OUTPUT_MAX) && 2622 (output_list[i][j] != OUTPUT_END)); 2623 j++) { 2624 if ((netperf_output_source[output_list[i][j]].format != NULL) && 2625 (netperf_output_source[output_list[i][j]].display_value != NULL)) { 2626 vallen = 2627 my_snprintf(tmpval, 2628 1024, 2629 &(netperf_output_source[output_list[i][j]])); 2630 if (vallen == -1) { 2631 snprintf(tmpval, 2632 1024, 2633 "my_snprintf failed with format %s\n", 2634 netperf_output_source[output_list[i][j]].format); 2635 } 2636 fprintf(where, 2637 "%s=%s\n",netperf_output_enum_to_str(output_list[i][j]), 2638 tmpval); 2639 } 2640 } 2641 } 2642 fflush(where); 2643 } 2644 2645 void 2646 print_omni_human() 2647 { 2648 2649 int i,j,k,buflen,buflen_max; 2650 2651 char *hdr[4]; 2652 char *val1 = NULL; 2653 char tmpval[1024]; /* excessive, but we may have the command line */ 2654 int vallen; 2655 2656 for (k = 0; k < 4; k ++) { 2657 hdr[k] = NULL; 2658 } 2659 2660 /* decisions, decisions... walk the list twice to only need to 2661 allocate the charcter buffers once, or walk it once and possibly 2662 reallocate them as I go... oh, lets walk it twice just for fun to 2663 start. since only now do we know that the values are around to be 2664 printed, we should try the snprintf for the value and see how 2665 much space it wants and update max_line_len accordingly */ 2666 buflen_max = 0; 2667 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 2668 buflen = 0; 2669 for (j = 0; 2670 ((j < NETPERF_OUTPUT_MAX) && 2671 (output_list[i][j] != OUTPUT_END)); 2672 j++) { 2673 if ((netperf_output_source[output_list[i][j]].format != NULL) && 2674 (netperf_output_source[output_list[i][j]].display_value != 2675 NULL)) 2676 /* need to count the \n */ 2677 vallen = my_snprintf(tmpval, 2678 1024, 2679 &(netperf_output_source[output_list[i][j]])) + 1; 2680 else 2681 vallen = 0; 2682 2683 if (vallen > 2684 netperf_output_source[output_list[i][j]].max_line_len) 2685 netperf_output_source[output_list[i][j]].max_line_len = vallen; 2686 2687 buflen += 2688 netperf_output_source[output_list[i][j]].max_line_len + 1; 2689 } 2690 2691 if (buflen > buflen_max) 2692 buflen_max = buflen; 2693 } 2694 2695 /* more belts and suspenders */ 2696 for (k = 0; (k < 4) && (print_headers); k++) { 2697 hdr[k] = malloc(buflen_max+1); 2698 } 2699 val1 = malloc(buflen_max+1); 2700 2701 /* we could probably be more succinct here but perhaps the compiler 2702 can figure that out for us :) */ 2703 for (k = 0; (k < 4) && (print_headers); k++) { 2704 if (hdr[k] == NULL) { 2705 fprintf(where,"Unable to allocate output buffers\n"); 2706 fflush(where); 2707 exit(-1); 2708 } 2709 } 2710 2711 /* ostensibly, we now "know" that we have enough space in all our 2712 strings, and we have spaces where we want them etc */ 2713 for (i = 0; i < NETPERF_MAX_BLOCKS; i++) { 2714 char *h[4]; 2715 char *v1 = val1; 2716 2717 for (k = 0; k < 4; k++) h[k] = hdr[k]; 2718 2719 /* we want to blank things out each time since we skip around a lot */ 2720 for (k = 0; (k < 4) && (print_headers); k++) { 2721 memset(hdr[k],' ',buflen_max+1); 2722 } 2723 memset(val1,' ',buflen_max+1); 2724 2725 2726 for (j = 0; 2727 ((j < NETPERF_OUTPUT_MAX) && 2728 (output_list[i][j] != OUTPUT_END)); 2729 j++) { 2730 if (print_headers) { 2731 for (k = 0; k < 4; k++) { 2732 memcpy(h[k], 2733 netperf_output_source[output_list[i][j]].line[k], 2734 strlen(netperf_output_source[output_list[i][j]].line[k])); 2735 } 2736 } 2737 if ((netperf_output_source[output_list[i][j]].format != NULL) && 2738 (netperf_output_source[output_list[i][j]].display_value != NULL)) { 2739 int len; 2740 len = my_snprintf(v1, 2741 netperf_output_source[output_list[i][j]].max_line_len, 2742 &(netperf_output_source[output_list[i][j]])); 2743 /* nuke the trailing \n" from the string routine. */ 2744 *(v1 + len) = ' '; 2745 } 2746 /* now move to the next starting column */ 2747 for (k = 0; (k < 4) && (print_headers); k++) { 2748 h[k] += 2749 netperf_output_source[output_list[i][j]].max_line_len + 1; 2750 } 2751 v1 += netperf_output_source[output_list[i][j]].max_line_len + 1; 2752 } 2753 /* ok, _now_ null terminate each line. do we have an OBOB here? */ 2754 for (k = 0; (k < 4) && (print_headers); k++) { 2755 *h[k] = 0; 2756 } 2757 *v1 = 0; 2758 /* and now spit it out, but only if it is going to have something 2759 in it. we don't want a bunch of blank lines or nulls... at some 2760 point we might want to work backwards collapsine whitespace from 2761 the right but for now, we won't bother */ 2762 if (output_list[i][0] != OUTPUT_END) { 2763 if (i > 0) printf("\n"); /* we want a blank line between blocks ? */ 2764 for (k = 0; (k < 4) && (print_headers); k++) { 2765 printf("%s\n",hdr[k]); 2766 } 2767 printf("%s\n",val1); 2768 } 2769 }; 2770 for (k = 0; k < 4; k++) { 2771 if (hdr[k] != NULL) free(hdr[k]); 2772 } 2773 } 2774 2775 void 2776 print_omni() 2777 { 2778 2779 print_omni_init(); 2780 2781 if (debug > 2) 2782 dump_netperf_output_source(where); 2783 2784 switch (netperf_output_mode) { 2785 case CSV: 2786 print_omni_csv(); 2787 break; 2788 case KEYVAL: 2789 print_omni_keyword(); 2790 break; 2791 case HUMAN: 2792 print_omni_human(); 2793 break; 2794 default: 2795 fprintf(where,"Yo Rick! There is a bug in netperf_output_mode!\n"); 2796 fflush(where); 2797 exit(-1); 2798 } 2799 2800 } 2801 /* for the next few routines (connect, accept, send, recv, 2802 disconnect/close) we will use a return of -1 to mean times up, -2 2803 to mean a transient error (eg ENOBUFS on a UDP send call) and -3 to 2804 mean hard error. this means it is ok for the connect routine to 2805 return a 0 (zero) if that happens to be the fd/SOCKET we get and in 2806 theory we will be able to support zero-length messages on those 2807 protocols which support it. all in theory of course. raj 2808 2008-01-09 */ 2809 2810 int 2811 connect_data_socket(SOCKET send_socket, struct addrinfo *remote_res, int dont_give_up) 2812 { 2813 int ret; 2814 2815 /* Connect up to the remote port on the data socket */ 2816 if ((ret = connect(send_socket, 2817 remote_res->ai_addr, 2818 remote_res->ai_addrlen)) == INVALID_SOCKET) { 2819 if (SOCKET_EINTR(ret)) { 2820 /* we interpret this to mean that the test is supposed to be 2821 over, so return a value of -1 to the caller */ 2822 return -1; 2823 } 2824 if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret) || dont_give_up) { 2825 /* likely something our explicit bind() would have caught in 2826 the past, so go get another port, via create_data_socket. 2827 yes, this is a bit more overhead than before, but the 2828 condition should be rather rare. we only get a new port if 2829 this was a connection-including test like TCP_CRR or 2830 TCP_CC. Otherwise we need to return an error. raj 2831 2008-01-08 */ 2832 return -2; 2833 } 2834 else 2835 /* -3 means there was an error */ 2836 return -3; 2837 } 2838 return 0; 2839 } 2840 2841 static 2842 int send_pktinfo(SOCKET data_socket, char *buffer, int len, struct sockaddr *destination, int destlen) { 2843 #ifdef IP_PKTINFO 2844 struct msghdr msg; 2845 struct iovec iovec[1]; 2846 char msg_control[512]; 2847 struct cmsghdr *cmsg; 2848 int cmsg_space = 0; 2849 2850 iovec[0].iov_base = buffer; 2851 iovec[0].iov_len = len; 2852 msg.msg_name = destination; 2853 msg.msg_namelen = destlen; 2854 msg.msg_iov = iovec; 2855 msg.msg_iovlen = 1; 2856 msg.msg_control = msg_control; 2857 msg.msg_controllen = sizeof(msg_control); 2858 msg.msg_flags = 0; 2859 2860 cmsg = CMSG_FIRSTHDR(&msg); 2861 if (have_pktinfo) { 2862 cmsg->cmsg_level = IPPROTO_IP; 2863 cmsg->cmsg_type = IP_PKTINFO; 2864 cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo)); 2865 *(struct in_pktinfo*)CMSG_DATA(cmsg) = in_pktinfo; 2866 cmsg_space += CMSG_SPACE(sizeof(in_pktinfo)); 2867 } 2868 msg.msg_controllen = cmsg_space; 2869 return sendmsg(data_socket, &msg, 0); 2870 #else 2871 return -1; 2872 #endif /* IP_PKTINFO */ 2873 } 2874 2875 2876 int 2877 send_data(SOCKET data_socket, struct ring_elt *send_ring, uint32_t bytes_to_send, struct sockaddr *destination, int destlen, int protocol) { 2878 2879 int len; 2880 2881 /* if the user has supplied a destination, we use sendto, otherwise 2882 we use send. we ass-u-me blocking operations always, so no need 2883 to check for eagain or the like. */ 2884 2885 if (debug > 2) { 2886 fprintf(where, 2887 "%s sock %d, ring elt %p, bytes %d, dest %p, len %d\n", 2888 __FUNCTION__, 2889 data_socket, 2890 send_ring, 2891 bytes_to_send, 2892 destination, 2893 destlen); 2894 fflush(where); 2895 } 2896 2897 if (destination) { 2898 if (have_pktinfo) { 2899 len = send_pktinfo(data_socket, 2900 send_ring->buffer_ptr, 2901 bytes_to_send, 2902 destination, 2903 destlen); 2904 } 2905 else { 2906 len = sendto(data_socket, 2907 send_ring->buffer_ptr, 2908 bytes_to_send, 2909 #if defined(MSG_FASTOPEN) 2910 (use_fastopen && protocol == IPPROTO_TCP) ? MSG_FASTOPEN : 0, 2911 #else 2912 0, 2913 #endif 2914 destination, 2915 destlen); 2916 } 2917 } 2918 else { 2919 if (!use_write) { 2920 len = send(data_socket, 2921 send_ring->buffer_ptr, 2922 bytes_to_send, 2923 0); 2924 } 2925 else { 2926 #ifndef WIN32 2927 len = write(data_socket, 2928 send_ring->buffer_ptr, 2929 bytes_to_send); 2930 #else 2931 fprintf(where,"I'm sorry Dave I cannot write() under Windows\n"); 2932 fflush(where); 2933 return -3; 2934 #endif 2935 } 2936 } 2937 if(len != bytes_to_send) { 2938 /* don't forget that some platforms may do a partial send upon 2939 receipt of the interrupt and not return an EINTR... */ 2940 if (SOCKET_EINTR(len) || (len >= 0)) 2941 { 2942 /* we hit the end of a timed test. */ 2943 return -1; 2944 } 2945 /* if this is UDP it is possible to receive an ENOBUFS on the send 2946 call and it would not be a fatal error. of course if we were 2947 to return 0 then it would make the test think it was over when 2948 it really wasn't. the question becomes what to do. for the 2949 time being, the answer will likely be to return something like 2950 -2 to indicate a non-fatal error happened on the send and let 2951 the caller figure it out :) we won't actually check to see if 2952 this is UDP - it is the author's experience in many, Many, MANY 2953 years that the only time an ENOBUFS has been returned in a 2954 netperf test has been with UDP. famous last words :) */ 2955 if (errno == ENOBUFS) 2956 return -2; 2957 else { 2958 fprintf(where,"%s: data send error: %s (errno %d)\n", 2959 __FUNCTION__, strerror(errno), errno); 2960 return -3; 2961 } 2962 } 2963 return len; 2964 } 2965 2966 #if defined(__linux) 2967 static int 2968 recv_data_no_copy(SOCKET data_socket, struct ring_elt *recv_ring, uint32_t bytes_to_recv, struct sockaddr *source, netperf_socklen_t *sourcelen, uint32_t flags, uint32_t *num_receives) { 2969 2970 #ifndef SPLICE_F_MOVE 2971 # define SPLICE_F_MOVE 0x01 2972 #endif 2973 #ifndef SPLICE_F_NONBLOCK 2974 # define SPLICE_F_NONBLOCK 0x02 2975 #endif 2976 2977 static int pfd[2] = {-1, -1}; 2978 static int fdnull = -1; 2979 2980 2981 char *temp_message_ptr; 2982 int bytes_left; 2983 int bytes_recvd; 2984 int my_recvs; 2985 int my_flags = SPLICE_F_MOVE | SPLICE_F_NONBLOCK; /* values 2986 suggested by 2987 Eric Dumazet */ 2988 int ret; 2989 2990 if (pfd[0] == -1) { 2991 if (pipe(pfd)) { 2992 fprintf(where, 2993 "%s pipe call failed with errno %d '%s'\n", 2994 __FUNCTION__, 2995 errno, 2996 strerror(errno)); 2997 return -4; /* this will cause recv_data to do things the 2998 old-fashioned way for the test */ 2999 } 3000 if ((fdnull = open("/dev/null",O_WRONLY)) == -1) { 3001 fprintf(where, 3002 "%s open call failed with errno %d '%s'\n", 3003 __FUNCTION__, 3004 errno, 3005 strerror(errno)); 3006 return -4; 3007 } 3008 } 3009 3010 /* receive data off the data_socket, ass-u-me-ing a blocking socket 3011 all the way!-) 2008-01-08 */ 3012 my_recvs = 0; 3013 bytes_left = bytes_to_recv; 3014 3015 if (debug > 1) { 3016 fprintf(where, 3017 "%s sock %d, ring elt %p, bytes %d, source %p, srclen %d, flags %x, num_recv %p\n", 3018 __FUNCTION__, 3019 data_socket, 3020 recv_ring, 3021 bytes_to_recv, 3022 source, 3023 (source != NULL) ? *sourcelen : -1, 3024 flags, 3025 num_receives); 3026 fflush(where); 3027 } 3028 do { 3029 3030 bytes_recvd = splice(data_socket, 3031 NULL, 3032 pfd[1], 3033 NULL, 3034 bytes_left, 3035 my_flags); 3036 3037 3038 if (bytes_recvd > 0) { 3039 /* per Eric Dumazet, we should just let this second splice call 3040 move as many bytes as it can and not worry about how much. 3041 this should make the call more robust when made on a system 3042 under memory pressure */ 3043 splice(pfd[0], NULL, fdnull, NULL, 1 << 30, my_flags); 3044 bytes_left -= bytes_recvd; 3045 } 3046 else { 3047 break; 3048 } 3049 my_recvs++; /* should the pair of splices count as one? */ 3050 } while ((bytes_left > 0) && (flags & NETPERF_WAITALL)); 3051 3052 *num_receives = my_recvs; 3053 3054 /* OK, we are out of the loop - now what? */ 3055 if (bytes_recvd < 0) { 3056 /* did the timer hit, or was there an error? */ 3057 if (SOCKET_EINTR(bytes_recvd)) 3058 { 3059 /* We hit the end of a timed test. */ 3060 return -1; 3061 } 3062 /* it was a hard error */ 3063 return -3; 3064 } 3065 3066 3067 /* this looks a little funny, but should be correct. if we had 3068 NETPERF_WAITALL set and we got here, it means we got all the 3069 bytes of the request/response. otherwise we would have hit the 3070 error or end of test cases. if NETPERF_WAITALL isn't set, this 3071 is a STREAM test, and we will have only made one call to recv, so 3072 bytes_recvd will be accurate. */ 3073 if (bytes_left) 3074 return bytes_recvd; 3075 else 3076 return bytes_to_recv; 3077 3078 } 3079 3080 #endif 3081 3082 static 3083 int recv_pktinfo(SOCKET data_socket, char *message_ptr, int bytes_to_recv, int my_flags, struct sockaddr *source, netperf_socklen_t *sourcelen) { 3084 3085 #ifdef IP_PKTINFO 3086 struct iovec my_iovec; 3087 struct msghdr my_header; 3088 struct cmsghdr *cmsg; 3089 struct in_pktinfo *pktinfo; 3090 3091 char control_buf[512]; 3092 int onoff = 1; 3093 int ret; 3094 3095 my_iovec.iov_base = message_ptr; 3096 my_iovec.iov_len = bytes_to_recv; 3097 3098 my_header.msg_name = source; 3099 my_header.msg_namelen = *sourcelen; 3100 my_header.msg_iov = &my_iovec; 3101 my_header.msg_iovlen = 1; 3102 my_header.msg_control = control_buf; 3103 my_header.msg_controllen = sizeof(control_buf); 3104 3105 /* not going to bother checking, if it doesn't work we are no 3106 worse-off than we were before. we are going to ignore IPv6 for 3107 the time being */ 3108 setsockopt(data_socket, IPPROTO_IP, IP_PKTINFO, &onoff, sizeof(onoff)); 3109 3110 ret = recvmsg(data_socket, &my_header, 0); 3111 3112 if (ret >= 0) { 3113 struct sockaddr_in me; 3114 struct sockaddr_in clear; 3115 netperf_socklen_t melen = sizeof(me); 3116 for (cmsg = CMSG_FIRSTHDR(&my_header); 3117 cmsg != NULL; 3118 cmsg = CMSG_NXTHDR(&my_header, cmsg)) { 3119 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { 3120 in_pktinfo = *(struct in_pktinfo *)CMSG_DATA(cmsg); 3121 have_pktinfo = 1; 3122 } 3123 } 3124 } 3125 3126 onoff = 0; 3127 setsockopt(data_socket, IPPROTO_IP, IP_PKTINFO, &onoff, sizeof(onoff)); 3128 3129 return ret; 3130 #else 3131 return -1; 3132 #endif 3133 } 3134 3135 3136 int 3137 recv_data(SOCKET data_socket, struct ring_elt *recv_ring, uint32_t bytes_to_recv, struct sockaddr *source, netperf_socklen_t *sourcelen, uint32_t flags, uint32_t *num_receives) { 3138 3139 char *temp_message_ptr; 3140 int bytes_left; 3141 int bytes_recvd; 3142 int my_recvs; 3143 int my_flags = 0; /* will we one day want to set MSG_WAITALL? */ 3144 3145 #if defined(__linux) 3146 int ret; 3147 if (loc_rcvavoid == 1) { 3148 ret = recv_data_no_copy(data_socket, recv_ring, bytes_to_recv, source, sourcelen, flags, num_receives); 3149 if (ret != -4) 3150 return ret; 3151 else 3152 loc_rcvavoid = 0; 3153 } 3154 #endif 3155 3156 /* receive data off the data_socket, ass-u-me-ing a blocking socket 3157 all the way!-) 2008-01-08 */ 3158 my_recvs = 0; 3159 bytes_left = bytes_to_recv; 3160 temp_message_ptr = recv_ring->buffer_ptr; 3161 3162 if (debug > 1) { 3163 fprintf(where, 3164 "%s sock %d, ring elt %p, bytes %d, source %p, srclen %d, flags %x, num_recv %p\n", 3165 __FUNCTION__, 3166 data_socket, 3167 recv_ring, 3168 bytes_to_recv, 3169 source, 3170 (source != NULL) ? *sourcelen : -1, 3171 flags, 3172 num_receives); 3173 fflush(where); 3174 } 3175 do { 3176 if (source) { 3177 /* call recvfrom it does look a little silly here inside the do 3178 while, but I think it is ok - a UDP or other DGRAM or 3179 SEQPACKET (?) socket, which should be the only time we 3180 pass-in a source pointer will have a semantic that should get 3181 us out of the dowhile on the first call anyway. if it 3182 turns-out not to be the case, then we can hoist the if above 3183 the do and put the dowhile in the else. */ 3184 if (use_pktinfo) { 3185 bytes_recvd = recv_pktinfo(data_socket, 3186 temp_message_ptr, 3187 bytes_left, 3188 my_flags, 3189 source, 3190 sourcelen); 3191 use_pktinfo = 0; 3192 } 3193 else { 3194 bytes_recvd = recvfrom(data_socket, 3195 temp_message_ptr, 3196 bytes_left, 3197 my_flags, 3198 source, 3199 sourcelen); 3200 } 3201 } 3202 else { 3203 /* just call recv */ 3204 bytes_recvd = recv(data_socket, 3205 temp_message_ptr, 3206 bytes_left, 3207 my_flags); 3208 } 3209 if (bytes_recvd > 0) { 3210 bytes_left -= bytes_recvd; 3211 temp_message_ptr += bytes_recvd; 3212 } 3213 else { 3214 break; 3215 } 3216 my_recvs++; 3217 } while ((bytes_left > 0) && (flags & NETPERF_WAITALL)); 3218 3219 *num_receives = my_recvs; 3220 3221 /* OK, we are out of the loop - now what? */ 3222 if (bytes_recvd < 0) { 3223 /* did the timer hit, or was there an error? */ 3224 if (SOCKET_EINTR(bytes_recvd)) 3225 { 3226 /* We hit the end of a timed test. */ 3227 return -1; 3228 } 3229 if (SOCKET_EAGAIN(bytes_recvd) || 3230 SOCKET_EWOULDBLOCK(bytes_recvd)) { 3231 return -2; 3232 } 3233 /* it was a hard error */ 3234 return -3; 3235 } 3236 3237 3238 /* this looks a little funny, but should be correct. if we had 3239 NETPERF_WAITALL set and we got here, it means we got all the 3240 bytes of the request/response. otherwise we would have hit the 3241 error or end of test cases. if NETPERF_WAITALL isn't set, this 3242 is a STREAM test, and we will have only made one call to recv, so 3243 bytes_recvd will be accurate. */ 3244 if (bytes_left) 3245 return bytes_recvd; 3246 else 3247 return bytes_to_recv; 3248 3249 } 3250 3251 3252 int 3253 close_data_socket(SOCKET data_socket, struct sockaddr *peer, int peerlen, int protocol) 3254 { 3255 3256 int ret; 3257 char buffer[4]; 3258 3259 if (debug) { 3260 fprintf(where, 3261 "%s sock %d peer %p peerlen %d protocol %d\n", 3262 __FUNCTION__, 3263 data_socket, 3264 peer, 3265 peerlen, 3266 protocol); 3267 fflush(where); 3268 } 3269 3270 if (protocol == IPPROTO_UDP) { 3271 /* try to give the remote a signal. what this means if we ever 3272 wanted to actually send zero-length messages remains to be seen 3273 :) */ 3274 int i; 3275 for (i = 0; i < 3; i++) { 3276 if (peer) 3277 ret = sendto(data_socket, 3278 buffer, 3279 0, 3280 0, 3281 peer, 3282 peerlen); 3283 else 3284 ret = send(data_socket, 3285 buffer, 3286 0, 3287 0); 3288 if (SOCKET_EINTR(ret)) { 3289 close(data_socket); 3290 return -1; 3291 } 3292 } 3293 } 3294 ret = close(data_socket); 3295 3296 if (SOCKET_EINTR(ret)) { 3297 /* end of test */ 3298 return -1; 3299 } 3300 else if (ret == 0) { 3301 return ret; 3302 } 3303 else 3304 return -3; 3305 3306 } 3307 3308 int 3309 disconnect_data_socket(SOCKET data_socket, int initiate, int do_close, struct sockaddr *peer, int peerlen) 3310 { 3311 3312 char buffer[4]; 3313 int bytes_recvd; 3314 3315 if (debug) { 3316 fprintf(where, 3317 "%s sock %d init %d do_close %d protocol %d\n", 3318 __FUNCTION__, 3319 data_socket, 3320 initiate, 3321 do_close, 3322 protocol); 3323 fflush(where); 3324 } 3325 3326 /* at some point we'll need to abstract this a little. for now, if 3327 the protocol is UDP, we try to send some number of zero-length 3328 datagrams to allow the remote to get out of its loop without 3329 having to wait for the padded timer to expire. if it isn't UDP, 3330 we assume a reliable connection and can do the usual graceful 3331 shutdown thing */ 3332 3333 /* this needs to be revisited for the netperf receiving case when 3334 the test is terminated by a Ctrl-C. raj 2012-01-24 */ 3335 3336 if (protocol != IPPROTO_UDP) { 3337 if (initiate) 3338 shutdown(data_socket, SHUT_WR); 3339 3340 /* we are expecting to get either a return of zero indicating 3341 connection close, or an error. of course, we *may* never 3342 receive anything from the remote which means we probably really 3343 aught to have a select here but until we are once bitten we 3344 will remain twice bold. */ 3345 bytes_recvd = recv(data_socket, 3346 buffer, 3347 1, 3348 0); 3349 3350 if (bytes_recvd != 0) { 3351 /* connection close, call close. we assume that the requisite 3352 number of bytes have been received */ 3353 if (SOCKET_EINTR(bytes_recvd)) 3354 { 3355 /* We hit the end of a timed test. */ 3356 return -1; 3357 } 3358 return -3; 3359 } 3360 } 3361 else { 3362 int i; 3363 for (i = 0; i < 3; i++) { 3364 if (peer) 3365 bytes_recvd = sendto(data_socket, 3366 buffer, 3367 0, 3368 0, 3369 peer, 3370 peerlen); 3371 else 3372 bytes_recvd = send(data_socket, 3373 buffer, 3374 0, 3375 0); 3376 /* we only really care if the timer expired on us */ 3377 if (SOCKET_EINTR(bytes_recvd)) { 3378 if (do_close) 3379 close(data_socket); 3380 return -1; 3381 } 3382 } 3383 } 3384 3385 if (do_close) 3386 close(data_socket); 3387 3388 return 0; 3389 } 3390 3391 #ifdef HAVE_LINUX_TCP_H 3392 static void 3393 dump_tcp_info(struct tcp_info *tcp_info) 3394 { 3395 3396 fprintf(stderr, 3397 "tcpi_rto %d tcpi_ato %d tcpi_pmtu %d tcpi_rcv_ssthresh %d\n" 3398 "tcpi_rtt %d tcpi_rttvar %d tcpi_snd_ssthresh %d tpci_snd_cwnd %d\n" 3399 "tcpi_reordering %d tcpi_total_retrans %d\n", 3400 tcp_info->tcpi_rto, 3401 tcp_info->tcpi_ato, 3402 tcp_info->tcpi_pmtu, 3403 tcp_info->tcpi_rcv_ssthresh, 3404 tcp_info->tcpi_rtt, 3405 tcp_info->tcpi_rttvar, 3406 tcp_info->tcpi_snd_ssthresh, 3407 tcp_info->tcpi_snd_cwnd, 3408 tcp_info->tcpi_reordering, 3409 tcp_info->tcpi_total_retrans); 3410 3411 return; 3412 } 3413 3414 #endif 3415 3416 static int 3417 get_transport_retrans(SOCKET socket, int protocol) { 3418 3419 #ifdef HAVE_LINUX_TCP_H 3420 struct tcp_info tcp_info; 3421 3422 int ret; 3423 netperf_socklen_t infosize; 3424 3425 if (protocol != IPPROTO_TCP) 3426 return -1; 3427 3428 infosize = sizeof(struct tcp_info); 3429 3430 if ((ret = getsockopt(socket,protocol,TCP_INFO,&tcp_info,&infosize)) < 0) { 3431 if (debug) { 3432 fprintf(where, 3433 "%s: getsockopt errno %d %s\n", 3434 __FUNCTION__, 3435 errno, 3436 strerror(errno)); 3437 fflush(where); 3438 } 3439 return -1; 3440 } 3441 else { 3442 3443 /* we assume that if we have LINUX_TCP_H we also have getenv */ 3444 if (debug > 1 || getenv("DUMP_TCP_INFO")) { 3445 dump_tcp_info(&tcp_info); 3446 } 3447 return tcp_info.tcpi_total_retrans; 3448 } 3449 3450 3451 #else 3452 return -1; 3453 #endif 3454 } 3455 3456 3457 static void 3458 get_transport_info(SOCKET socket, int *mss, int protocol) 3459 { 3460 3461 netperf_socklen_t sock_opt_len; 3462 int option; 3463 sock_opt_len = sizeof(netperf_socklen_t); 3464 3465 switch (protocol) { 3466 #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG) 3467 case IPPROTO_TCP: 3468 option = TCP_MAXSEG; 3469 break; 3470 #endif 3471 3472 #if defined(IPPROTO_SCTP) && defined(SCTP_MAXSEG) 3473 case IPPROTO_SCTP: 3474 option = SCTP_MAXSEG; 3475 break; 3476 #endif 3477 default: 3478 *mss = -1; 3479 return; 3480 } 3481 3482 if (getsockopt(socket, 3483 protocol, 3484 option, 3485 (char *)mss, 3486 &sock_opt_len) == SOCKET_ERROR) { 3487 fprintf(where, 3488 "%s: getsockopt: errno %d\n", 3489 __FUNCTION__, 3490 errno); 3491 fflush(where); 3492 *mss = -1; 3493 } 3494 3495 } 3496 3497 static void 3498 get_transport_cong_control(SOCKET socket, int protocol, char cong_control[], int len) 3499 { 3500 #ifdef TCP_CONGESTION 3501 int my_len = len; 3502 if (protocol != IPPROTO_TCP) { 3503 strncpy(cong_control,"TCP Only",len); 3504 } 3505 else if (getsockopt(socket, 3506 protocol, TCP_CONGESTION, cong_control, &my_len) == 3507 SOCKET_ERROR) { 3508 snprintf(cong_control,len,"%d errno",errno); 3509 } 3510 #else 3511 strncpy(cong_control,"Unavailable",len); 3512 #endif 3513 cong_control[len-1] = '\0'; 3514 } 3515 3516 static void 3517 set_transport_cong_control(SOCKET socket, int protocol, char cong_control[], int len) 3518 { 3519 #ifdef TCP_CONGESTION 3520 if (protocol == IPPROTO_TCP) { 3521 /* if it fails, we'll pick that up via the subsequent "get" */ 3522 setsockopt(socket, protocol, TCP_CONGESTION, cong_control, len); 3523 } 3524 #endif 3525 } 3526 3527 static void 3528 set_receive_timeout(SOCKET sock, int timeout) 3529 { 3530 #ifdef SO_RCVTIMEO 3531 #ifndef WIN32 3532 struct timeval foo; 3533 3534 foo.tv_sec = timeout; 3535 foo.tv_usec = 0; 3536 3537 if (setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&foo,sizeof(foo)) < 0) { 3538 if (debug) { 3539 fprintf(where,"Note - attempt to set a receive timeout on the data socket failed with errno %d (%s)\n", 3540 errno, 3541 strerror(errno)); 3542 fflush(where); 3543 } 3544 } 3545 #endif 3546 #endif 3547 } 3548 3549 static SOCKET 3550 omni_create_data_socket(struct addrinfo *res) 3551 { 3552 SOCKET temp_socket; 3553 3554 temp_socket = create_data_socket(res); 3555 3556 if (temp_socket != SOCKET_ERROR) { 3557 if (local_cong_control_req[0] != '\0') { 3558 set_transport_cong_control(temp_socket, 3559 res->ai_protocol, 3560 local_cong_control_req, 3561 sizeof(local_cong_control_req)); 3562 } 3563 3564 if ((res->ai_protocol == IPPROTO_UDP) && 3565 (receive_timeout != -1)) { 3566 set_receive_timeout(temp_socket, receive_timeout); 3567 } 3568 3569 if (socket_debug) { 3570 int one = 1; 3571 setsockopt(temp_socket, 3572 SOL_SOCKET, 3573 SO_DEBUG, 3574 &one, 3575 sizeof(one)); 3576 } 3577 } 3578 return temp_socket; 3579 } 3580 /* choosing the default send size is a trifle more complicated than it 3581 used to be as we have to account for different protocol limits */ 3582 3583 #define UDP_LENGTH_MAX (0xFFFF - 28) 3584 3585 static int 3586 choose_send_size(int lss, int protocol) { 3587 3588 int send_size; 3589 3590 if (lss > 0) { 3591 send_size = lss_size; 3592 3593 /* we will assume that everyone has IPPROTO_UDP and thus avoid an 3594 issue with Windows using an enum */ 3595 if ((protocol == IPPROTO_UDP) && (send_size > UDP_LENGTH_MAX)) 3596 send_size = UDP_LENGTH_MAX; 3597 3598 } 3599 else { 3600 send_size = 4096; 3601 } 3602 return send_size; 3603 } 3604 3605 /* brain dead simple way to get netperf to emit a uuid. sadly, by this 3606 point we will have already established the control connection but 3607 those are the breaks. we do _NOT_ include a trailing newline 3608 because we want to be able to use this in a script */ 3609 3610 void 3611 print_uuid(char remote_host[]) 3612 { 3613 printf("%s",test_uuid); 3614 } 3615 #if defined(__linux) 3616 /* 3617 * Linux has this odd behavior where if the socket buffers are larger 3618 * than a device's txqueuelen, the kernel will silently drop transmits 3619 * which would not fit into the tx queue, and not pass an ENOBUFS 3620 * error back to the application. As a result, a UDP stream test can 3621 * report absurd transmit bandwidths (like 20Gb/s on a 1GbE NIC). 3622 * This behavior can be avoided if you request extended error 3623 * reporting on the socket. This is done by setting the IP_RECVERR 3624 * socket option at the IP level. 3625 */ 3626 static void 3627 enable_enobufs(int s) 3628 { 3629 struct protoent *pr; 3630 int on = 1; 3631 3632 if ((pr = getprotobyname("ip")) == NULL) { 3633 fprintf(where, "%s failed: getprotobyname\n",__FUNCTION__); 3634 fflush(where); 3635 return; 3636 } 3637 if (setsockopt(s, pr->p_proto, IP_RECVERR, (char *)&on, sizeof(on)) < 0) { 3638 fprintf(where, "%s failed: setsockopt (errno %d)\n",__FUNCTION__,errno); 3639 fflush(where); 3640 return; 3641 } 3642 } 3643 #endif 3644 3645 void 3646 set_omni_request_flags(struct omni_request_struct *omni_request) { 3647 3648 /* we have no else clauses here because we previously set flags 3649 to zero above raj 20090803 */ 3650 if (rem_nodelay) 3651 omni_request->flags |= OMNI_NO_DELAY; 3652 3653 if (remote_use_sendfile) 3654 omni_request->flags |= OMNI_USE_SENDFILE; 3655 3656 if (connection_test) 3657 omni_request->flags |= OMNI_CONNECT_TEST; 3658 3659 if (remote_checksum_off) 3660 omni_request->flags |= OMNI_CHECKSUM_OFF; 3661 3662 if (remote_cpu_usage) 3663 omni_request->flags |= OMNI_MEASURE_CPU; 3664 3665 if (routing_allowed) 3666 omni_request->flags |= OMNI_ROUTING_ALLOWED; 3667 3668 if (desired_output_groups & OMNI_WANT_REM_IFNAME) 3669 omni_request->flags |= OMNI_WANT_IFNAME; 3670 3671 if (desired_output_groups & OMNI_WANT_REM_IFSLOT) 3672 omni_request->flags |= OMNI_WANT_IFSLOT; 3673 3674 if (desired_output_groups & OMNI_WANT_REM_IFIDS) 3675 omni_request->flags |= OMNI_WANT_IFIDS; 3676 3677 if (desired_output_groups & OMNI_WANT_REM_DRVINFO) 3678 omni_request->flags |= OMNI_WANT_DRVINFO; 3679 3680 if (desired_output_groups & OMNI_WANT_REM_CONG) 3681 omni_request->flags |= OMNI_WANT_REM_CONG; 3682 3683 if (use_fastopen) 3684 omni_request->flags |= OMNI_FASTOPEN; 3685 3686 if (want_use_pktinfo) 3687 omni_request->flags |= OMNI_USE_PKTINFO; 3688 3689 if (want_defer_accept) 3690 omni_request->flags |= OMNI_WANT_DEFER_ACCEPT; 3691 3692 } 3693 3694 3695 /* this code is intended to be "the two routines to run them all" for 3696 BSDish sockets. it comes about as part of a desire to shrink the 3697 code footprint of netperf and to avoid having so many blessed 3698 routines to alter as time goes by. the downside is there will be 3699 more "ifs" than there were before. raj 2008-01-07 */ 3700 3701 void 3702 send_omni_inner(char remote_host[], unsigned int legacy_caller, char header_str[]) 3703 { 3704 3705 int ret,rret; 3706 int connected = 0; 3707 int timed_out = 0; 3708 int pad_time = 0; 3709 3710 struct ring_elt *send_ring; 3711 struct ring_elt *recv_ring; 3712 3713 struct sockaddr_storage remote_addr; 3714 struct sockaddr_storage my_addr; 3715 int remote_addr_len = sizeof(remote_addr); 3716 netperf_socklen_t my_addr_len = sizeof(my_addr); 3717 3718 SOCKET data_socket; 3719 int need_socket; 3720 3721 uint32_t temp_recvs; 3722 char tmpfmt; 3723 3724 struct addrinfo *local_res; 3725 struct addrinfo *remote_res; 3726 3727 struct omni_request_struct *omni_request; 3728 struct omni_response_struct *omni_response; 3729 struct omni_results_struct *omni_result; 3730 3731 #ifdef WANT_FIRST_BURST 3732 int requests_outstanding = 0; 3733 #endif 3734 3735 omni_request = 3736 (struct omni_request_struct *)netperf_request.content.test_specific_data; 3737 omni_response = 3738 (struct omni_response_struct *)netperf_response.content.test_specific_data; 3739 omni_result = 3740 (struct omni_results_struct *)netperf_response.content.test_specific_data; 3741 3742 3743 if (keep_histogram) { 3744 if (first_burst_size > 0) 3745 time_hist = HIST_new_n(first_burst_size + 1); 3746 else 3747 time_hist = HIST_new_n(1); 3748 } 3749 3750 /* since we are now disconnected from the code that established the 3751 control socket, and since we want to be able to use different 3752 protocols and such, we are passed the name of the remote host and 3753 must turn that into the test specific addressing information. */ 3754 3755 complete_addrinfos(&remote_res, 3756 &local_res, 3757 remote_host, 3758 socket_type, 3759 protocol, 3760 0); 3761 3762 if ( print_headers ) { 3763 print_top_test_header(header_str,local_res,remote_res); 3764 } 3765 3766 /* initialize a few counters */ 3767 3768 need_socket = 1; 3769 3770 if (connection_test) 3771 pick_next_port_number(local_res,remote_res); 3772 3773 3774 /* If the user has requested cpu utilization measurements, we must 3775 calibrate the cpu(s). We will perform this task within the tests 3776 themselves. If the user has specified the cpu rate, then 3777 calibrate_local_cpu will return rather quickly as it will have 3778 nothing to do. If local_cpu_rate is zero, then we will go through 3779 all the "normal" calibration stuff and return the rate back.*/ 3780 3781 if (local_cpu_usage) { 3782 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 3783 } 3784 3785 confidence_iteration = 1; 3786 init_stat(); 3787 3788 send_ring = NULL; 3789 recv_ring = NULL; 3790 3791 /* you will keep running the test until you get it right! :) */ 3792 while (((confidence < 0) && (confidence_iteration <= iteration_max)) || 3793 (confidence_iteration <= iteration_min)) { 3794 3795 trans_completed = 0; 3796 bytes_xferd = 0.0; 3797 remote_bytes_xferd = 0.0; 3798 times_up = 0; 3799 bytes_sent = 0; 3800 bytes_received = 0; 3801 local_send_calls = 0; 3802 local_receive_calls = 0; 3803 3804 /* since we are tracking the number of outstanding requests for 3805 timestamping purposes, and since the previous iteration of 3806 using confidence intervals may not have completed all of them, 3807 we now need to forget about them or we will mistakenly fill our 3808 tracking array. raj 2011-03-14 */ 3809 if (keep_histogram) { 3810 HIST_purge(time_hist); 3811 } 3812 3813 #ifdef WANT_FIRST_BURST 3814 /* we have to remember to reset the number of transactions 3815 outstanding and the "congestion window for each new 3816 iteration. raj 2006-01-31. */ 3817 requests_outstanding = 0; 3818 #endif 3819 3820 /* if the command-line included requests to randomize the IP 3821 addresses, then honor it. of course, this may not work all that 3822 well for some tests... raj 20101129 */ 3823 if (local_mask_len) 3824 random_ip_address(local_res, local_mask_len); 3825 if (remote_mask_len) 3826 random_ip_address(remote_res, remote_mask_len); 3827 3828 data_socket = omni_create_data_socket(local_res); 3829 3830 if (data_socket == INVALID_SOCKET) { 3831 perror("netperf: send_omni: unable to create data socket"); 3832 exit(1); 3833 } 3834 #if defined(__linux) 3835 /* we really only need this for a UDP_STREAM test. we particularly 3836 do not want it for a CC or CRR test. raj 2012-08-06 */ 3837 if ((protocol == IPPROTO_UDP) && 3838 NETPERF_XMIT_ONLY(direction)) { 3839 enable_enobufs(data_socket); 3840 } 3841 #endif 3842 need_socket = 0; 3843 3844 /* we need to consider if this is a request/response test, if we 3845 are receiving, if we are sending, etc, when setting-up our recv 3846 and send buffer rings. we should only need to do this once, and 3847 that would be when the relevant _ring variable is NULL. raj 3848 2008-01-18 */ 3849 if (direction & NETPERF_XMIT) { 3850 if (is_multicast_addr(remote_res)) { 3851 set_multicast_ttl(data_socket); 3852 } 3853 3854 if (NULL == send_ring) { 3855 if (req_size > 0) { 3856 /* request/response test */ 3857 if (send_width == 0) send_width = 1; 3858 bytes_to_send = req_size; 3859 } 3860 else { 3861 /* stream test */ 3862 if (send_size == 0) { 3863 send_size = choose_send_size(lss_size,protocol); 3864 } 3865 if (send_width == 0) 3866 send_width = (lss_size/send_size) + 1; 3867 if (send_width == 1) send_width++; 3868 bytes_to_send = send_size; 3869 } 3870 3871 send_ring = allocate_buffer_ring(send_width, 3872 bytes_to_send, 3873 local_send_align, 3874 local_send_offset); 3875 if (debug) { 3876 fprintf(where, 3877 "%s: %d entry send_ring obtained...\n", 3878 __FUNCTION__, 3879 send_width); 3880 } 3881 } 3882 } 3883 3884 if (direction & NETPERF_RECV) { 3885 /* do we need to join a multicast group? */ 3886 if (is_multicast_addr(local_res)) { 3887 join_multicast_addr(data_socket, local_res); 3888 } 3889 3890 /* do we need to allocate a recv_ring? */ 3891 if (NULL == recv_ring) { 3892 if (rsp_size > 0) { 3893 if (recv_width == 0) recv_width = 1; 3894 bytes_to_recv = rsp_size; 3895 } 3896 else { 3897 /* stream test */ 3898 if (recv_size == 0) { 3899 if (lsr_size > 0) { 3900 recv_size = lsr_size; 3901 } 3902 else { 3903 recv_size = 4096; 3904 } 3905 } 3906 if (recv_width == 0) { 3907 recv_width = (lsr_size/recv_size) + 1; 3908 if (recv_width == 1) recv_width++; 3909 } 3910 bytes_to_recv = recv_size; 3911 } 3912 3913 recv_ring = allocate_buffer_ring(recv_width, 3914 bytes_to_recv, 3915 local_recv_align, 3916 local_recv_offset); 3917 if (debug) { 3918 fprintf(where, 3919 "%s: %d entry recv_ring obtained...\n", 3920 __FUNCTION__, 3921 recv_width); 3922 } 3923 } 3924 } 3925 3926 if (!no_control) { 3927 3928 /* Tell the remote end to do a listen or otherwise prepare for 3929 what is to come. The server alters the socket paramters on the 3930 other side at this point, hence the reason for all the values 3931 being passed in the setup message. If the user did not specify 3932 any of the parameters, they will be passed as values which will 3933 indicate to the remote that no changes beyond the system's 3934 default should be used. Alignment is the exception, it will 3935 default to 8, which will probably be no alignment 3936 alterations. */ 3937 3938 netperf_request.content.request_type = DO_OMNI; 3939 omni_request->flags = 0; 3940 omni_request->send_buf_size = rss_size_req; 3941 omni_request->send_size = remote_send_size_req; 3942 omni_request->send_alignment = remote_send_align; 3943 omni_request->send_offset = remote_send_offset; 3944 omni_request->send_width = send_width; 3945 omni_request->request_size = req_size; 3946 3947 omni_request->recv_buf_size = rsr_size_req; 3948 omni_request->receive_size = remote_recv_size_req; 3949 omni_request->recv_alignment = remote_recv_align; 3950 omni_request->recv_offset = remote_recv_offset; 3951 omni_request->recv_width = recv_width; 3952 omni_request->response_size = rsp_size; 3953 omni_request->socket_prio = remote_socket_prio; 3954 omni_request->socket_tos = remote_socket_tos; 3955 3956 set_omni_request_flags(omni_request); 3957 3958 /* perhaps this should be made conditional on 3959 remote_cong_control_req[0] not being NULL? */ 3960 strncpy(omni_request->cong_control, 3961 remote_cong_control_req, 3962 sizeof(omni_request->cong_control)); 3963 omni_request->cong_control[sizeof(omni_request->cong_control) - 1] = 3964 '\0'; 3965 3966 if (want_keepalive) 3967 omni_request->flags |= OMNI_WANT_KEEPALIVE; 3968 3969 omni_request->cpu_rate = remote_cpu_rate; 3970 if (test_time) 3971 omni_request->test_length = test_time; 3972 else 3973 omni_request->test_length = test_trans * -1; 3974 omni_request->so_rcvavoid = rem_rcvavoid; 3975 omni_request->so_sndavoid = rem_sndavoid; 3976 omni_request->send_dirty_count = rem_dirty_count; 3977 omni_request->recv_dirty_count = rem_dirty_count; 3978 omni_request->recv_clean_count = rem_clean_count; 3979 3980 omni_request->data_port = atoi(remote_data_port); 3981 omni_request->ipfamily = af_to_nf(remote_res->ai_family); 3982 omni_request->socket_type = hst_to_nst(socket_type); 3983 omni_request->protocol = protocol; 3984 3985 omni_request->interval_burst = remote_interval_burst; 3986 omni_request->interval_usecs = remote_interval_usecs; 3987 3988 omni_request->direction = 0; 3989 /* yes, the sense here is correct - if we are transmitting, they 3990 receive, if we are receiving, they are transmitting... */ 3991 if (direction & NETPERF_XMIT) 3992 omni_request->direction |= NETPERF_RECV; 3993 if (direction & NETPERF_RECV) 3994 omni_request->direction |= NETPERF_XMIT; 3995 3996 /* some tests may require knowledge of our local addressing. such 3997 tests will for the time being require that the user specify a 3998 local IP/name so we can extract them from the data_socket. */ 3999 getsockname(data_socket, (struct sockaddr *)&my_addr, &my_addr_len); 4000 4001 ret = get_sockaddr_family_addr_port(&my_addr, 4002 nf_to_af(omni_request->ipfamily), 4003 omni_request->netperf_ip, 4004 &(omni_request->netperf_port)); 4005 ret = get_sockaddr_family_addr_port((struct sockaddr_storage *)remote_res->ai_addr, 4006 nf_to_af(omni_request->ipfamily), 4007 omni_request->netserver_ip, 4008 &(omni_request->data_port)); 4009 /* if the user didn't explicitly set the remote data address we 4010 don't want to pass along the one we picked implicitly, or a 4011 netserver sitting behind a (BLETCH) NAT will be asked to try 4012 to bind to the "public" IP. */ 4013 if (!explicit_data_address) { 4014 omni_request->netserver_ip[0] = 0; 4015 omni_request->netserver_ip[1] = 0; 4016 omni_request->netserver_ip[2] = 0; 4017 omni_request->netserver_ip[3] = 0; 4018 } 4019 if (debug > 1) { 4020 fprintf(where,"netperf: %s: requesting OMNI test\n",__FUNCTION__); 4021 } 4022 4023 strncpy(omni_request->fill_file, 4024 remote_fill_file, 4025 sizeof(omni_request->fill_file)); 4026 4027 send_request_n(OMNI_REQUEST_CONV_CUTOFF); 4028 4029 4030 /* the response from the remote should contain all the relevant 4031 socket and other parameters we need to know for this test. 4032 so, we can shove them back into the relevant variables here 4033 and be on our way. */ 4034 4035 recv_response_n(OMNI_RESPONSE_CONV_CUTOFF); /* brittle, but functional */ 4036 4037 if (!netperf_response.content.serv_errno) { 4038 rsr_size = omni_response->recv_buf_size; 4039 remote_recv_size = omni_response->receive_size; 4040 rss_size = omni_response->send_buf_size; 4041 remote_send_size = omni_response->send_size; 4042 rem_nodelay = omni_response->flags & OMNI_NO_DELAY; 4043 remote_use_sendfile = omni_response->flags & OMNI_USE_SENDFILE; 4044 remote_cpu_usage = omni_response->flags & OMNI_MEASURE_CPU; 4045 remote_cpu_rate = omni_response->cpu_rate; 4046 remote_send_width = omni_response->send_width; 4047 remote_recv_width = omni_response->recv_width; 4048 remote_socket_prio = omni_response->socket_prio; 4049 remote_socket_tos = omni_response->socket_tos; 4050 4051 /* make sure that port numbers are in network order because 4052 recv_response will have put everything into host order */ 4053 set_port_number(remote_res, 4054 (unsigned short)omni_response->data_port); 4055 4056 if (debug) { 4057 fprintf(where,"remote listen done.\n"); 4058 fprintf(where,"remote port is %u\n",get_port_number(remote_res)); 4059 fflush(where); 4060 } 4061 } 4062 else { 4063 Set_errno(netperf_response.content.serv_errno); 4064 fprintf(where, 4065 "netperf: remote error %d", 4066 netperf_response.content.serv_errno); 4067 perror(""); 4068 fflush(where); 4069 exit(-1); 4070 } 4071 4072 } 4073 4074 #ifdef WANT_DEMO 4075 /* at some point we will have to be more clever about this, but 4076 for now we won't */ 4077 4078 demo_rr_setup(100); 4079 #endif 4080 4081 /* if we are not a connectionless protocol, we need to connect. at 4082 some point even if we are a connectionless protocol, we may 4083 still want to "connect" for convenience raj 2008-01-14 */ 4084 need_to_connect = (protocol != IPPROTO_UDP) || local_connected; 4085 4086 /* possibly wait just a moment before actually starting - used 4087 mainly when one is doing many many many concurrent netperf 4088 tests */ 4089 WAIT_BEFORE_DATA_TRAFFIC(); 4090 4091 /* Set-up the test end conditions. For tests over a 4092 "reliable/connection-oriented" transport (eg TCP, SCTP, etc) 4093 this can be either time or byte/transaction count based. for 4094 unreliable transport or connection tests it can only be time 4095 based. having said that, we rely entirely on other code to 4096 enforce this before we even get here. raj 2008-01-08 */ 4097 4098 /* enable a test_time of 0 to mean just keep running until 4099 something other than alarm() generates a signal. raj 4100 2012-02-01 */ 4101 if ((test_time) || ((test_trans == 0) && (test_bytes == 0))) { 4102 /* The user wanted to end the test after a period of time. if 4103 we are a recv-only test, we need to protect ourself against 4104 the remote going poof, but we want to make sure we don't 4105 give-up before they finish, so we will add a PAD_TIME to the 4106 timer. if we are RR or XMIT, there should be no need for 4107 padding */ 4108 times_up = 0; 4109 units_remaining = 0; 4110 if ((!no_control) && 4111 (NETPERF_RECV_ONLY(direction)) && 4112 ((test_trans == 0) && (test_bytes == 0))) 4113 pad_time = 0; 4114 start_timer(test_time + pad_time); 4115 } 4116 else { 4117 /* The tester wanted to send a number of bytes or exchange a 4118 number of transactions. */ 4119 if (NETPERF_IS_RR(direction)) 4120 units_remaining = test_trans; 4121 else 4122 units_remaining = test_bytes; 4123 times_up = 1; 4124 } 4125 4126 /* grab the current time, and if necessary any starting information 4127 for the gathering of CPU utilization at this end. */ 4128 cpu_start(local_cpu_usage); 4129 4130 #if defined(WANT_INTERVALS) 4131 INTERVALS_INIT(); 4132 #endif /* WANT_INTERVALS */ 4133 4134 #ifdef WANT_DEMO 4135 if (demo_mode) { 4136 demo_first_timestamp(); 4137 } 4138 #endif 4139 4140 /* the "OR" here allows us to control test length by either 4141 byte/transaction count or by timer. when the test is 4142 byte/transaction count based the time test will always evaluate 4143 false. when the test is controlled by time, the byte/transaction 4144 count will always evaluate to false. when the test is finished 4145 the whole expression will go false and we will stop sending 4146 data. at least that is the plan :) raj 2008-01-08 */ 4147 4148 while ((!times_up) || (units_remaining > 0)) { 4149 4150 /* we need to be careful about when we snap a timestamp 4151 depending on the test parameters. this one *should* cover 4152 everything but the burst request/response test - famous last 4153 words of course. raj 20110111 */ 4154 4155 if (keep_histogram) { 4156 HIST_timestamp_start(time_hist); 4157 } 4158 4159 4160 again: 4161 4162 if (need_socket) { 4163 if (connection_test) 4164 pick_next_port_number(local_res,remote_res); 4165 4166 data_socket = omni_create_data_socket(local_res); 4167 4168 if (data_socket == INVALID_SOCKET) { 4169 perror("netperf: send_omni: unable to create data socket"); 4170 exit(1); 4171 } 4172 need_socket = 0; 4173 #if defined(__linux) 4174 if ((protocol == IPPROTO_UDP) && 4175 (direction & NETPERF_XMIT)) { 4176 enable_enobufs(data_socket); 4177 } 4178 #endif 4179 } 4180 4181 /* only connect if and when we need to */ 4182 if (need_to_connect && !use_fastopen) { 4183 /* assign to data_socket since connect_data_socket returns 4184 SOCKET and not int thanks to Windows. */ 4185 ret = connect_data_socket(data_socket,remote_res,dont_give_up); 4186 if (ret == 0) { 4187 connected = 1; 4188 need_to_connect = 0; 4189 } 4190 else if (ret == -1) { 4191 times_up = 1; 4192 timed_out = 1; 4193 break; 4194 } 4195 else if ((ret == -2) && connection_test) { 4196 /* transient error on a connection test means go around and 4197 try again with another local port number */ 4198 if (debug) { 4199 fprintf(where,"transient! transient! torpedo in the water!\n"); 4200 fflush(where); 4201 } 4202 close(data_socket); 4203 connected = 0; /* probably redundant but what the heck... */ 4204 need_socket = 1; 4205 need_to_connect = 1; 4206 /* this will stuff the next local port number within bounds 4207 into our local res, and then when the goto has us 4208 allocating a new socket it will do the right thing with the 4209 bind() call */ 4210 pick_next_port_number(local_res,remote_res); 4211 /* yes Virginia, a goto. perhaps one day we will rewrite 4212 the code to avoid it but for now, a goto... raj */ 4213 goto again; 4214 } 4215 else { 4216 /* either this was a hard failure (-3) or a soft failure on 4217 something other than a connection test */ 4218 perror("netperf: send_omni: connect_data_socket failed"); 4219 exit(1); 4220 } 4221 } 4222 4223 #ifdef WANT_FIRST_BURST 4224 /* Long ago and far away, on just about any *nix, one could 4225 avoid having multiple requests bundled into the same TCP 4226 segment simply by setting TCP_NODELAY and perhaps not trying 4227 to have more outstanding at one time than our guesstimate as 4228 to the TCP congestion window. In that way one could use a 4229 burst mode TCP_RR test as part of trying to measure maximum 4230 packets per second (PPS) on a system or through a NIC (well, 4231 assuming there weren't many retransmissions anyway) These 4232 days with Linux the dominant *nix and with it having made it 4233 virtually impossible to do any longer, it is no longer worth 4234 it to try the application-layer backflips. So, I am removing 4235 them. At some point we'll simply have to enhance this code 4236 to deal with multiple connections at one time, each with just 4237 the one transaction in flight for our PPS testing. Multiple 4238 netperfs, each with one connection and one transaction in 4239 flight rapidly becomes a context-switching benchmark rather 4240 than "networking". raj 2015-04-20 */ 4241 4242 while ((first_burst_size > 0) && 4243 (requests_outstanding < first_burst_size) && 4244 (NETPERF_IS_RR(direction)) && 4245 (!connection_test)) { 4246 if (debug > 1) { 4247 fprintf(where, 4248 "injecting, req_outstanding %d burst %d\n", 4249 requests_outstanding, 4250 first_burst_size); 4251 } 4252 4253 if ((ret = send_data(data_socket, 4254 send_ring, 4255 bytes_to_send, 4256 (connected) ? NULL : remote_res->ai_addr, 4257 remote_res->ai_addrlen, 4258 protocol)) != bytes_to_send) { 4259 /* in theory, we should never hit the end of the test in the 4260 first burst. however, in practice I have indeed seen 4261 some ENOBUFS happen in some aggregate tests. so we need 4262 to be a bit more sophisticated in how we handle it. raj 4263 20130516 */ 4264 if (ret != -2) { 4265 perror("send_omni: initial burst data send error"); 4266 exit(-1); 4267 } 4268 failed_sends++; 4269 } 4270 else { 4271 local_send_calls += 1; 4272 requests_outstanding += 1; 4273 } 4274 4275 /* yes, it seems a trifle odd having this *after* the send() 4276 just above, but really this is for the next send() or 4277 recv() call below or in the iteration of this loop, and the 4278 first HIST_timestamp_start() call at the top of the 4279 outermost loop will be for the first send() call here in 4280 the burst code. clear ain't it?-) raj 20110111 */ 4281 4282 if (keep_histogram) { 4283 HIST_timestamp_start(time_hist); 4284 } 4285 } 4286 4287 #endif /* WANT_FIRST_BURST */ 4288 4289 /* if we should try to send something, then by all means, let us 4290 try to send something. */ 4291 if (direction & NETPERF_XMIT) { 4292 4293 ret = send_data(data_socket, 4294 send_ring, 4295 bytes_to_send, 4296 (connected) ? NULL : remote_res->ai_addr, 4297 /* if the destination above is NULL, this is ignored */ 4298 remote_res->ai_addrlen, 4299 protocol); 4300 /* the order of these if's will seem a triffle strange, but they 4301 are my best guess as to order of probabilty and/or importance 4302 to the overhead raj 2008-01-09*/ 4303 if (ret == bytes_to_send) { 4304 /* if this is a send-only test controlled by byte count we 4305 decrement units_remaining by the bytes sent */ 4306 if (!(direction & NETPERF_RECV) && (units_remaining > 0)) { 4307 units_remaining -= ret; 4308 } 4309 bytes_sent += ret; 4310 send_ring = send_ring->next; 4311 local_send_calls++; 4312 } 4313 else if (ret == -2) { 4314 /* what to do here -2 means a non-fatal error - probably 4315 ENOBUFS and so our send didn't happen. in the old code for 4316 UDP_STREAM we would just continue in the while loop. it 4317 isn't clear that is what to do here, so we will simply 4318 increment the failed_sends stat and fall-through. If this 4319 is a UDP_STREAM style of test, the net effect should be the 4320 same. if this is a UDP_RR with a really-big burst count, I 4321 don't think we were checking for ENOBUFS there anyway and 4322 so would have failed. Here we can just let things 4323 slide. */ 4324 failed_sends++; 4325 } 4326 else if (ret == 0) { 4327 /* was this a zero-byte send? if it was, then ostensibly we 4328 would hit the ret == bytes_to_send case which means we'd 4329 never get here as we are using blocking semantics */ 4330 fprintf(where,"HOW DID I GET HERE?\n"); 4331 fflush(where); 4332 } 4333 else if (ret == -1) { 4334 times_up = 1; 4335 timed_out = 1; 4336 break; 4337 } 4338 else { 4339 perror("netperf: send_omni: send_data failed"); 4340 exit(1); 4341 } 4342 4343 } 4344 4345 #ifdef WANT_FIRST_BURST 4346 /* it isn't clear we need to check the directions here. the 4347 increment should be cheaper than the conditional, and it 4348 shouldn't hurt the other directions because they'll never 4349 look at them. famous last words of raj 2008-01-25 */ 4350 requests_outstanding += 1; 4351 #endif 4352 4353 #ifdef WIN32 4354 /* this is used so the timer thread can close the socket out 4355 from under us, which to date is the easiest/cleanest/least 4356 Windows-specific way I can find to force the winsock calls to 4357 return WSAEINTR with the test is over. anything that will run 4358 on 95 and NT and is closer to what netperf expects from Unix 4359 signals and such would be appreciated raj 1/96 */ 4360 win_kludge_socket = data_socket; 4361 #endif /* WIN32 */ 4362 4363 if (direction & NETPERF_RECV) { 4364 rret = recv_data(data_socket, 4365 recv_ring, 4366 bytes_to_recv, 4367 (connected) ? NULL : (struct sockaddr *)&remote_addr, 4368 /* if remote_addr NULL this is ignored */ 4369 &remote_addr_len, 4370 /* if XMIT also set this is RR so waitall */ 4371 (direction & NETPERF_XMIT) ? NETPERF_WAITALL: 0, 4372 &temp_recvs); 4373 if (rret > 0) { 4374 /* if this is a recv-only test controlled by byte count we 4375 decrement the units_remaining by the bytes received */ 4376 if (!(direction & NETPERF_XMIT) && (units_remaining > 0)) { 4377 units_remaining -= rret; 4378 } 4379 bytes_received += rret; 4380 local_receive_calls += temp_recvs; 4381 } 4382 else if (rret == 0) { 4383 /* is this the end of a test, just a zero-byte recv, or 4384 something else? that is an exceedingly good question and 4385 one for which I don't presently have a good answer, but 4386 that won't stop me from guessing :) raj 2008-01-09 */ 4387 if (!((connection_test) || (null_message_ok))) { 4388 /* if it is neither a connection_test nor null_message_ok it 4389 must be the end of the test */ 4390 times_up = 1; /* ostensibly the signal handler did this */ 4391 break; 4392 } 4393 local_receive_calls += temp_recvs; 4394 } 4395 else if (rret == -1) { 4396 /* test timed-out */ 4397 times_up = 1; 4398 timed_out = 1; 4399 break; 4400 } 4401 else if (rret == -2) { 4402 /* we timed-out on a data receive. this is only allowed for 4403 a UDP_RR test. we want to set things up so we start 4404 ramping up again like we were at the beginning. if we 4405 actually timeout it means that all has been lost. or at 4406 least we assume so */ 4407 if (debug) { 4408 fprintf(where,"Timeout receiving resonse from remote\n"); 4409 fflush(where); 4410 } 4411 #ifdef WANT_FIRST_BURST 4412 if (first_burst_size) { 4413 requests_outstanding = 0; 4414 } 4415 #endif 4416 if (keep_histogram) { 4417 HIST_purge(time_hist); 4418 } 4419 #ifdef WANT_DEMO 4420 /* "start over" on a demo interval. we will forget about 4421 everything that happened in the demo interval up to the 4422 timeout and begin fresh. */ 4423 demo_reset(); 4424 #endif /* WANT_DEMO */ 4425 4426 continue; 4427 } 4428 else { 4429 /* anything else is bad */ 4430 perror("netperf: send_omni: recv_data failed"); 4431 exit(1); 4432 } 4433 recv_ring = recv_ring->next; 4434 4435 #ifdef WANT_FIRST_BURST 4436 /* so, since we've gotten a response back, update the 4437 bookkeeping accordingly. there is one less request 4438 outstanding and we can put one more out there than 4439 before. */ 4440 requests_outstanding -= 1; 4441 #endif 4442 4443 } 4444 4445 /* if this is a connection test, we want to do some stuff about 4446 connection close here in the test loop. raj 2008-01-08 */ 4447 if (connection_test) { 4448 4449 #ifdef __linux 4450 /* so, "Linux" with autotuning likes to alter the socket buffer 4451 sizes over the life of the connection, but only does so when 4452 one takes the defaults at time of socket creation. if we 4453 took those defaults, we should inquire as to what the values 4454 ultimately became. raj 2008-01-15 */ 4455 /* however annoying having to do this might be, it really 4456 shouldn't be done over and over again. instead we will 4457 assume it does not change, which is fine since we would 4458 have only reported one of them anyway. raj 20100917 */ 4459 if ((lsr_size_req < 0) && (-1 == lsr_size_end)) 4460 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 4461 else 4462 lsr_size_end = lsr_size; 4463 if ((lss_size_req < 0) && (-1 == lss_size_end)) 4464 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 4465 else 4466 lss_size_end = lss_size; 4467 #else 4468 lsr_size_end = lsr_size; 4469 lss_size_end = lss_size; 4470 #endif 4471 4472 /* we will only make this call the one time - after the first 4473 call, the value will be real or -1. if this is a connection 4474 test we want to do this here because later we won't be 4475 connected and the data may no longer be available. */ 4476 if (transport_mss == -2) 4477 get_transport_info(data_socket, 4478 &transport_mss, 4479 local_res->ai_protocol); 4480 4481 4482 ret = disconnect_data_socket(data_socket, 4483 (no_control) ? 1 : 0, 4484 1, 4485 NULL, 4486 0); 4487 if (ret == 0) { 4488 /* we will need a new connection to be established next time 4489 around the loop. However, the next time around the loop 4490 will already be picking the next port number */ 4491 need_to_connect = 1; 4492 connected = 0; 4493 need_socket = 1; 4494 } 4495 else if (ret == -1) { 4496 times_up = 1; 4497 timed_out = 1; 4498 break; 4499 } 4500 else { 4501 perror("netperf: send_omni: disconnect_data_socket failed"); 4502 exit(1); 4503 } 4504 } 4505 4506 4507 if (keep_histogram) { 4508 HIST_timestamp_stop_add(time_hist); 4509 } 4510 4511 #ifdef WANT_DEMO 4512 if (NETPERF_IS_RR(direction)) { 4513 if (libfmt == 'x') { 4514 demo_interval_tick(1); 4515 } 4516 else { 4517 demo_interval_tick(req_size + rsp_size); 4518 } 4519 } 4520 else if (NETPERF_XMIT_ONLY(direction)) { 4521 demo_interval_tick(bytes_to_send); 4522 } 4523 else { 4524 demo_interval_tick(rret); 4525 } 4526 #endif 4527 4528 #if defined(WANT_INTERVALS) 4529 INTERVALS_WAIT(); 4530 #endif /* WANT_INTERVALS */ 4531 4532 4533 /* was this a "transaction" test? */ 4534 if (NETPERF_IS_RR(direction)) { 4535 trans_completed++; 4536 if (units_remaining) { 4537 units_remaining--; 4538 } 4539 } 4540 4541 4542 } 4543 4544 /* we are now, ostensibly, at the end of this iteration */ 4545 4546 #if defined(WANT_DEMO) 4547 /* if we were in demo mode this will ensure one final interim 4548 result, which, naturally might be a bit early :) */ 4549 demo_interval_final(); 4550 #endif 4551 4552 if (transport_mss == -2) 4553 get_transport_info(data_socket, 4554 &transport_mss, 4555 local_res->ai_protocol); 4556 local_transport_retrans = get_transport_retrans(data_socket, 4557 local_res->ai_protocol); 4558 4559 4560 /* so, if we have/had a data connection, we will want to close it 4561 now, and this will be independent of whether there is a control 4562 connection. */ 4563 4564 if (connected) { 4565 4566 #ifdef __linux 4567 /* so, "Linux" with autotuning likes to alter the socket buffer 4568 sizes over the life of the connection, but only does so when 4569 one takes the defaults at time of socket creation. if we took 4570 those defaults, we should inquire as to what the values 4571 ultimately became. raj 2008-01-15 */ 4572 if (lsr_size_req < 0) 4573 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 4574 else 4575 lsr_size_end = lsr_size; 4576 if (lss_size_req < 0) 4577 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 4578 else 4579 lss_size_end = lss_size; 4580 #else 4581 lsr_size_end = lsr_size; 4582 lss_size_end = lss_size; 4583 #endif 4584 if ((desired_output_groups & OMNI_WANT_LOC_CONG) && 4585 (local_cong_control[0] == '\0')) { 4586 get_transport_cong_control(data_socket, 4587 local_res->ai_protocol, 4588 local_cong_control, 4589 sizeof(local_cong_control)); 4590 } 4591 4592 /* CHECK PARMS HERE; */ 4593 ret = disconnect_data_socket(data_socket, 4594 1, 4595 1, 4596 NULL, 4597 0); 4598 connected = 0; 4599 need_socket = 1; 4600 4601 } 4602 else { 4603 /* this is the UDP case at present */ 4604 ret = disconnect_data_socket(data_socket, 4605 1, 4606 1, 4607 remote_res->ai_addr, 4608 remote_res->ai_addrlen); 4609 need_socket = 1; 4610 lsr_size_end = lsr_size; 4611 lss_size_end = lss_size; 4612 } 4613 4614 /* this call will always give us the elapsed time for the test, and 4615 will also store-away the necessaries for cpu utilization */ 4616 4617 cpu_stop(local_cpu_usage,&elapsed_time); 4618 4619 /* if we timed-out, and had padded the timer, we need to subtract 4620 the pad_time from the elapsed time on the assumption that we 4621 were essentially idle for pad_time and just waiting for a timer 4622 to expire on something like a UDP test. if we have not padded 4623 the timer, pad_time will be zero. if we have not timed out 4624 then we want to make sure we stop the timer. */ 4625 if (timed_out) { 4626 if (debug) { 4627 fprintf(where,"Adjusting elapsed_time by %d seconds\n",pad_time); 4628 fflush(where); 4629 } 4630 elapsed_time -= (float)pad_time; 4631 } 4632 else { 4633 stop_timer(); 4634 } 4635 4636 if (!no_control) { 4637 /* Get the statistics from the remote end. The remote will have 4638 calculated service demand and all those interesting things. If 4639 it wasn't supposed to care, it will return obvious values. */ 4640 4641 recv_response_n(OMNI_RESULTS_CONV_CUTOFF); 4642 if (!netperf_response.content.serv_errno) { 4643 if (debug) 4644 fprintf(where,"remote results obtained\n"); 4645 remote_cpu_method = format_cpu_method(omni_result->cpu_method); 4646 lib_num_rem_cpus = omni_result->num_cpus; 4647 lib_remote_cpu_stats.cpu_util = omni_result->cpu_util; 4648 lib_remote_cpu_stats.cpu_user = omni_result->cpu_percent_user; 4649 lib_remote_cpu_stats.cpu_system = omni_result->cpu_percent_system; 4650 lib_remote_cpu_stats.cpu_iowait = omni_result->cpu_percent_iowait; 4651 lib_remote_cpu_stats.cpu_irq = omni_result->cpu_percent_irq; 4652 lib_remote_cpu_stats.cpu_swintr = omni_result->cpu_percent_swintr; 4653 lib_remote_cpu_stats.peak_cpu_util = omni_result->peak_cpu_util; 4654 lib_remote_cpu_stats.peak_cpu_id = omni_result->peak_cpu_id; 4655 /* why? because some stacks want to be clever and autotune their 4656 socket buffer sizes, which means that if we accept the defaults, 4657 the size we get from getsockopt() at the beginning of a 4658 connection may not be what we would get at the end of the 4659 connection... */ 4660 rsr_size_end = omni_result->recv_buf_size; 4661 rss_size_end = omni_result->send_buf_size; 4662 remote_bytes_sent = (uint64_t)omni_result->bytes_sent_hi << 32; 4663 remote_bytes_sent += omni_result->bytes_sent_lo; 4664 remote_send_calls = omni_result->send_calls; 4665 remote_bytes_received = (uint64_t)omni_result->bytes_received_hi << 32; 4666 remote_bytes_received += omni_result->bytes_received_lo; 4667 remote_receive_calls = omni_result->recv_calls; 4668 remote_bytes_xferd = (double) remote_bytes_received + 4669 remote_bytes_sent; 4670 if (omni_result->recv_calls > 0) 4671 remote_bytes_per_recv = (double) remote_bytes_received / 4672 (double) omni_result->recv_calls; 4673 else 4674 remote_bytes_per_recv = 0.0; 4675 if (omni_result->send_calls > 0) 4676 remote_bytes_per_send = (double) remote_bytes_sent / 4677 (double) omni_result->send_calls; 4678 else 4679 remote_bytes_per_send = 0.0; 4680 4681 remote_transport_retrans = omni_result->transport_retrans; 4682 /* what was the congestion control? */ 4683 if (desired_output_groups & OMNI_WANT_REM_CONG) { 4684 strncpy(remote_cong_control, 4685 omni_result->cong_control, 4686 sizeof(remote_cong_control)); 4687 remote_cong_control[sizeof(remote_cong_control) - 1] = '\0'; 4688 } 4689 } 4690 else { 4691 Set_errno(netperf_response.content.serv_errno); 4692 fprintf(where, 4693 "netperf: remote error %d", 4694 netperf_response.content.serv_errno); 4695 perror(""); 4696 fflush(where); 4697 4698 exit(-1); 4699 } 4700 } 4701 else { 4702 /* when we are sending, in a no_control test, we have to 4703 ass-u-me that everything we sent was received, otherwise, we 4704 will report a transfer rate of zero. */ 4705 remote_bytes_xferd = (double) bytes_sent; 4706 } 4707 4708 /* so, what was the end result? */ 4709 local_cpu_method = format_cpu_method(cpu_method); 4710 4711 if (local_send_calls > 0) 4712 bytes_per_send = (double) bytes_sent / (double) local_send_calls; 4713 else bytes_per_send = 0.0; 4714 4715 if (local_receive_calls > 0) 4716 bytes_per_recv = (double) bytes_received / (double) local_receive_calls; 4717 else 4718 bytes_per_recv = 0.0; 4719 4720 bytes_xferd = (double) bytes_sent + bytes_received; 4721 4722 /* if the output format is 'x' we know the test was 4723 request/response. if the libfmt is something else, it could be 4724 xmit, recv or bidirectional. if we were the receiver then we 4725 can use our byte totals even if it is 4726 UDP/unreliable. otherwise, we use the remote totals - they 4727 should be the same if the protocol is reliable, and if it is 4728 unreliable then we want what was actually received */ 4729 if ('x' == libfmt) 4730 /* it was a request/response test */ 4731 thruput = calc_thruput((double)trans_completed); 4732 else if (NETPERF_RECV_ONLY(direction)) 4733 thruput = calc_thruput(bytes_xferd); 4734 else 4735 thruput = calc_thruput(remote_bytes_xferd); 4736 4737 if (NETPERF_IS_RR(direction)) { 4738 float rtt_elapsed_time = elapsed_time; 4739 4740 #ifdef WANT_INTERVALS 4741 /* if the test was paced, we need to subtract the time we were 4742 sitting paced from the time we use to calculate the average 4743 rtt_latency. Of course, won't really know how long we were 4744 sitting unless we bracket the sit with timing calls, which 4745 will be additional overhead affecting CPU utilization. but, 4746 there is no such thing as a free lunch is there :) raj 4747 20110121 */ 4748 if (interval_burst) { 4749 rtt_elapsed_time -= (float)(interval_wait_microseconds / 1000000.0); 4750 } 4751 #endif /* WANT_INTERVALS */ 4752 4753 if (!connection_test) { 4754 /* calculate the round trip latency, using the transaction rate 4755 whether or not the user was asking for thruput to be in 'x' 4756 units please... however... a connection_test only ever has 4757 one transaction in flight at one time */ 4758 rtt_latency = 4759 (((double)1.0/(trans_completed/rtt_elapsed_time)) * 4760 (double)1000000.0) * 4761 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)); 4762 } 4763 else { 4764 rtt_latency = ((double)1.0/(trans_completed/rtt_elapsed_time)) * 4765 (double)1000000.0; 4766 } 4767 tmpfmt = libfmt; 4768 libfmt = 'x'; 4769 transaction_rate = calc_thruput((double)trans_completed); 4770 libfmt = tmpfmt; 4771 } 4772 4773 /* ok, time to possibly calculate cpu util and/or service demand */ 4774 if (local_cpu_usage) { 4775 4776 local_cpu_utilization = calc_cpu_util(elapsed_time); 4777 4778 /* we need to decide what to feed the service demand beast, 4779 which will, ultimately, depend on what sort of test it is and 4780 whether or not the user asked for something specific - as in 4781 per KB even on a TCP_RR test if it is being (ab)used as a 4782 bidirectional bulk-transfer test. raj 2008-01-14 */ 4783 local_service_demand = 4784 calc_service_demand_fmt(('x' == libfmt) ? (double)trans_completed: bytes_xferd, 4785 0.0, 4786 0.0, 4787 0); 4788 } 4789 else { 4790 local_cpu_utilization = (float) -1.0; 4791 local_service_demand = (float) -1.0; 4792 } 4793 4794 if (remote_cpu_usage) { 4795 4796 remote_cpu_utilization = omni_result->cpu_util; 4797 4798 remote_service_demand = 4799 calc_service_demand_fmt(('x' == libfmt) ? (double) trans_completed: bytes_xferd, 4800 0.0, 4801 remote_cpu_utilization, 4802 omni_result->num_cpus); 4803 } 4804 else { 4805 remote_cpu_utilization = (float) -1.0; 4806 remote_service_demand = (float) -1.0; 4807 } 4808 4809 /* time to calculate our confidence */ 4810 calculate_confidence(confidence_iteration, 4811 elapsed_time, 4812 thruput, 4813 local_cpu_utilization, 4814 remote_cpu_utilization, 4815 local_service_demand, 4816 remote_service_demand); 4817 4818 /* this this is the end of the confidence while loop? */ 4819 confidence_iteration++; 4820 } 4821 4822 /* we end with confidence_iteration one larger than the number of 4823 iterations. if we weren't doing confidence intervals this will 4824 still be reported as one */ 4825 confidence_iteration--; 4826 4827 #if defined(WANT_INTERVALS) 4828 #ifdef WIN32 4829 stop_itimer(); 4830 #endif 4831 #endif /* WANT_INTERVALS */ 4832 4833 /* at some point we may want to actually display some results :) */ 4834 4835 retrieve_confident_values(&elapsed_time, 4836 &thruput, 4837 &local_cpu_utilization, 4838 &remote_cpu_utilization, 4839 &local_service_demand, 4840 &remote_service_demand); 4841 4842 /* a kludge for omni printing because I don't know how to tell that 4843 something is a float vs a double in my_snprintf() given what it 4844 is passed and I'm not ready to force all the netlib.c stuff to 4845 use doubles rather than floats. help there would be 4846 appreciated. raj 2008-01-28 */ 4847 elapsed_time_double = (double) elapsed_time; 4848 local_service_demand_double = (double)local_service_demand; 4849 remote_service_demand_double = (double)remote_service_demand; 4850 4851 if ('x' == libfmt) sd_str = "usec/Tran"; 4852 else sd_str = "usec/KB"; 4853 4854 if (iteration_max > 1) { 4855 result_confid_pct = get_result_confid(); 4856 loc_cpu_confid_pct = get_loc_cpu_confid(); 4857 rem_cpu_confid_pct = get_rem_cpu_confid(); 4858 interval_pct = interval * 100.0; 4859 } 4860 4861 /* at some point we need to average these during a confidence 4862 interval run, and when we do do that, we need to make sure we 4863 restore the value of libfmt correctly */ 4864 tmpfmt = libfmt; 4865 if ('x' == libfmt) { 4866 libfmt = 'm'; 4867 } 4868 local_send_thruput = calc_thruput((double)bytes_sent); 4869 local_recv_thruput = calc_thruput((double)bytes_received); 4870 remote_send_thruput = calc_thruput((double)remote_bytes_sent); 4871 remote_recv_thruput = calc_thruput((double)remote_bytes_received); 4872 4873 libfmt = tmpfmt; 4874 4875 /* were we tracking possibly expensive statistics? */ 4876 if (keep_statistics) { 4877 HIST_get_stats(time_hist, 4878 &min_latency, 4879 &max_latency, 4880 &mean_latency, 4881 &stddev_latency); 4882 p50_latency = HIST_get_percentile(time_hist, 0.50); 4883 p90_latency = HIST_get_percentile(time_hist, 0.90); 4884 p99_latency = HIST_get_percentile(time_hist, 0.99); 4885 4886 } 4887 4888 /* if we are running a legacy test we do not do the nifty new omni 4889 output stuff */ 4890 if (!legacy) { 4891 print_omni(); 4892 } 4893 4894 #if defined(DEBUG_OMNI_OUTPUT) 4895 { 4896 /* just something quick to sanity check the output selectors. this 4897 should be gone for "production" :) */ 4898 int i; 4899 print_omni_init(); 4900 output_list[0][1] = OUTPUT_END; 4901 for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++) { 4902 output_list[0][0] = i; 4903 print_omni_csv(); 4904 } 4905 } 4906 #endif 4907 4908 /* likely as not we are going to do something slightly different here */ 4909 if ((verbosity > 1) && (!legacy)) { 4910 4911 #ifdef WANT_HISTOGRAM 4912 fprintf(where,"\nHistogram of "); 4913 if (NETPERF_RECV_ONLY(direction)) 4914 fprintf(where,"recv"); 4915 if (NETPERF_XMIT_ONLY(direction)) 4916 fprintf(where,"send"); 4917 if (NETPERF_IS_RR(direction)) { 4918 if (connection_test) { 4919 if (NETPERF_CC(direction)) { 4920 fprintf(where,"connect/close"); 4921 } 4922 else { 4923 fprintf(where,"connect/request/response/close"); 4924 } 4925 } 4926 else { 4927 fprintf(where,"request/response"); 4928 } 4929 } 4930 fprintf(where," times\n"); 4931 HIST_report(time_hist); 4932 fflush(where); 4933 #endif /* WANT_HISTOGRAM */ 4934 4935 } 4936 4937 } 4938 4939 4940 void 4941 send_omni(char remote_host[]) 4942 { 4943 char name_buf[32]; 4944 snprintf(name_buf,sizeof(name_buf),"OMNI %s TEST",direction_str); 4945 name_buf[31] = '\0'; 4946 send_omni_inner(remote_host, 0, name_buf); 4947 } 4948 4949 #if defined(WIN32) 4950 #if !defined(InetNtop) 4951 /* +*+ Why isn't this in the winsock headers yet? */ 4952 const char * 4953 inet_ntop(int af, const void *src, char *dst, size_t size); 4954 #endif 4955 #endif 4956 4957 static void 4958 set_hostname_and_port_2(void *addr, char *hostname, char *portstr, int family, int port) 4959 { 4960 4961 inet_ntop(family, addr, hostname, BUFSIZ); 4962 4963 sprintf(portstr, "%u", port); 4964 4965 } 4966 4967 4968 4970 /* the name is something of a misnomer since this test could send, or 4971 receive, or both, but it matches the historical netperf routine 4972 naming convention for what runs in the netserver context. */ 4973 void 4974 recv_omni() 4975 { 4976 4977 struct addrinfo *local_res; 4978 char local_name[BUFSIZ]; 4979 char port_buffer[PORTBUFSIZE]; 4980 4981 struct sockaddr_storage myaddr_in, peeraddr_in; 4982 int peeraddr_set = 0; 4983 SOCKET s_listen, data_socket; 4984 netperf_socklen_t addrlen; 4985 4986 struct ring_elt *send_ring; 4987 struct ring_elt *recv_ring; 4988 4989 int timed_out = 0; 4990 int pad_time = 0; 4991 int need_to_connect = 0; 4992 int need_to_accept; 4993 int connected; 4994 int ret; 4995 uint32_t temp_recvs; 4996 4997 struct omni_request_struct *omni_request; 4998 struct omni_response_struct *omni_response; 4999 struct omni_results_struct *omni_results; 5000 5001 omni_request = 5002 (struct omni_request_struct *)netperf_request.content.test_specific_data; 5003 omni_response = 5004 (struct omni_response_struct *)netperf_response.content.test_specific_data; 5005 omni_results = 5006 (struct omni_results_struct *)netperf_response.content.test_specific_data; 5007 5008 if (debug) { 5009 fprintf(where,"netserver: %s: entered...\n",__FUNCTION__); 5010 fflush(where); 5011 } 5012 5013 /* netserver has no good way of knowing where the conversion cutoff 5014 point is, so we have to fix it after the fact */ 5015 fixup_request_n(OMNI_REQUEST_CONV_CUTOFF); 5016 5017 /* thus fixed-up, we can extract the requested congestion control 5018 algorithm */ 5019 strncpy(local_cong_control_req, 5020 omni_request->cong_control, 5021 sizeof(local_cong_control_req)); 5022 5023 /* based on what we have been told by the remote netperf, we want to 5024 setup our endpoint for the "data connection" and let the remote 5025 netperf know the situation. */ 5026 5027 if (debug) { 5028 fprintf(where,"%s: setting the response type...\n",__FUNCTION__); 5029 fflush(where); 5030 } 5031 5032 netperf_response.content.response_type = OMNI_RESPONSE; 5033 5034 if (debug) { 5035 fprintf(where,"%s: the response type is set...\n",__FUNCTION__); 5036 fflush(where); 5037 } 5038 5039 /* Grab a socket to listen on, and then listen on it. */ 5040 5041 if (debug) { 5042 fprintf(where,"%s: grabbing a socket...\n",__FUNCTION__); 5043 fflush(where); 5044 } 5045 5046 /* create_data_socket expects to find some things in the global 5047 variables, so set the globals based on the values in the request. 5048 once the socket has been created, we will set the response values 5049 based on the updated value of those globals. raj 7/94 */ 5050 lss_size_req = omni_request->send_buf_size; 5051 lsr_size_req = omni_request->recv_buf_size; 5052 loc_nodelay = (omni_request->flags) & OMNI_NO_DELAY; 5053 loc_rcvavoid = omni_request->so_rcvavoid; 5054 loc_sndavoid = omni_request->so_sndavoid; 5055 routing_allowed = (omni_request->flags) & OMNI_ROUTING_ALLOWED; 5056 want_keepalive = (omni_request->flags) & OMNI_WANT_KEEPALIVE; 5057 local_socket_prio = omni_request->socket_prio; 5058 local_socket_tos = omni_request->socket_tos; 5059 want_defer_accept = omni_request->flags & OMNI_WANT_DEFER_ACCEPT; 5060 5061 #ifdef WANT_INTERVALS 5062 interval_usecs = omni_request->interval_usecs; 5063 interval_wate = interval_usecs / 1000; 5064 interval_burst = omni_request->interval_burst; 5065 #else 5066 interval_usecs = 0; 5067 interval_wate = 1; 5068 interval_burst = 0; 5069 #endif 5070 5071 connection_test = omni_request->flags & OMNI_CONNECT_TEST; 5072 #ifdef TCP_FASTOPEN 5073 use_fastopen = omni_request->flags & OMNI_FASTOPEN; 5074 #endif 5075 direction = omni_request->direction; 5076 use_pktinfo = (omni_request->flags) & OMNI_USE_PKTINFO; 5077 5078 /* let's be quite certain the fill file string is null terminated */ 5079 omni_request->fill_file[sizeof(omni_request->fill_file) - 1] = '\0'; 5080 strncpy(local_fill_file, 5081 omni_request->fill_file, 5082 sizeof(local_fill_file)); 5083 5084 /* kludgy, because I have no way at present to say how many bytes 5085 needed to be swapped around for the request from which this is 5086 pulled, and it is probably all wrong for IPv6 :( */ 5087 switch (nf_to_af(omni_request->ipfamily)) { 5088 case AF_INET6: 5089 /* yes indeed it is, do nothing, bz */ 5090 break; 5091 case AF_INET: 5092 default: 5093 for (ret=0; ret < 4; ret++) { 5094 omni_request->netserver_ip[ret] = htonl(omni_request->netserver_ip[ret]); 5095 omni_request->netperf_ip[ret] = htonl(omni_request->netperf_ip[ret]); 5096 } 5097 break; 5098 } 5099 5100 set_hostname_and_port_2(omni_request->netserver_ip, 5101 local_name, 5102 port_buffer, 5103 nf_to_af(omni_request->ipfamily), 5104 omni_request->data_port); 5105 5106 local_res = complete_addrinfo(local_name, 5107 local_name, 5108 port_buffer, 5109 nf_to_af(omni_request->ipfamily), 5110 nst_to_hst(omni_request->socket_type), 5111 omni_request->protocol, 5112 0); 5113 5114 s_listen = omni_create_data_socket(local_res); 5115 5116 if (s_listen == INVALID_SOCKET) { 5117 netperf_response.content.serv_errno = errno; 5118 send_response(); 5119 if (debug) { 5120 fprintf(where,"could not create data socket\n"); 5121 fflush(where); 5122 } 5123 exit(-1); 5124 } 5125 5126 /* We now alter the message_ptr variables to be at the desired */ 5127 /* alignments with the desired offsets. */ 5128 5129 if (debug) { 5130 fprintf(where, 5131 "recv_omni: requested recv alignment of %d offset %d\n" 5132 "recv_omni: requested send alignment of %d offset %d\n", 5133 omni_request->recv_alignment, 5134 omni_request->recv_offset, 5135 omni_request->send_alignment, 5136 omni_request->send_offset); 5137 fflush(where); 5138 } 5139 5140 omni_response->send_size = omni_request->send_size; 5141 omni_response->send_width = omni_request->send_width; 5142 omni_response->socket_prio = local_socket_prio; 5143 omni_response->socket_tos = local_socket_tos; 5144 5145 if (omni_request->direction & NETPERF_XMIT) { 5146 #ifdef fo 5147 /* do we need to set multicast ttl? */ 5148 if (is_multicast_addr(remote_res)) { 5149 /* yes, s_listen - for a UDP test we will be copying it to 5150 data_socket but that hasn't happened yet. raj 20100315 */ 5151 set_multicast_ttl(s_listen); 5152 } 5153 #endif 5154 5155 if (omni_request->response_size > 0) { 5156 /* request/response_test */ 5157 bytes_to_send = omni_request->response_size; 5158 if (omni_request->send_width == 0) send_width = 1; 5159 else send_width = omni_request->send_width; 5160 } 5161 else { 5162 if (omni_request->send_size == -1) { 5163 bytes_to_send = choose_send_size(lss_size,omni_request->protocol); 5164 } 5165 else bytes_to_send = omni_request->send_size; 5166 /* set the send_width */ 5167 if (omni_request->send_width == 0) { 5168 send_width = (lss_size/bytes_to_send) + 1; 5169 if (send_width == 1) send_width++; 5170 } 5171 else 5172 send_width = omni_request->send_width; 5173 } 5174 send_ring = allocate_buffer_ring(send_width, 5175 bytes_to_send, 5176 omni_request->send_alignment, 5177 omni_request->send_offset); 5178 5179 omni_response->send_width = send_width; 5180 omni_response->send_size = bytes_to_send; 5181 } 5182 5183 omni_response->receive_size = omni_request->receive_size; 5184 omni_response->recv_width = omni_request->recv_width; 5185 if (omni_request->direction & NETPERF_RECV) { 5186 5187 /* do we need to join a multicast group? */ 5188 if (is_multicast_addr(local_res)) { 5189 /* yes, s_listen - for a UDP test we will be copying it to 5190 data_socket but that hasn't happened yet. raj 20100315 */ 5191 join_multicast_addr(s_listen, local_res); 5192 } 5193 5194 if (omni_request->request_size > 0) { 5195 /* request/response test */ 5196 bytes_to_recv = omni_request->request_size; 5197 if (omni_request->recv_width == 0) recv_width = 1; 5198 else recv_width = omni_request->recv_width; 5199 } 5200 else { 5201 if (omni_request->receive_size == -1) { 5202 if (lsr_size > 0) bytes_to_recv = lsr_size; 5203 else bytes_to_recv = 4096; 5204 } 5205 else { 5206 bytes_to_recv = omni_request->receive_size; 5207 } 5208 /* set the recv_width */ 5209 if (omni_request->recv_width == 0) { 5210 recv_width = (lsr_size/bytes_to_recv) + 1; 5211 if (recv_width == 1) recv_width++; 5212 } 5213 else 5214 recv_width = omni_request->recv_width; 5215 } 5216 recv_ring = allocate_buffer_ring(recv_width, 5217 bytes_to_recv, 5218 omni_request->recv_alignment, 5219 omni_request->recv_offset); 5220 5221 omni_response->receive_size = bytes_to_recv; 5222 omni_response->recv_width = recv_width; 5223 } 5224 5225 #ifdef WIN32 5226 /* The test timer can fire during operations on the listening socket, 5227 so to make the start_timer below work we have to move 5228 it to close s_listen while we are blocked on accept. */ 5229 win_kludge_socket2 = s_listen; 5230 #endif 5231 5232 need_to_accept = (omni_request->protocol != IPPROTO_UDP); 5233 5234 /* we need to hang a listen for everything that needs at least one 5235 accept. the age-old constant of 5 is probably OK for our purposes 5236 but does not necessarily represent best practice */ 5237 if (need_to_accept) { 5238 int backlog = 5; 5239 #ifdef TCP_FASTOPEN 5240 /* one of these days I will have to go find-out what the backlog 5241 is supposed to be here. until then, I'll just set it to five 5242 like the listen() call does - it is classic, and was what was 5243 used in the online example I found */ 5244 if (use_fastopen && 5245 (setsockopt(s_listen,IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog)) == 5246 SOCKET_ERROR)) { 5247 netperf_response.content.serv_errno = errno; 5248 close(s_listen); 5249 send_response(); 5250 if (debug) { 5251 fprintf(where,"netperfserver: %s could not fastopen\n",__FUNCTION__); 5252 fflush(where); 5253 } 5254 exit(1); 5255 } 5256 #endif /* TCP_FASTOPEN */ 5257 #ifdef TCP_DEFER_ACCEPT 5258 if (want_defer_accept && 5259 (setsockopt(s_listen, IPPROTO_TCP, TCP_DEFER_ACCEPT, &backlog, sizeof(backlog)) == SOCKET_ERROR)) { 5260 netperf_response.content.serv_errno = errno; 5261 close(s_listen); 5262 send_response(); 5263 if (debug) { 5264 fprintf(where, 5265 "netperfserver: %s could not defer accept\n",__FUNCTION__); 5266 fflush(where); 5267 } 5268 exit(1); 5269 } 5270 #endif /* TCP_DEFER_ACCEPT */ 5271 if (listen(s_listen, backlog) == SOCKET_ERROR) { 5272 netperf_response.content.serv_errno = errno; 5273 close(s_listen); 5274 send_response(); 5275 if (debug) { 5276 fprintf(where,"netperfserver: %s could not listen\n",__FUNCTION__); 5277 fflush(where); 5278 } 5279 exit(1); 5280 } 5281 } 5282 5283 /* now get the port number assigned by the system */ 5284 addrlen = sizeof(myaddr_in); 5285 if (getsockname(s_listen, 5286 (struct sockaddr *)&myaddr_in, 5287 &addrlen) == SOCKET_ERROR){ 5288 netperf_response.content.serv_errno = errno; 5289 close(s_listen); 5290 send_response(); 5291 if (debug) { 5292 fprintf(where,"could not getsockname\n"); 5293 fflush(where); 5294 } 5295 exit(-1); 5296 } 5297 5298 /* Now myaddr_in contains the port and the internet address this is 5299 returned to the sender also implicitly telling the sender that 5300 the socket buffer sizing has been done. likely as not, the IP 5301 address will be the wildcard - so we only really need to extract 5302 the port number. since send_response is going to call htonl on 5303 all the fields, we want to initially put the port number in there 5304 in host order. */ 5305 5306 omni_response->data_port = 5307 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 5308 if (debug) { 5309 fprintf(where,"telling the remote to call me at %d\n", 5310 omni_response->data_port); 5311 fflush(where); 5312 } 5313 netperf_response.content.serv_errno = 0; 5314 5315 /* But wait, there's more. If the initiator wanted cpu measurements, */ 5316 /* then we must call the calibrate routine, which will return the max */ 5317 /* rate back to the initiator. If the CPU was not to be measured, or */ 5318 /* something went wrong with the calibration, we will return a 0.0 to */ 5319 /* the initiator. */ 5320 5321 omni_response->cpu_rate = (float)0.0; /* assume no cpu */ 5322 omni_response->flags &= ~OMNI_MEASURE_CPU; 5323 if (omni_request->flags & OMNI_MEASURE_CPU) { 5324 omni_response->flags |= OMNI_MEASURE_CPU; 5325 omni_response->cpu_rate = 5326 calibrate_local_cpu(omni_request->cpu_rate); 5327 } 5328 5329 /* before we send the response back to the initiator, pull some of */ 5330 /* the socket parms from the globals */ 5331 omni_response->send_buf_size = lss_size; 5332 omni_response->recv_buf_size = lsr_size; 5333 if (loc_nodelay) 5334 omni_response->flags |= OMNI_NO_DELAY; 5335 else 5336 omni_response->flags &= ~OMNI_NO_DELAY; 5337 5338 omni_response->so_rcvavoid = loc_rcvavoid; 5339 omni_response->so_sndavoid = loc_sndavoid; 5340 omni_response->interval_usecs = interval_usecs; 5341 omni_response->interval_burst = interval_burst; 5342 5343 send_response_n(OMNI_RESPONSE_CONV_CUTOFF); /* brittle, but functional */ 5344 5345 local_send_calls = 0; 5346 local_receive_calls = 0; 5347 5348 addrlen = sizeof(peeraddr_in); 5349 memset(&peeraddr_in,0,sizeof(peeraddr_in)); 5350 5351 /* Now it's time to start receiving data on the connection. We will */ 5352 /* first grab the apropriate counters and then start grabbing. */ 5353 5354 cpu_start(omni_request->flags & OMNI_MEASURE_CPU); 5355 5356 /* if the test is timed, set a timer of suitable length. if the 5357 test is by byte/transaction count, we don't need a timer - or 5358 rather we rely on the netperf to only ask us to do transaction 5359 counts over "reliable" protocols. perhaps at some point we 5360 should add a check herebouts to verify that... */ 5361 5362 if (omni_request->test_length >= 0) { 5363 times_up = 0; 5364 units_remaining = 0; 5365 test_time=omni_request->test_length; 5366 /* if we are the sender and only sending, then we don't need/want 5367 the padding, otherwise, we need the padding */ 5368 if (!(NETPERF_XMIT_ONLY(omni_request->direction)) && 5369 (omni_request->test_length > 0)) 5370 pad_time = PAD_TIME; 5371 start_timer(omni_request->test_length + pad_time); 5372 } 5373 else { 5374 times_up = 1; 5375 units_remaining = omni_request->test_length * -1; 5376 } 5377 5378 #if defined(WANT_INTERVALS) 5379 INTERVALS_INIT(); 5380 #endif /* WANT_INTERVALS */ 5381 5382 5383 trans_completed = 0; 5384 bytes_sent = 0; 5385 bytes_received = 0; 5386 connected = 0; 5387 5388 while ((!times_up) || (units_remaining > 0)) { 5389 5390 if (need_to_accept) { 5391 /* accept a connection from the remote */ 5392 #ifdef WIN32 5393 /* The test timer will probably fire during this accept, 5394 so to make the start_timer above work we have to move 5395 it to close s_listen while we are blocked on accept. */ 5396 win_kludge_socket = s_listen; 5397 #endif 5398 if ((data_socket=accept(s_listen, 5399 (struct sockaddr *)&peeraddr_in, 5400 &addrlen)) == INVALID_SOCKET) { 5401 if (errno == EINTR) { 5402 /* the timer popped */ 5403 times_up = 1; /* ostensibly the signal hander dealt with this?*/ 5404 timed_out = 1; 5405 break; 5406 } 5407 netperf_response.content.serv_errno = errno; 5408 send_response(); 5409 fprintf(where,"%s: accept: errno = %d\n",__FUNCTION__,errno); 5410 fflush(where); 5411 close(s_listen); 5412 5413 exit(-1); 5414 } 5415 5416 if (debug) { 5417 fprintf(where,"%s: accepted data connection.\n",__FUNCTION__); 5418 fflush(where); 5419 } 5420 need_to_accept = 0; 5421 connected = 1; 5422 5423 #ifdef KLUDGE_SOCKET_OPTIONS 5424 /* this is for those systems which *INCORRECTLY* fail to pass 5425 attributes across an accept() call. Including this goes 5426 against my better judgement :( raj 11/95 */ 5427 5428 kludge_socket_options(data_socket); 5429 5430 #endif /* KLUDGE_SOCKET_OPTIONS */ 5431 5432 } 5433 else { 5434 /* I wonder if duping would be better here? we also need to set 5435 peeraddr_in so we can send to netperf if this isn't a 5436 request/response test or if we are going to connect() the 5437 socket, but we only need to do it once. */ 5438 if ((omni_request->protocol == IPPROTO_UDP) && 5439 (!peeraddr_set)) { 5440 peeraddr_set = 1; 5441 data_socket = s_listen; 5442 set_sockaddr_family_addr_port(&peeraddr_in, 5443 nf_to_af(omni_request->ipfamily), 5444 omni_request->netperf_ip, 5445 omni_request->netperf_port); 5446 } 5447 } 5448 5449 #ifdef WIN32 5450 /* this is used so the timer thread can close the socket out from 5451 under us, which to date is the easiest/cleanest/least 5452 Windows-specific way I can find to force the winsock calls to 5453 return WSAEINTR with the test is over. anything that will run on 5454 95 and NT and is closer to what netperf expects from Unix signals 5455 and such would be appreciated raj 1/96 */ 5456 win_kludge_socket = data_socket; 5457 #endif /* WIN32 */ 5458 5459 /* in recv_omni, we check recv first, and _then_ send, otherwise, 5460 a request/response test will be all messed-up :) and that then 5461 is why there are two routines to rule them all rather than just 5462 one :) */ 5463 if ((omni_request->direction & NETPERF_RECV) && 5464 ((!times_up) || (units_remaining > 0))) { 5465 ret = recv_data(data_socket, 5466 recv_ring, 5467 bytes_to_recv, 5468 (connected) ? NULL : (struct sockaddr *)&peeraddr_in, 5469 &addrlen, 5470 /* if XMIT also, then this is RR test so waitall */ 5471 (direction & NETPERF_XMIT) ? NETPERF_WAITALL: 0, 5472 &temp_recvs); 5473 if (ret > 0) { 5474 /* if this is a recv-only test controlled by byte count we 5475 decrement the units_remaining by the bytes received */ 5476 if (!(direction & NETPERF_XMIT) && (units_remaining > 0)) { 5477 units_remaining -= ret; 5478 } 5479 bytes_received += ret; 5480 local_receive_calls += temp_recvs; 5481 } 5482 else if (ret == 0) { 5483 /* is this the end of a test, just a zero-byte recv, or 5484 something else? that is an exceedingly good question and 5485 one for which I don't presently have a good answer, but 5486 that won't stop me from guessing :) raj 2008-01-09 */ 5487 if (!((connection_test) || (null_message_ok))) { 5488 /* if it is neither a connection_test nor null_message_ok it 5489 must be the end of the test */ 5490 times_up = 1; 5491 break; 5492 } 5493 local_receive_calls += temp_recvs; 5494 } 5495 else if (ret == -1) { 5496 /* test timed-out */ 5497 times_up = 1; 5498 timed_out = 1; 5499 break; 5500 } 5501 else { 5502 /* presently at least, -2 and -3 are equally bad on recv */ 5503 /* we need a response message here for the control connection 5504 before we exit! */ 5505 netperf_response.content.serv_errno = errno; 5506 send_response(); 5507 exit(-1); 5508 } 5509 recv_ring = recv_ring->next; 5510 } 5511 5512 /* if we should try to send something, then by all means, let us 5513 try to send something. */ 5514 if ((omni_request->direction & NETPERF_XMIT) && 5515 ((!times_up) || (units_remaining > 0))) { 5516 5517 /* there used to be some code here looking sched_yield() until 5518 there was no more queued, unsent data on the socket but 5519 frankly, I've no idea what that was all about so I have 5520 removed it. It may have been part of a kludge to try to avoid 5521 coalescing requests and responses */ 5522 5523 if (omni_request->protocol == IPPROTO_UDP && need_to_connect && 5524 !connected) { 5525 if (connect(data_socket, 5526 (struct sockaddr*)&peeraddr_in, 5527 addrlen) == INVALID_SOCKET) { 5528 netperf_response.content.serv_errno = errno; 5529 send_response(); 5530 close(data_socket); 5531 exit(-1); 5532 } 5533 connected = 1; 5534 } 5535 5536 ret = send_data(data_socket, 5537 send_ring, 5538 bytes_to_send, 5539 (connected) ? NULL : (struct sockaddr *)&peeraddr_in, 5540 addrlen, 5541 omni_request->protocol); 5542 5543 /* the order of these if's will seem a triffle strange, but they 5544 are my best guess as to order of probabilty and/or importance 5545 to the overhead raj 2008-01-09*/ 5546 if (ret == bytes_to_send) { 5547 /* if this is a send-only test controlled by byte count we 5548 decrement units_remaining by the bytes sent */ 5549 if (!(direction & NETPERF_RECV) && (units_remaining > 0)) { 5550 units_remaining -= ret; 5551 } 5552 bytes_sent += ret; 5553 send_ring = send_ring->next; 5554 local_send_calls++; 5555 } 5556 else if (ret == -2) { 5557 /* what to do here -2 means a non-fatal error - probably 5558 ENOBUFS and so our send didn't happen. in the old code for 5559 UDP_STREAM we would just continue in the while loop. it 5560 isn't clear that is what to do here, so we will simply 5561 increment the failed_sends stat and fall-through. If this 5562 is a UDP_STREAM style of test, the net effect should be the 5563 same. if this is a UDP_RR with a really-big burst count, I 5564 don't think we were checking for ENOBUFS there anyway and 5565 so would have failed. Here we can just let things 5566 slide. */ 5567 failed_sends++; 5568 } 5569 else if (ret == 0) { 5570 /* was this a zero-byte send? if it was, then ostensibly we 5571 would hit the ret == bytes_to_send case which means we'd 5572 never get here as we are using blocking semantics */ 5573 } 5574 else if (ret == -1) { 5575 times_up = 1; 5576 timed_out = 1; 5577 break; 5578 } 5579 else { 5580 /* we need a response message back to netperf here before we 5581 exit */ 5582 /* NEED RESPONSE; */ 5583 netperf_response.content.serv_errno = errno; 5584 send_response(); 5585 exit(-1); 5586 } 5587 5588 } 5589 5590 if (connection_test) { 5591 #ifdef __linux 5592 /* so, "Linux" with autotuning likes to alter the socket buffer 5593 sizes over the life of the connection, but only does so when 5594 one takes the defaults at time of socket creation. if we 5595 took those defaults, we should inquire as to what the values 5596 ultimately became. raj 2008-01-15 */ 5597 /* but as annoying as it is to have to make these calls, don't 5598 penalize linux by calling them over and over again. instead 5599 we will simply ass-u-me that it will become the same value 5600 over and over again. raj 20100917 */ 5601 if ((lsr_size_req < 0) && (-1 == lsr_size_end)) 5602 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 5603 else 5604 lsr_size_end = lsr_size; 5605 if ((lss_size_req < 0) && (-1 == lss_size_end)) 5606 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 5607 else 5608 lss_size_end = lss_size; 5609 #else 5610 lsr_size_end = lsr_size; 5611 lss_size_end = lss_size; 5612 #endif 5613 ret = close_data_socket(data_socket,NULL,0,omni_request->protocol); 5614 if (ret == -1) { 5615 times_up = 1; 5616 timed_out = 1; 5617 break; 5618 } 5619 else if (ret < 0) { 5620 netperf_response.content.serv_errno = errno; 5621 send_response(); 5622 perror("netperf: recv_omni: close_data_socket failed"); 5623 fflush(where); 5624 exit(-1); 5625 } 5626 /* we will need a new connection to be established */ 5627 need_to_accept = 1; 5628 connected = 0; 5629 } 5630 5631 #if defined(WANT_INTERVALS) 5632 INTERVALS_WAIT(); 5633 #endif /* WANT_INTERVALS */ 5634 5635 /* was this a "transaction" test? don't for get that a TCP_CC 5636 style test will have no xmit or recv :) so, we check for either 5637 both XMIT and RECV set, or neither XMIT nor RECV set */ 5638 if (NETPERF_IS_RR(omni_request->direction)) { 5639 trans_completed++; 5640 if (units_remaining) { 5641 units_remaining--; 5642 } 5643 } 5644 } 5645 5646 /* The current iteration loop now exits due to timeout or unit count 5647 being reached */ 5648 stop_timer(); 5649 cpu_stop(omni_request->flags & OMNI_MEASURE_CPU,&elapsed_time); 5650 close(s_listen); 5651 5652 #if defined(WANT_INTERVALS) 5653 #ifdef WIN32 5654 stop_itimer(); 5655 #endif 5656 #endif /* WANT_INTERVALS */ 5657 5658 if (timed_out) { 5659 /* we ended the test by time, which may have been PAD_TIME seconds 5660 longer than we wanted to run. so, we want to subtract pad_time 5661 from the elapsed_time. if we didn't pad the timer pad_time will 5662 be 0 so we can just subtract it anyway :) */ 5663 if (debug) { 5664 fprintf(where,"Adjusting elapsed time by %d seconds\n",pad_time); 5665 fflush(where); 5666 } 5667 elapsed_time -= pad_time; 5668 } 5669 5670 remote_transport_retrans = get_transport_retrans(data_socket, 5671 omni_request->protocol); 5672 5673 if (connected) { 5674 #ifdef __linux 5675 /* so, "Linux" with autotuning likes to alter the socket buffer 5676 sizes over the life of the connection, but only does so when 5677 one takes the defaults at time of socket creation. if we took 5678 those defaults, we should inquire as to what the values 5679 ultimately became. raj 2008-01-15 */ 5680 if (lsr_size_req < 0) 5681 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 5682 else 5683 lsr_size_end = lsr_size; 5684 if (lss_size_req < 0) 5685 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 5686 else 5687 lss_size_end = lss_size; 5688 #else 5689 lsr_size_end = lsr_size; 5690 lss_size_end = lss_size; 5691 #endif 5692 if (omni_request->flags & OMNI_WANT_REM_CONG) { 5693 get_transport_cong_control(data_socket, 5694 local_res->ai_protocol, 5695 omni_results->cong_control, 5696 sizeof(omni_results->cong_control)); 5697 } 5698 else { 5699 strncpy(omni_results->cong_control,"",sizeof(omni_results->cong_control)); 5700 } 5701 5702 5703 close_data_socket(data_socket,NULL,0,omni_request->protocol); 5704 } 5705 else { 5706 close_data_socket(data_socket,(struct sockaddr *)&peeraddr_in,addrlen,omni_request->protocol); 5707 lsr_size_end = lsr_size; 5708 lss_size_end = lss_size; 5709 } 5710 5711 /* send the results to the sender */ 5712 5713 omni_results->send_calls = (uint32_t) local_send_calls; 5714 omni_results->bytes_received_lo = bytes_received & 0x00000000FFFFFFFFULL; 5715 omni_results->bytes_received_hi = (bytes_received & 0xFFFFFFFF00000000ULL) >> 32; 5716 omni_results->recv_buf_size = lsr_size_end; 5717 omni_results->recv_calls = (uint32_t) local_receive_calls; 5718 omni_results->bytes_sent_lo = bytes_sent & 0x00000000FFFFFFFFULL; 5719 omni_results->bytes_sent_hi = (bytes_sent & 0xFFFFFFFF00000000ULL) >> 32; 5720 omni_results->send_buf_size = lss_size_end; 5721 omni_results->trans_received = (uint32_t) trans_completed; 5722 omni_results->elapsed_time = elapsed_time; 5723 omni_results->transport_retrans = remote_transport_retrans; 5724 omni_results->cpu_method = cpu_method; 5725 omni_results->num_cpus = lib_num_loc_cpus; 5726 if (omni_request->flags & OMNI_MEASURE_CPU) { 5727 omni_results->cpu_util = calc_cpu_util(elapsed_time); 5728 omni_results->cpu_percent_user = lib_local_cpu_stats.cpu_user; 5729 omni_results->cpu_percent_system = lib_local_cpu_stats.cpu_system; 5730 omni_results->cpu_percent_iowait = lib_local_cpu_stats.cpu_iowait; 5731 omni_results->cpu_percent_irq = lib_local_cpu_stats.cpu_irq; 5732 omni_results->cpu_percent_swintr = lib_local_cpu_stats.cpu_swintr; 5733 omni_results->peak_cpu_util = lib_local_cpu_stats.peak_cpu_util; 5734 omni_results->peak_cpu_id = lib_local_cpu_stats.peak_cpu_id; 5735 } 5736 5737 #if defined(WANT_INTERVALS) 5738 #ifdef WIN32 5739 stop_itimer(); 5740 #endif 5741 #endif /* WANT_INTERVALS */ 5742 5743 if (debug) { 5744 fprintf(where, 5745 "%s: test complete, sending results.\n", 5746 __FUNCTION__); 5747 fflush(where); 5748 } 5749 5750 send_response_n(OMNI_RESULTS_CONV_CUTOFF); 5751 5752 } 5753 5754 5755 #ifdef WANT_MIGRATION 5757 void 5758 send_tcp_stream(char remote_host[]) 5759 { 5760 5761 char *tput_title = "\ 5762 Recv Send Send \n\ 5763 Socket Socket Message Elapsed \n\ 5764 Size Size Size Time Throughput \n\ 5765 bytes bytes bytes secs. %s/sec \n\n"; 5766 5767 char *tput_fmt_0 = 5768 "%7.2f %s\n"; 5769 5770 char *tput_fmt_1 = 5771 "%6d %6d %6d %-6.2f %7.2f %s\n"; 5772 5773 char *cpu_title = "\ 5774 Recv Send Send Utilization Service Demand\n\ 5775 Socket Socket Message Elapsed Send Recv Send Recv\n\ 5776 Size Size Size Time Throughput local remote local remote\n\ 5777 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 5778 5779 char *cpu_fmt_0 = 5780 "%6.3f %c %s\n"; 5781 5782 char *cpu_fmt_1 = 5783 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 5784 5785 char *ksink_fmt = "\n\ 5786 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 5787 Local Remote Local Remote Xfered Per Per\n\ 5788 Send Recv Send Recv Send (avg) Recv (avg)\n\ 5789 %5d %5d %5d %5d %6"PRId64" %6.2f %6"PRId64" %6.2f %6"PRId64"\n"; 5790 5791 char *ksink_fmt2 = "\n\ 5792 Maximum\n\ 5793 Segment\n\ 5794 Size (bytes)\n\ 5795 %6d\n"; 5796 5797 send_omni_inner(remote_host, legacy, "MIGRATED TCP STREAM TEST"); 5798 5799 5800 if (legacy) { 5801 5802 /* We are now ready to print all the information, but only if we 5803 are truly acting as a legacy test. If the user has specified 5804 zero-level verbosity, we will just print the local service 5805 demand, or the remote service demand. If the user has requested 5806 verbosity level 1, he will get the basic "streamperf" 5807 numbers. If the user has specified a verbosity of greater than 5808 1, we will display a veritable plethora of background 5809 information from outside of this block as it it not 5810 cpu_measurement specific... */ 5811 5812 if (confidence < 0) { 5813 /* we did not hit confidence, but were we asked to look for it? */ 5814 if (iteration_max > 1) { 5815 display_confidence(); 5816 } 5817 } 5818 5819 if (local_cpu_usage || remote_cpu_usage) { 5820 5821 switch (verbosity) { 5822 case 0: 5823 if (local_cpu_usage) { 5824 fprintf(where, 5825 cpu_fmt_0, 5826 local_service_demand, 5827 local_cpu_method, 5828 ((print_headers) || 5829 (result_brand == NULL)) ? "" : result_brand); 5830 } 5831 else { 5832 fprintf(where, 5833 cpu_fmt_0, 5834 remote_service_demand, 5835 remote_cpu_method, 5836 ((print_headers) || 5837 (result_brand == NULL)) ? "" : result_brand); 5838 } 5839 break; 5840 case 1: 5841 case 2: 5842 if (print_headers) { 5843 fprintf(where, 5844 cpu_title, 5845 format_units(), 5846 local_cpu_method, 5847 remote_cpu_method); 5848 } 5849 5850 fprintf(where, 5851 cpu_fmt_1, /* the format string */ 5852 rsr_size, /* remote recvbuf size */ 5853 lss_size, /* local sendbuf size */ 5854 send_size, /* how large were the sends */ 5855 elapsed_time, /* how long was the test */ 5856 thruput, /* what was the xfer rate */ 5857 local_cpu_utilization, /* local cpu */ 5858 remote_cpu_utilization, /* remote cpu */ 5859 local_service_demand, /* local service demand */ 5860 remote_service_demand, /* remote service demand */ 5861 ((print_headers) || 5862 (result_brand == NULL)) ? "" : result_brand); 5863 break; 5864 } 5865 } 5866 else { 5867 /* The tester did not wish to measure service demand. */ 5868 5869 switch (verbosity) { 5870 case 0: 5871 fprintf(where, 5872 tput_fmt_0, 5873 thruput, 5874 ((print_headers) || 5875 (result_brand == NULL)) ? "" : result_brand); 5876 break; 5877 case 1: 5878 case 2: 5879 if (print_headers) { 5880 fprintf(where,tput_title,format_units()); 5881 } 5882 fprintf(where, 5883 tput_fmt_1, /* the format string */ 5884 rsr_size, /* remote recvbuf size */ 5885 lss_size, /* local sendbuf size */ 5886 send_size, /* how large were the sends */ 5887 elapsed_time, /* how long did it take */ 5888 thruput, /* how fast did it go */ 5889 ((print_headers) || 5890 (result_brand == NULL)) ? "" : result_brand); 5891 break; 5892 } 5893 } 5894 5895 /* it would be a good thing to include information about some of the */ 5896 /* other parameters that may have been set for this test, but at the */ 5897 /* moment, I do not wish to figure-out all the formatting, so I will */ 5898 /* just put this comment here to help remind me that it is something */ 5899 /* that should be done at a later time. */ 5900 5901 if (verbosity > 1) { 5902 /* The user wanted to know it all, so we will give it to him. */ 5903 /* This information will include as much as we can find about */ 5904 /* TCP statistics, the alignments of the sends and receives */ 5905 /* and all that sort of rot... */ 5906 5907 /* this stuff needs to be worked-out in the presence of confidence */ 5908 /* intervals and multiple iterations of the test... raj 11/94 */ 5909 5910 fprintf(where, 5911 ksink_fmt, 5912 "Bytes", 5913 "Bytes", 5914 "Bytes", 5915 local_send_align, 5916 remote_recv_align, 5917 local_send_offset, 5918 remote_recv_offset, 5919 bytes_sent, 5920 bytes_sent / (double)local_send_calls, 5921 local_send_calls, 5922 bytes_sent / (double)remote_receive_calls, 5923 remote_receive_calls); 5924 fprintf(where, 5925 ksink_fmt2, 5926 transport_mss); 5927 #ifdef WANT_HISTOGRAM 5928 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 5929 HIST_report(time_hist); 5930 #endif /* WANT_HISTOGRAM */ 5931 fflush(where); 5932 } 5933 5934 } 5935 } 5936 5937 void 5938 send_tcp_maerts(char remote_host[]) 5939 { 5940 5941 char *tput_title = "\ 5942 Recv Send Send \n\ 5943 Socket Socket Message Elapsed \n\ 5944 Size Size Size Time Throughput \n\ 5945 bytes bytes bytes secs. %s/sec \n\n"; 5946 5947 char *tput_fmt_0 = 5948 "%7.2f %s\n"; 5949 5950 char *tput_fmt_1 = 5951 "%6d %6d %6d %-6.2f %7.2f %s\n"; 5952 5953 char *cpu_title = "\ 5954 Recv Send Send Utilization Service Demand\n\ 5955 Socket Socket Message Elapsed Recv Send Recv Send\n\ 5956 Size Size Size Time Throughput local remote local remote\n\ 5957 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 5958 5959 char *cpu_fmt_0 = 5960 "%6.3f %c %s\n"; 5961 5962 char *cpu_fmt_1 = 5963 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 5964 5965 char *ksink_fmt = "\n\ 5966 Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\ 5967 Local Remote Local Remote Xfered Per Per\n\ 5968 Recv Send Recv Send Recv (avg) Send (avg)\n\ 5969 %5d %5d %5d %5d %6"PRId64" %6.2f %6d %6.2f %6d\n"; 5970 5971 char *ksink_fmt2 = "\n\ 5972 Maximum\n\ 5973 Segment\n\ 5974 Size (bytes)\n\ 5975 %6d\n"; 5976 5977 send_omni_inner(remote_host, legacy, "MIGRATED TCP MAERTS TEST"); 5978 5979 5980 /* We are now ready to print all the information, but only if we are 5981 truly acting as a leacy test. If the user has specified 5982 zero-level verbosity, we will just print the local service 5983 demand, or the remote service demand. If the user has requested 5984 verbosity level 1, he will get the basic "streamperf" numbers. If 5985 the user has specified a verbosity of greater than 1, we will 5986 display a veritable plethora of background information from 5987 outside of this block as it it not cpu_measurement 5988 specific... */ 5989 5990 if (legacy) { 5991 5992 if (confidence < 0) { 5993 /* we did not hit confidence, but were we asked to look for it? */ 5994 if (iteration_max > 1) { 5995 display_confidence(); 5996 } 5997 } 5998 5999 if (local_cpu_usage || remote_cpu_usage) { 6000 6001 switch (verbosity) { 6002 case 0: 6003 if (local_cpu_usage) { 6004 fprintf(where, 6005 cpu_fmt_0, 6006 local_service_demand, 6007 local_cpu_method, 6008 ((print_headers) || 6009 (result_brand == NULL)) ? "" : result_brand); 6010 } 6011 else { 6012 fprintf(where, 6013 cpu_fmt_0, 6014 remote_service_demand, 6015 remote_cpu_method, 6016 ((print_headers) || 6017 (result_brand == NULL)) ? "" : result_brand); 6018 } 6019 break; 6020 case 1: 6021 case 2: 6022 if (print_headers) { 6023 fprintf(where, 6024 cpu_title, 6025 format_units(), 6026 local_cpu_method, 6027 remote_cpu_method); 6028 } 6029 6030 fprintf(where, 6031 cpu_fmt_1, /* the format string */ 6032 rsr_size, /* remote recvbuf size */ 6033 lss_size, /* local sendbuf size */ 6034 remote_send_size, /* how large were the recvs */ 6035 elapsed_time, /* how long was the test */ 6036 thruput, /* what was the xfer rate */ 6037 local_cpu_utilization, /* local cpu */ 6038 remote_cpu_utilization, /* remote cpu */ 6039 local_service_demand, /* local service demand */ 6040 remote_service_demand, /* remote service demand */ 6041 ((print_headers) || 6042 (result_brand == NULL)) ? "" : result_brand); 6043 break; 6044 } 6045 } 6046 else { 6047 /* The tester did not wish to measure service demand. */ 6048 6049 switch (verbosity) { 6050 case 0: 6051 fprintf(where, 6052 tput_fmt_0, 6053 thruput, 6054 ((print_headers) || 6055 (result_brand == NULL)) ? "" : result_brand); 6056 break; 6057 case 1: 6058 case 2: 6059 if (print_headers) { 6060 fprintf(where,tput_title,format_units()); 6061 } 6062 fprintf(where, 6063 tput_fmt_1, /* the format string */ 6064 lsr_size, /* local recvbuf size */ 6065 rss_size, /* remot sendbuf size */ 6066 remote_send_size, /* how large were the recvs */ 6067 elapsed_time, /* how long did it take */ 6068 thruput, /* how fast did it go */ 6069 ((print_headers) || 6070 (result_brand == NULL)) ? "" : result_brand); 6071 break; 6072 } 6073 } 6074 6075 /* it would be a good thing to include information about some of the */ 6076 /* other parameters that may have been set for this test, but at the */ 6077 /* moment, I do not wish to figure-out all the formatting, so I will */ 6078 /* just put this comment here to help remind me that it is something */ 6079 /* that should be done at a later time. */ 6080 6081 if (verbosity > 1) { 6082 /* The user wanted to know it all, so we will give it to him. */ 6083 /* This information will include as much as we can find about */ 6084 /* TCP statistics, the alignments of the sends and receives */ 6085 /* and all that sort of rot... */ 6086 6087 /* this stuff needs to be worked-out in the presence of confidence */ 6088 /* intervals and multiple iterations of the test... raj 11/94 */ 6089 6090 fprintf(where, 6091 ksink_fmt, 6092 "Bytes", 6093 "Bytes", 6094 "Bytes", 6095 local_recv_align, 6096 remote_recv_align, 6097 local_recv_offset, 6098 remote_recv_offset, 6099 bytes_received, 6100 bytes_received / (double)local_receive_calls, 6101 local_receive_calls, 6102 remote_bytes_sent / (double)remote_send_calls, 6103 remote_send_calls); 6104 fprintf(where, 6105 ksink_fmt2, 6106 transport_mss); 6107 6108 #ifdef WANT_HISTOGRAM 6109 fprintf(where,"\n\nHistogram of time spent in recv() call.\n"); 6110 HIST_report(time_hist); 6111 #endif /* WANT_HISTOGRAM */ 6112 fflush(where); 6113 } 6114 } 6115 } 6116 6117 6118 void 6120 send_tcp_rr(char remote_host[]) { 6121 6122 char *tput_title = "\ 6123 Local /Remote\n\ 6124 Socket Size Request Resp. Elapsed Trans.\n\ 6125 Send Recv Size Size Time Rate \n\ 6126 bytes Bytes bytes bytes secs. per sec \n\n"; 6127 6128 char *tput_title_band = "\ 6129 Local /Remote\n\ 6130 Socket Size Request Resp. Elapsed \n\ 6131 Send Recv Size Size Time Throughput \n\ 6132 bytes Bytes bytes bytes secs. %s/sec \n\n"; 6133 6134 char *tput_fmt_0 = 6135 "%7.2f %s\n"; 6136 6137 char *tput_fmt_1_line_1 = "\ 6138 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 6139 char *tput_fmt_1_line_2 = "\ 6140 %-6d %-6d\n"; 6141 6142 char *cpu_title = "\ 6143 Local /Remote\n\ 6144 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6145 Send Recv Size Size Time Rate local remote local remote\n\ 6146 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 6147 6148 char *cpu_title_tput = "\ 6149 Local /Remote\n\ 6150 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 6151 Send Recv Size Size Time %-8.8s local remote local remote\n\ 6152 bytes bytes bytes bytes secs. per sec %% %c %% %c us/KB us/KB\n\n"; 6153 6154 char *cpu_title_latency = "\ 6155 Local /Remote\n\ 6156 Socket Size Request Resp. Elapsed Latency CPU CPU S.dem S.dem\n\ 6157 Send Recv Size Size Time usecs local remote local remote\n\ 6158 bytes bytes bytes bytes secs. per tran %% %c %% %c us/Tr us/Tr\n\n"; 6159 6160 char *cpu_fmt_0 = 6161 "%6.3f %c %s\n"; 6162 6163 char *cpu_fmt_1_line_1 = "\ 6164 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 6165 6166 char *cpu_fmt_1_line_2 = "\ 6167 %-6d %-6d\n"; 6168 6169 char *ksink_fmt = "\ 6170 Alignment Offset RoundTrip Trans Throughput\n\ 6171 Local Remote Local Remote Latency Rate %-8.8s/s\n\ 6172 Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\ 6173 %5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n"; 6174 6175 send_omni_inner(remote_host, legacy, "MIGRATED TCP REQUEST/RESPONSE TEST"); 6176 6177 if (legacy) { 6178 /* We are now ready to print all the information. If the user has 6179 specified zero-level verbosity, we will just print the local 6180 service demand, or the remote service demand. If the user has 6181 requested verbosity level 1, he will get the basic "streamperf" 6182 numbers. If the user has specified a verbosity of greater than 1, 6183 we will display a veritable plethora of background information 6184 from outside of this block as it it not cpu_measurement 6185 specific... */ 6186 6187 if (confidence < 0) { 6188 /* we did not hit confidence, but were we asked to look for it? */ 6189 if (iteration_max > 1) { 6190 display_confidence(); 6191 } 6192 } 6193 6194 if (local_cpu_usage || remote_cpu_usage) { 6195 6196 switch (verbosity) { 6197 case 0: 6198 if (local_cpu_usage) { 6199 fprintf(where, 6200 cpu_fmt_0, 6201 local_service_demand, 6202 local_cpu_method, 6203 ((print_headers) || 6204 (result_brand == NULL)) ? "" : result_brand); 6205 } 6206 else { 6207 fprintf(where, 6208 cpu_fmt_0, 6209 remote_service_demand, 6210 remote_cpu_method, 6211 ((print_headers) || 6212 (result_brand == NULL)) ? "" : result_brand); 6213 } 6214 break; 6215 case 1: 6216 case 2: 6217 if (print_headers) { 6218 if ('x' == libfmt) { 6219 fprintf(where, 6220 cpu_title, 6221 local_cpu_method, 6222 remote_cpu_method); 6223 } 6224 else { 6225 fprintf(where, 6226 cpu_title_tput, 6227 format_units(), 6228 local_cpu_method, 6229 remote_cpu_method); 6230 } 6231 } 6232 6233 fprintf(where, 6234 cpu_fmt_1_line_1, /* the format string */ 6235 lss_size, /* local sendbuf size */ 6236 lsr_size, 6237 req_size, /* how large were the requests */ 6238 rsp_size, /* guess */ 6239 elapsed_time, /* how long was the test */ 6240 thruput, 6241 local_cpu_utilization, /* local cpu */ 6242 remote_cpu_utilization, /* remote cpu */ 6243 local_service_demand, /* local service demand */ 6244 remote_service_demand, /* remote service demand */ 6245 ((print_headers) || 6246 (result_brand == NULL)) ? "" : result_brand); 6247 fprintf(where, 6248 cpu_fmt_1_line_2, 6249 rss_size, 6250 rsr_size); 6251 break; 6252 } 6253 } 6254 else { 6255 /* The tester did not wish to measure service demand. */ 6256 6257 switch (verbosity) { 6258 case 0: 6259 fprintf(where, 6260 tput_fmt_0, 6261 thruput, 6262 ((print_headers) || 6263 (result_brand == NULL)) ? "" : result_brand); 6264 break; 6265 case 1: 6266 case 2: 6267 if (print_headers) { 6268 fprintf(where, 6269 ('x' == libfmt) ? tput_title : tput_title_band, 6270 format_units()); 6271 } 6272 6273 fprintf(where, 6274 tput_fmt_1_line_1, /* the format string */ 6275 lss_size, 6276 lsr_size, 6277 req_size, /* how large were the requests */ 6278 rsp_size, /* how large were the responses */ 6279 elapsed_time, /* how long did it take */ 6280 /* are we trans or do we need to convert to bytes then 6281 bits? at this point, thruput is in our "confident" 6282 transactions per second. we can convert to a 6283 bidirectional bitrate by multiplying that by the sum 6284 of the req_size and rsp_size. we pass that to 6285 calc_thruput_interval_omni with an elapsed time of 6286 1.0 s to get it converted to [kmg]bits/s or 6287 [KMG]Bytes/s */ 6288 thruput, 6289 ((print_headers) || 6290 (result_brand == NULL)) ? "" : result_brand); 6291 fprintf(where, 6292 tput_fmt_1_line_2, 6293 rss_size, /* remote recvbuf size */ 6294 rsr_size); 6295 6296 break; 6297 } 6298 } 6299 6300 /* it would be a good thing to include information about some of the */ 6301 /* other parameters that may have been set for this test, but at the */ 6302 /* moment, I do not wish to figure-out all the formatting, so I will */ 6303 /* just put this comment here to help remind me that it is something */ 6304 /* that should be done at a later time. */ 6305 6306 /* how to handle the verbose information in the presence of */ 6307 /* confidence intervals is yet to be determined... raj 11/94 */ 6308 if (verbosity > 1) { 6309 /* The user wanted to know it all, so we will give it to him. */ 6310 /* This information will include as much as we can find about */ 6311 /* TCP statistics, the alignments of the sends and receives */ 6312 /* and all that sort of rot... */ 6313 6314 /* normally, you might think that if we were messing about with 6315 the value of libfmt we would need to put it back again, but 6316 since this is basically the last thing we are going to do with 6317 it, it does not matter. so there :) raj 2007-06-08 */ 6318 /* if the user was asking for transactions, then we report 6319 megabits per second for the unidirectional throughput, 6320 otherwise we use the desired units. */ 6321 if ('x' == libfmt) { 6322 libfmt = 'm'; 6323 } 6324 6325 fprintf(where, 6326 ksink_fmt, 6327 format_units(), 6328 local_send_align, 6329 remote_recv_offset, 6330 local_send_offset, 6331 remote_recv_offset, 6332 /* if the user has enable burst mode, we have to remember 6333 to account for that in the number of transactions 6334 outstanding at any one time. otherwise we will 6335 underreport the latency of individual 6336 transactions. learned from saf by raj 2007-06-08 */ 6337 (((double)1.0/transaction_rate)*(double)1000000.0) * 6338 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)), 6339 transaction_rate, 6340 calc_thruput_interval_omni(transaction_rate * (double)req_size, 6341 1.0), 6342 calc_thruput_interval_omni(transaction_rate * (double)rsp_size, 6343 1.0)); 6344 6345 #ifdef WANT_HISTOGRAM 6346 fprintf(where,"\nHistogram of request/response times\n"); 6347 HIST_report(time_hist); 6348 #endif /* WANT_HISTOGRAM */ 6349 fflush(where); 6350 } 6351 } 6352 } 6353 6354 6355 void 6356 send_tcp_conn_rr(char remote_host[]) 6357 { 6358 6359 char *tput_title = "\ 6360 Local /Remote\n\ 6361 Socket Size Request Resp. Elapsed Trans.\n\ 6362 Send Recv Size Size Time Rate \n\ 6363 bytes Bytes bytes bytes secs. per sec \n\n"; 6364 6365 char *tput_fmt_0 = 6366 "%7.2f\n"; 6367 6368 char *tput_fmt_1_line_1 = "\ 6369 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 6370 char *tput_fmt_1_line_2 = "\ 6371 %-6d %-6d\n"; 6372 6373 char *cpu_title = "\ 6374 Local /Remote\n\ 6375 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6376 Send Recv Size Size Time Rate local remote local remote\n\ 6377 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 6378 6379 char *cpu_fmt_0 = 6380 "%6.3f\n"; 6381 6382 char *cpu_fmt_1_line_1 = "\ 6383 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 6384 6385 char *cpu_fmt_1_line_2 = "\ 6386 %-6d %-6d\n"; 6387 6388 char *ksink_fmt = "\n\ 6389 Alignment Offset\n\ 6390 Local Remote Local Remote\n\ 6391 Send Recv Send Recv\n\ 6392 %5d %5d %5d %5d\n"; 6393 6394 send_omni_inner(remote_host, 6395 legacy, 6396 "MIGRATED TCP Connect/Request/Response TEST"); 6397 6398 /* We are now ready to print all the information. If the user */ 6399 /* has specified zero-level verbosity, we will just print the */ 6400 /* local service demand, or the remote service demand. If the */ 6401 /* user has requested verbosity level 1, he will get the basic */ 6402 /* "streamperf" numbers. If the user has specified a verbosity */ 6403 /* of greater than 1, we will display a veritable plethora of */ 6404 /* background information from outside of this block as it it */ 6405 /* not cpu_measurement specific... */ 6406 6407 if (legacy) { 6408 if (confidence < 0) { 6409 /* we did not hit confidence, but were we asked to look for it? */ 6410 if (iteration_max > 1) { 6411 display_confidence(); 6412 } 6413 } 6414 6415 if (local_cpu_usage || remote_cpu_usage) { 6416 6417 switch (verbosity) { 6418 case 0: 6419 if (local_cpu_usage) { 6420 fprintf(where, 6421 cpu_fmt_0, 6422 local_service_demand, 6423 local_cpu_method); 6424 } 6425 else { 6426 fprintf(where, 6427 cpu_fmt_0, 6428 remote_service_demand, 6429 remote_cpu_method); 6430 } 6431 break; 6432 case 1: 6433 case 2: 6434 if (print_headers) { 6435 fprintf(where, 6436 cpu_title, 6437 local_cpu_method, 6438 remote_cpu_method); 6439 } 6440 6441 fprintf(where, 6442 cpu_fmt_1_line_1, /* the format string */ 6443 lss_size, /* local sendbuf size */ 6444 lsr_size, 6445 req_size, /* how large were the requests */ 6446 rsp_size, /* guess */ 6447 elapsed_time, /* how long was the test */ 6448 thruput, 6449 local_cpu_utilization, /* local cpu */ 6450 remote_cpu_utilization, /* remote cpu */ 6451 local_service_demand, /* local service demand */ 6452 remote_service_demand); /* remote service demand */ 6453 fprintf(where, 6454 cpu_fmt_1_line_2, 6455 rss_size, 6456 rsr_size); 6457 break; 6458 } 6459 } 6460 else { 6461 /* The tester did not wish to measure service demand. */ 6462 6463 switch (verbosity) { 6464 case 0: 6465 fprintf(where, 6466 tput_fmt_0, 6467 thruput); 6468 break; 6469 case 1: 6470 case 2: 6471 if (print_headers) { 6472 fprintf(where,tput_title,format_units()); 6473 } 6474 6475 fprintf(where, 6476 tput_fmt_1_line_1, /* the format string */ 6477 lss_size, 6478 lsr_size, 6479 req_size, /* how large were the requests */ 6480 rsp_size, /* how large were the responses */ 6481 elapsed_time, /* how long did it take */ 6482 thruput); 6483 fprintf(where, 6484 tput_fmt_1_line_2, 6485 rss_size, /* remote recvbuf size */ 6486 rsr_size); 6487 6488 break; 6489 } 6490 } 6491 6492 /* it would be a good thing to include information about some of the */ 6493 /* other parameters that may have been set for this test, but at the */ 6494 /* moment, I do not wish to figure-out all the formatting, so I will */ 6495 /* just put this comment here to help remind me that it is something */ 6496 /* that should be done at a later time. */ 6497 6498 /* how to handle the verbose information in the presence of */ 6499 /* confidence intervals is yet to be determined... raj 11/94 */ 6500 if (verbosity > 1) { 6501 /* The user wanted to know it all, so we will give it to him. */ 6502 /* This information will include as much as we can find about */ 6503 /* TCP statistics, the alignments of the sends and receives */ 6504 /* and all that sort of rot... */ 6505 6506 fprintf(where, 6507 ksink_fmt, 6508 local_send_align, 6509 remote_recv_align, 6510 local_send_offset, 6511 remote_recv_offset); 6512 6513 #ifdef WANT_HISTOGRAM 6514 fprintf(where,"\nHistogram of request/response times\n"); 6515 HIST_report(time_hist); 6516 #endif /* WANT_HISTOGRAM */ 6517 fflush(where); 6518 } 6519 } 6520 } 6521 6522 void 6523 send_udp_stream(char remote_host[]) 6524 { 6525 /**********************************************************************/ 6526 /* */ 6527 /* UDP Unidirectional Send Test */ 6528 /* */ 6529 /**********************************************************************/ 6530 6531 char *tput_title = "\ 6532 Socket Message Elapsed Messages \n\ 6533 Size Size Time Okay Errors Throughput\n\ 6534 bytes bytes secs # # %s/sec\n\n"; 6535 6536 char *tput_fmt_0 = 6537 "%7.2f\n"; 6538 6539 char *tput_fmt_1 = "\ 6540 %6d %6d %-7.2f %7"PRIu64" %6d %7.2f\n\ 6541 %6d %-7.2f %7"PRIu64" %7.2f\n\n"; 6542 6543 6544 char *cpu_title = "\ 6545 Socket Message Elapsed Messages CPU Service\n\ 6546 Size Size Time Okay Errors Throughput Util Demand\n\ 6547 bytes bytes secs # # %s/sec %% %c%c us/KB\n\n"; 6548 6549 char *cpu_fmt_0 = 6550 "%6.2f %c\n"; 6551 6552 char *cpu_fmt_1 = "\ 6553 %6d %6d %-7.2f %7"PRIu64" %6d %7.1f %-6.2f %-6.3f\n\ 6554 %6d %-7.2f %7"PRIu64" %7.1f %-6.2f %-6.3f\n\n"; 6555 6556 6557 send_omni_inner(remote_host, legacy, "MIGRATED UDP STREAM TEST"); 6558 6559 if (legacy) { 6560 /* We are now ready to print all the information. If the user has 6561 specified zero-level verbosity, we will just print the local 6562 service demand, or the remote service demand. If the user has 6563 requested verbosity level 1, he will get the basic "streamperf" 6564 numbers. If the user has specified a verbosity of greater than 6565 1, we will display a veritable plethora of background 6566 information from outside of this block as it it not 6567 cpu_measurement specific... */ 6568 6569 6570 if (confidence < 0) { 6571 /* we did not hit confidence, but were we asked to look for it? */ 6572 if (iteration_max > 1) { 6573 display_confidence(); 6574 } 6575 } 6576 6577 if (local_cpu_usage || remote_cpu_usage) { 6578 6579 switch (verbosity) { 6580 case 0: 6581 if (local_cpu_usage) { 6582 fprintf(where, 6583 cpu_fmt_0, 6584 local_service_demand, 6585 local_cpu_method); 6586 } 6587 else { 6588 fprintf(where, 6589 cpu_fmt_0, 6590 remote_service_demand, 6591 local_cpu_method); 6592 } 6593 break; 6594 case 1: 6595 case 2: 6596 if (print_headers) { 6597 fprintf(where, 6598 cpu_title, 6599 format_units(), 6600 local_cpu_method, 6601 remote_cpu_method); 6602 } 6603 6604 fprintf(where, 6605 cpu_fmt_1, /* the format string */ 6606 lss_size, /* local sendbuf size */ 6607 send_size, /* how large were the sends */ 6608 elapsed_time, /* how long was the test */ 6609 local_send_calls, 6610 failed_sends, 6611 local_send_thruput, /* what was the xfer rate */ 6612 local_cpu_utilization, /* local cpu */ 6613 local_service_demand, /* local service demand */ 6614 rsr_size, 6615 elapsed_time, 6616 remote_receive_calls, 6617 remote_recv_thruput, 6618 remote_cpu_utilization, /* remote cpu */ 6619 remote_service_demand); /* remote service demand */ 6620 break; 6621 } 6622 } 6623 else { 6624 /* The tester did not wish to measure service demand. */ 6625 switch (verbosity) { 6626 case 0: 6627 fprintf(where, 6628 tput_fmt_0, 6629 local_send_thruput); 6630 break; 6631 case 1: 6632 case 2: 6633 if (print_headers) { 6634 fprintf(where,tput_title,format_units()); 6635 } 6636 fprintf(where, 6637 tput_fmt_1, /* the format string */ 6638 lss_size, /* local sendbuf size */ 6639 send_size, /* how large were the sends */ 6640 elapsed_time, /* how long did it take */ 6641 local_send_calls, 6642 failed_sends, 6643 local_send_thruput, 6644 rsr_size, /* remote recvbuf size */ 6645 elapsed_time, 6646 remote_receive_calls, 6647 remote_recv_thruput); 6648 break; 6649 } 6650 } 6651 6652 #ifdef WANT_HISTOGRAM 6653 if (verbosity > 1) { 6654 fprintf(where,"\nHistogram of time spent in send() call\n"); 6655 HIST_report(time_hist); 6656 } 6657 #endif /* WANT_HISTOGRAM */ 6658 fflush(where); 6659 } 6660 } 6661 6662 void 6663 send_udp_rr(char remote_host[]) 6664 { 6665 6666 char *tput_title = "\ 6667 Local /Remote\n\ 6668 Socket Size Request Resp. Elapsed Trans.\n\ 6669 Send Recv Size Size Time Rate \n\ 6670 bytes Bytes bytes bytes secs. per sec \n\n"; 6671 6672 char *tput_title_band = "\ 6673 Local /Remote\n\ 6674 Socket Size Request Resp. Elapsed \n\ 6675 Send Recv Size Size Time Throughput \n\ 6676 bytes Bytes bytes bytes secs. %s/sec \n\n"; 6677 6678 char *tput_fmt_0 = 6679 "%7.2f %s\n"; 6680 6681 char *tput_fmt_1_line_1 = "\ 6682 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 6683 6684 char *tput_fmt_1_line_2 = "\ 6685 %-6d %-6d\n"; 6686 6687 char *cpu_title = "\ 6688 Local /Remote\n\ 6689 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6690 Send Recv Size Size Time Rate local remote local remote\n\ 6691 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 6692 6693 char *cpu_title_tput = "\ 6694 Local /Remote\n\ 6695 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 6696 Send Recv Size Size Time %-8.8s local remote local remote\n\ 6697 bytes bytes bytes bytes secs. per sec %% %c %% %c us/KB us/KB\n\n"; 6698 6699 char *cpu_fmt_0 = 6700 "%6.3f %c %s\n"; 6701 6702 char *cpu_fmt_1_line_1 = "\ 6703 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 6704 6705 char *cpu_fmt_1_line_2 = "\ 6706 %-6d %-6d\n"; 6707 6708 send_omni_inner(remote_host, legacy, "MIGRATED UDP REQUEST/RESPONSE TEST"); 6709 6710 if (legacy) { 6711 /* We are now ready to print all the information. If the user has 6712 specified zero-level verbosity, we will just print the local 6713 service demand, or the remote service demand. If the user has 6714 requested verbosity level 1, he will get the basic "streamperf" 6715 numbers. If the user has specified a verbosity of greater than 6716 1, we will display a veritable plethora of background 6717 information from outside of this block as it it not 6718 cpu_measurement specific... */ 6719 6720 if (confidence < 0) { 6721 /* we did not hit confidence, but were we asked to look for it? */ 6722 if (iteration_max > 1) { 6723 display_confidence(); 6724 } 6725 } 6726 6727 if (local_cpu_usage || remote_cpu_usage) { 6728 6729 switch (verbosity) { 6730 case 0: 6731 if (local_cpu_usage) { 6732 fprintf(where, 6733 cpu_fmt_0, 6734 local_service_demand, 6735 local_cpu_method, 6736 ((print_headers) || 6737 (result_brand == NULL)) ? "" : result_brand); 6738 6739 } 6740 else { 6741 fprintf(where, 6742 cpu_fmt_0, 6743 remote_service_demand, 6744 remote_cpu_method, 6745 ((print_headers) || 6746 (result_brand == NULL)) ? "" : result_brand); 6747 6748 } 6749 break; 6750 case 1: 6751 case 2: 6752 if (print_headers) { 6753 if ('x' == libfmt) { 6754 fprintf(where, 6755 cpu_title, 6756 local_cpu_method, 6757 remote_cpu_method); 6758 } 6759 else { 6760 fprintf(where, 6761 cpu_title_tput, 6762 format_units(), 6763 local_cpu_method, 6764 remote_cpu_method); 6765 } 6766 } 6767 6768 fprintf(where, 6769 cpu_fmt_1_line_1, /* the format string */ 6770 lss_size, /* local sendbuf size */ 6771 lsr_size, 6772 req_size, /* how large were the requests */ 6773 rsp_size, /* guess */ 6774 elapsed_time, /* how long was the test */ 6775 thruput, 6776 local_cpu_utilization, /* local cpu */ 6777 remote_cpu_utilization, /* remote cpu */ 6778 local_service_demand, /* local service demand */ 6779 remote_service_demand, /* remote service demand */ 6780 ((print_headers) || 6781 (result_brand == NULL)) ? "" : result_brand); 6782 fprintf(where, 6783 cpu_fmt_1_line_2, 6784 rss_size, 6785 rsr_size); 6786 break; 6787 } 6788 } 6789 else { 6790 /* The tester did not wish to measure service demand. */ 6791 switch (verbosity) { 6792 case 0: 6793 fprintf(where, 6794 tput_fmt_0, 6795 thruput, 6796 ((print_headers) || 6797 (result_brand == NULL)) ? "" : result_brand); 6798 break; 6799 case 1: 6800 case 2: 6801 if (print_headers) { 6802 fprintf(where, 6803 ('x' == libfmt) ? tput_title : tput_title_band, 6804 format_units()); 6805 } 6806 6807 fprintf(where, 6808 tput_fmt_1_line_1, /* the format string */ 6809 lss_size, 6810 lsr_size, 6811 req_size, /* how large were the requests */ 6812 rsp_size, /* how large were the responses */ 6813 elapsed_time, /* how long did it take */ 6814 thruput, 6815 ((print_headers) || 6816 (result_brand == NULL)) ? "" : result_brand); 6817 fprintf(where, 6818 tput_fmt_1_line_2, 6819 rss_size, /* remote recvbuf size */ 6820 rsr_size); 6821 6822 break; 6823 } 6824 } 6825 6826 /* it would be a good thing to include information about some of the */ 6827 /* other parameters that may have been set for this test, but at the */ 6828 /* moment, I do not wish to figure-out all the formatting, so I will */ 6829 /* just put this comment here to help remind me that it is something */ 6830 /* that should be done at a later time. */ 6831 6832 /* how to handle the verbose information in the presence of */ 6833 /* confidence intervals is yet to be determined... raj 11/94 */ 6834 6835 if (verbosity > 1) { 6836 /* The user wanted to know it all, so we will give it to him. */ 6837 /* This information will include as much as we can find about */ 6838 /* UDP statistics, the alignments of the sends and receives */ 6839 /* and all that sort of rot... */ 6840 6841 #ifdef WANT_HISTOGRAM 6842 fprintf(where,"\nHistogram of request/reponse times.\n"); 6843 HIST_report(time_hist); 6844 #endif /* WANT_HISTOGRAM */ 6845 } 6846 fflush(where); 6847 } 6848 } 6849 6850 6851 #endif /* WANT_MIGRATION */ 6852 6853 6854 /* using legacy test names will cause certain default settings to be 6856 made before we scan the test-specific arguments. raj 2010-07-20 */ 6857 static void 6858 set_omni_defaults_by_legacy_testname() { 6859 6860 /* the uber defaults are for a unidirectional test using TCP */ 6861 protocol = IPPROTO_TCP; 6862 socket_type = SOCK_STREAM; 6863 connection_test = 0; 6864 req_size = rsp_size = -1; 6865 was_legacy = 1; 6866 legacy = 1; 6867 implicit_direction = 0; /* do we allow certain options to 6868 implicitly affect the test direction? */ 6869 if (strcasecmp(test_name,"TCP_STREAM") == 0) { 6870 direction = NETPERF_XMIT; 6871 } 6872 else if (strcasecmp(test_name,"TCP_MAERTS") == 0) { 6873 direction = NETPERF_RECV; 6874 } 6875 else if (strcasecmp(test_name,"TCP_RR") == 0) { 6876 req_size = rsp_size = 1; 6877 direction = 0; 6878 direction |= NETPERF_XMIT; 6879 direction |= NETPERF_RECV; 6880 } 6881 else if (strcasecmp(test_name,"UDP_STREAM") == 0) { 6882 protocol = IPPROTO_UDP; 6883 socket_type = SOCK_DGRAM; 6884 } 6885 else if (strcasecmp(test_name,"UDP_RR") == 0) { 6886 protocol = IPPROTO_UDP; 6887 socket_type = SOCK_DGRAM; 6888 direction = 0; 6889 direction |= NETPERF_XMIT; 6890 direction |= NETPERF_RECV; 6891 req_size = rsp_size = 1; 6892 } 6893 else if (strcasecmp(test_name,"TCP_CC") == 0) { 6894 direction = 0; 6895 connection_test = 1; 6896 } 6897 else if (strcasecmp(test_name,"TCP_CRR") == 0) { 6898 direction = 0; 6899 direction |= NETPERF_XMIT; 6900 direction |= NETPERF_RECV; 6901 req_size = rsp_size = 1; 6902 connection_test = 1; 6903 } 6904 else if (strcasecmp(test_name,"omni") == 0) { 6905 /* there is not much to do here but clear the legacy flag */ 6906 was_legacy = 0; 6907 legacy = 0; 6908 implicit_direction = 1; 6909 } 6910 socket_type_str = hst_to_str(socket_type); 6911 } 6912 6913 char omni_usage[] = "\n\ 6914 Usage: netperf [global options] -- [test options] \n\ 6915 \n\ 6916 OMNI and Migrated BSD Sockets Test Options:\n\ 6917 -b number Send number requests at start of _RR tests\n\ 6918 -c Explicitly declare this a connection test such as\n\ 6919 TCP_CRR or TCP_CC\n\ 6920 -C Set TCP_CORK when available\n\ 6921 -d direction Explicitly set test direction based on bitwise OR\n\ 6922 of 0x2 for transmit and 0x4 for receive. Default:\n\ 6923 based on test type\n\ 6924 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\ 6925 -h Display this text\n\ 6926 -H name[/mask],fam Use name (or IP) and family as target of data connection\n\ 6927 A mask value will cause randomization of the IP used\n\ 6928 -k [file] Generate keyval output optionally based on file\n\ 6929 Use filename of '?' to get the list of choices\n\ 6930 -K loc[,rem] Set the local and/or remote congestion control\n\ 6931 algorithm to use on those platforms where it can\n\ 6932 be set.\n\ 6933 -L name[/mask],fam Use name (or IP) and family as source of data connection\n\ 6934 A mask value will cause randomization of the IP used\n\ 6935 -m local,remote Set the send size for _STREAM/_MAERTS tests\n\ 6936 -M local,remote Set the recv size for _STREAM/_MAERTS tests\n\ 6937 -n Use the connected socket for UDP locally\n\ 6938 -N Use the connected socket for UDP remotely\n\ 6939 -o [file] Generate CSV output optionally based on file\n\ 6940 Use filename of '?' to get the list of choices\n\ 6941 -O [file] Generate classic-style output based on file\n\ 6942 Use filename of '?' to get the list of choices\n\ 6943 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\ 6944 -P local[,remote] Set the local/remote port for the data socket\n\ 6945 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\ 6946 -R 0/1 Allow routing of traffic on data connection.\n\ 6947 Default: 0 (off) for UDP_STREAM, 1 (on) otherwise\n\ 6948 -s send[,recv] Set local socket send/recv buffer sizes\n\ 6949 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 6950 -t type Explicitly set socket type. Default is implicit\n\ 6951 based on other settings\n\ 6952 -T protocol Explicitly set data connection protocol. Default is\n\ 6953 implicit based on other settings\n\ 6954 -u uuid Use the supplied string as the UUID for this test.\n\ 6955 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 6956 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 6957 \n\ 6958 For those options taking two parms, at least one must be specified;\n\ 6959 specifying one value without a comma will set both parms to that\n\ 6960 value, specifying a value with a leading comma will set just the second\n\ 6961 parm, a value with a trailing comma will set just the first. To set\n\ 6962 each parm to unique values, specify both and separate them with a\n\ 6963 comma.\n"; 6964 6965 void 6966 print_omni_usage() 6967 { 6968 6969 fwrite(omni_usage, sizeof(char), strlen(omni_usage), stdout); 6970 exit(1); 6971 6972 } 6973 6974 6975 void 6977 scan_omni_args(int argc, char *argv[]) 6978 6979 { 6980 6981 #define OMNI_ARGS "aBb:cCd:De:FgG:hH:i:Ij:kK:l:L:m:M:nNoOp:P:r:R:s:S:t:T:u:UVw:W:46" 6982 6983 extern char *optarg; /* pointer to option string */ 6984 6985 int c; 6986 int have_uuid = 0; 6987 int have_R_option = 0; 6988 6989 char 6990 arg1[BUFSIZ], /* argument holders */ 6991 arg2[BUFSIZ], 6992 arg3[BUFSIZ]; 6993 6994 if (debug) { 6995 int i; 6996 printf("%s called with the following argument vector\n", 6997 __FUNCTION__); 6998 for (i = 0; i< argc; i++) { 6999 printf("%s ",argv[i]); 7000 } 7001 printf("\n"); 7002 } 7003 7004 /* double-check struct sizes */ 7005 { 7006 const union netperf_request_struct * u = (const union netperf_request_struct *)0; 7007 if (debug) { 7008 fprintf(where, "sizeof(omni_request_struct)=%d/%d\n", 7009 (int)sizeof(struct omni_request_struct), 7010 (int)sizeof(u->content.test_specific_data)); 7011 fprintf(where, "sizeof(omni_response_struct)=%d/%d\n", 7012 (int)sizeof(struct omni_response_struct), 7013 (int)sizeof(u->content.test_specific_data)); 7014 fprintf(where, "sizeof(omni_results_struct)=%d/%d\n", 7015 (int)sizeof(struct omni_results_struct), 7016 (int)sizeof(u->content.test_specific_data)); 7017 } 7018 assert(sizeof(struct omni_request_struct) 7019 <= sizeof(u->content.test_specific_data)); 7020 assert(sizeof(struct omni_response_struct) 7021 <= sizeof(u->content.test_specific_data)); 7022 assert(sizeof(struct omni_results_struct) 7023 <= sizeof(u->content.test_specific_data)); 7024 } 7025 7026 strncpy(local_data_port,"0",sizeof(local_data_port)); 7027 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 7028 7029 /* this will handle setting default settings based on test name */ 7030 set_omni_defaults_by_legacy_testname(); 7031 7032 /* Go through all the command line arguments and break them out. For 7033 those options that take two parms, specifying only the first will 7034 set both to that value. Specifying only the second will leave the 7035 first untouched. To change only the first, use the form "first," 7036 (see the routine break_args.. */ 7037 7038 while ((c= getopt(argc, argv, OMNI_ARGS)) != EOF) { 7039 switch (c) { 7040 case '?': 7041 case '4': 7042 remote_data_family = AF_INET; 7043 local_data_family = AF_INET; 7044 break; 7045 case '6': 7046 #if defined(AF_INET6) 7047 remote_data_family = AF_INET6; 7048 local_data_family = AF_INET6; 7049 #else 7050 fprintf(stderr, 7051 "This netperf was not compiled on an IPv6 capable host!\n"); 7052 fflush(stderr); 7053 exit(-1); 7054 #endif 7055 break; 7056 case 'h': 7057 print_omni_usage(); 7058 exit(1); 7059 case 'a': 7060 want_defer_accept = 1; 7061 break; 7062 case 'B': 7063 want_use_pktinfo = 1; 7064 break; 7065 case 'b': 7066 #ifdef WANT_FIRST_BURST 7067 first_burst_size = atoi(optarg); 7068 #else /* WANT_FIRST_BURST */ 7069 printf("Initial request burst functionality not compiled-in!\n"); 7070 #endif /* WANT_FIRST_BURST */ 7071 break; 7072 case 'c': 7073 /* this is a connection test */ 7074 connection_test = 1; 7075 break; 7076 case 'C': 7077 #ifdef TCP_CORK 7078 /* set TCP_CORK */ 7079 loc_tcpcork = 1; 7080 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */ 7081 #else 7082 printf("WARNING: TCP_CORK not available on this platform!\n"); 7083 #endif /* TCP_CORK */ 7084 break; 7085 case 'd': 7086 /* arbitrarily set the direction variable, but only for an 7087 actual omni test and then disable implicit setting of 7088 direction */ 7089 if (!was_legacy) { 7090 direction = parse_direction(optarg); 7091 implicit_direction = 0; 7092 } 7093 break; 7094 case 'D': 7095 /* set the TCP nodelay flag */ 7096 loc_nodelay = 1; 7097 rem_nodelay = 1; 7098 break; 7099 case 'F': 7100 #if defined(MSG_FASTOPEN) 7101 use_fastopen = 1; 7102 #else 7103 printf("WARNING: TCP FASTOPEN not available on this platform!\n"); 7104 #endif 7105 break; 7106 case 'e': 7107 /* set the rEceive timeout */ 7108 receive_timeout = atoi(optarg); 7109 break; 7110 case 'g': 7111 /* enable SO_DEBUG, or at least make the attempt, on the data socket */ 7112 socket_debug = 1; 7113 break; 7114 case 'G': 7115 /* set the value for a tcp_maxseG call*/ 7116 transport_mss_req = atoi(optarg); 7117 break; 7118 case 'H': 7119 break_args_explicit_sep(optarg,',',arg1,arg2); 7120 if (arg1[0]) { 7121 /* check to see if there was a width, which we would want to 7122 be arg3. for simplicities sake, we will assume the width 7123 must follow the address and not the address family - ie 7124 1.2.3.4/24,inet. This means we can just pass optarg again 7125 as the source rather than have to shuffle arg values. */ 7126 break_args_explicit_sep(optarg,'/',arg1,arg3); 7127 if (arg1[0]) { 7128 remote_data_address = malloc(strlen(arg1)+1); 7129 strcpy(remote_data_address,arg1); 7130 explicit_data_address = 1; 7131 } 7132 if (arg3[0]) { 7133 remote_mask_len = convert(arg3); 7134 } 7135 } 7136 if (arg2[0]) { 7137 remote_data_family = parse_address_family(arg2); 7138 } 7139 break; 7140 case 'i': 7141 fprintf(stderr,"The support for check_interval has been removed because the contributing editor no longer knew what it was for\n"); 7142 fflush(stderr); 7143 break; 7144 case 'I': 7145 use_write = 1; 7146 break; 7147 case 'j': 7148 parallel_connections = atoi(optarg); 7149 break; 7150 case 'k': 7151 netperf_output_mode = KEYVAL; 7152 legacy = 0; 7153 /* obliterate any previous file name */ 7154 if (output_selection_spec) { 7155 free(output_selection_spec); 7156 output_selection_spec = NULL; 7157 } 7158 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7159 /* we assume that what follows is the name of a file with the 7160 list of desired output values. */ 7161 output_selection_spec = strdup(argv[optind]); 7162 optind++; 7163 /* special case - if the file name is "?" then we will emit a 7164 list of the available outputs */ 7165 if (strcmp(output_selection_spec,"?") == 0) { 7166 dump_netperf_output_choices(stdout,1); 7167 exit(1); 7168 } 7169 } 7170 break; 7171 case 'K': 7172 /* "Kongestion Kontrol */ 7173 break_args(optarg,arg1,arg2); 7174 if (arg1[0]) 7175 strncpy(local_cong_control_req,arg1,sizeof(local_cong_control_req)); 7176 if (arg2[2]) 7177 strncpy(remote_cong_control_req,arg2,sizeof(remote_cong_control_req)); 7178 break; 7179 case 'l': 7180 multicast_ttl = atoi(optarg); 7181 break; 7182 case 'L': 7183 break_args_explicit_sep(optarg,',',arg1,arg2); 7184 if (arg1[0]) { 7185 /* check to see if there was a width, which we would want to 7186 be arg3. for simplicities sake, we will assume the width 7187 must follow the address and not the address family - ie 7188 1.2.3.4/24,inet. This means we can just pass optarg again 7189 as the source rather than have to shuffle arg values. */ 7190 break_args_explicit_sep(optarg,'/',arg1,arg3); 7191 if (arg1[0]) { 7192 local_data_address = malloc(strlen(arg1)+1); 7193 strcpy(local_data_address,arg1); 7194 } 7195 if (arg3[0]) { 7196 local_mask_len = convert(arg3); 7197 } 7198 } 7199 if (arg2[0]) { 7200 local_data_family = parse_address_family(arg2); 7201 } 7202 break; 7203 case 'm': 7204 /* set the send size. if we set the local send size it will add 7205 XMIT to direction. if we set the remote send size it will 7206 add RECV to the direction. likely as not this will need some 7207 additional throught */ 7208 break_args_explicit(optarg,arg1,arg2); 7209 if (arg1[0]) { 7210 send_size = convert(arg1); 7211 if (implicit_direction) 7212 direction |= NETPERF_XMIT; 7213 } 7214 if (arg2[0]) { 7215 remote_send_size_req = convert(arg2); 7216 if (implicit_direction) 7217 direction |= NETPERF_RECV; 7218 } 7219 break; 7220 case 'M': 7221 /* set the recv sizes. if we set the local recv size it will 7222 add RECV to direction. if we set the remote recv size it 7223 will add XMIT to direction */ 7224 break_args_explicit(optarg,arg1,arg2); 7225 if (arg1[0]) { 7226 remote_recv_size_req = convert(arg1); 7227 if (implicit_direction) 7228 direction |= NETPERF_XMIT; 7229 } 7230 if (arg2[0]) { 7231 recv_size = convert(arg2); 7232 if (implicit_direction) 7233 direction |= NETPERF_RECV; 7234 } 7235 break; 7236 case 'n': 7237 /* set the local socket type */ 7238 local_connected = 1; 7239 break; 7240 case 'N': 7241 /* set the remote socket type */ 7242 remote_connected = 1; 7243 break; 7244 case 'o': 7245 netperf_output_mode = CSV; 7246 legacy = 0; 7247 /* obliterate any previous file name */ 7248 if (output_selection_spec) { 7249 free(output_selection_spec); 7250 output_selection_spec = NULL; 7251 } 7252 if (output_selection_spec) { 7253 free(output_selection_spec); 7254 output_selection_spec = NULL; 7255 } 7256 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7257 /* we assume that what follows is the name of a file with the 7258 list of desired output values. */ 7259 output_selection_spec = strdup(argv[optind]); 7260 optind++; 7261 /* special case - if the file name is "?" then we will emit a 7262 list of the available outputs */ 7263 if (strcmp(output_selection_spec,"?") == 0) { 7264 dump_netperf_output_choices(stdout,1); 7265 exit(1); 7266 } 7267 } 7268 break; 7269 case 'O': 7270 netperf_output_mode = HUMAN; 7271 legacy = 0; 7272 /* obliterate any previous file name */ 7273 if (output_selection_spec) { 7274 free(output_selection_spec); 7275 output_selection_spec = NULL; 7276 } 7277 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7278 /* we assume that what follows is the name of a file with the 7279 list of desired output values */ 7280 output_selection_spec = strdup(argv[optind]); 7281 optind++; 7282 if (strcmp(output_selection_spec,"?") == 0) { 7283 dump_netperf_output_choices(stdout,0); 7284 exit(1); 7285 } 7286 } 7287 break; 7288 case 'p': 7289 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */ 7290 /* tests. */ 7291 break_args(optarg,arg1,arg2); 7292 if (arg1[0]) 7293 client_port_min = atoi(arg1); 7294 if (arg2[0]) 7295 client_port_max = atoi(arg2); 7296 break; 7297 case 'P': 7298 /* set the local and remote data port numbers for the tests to 7299 allow them to run through those blankety blank end-to-end 7300 breaking firewalls. raj 2004-06-15 */ 7301 break_args(optarg,arg1,arg2); 7302 if (arg1[0]) 7303 strncpy(local_data_port,arg1,sizeof(local_data_port)); 7304 if (arg2[0]) 7305 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 7306 break; 7307 case 'r': 7308 /* set the request/response sizes. setting request/response 7309 sizes implicitly sets direction to XMIT and RECV */ 7310 if (implicit_direction) { 7311 direction |= NETPERF_XMIT; 7312 direction |= NETPERF_RECV; 7313 } 7314 break_args(optarg,arg1,arg2); 7315 if (arg1[0]) 7316 req_size = convert(arg1); 7317 if (arg2[0]) 7318 rsp_size = convert(arg2); 7319 break; 7320 case 'R': 7321 routing_allowed = atoi(optarg); 7322 have_R_option = 1; 7323 break; 7324 case 's': 7325 /* set local socket sizes */ 7326 break_args(optarg,arg1,arg2); 7327 if (arg1[0]) 7328 lss_size_req = convert(arg1); 7329 if (arg2[0]) 7330 lsr_size_req = convert(arg2); 7331 break; 7332 case 'S': 7333 /* set remote socket sizes */ 7334 break_args(optarg,arg1,arg2); 7335 if (arg1[0]) 7336 rss_size_req = convert(arg1); 7337 if (arg2[0]) 7338 rsr_size_req = convert(arg2); 7339 break; 7340 case 't': 7341 /* set the socket type */ 7342 socket_type = parse_socket_type(optarg); 7343 break; 7344 case 'T': 7345 /* set the protocol - aka "Transport" */ 7346 protocol = parse_protocol(optarg); 7347 break; 7348 case 'u': 7349 /* use the supplied string as the UUID for this test. at some 7350 point we may want to sanity check the string we are given but 7351 for now we won't worry about it */ 7352 strncpy(test_uuid,optarg,sizeof(test_uuid)); 7353 /* strncpy may leave us with a string without a null at the end */ 7354 test_uuid[sizeof(test_uuid) - 1] = 0; 7355 have_uuid = 1; 7356 break; 7357 case 'U': 7358 /* we don't want to give-up on the failure of a connect() call */ 7359 dont_give_up = 1; 7360 break; 7361 case 'W': 7362 /* set the "width" of the user space data */ 7363 /* buffer. This will be the number of */ 7364 /* send_size buffers malloc'd in the */ 7365 /* *_STREAM test. It may be enhanced to set */ 7366 /* both send and receive "widths" but for now */ 7367 /* it is just the sending *_STREAM. */ 7368 send_width = convert(optarg); 7369 break; 7370 case 'V' : 7371 /* we want to do copy avoidance and will set */ 7372 /* it for everything, everywhere, if we really */ 7373 /* can. of course, we don't know anything */ 7374 /* about the remote... */ 7375 loc_sndavoid = 1; 7376 loc_rcvavoid = 1; 7377 rem_sndavoid = 1; 7378 rem_rcvavoid = 1; 7379 break; 7380 }; 7381 } 7382 7383 /* generate the UUID for this test if the user has not supplied it */ 7384 if (!have_uuid) 7385 get_uuid_string(test_uuid,sizeof(test_uuid)); 7386 7387 protocol_str = protocol_to_str(protocol); 7388 /* ok, if we have gone through all that, and direction is still 7389 zero, let us see if it needs to be set to something else. */ 7390 if ((0 == direction) && (!connection_test)) direction = NETPERF_XMIT; 7391 direction_str = direction_to_str(direction); 7392 7393 /* to cover the backside of blithering idiots who run unidirectional 7394 UDP tests on test setups where they might trash their corporate 7395 WAN, we grudgingly provide a safety latch. unless explicitly 7396 enabled, UDP_STREAM/UDP_MAERTS sockets will not allow themselves 7397 to be routed via a gateway. raj 20091026 */ 7398 7399 if ((!have_R_option) && 7400 (protocol == IPPROTO_UDP) && 7401 (!NETPERF_IS_RR(direction))) { 7402 routing_allowed = 0; 7403 } 7404 7405 /* some other sanity checks we need to make would include stuff when 7406 the user has set -m and -M such that both XMIT and RECV are set 7407 and has not set -r. initially we will not allow that. at some 7408 point we might allow that if the user has also set -r, but until 7409 then the code will simply ignore the values from -m and -M when 7410 -r is set. */ 7411 7412 #if defined(WANT_HISTOGRAM) 7413 if (verbosity > 1) keep_histogram = 1; 7414 #endif 7415 7416 /* did the user use -d 6 but not set -r? */ 7417 if (NETPERF_IS_RR(direction) && !NETPERF_CC(direction)) { 7418 if (req_size == -1) 7419 req_size = 1; 7420 if (rsp_size == -1) 7421 rsp_size = 1; 7422 } 7423 7424 /* ok, time to sanity check the output units */ 7425 if ('?' == libfmt) { 7426 /* if this is a RR test then set it to 'x' for transactions */ 7427 if (NETPERF_IS_RR(direction)) { 7428 libfmt = 'x'; 7429 } 7430 else { 7431 libfmt = 'm'; 7432 } 7433 } 7434 else if ('x' == libfmt) { 7435 /* now, a format of 'x' makes no sense for anything other than 7436 an RR test. if someone has been silly enough to try to set 7437 that, we will reset it silently to default - namely 'm' */ 7438 if (!NETPERF_IS_RR(direction)) { 7439 libfmt = 'm'; 7440 } 7441 } 7442 7443 /* this needs to be strdup :) */ 7444 thruput_format_str = strdup(format_units()); 7445 7446 /* so, if there is to be no control connection, we want to have some 7447 different settings for a few things */ 7448 7449 if (no_control) { 7450 if (strcmp(remote_data_port,"0") == 0) { 7451 /* we need to select either the discard port, echo port or 7452 chargen port dedepending on the test direction. raj 7453 20101220 */ 7454 if (NETPERF_XMIT_ONLY(direction)) { 7455 strncpy(remote_data_port,"discard",sizeof(remote_data_port)); 7456 recv_size = -1; 7457 } 7458 else if (NETPERF_RECV_ONLY(direction)) { 7459 strncpy(remote_data_port,"chargen",sizeof(remote_data_port)); 7460 send_size = -1; 7461 } 7462 else if (NETPERF_IS_RR(direction) || NETPERF_CC(direction)) { 7463 strncpy(remote_data_port,"echo",sizeof(remote_data_port)); 7464 rsp_size = req_size; 7465 } 7466 else { 7467 printf("No default port known for the %s test, please set one yourself\n",test_name); 7468 exit(-1); 7469 } 7470 } 7471 remote_data_port[sizeof(remote_data_port) - 1] = '\0'; 7472 7473 /* I go back and forth on whether these should become -1 or if 7474 they should become 0 for a no_control test. what do you think? 7475 raj 2006-02-08 */ 7476 7477 rem_rcvavoid = -1; 7478 rem_sndavoid = -1; 7479 rss_size_req = -1; 7480 rsr_size_req = -1; 7481 rem_nodelay = -1; 7482 7483 } 7484 /* so, did the user request a few things implicitly via output selection? */ 7485 if (!legacy) 7486 print_omni_init(); 7487 7488 if (desired_output_groups & OMNI_WANT_STATS) { 7489 keep_statistics = 1; 7490 keep_histogram = 1; 7491 } 7492 7493 } 7494 7495 #endif /* WANT_OMNI */ 7496