1#ifdef HAVE_CONFIG_H 2#include <config.h> 3#endif 4 5#ifdef WANT_OMNI 6char 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 158static HIST time_hist; 159 160 161 162#ifdef WANT_INTERVALS 163int interval_count; 164unsigned 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 170static hrtime_t intvl_one; 171static hrtime_t intvl_two; 172static hrtime_t intvl_wait_start; 173static hrtime_t *intvl_one_ptr = &intvl_one; 174static hrtime_t *intvl_two_ptr = &intvl_two; 175static hrtime_t *temp_intvl_ptr = &intvl_one; 176#elif defined(WIN32) 177static LARGE_INTEGER intvl_one; 178static LARGE_INTEGER intvl_two; 179static LARGE_INTEGER intvl_wait_start; 180static LARGE_INTEGER *intvl_one_ptr = &intvl_one; 181static LARGE_INTEGER *intvl_two_ptr = &intvl_two; 182static LARGE_INTEGER *temp_intvl_ptr = &intvl_one; 183#else 184static struct timeval intvl_one; 185static struct timeval intvl_two; 186static struct timeval intvl_wait_start; 187static struct timeval *intvl_one_ptr = &intvl_one; 188static struct timeval *intvl_two_ptr = &intvl_two; 189static 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 205sigset_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 310extern void get_uuid_string(char *string, size_t size); 311 312/* a boatload of globals while I settle things out */ 313char *output_selection_spec = NULL; 314 315char test_uuid[38]; 316 317double result_confid_pct = -1.0; 318double loc_cpu_confid_pct = -1.0; 319double rem_cpu_confid_pct = -1.0; 320double interval_pct = -1.0; 321 322int protocol; 323int direction; 324int remote_send_size = -1; 325int remote_recv_size = -1; 326int remote_send_size_req = -1; 327int remote_recv_size_req = -1; 328int remote_use_sendfile; 329 330extern int loc_dirty_count; 331extern int loc_clean_count; 332extern int rem_dirty_count; 333extern int rem_clean_count; 334int remote_checksum_off; 335int connection_test; 336int dont_give_up = 0; 337int use_fastopen = 0; 338int use_write = 0; 339int need_to_connect; 340int need_connection; 341int bytes_to_send; 342double bytes_per_send; 343int failed_sends; 344int bytes_to_recv; 345double bytes_per_recv; 346int null_message_ok = 0; 347 348int was_legacy = 0; 349int legacy = 0; 350int implicit_direction = 0; 351int explicit_data_address = 0; 352int want_defer_accept = 0; 353 354uint64_t trans_completed = 0; 355int64_t units_remaining; 356uint64_t bytes_sent = 0; 357uint64_t bytes_received = 0; 358uint64_t local_send_calls = 0; 359uint64_t local_receive_calls = 0; 360uint64_t remote_bytes_sent; 361uint64_t remote_bytes_received; 362uint64_t remote_send_calls; 363uint64_t remote_receive_calls; 364double bytes_xferd; 365double remote_bytes_xferd; 366double remote_bytes_per_recv; 367double remote_bytes_per_send; 368float elapsed_time; 369float local_cpu_utilization; 370float local_service_demand; 371float remote_cpu_utilization; 372float remote_service_demand; 373double thruput; 374double local_send_thruput; 375double local_recv_thruput; 376double remote_send_thruput; 377double remote_recv_thruput; 378 379/* kludges for omni output */ 380double elapsed_time_double; 381double local_service_demand_double; 382double remote_service_demand_double; 383double transaction_rate = 1.0; 384double rtt_latency = -1.0; 385int32_t transport_mss = -2; 386int32_t local_transport_retrans = -2; 387int32_t remote_transport_retrans = -2; 388char *deprecated_str = "Deprecated"; 389int remote_interface_vendor = -2; 390int remote_interface_device = -2; 391int remote_interface_subvendor = -2; 392int remote_interface_subdevice = -2; 393int local_interface_vendor = -2; 394int local_interface_device = -2; 395int local_interface_subvendor = -2; 396int local_interface_subdevice = -2; 397int local_cpu_frequency = 0; 398int remote_cpu_frequency = 0; 399 400int local_security_type_id; 401int local_security_enabled_num; 402int remote_security_type_id; 403int remote_security_enabled_num; 404 405char local_cong_control[16] = ""; 406char remote_cong_control[16] = ""; 407char local_cong_control_req[16] = ""; 408char remote_cong_control_req[16] = ""; 409 410int 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" */ 417int min_latency = -1, max_latency = -1; 418/* the percentiles */ 419int 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 */ 422double mean_latency = -1.0, stddev_latency = -1.0; 423 424/* default to zero to avoid randomizing */ 425int local_mask_len = 0; 426int remote_mask_len = 0; 427 428int printing_initialized = 0; 429 430char *sd_str; 431char *thruput_format_str; 432 433char *socket_type_str; 434char *protocol_str; 435char *direction_str; 436 437extern int first_burst_size; 438 439int parallel_connections = 1; 440 441static 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 447static int confidence_iteration; 448 449static int local_cpu_method; 450static 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 */ 454static int client_port_min = 5000; 455static int client_port_max = 65535; 456 457 /* different options for the sockets */ 458 459int 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 467extern int 468 loc_tcpcork, 469 rem_tcpcork, 470 local_connected, 471 remote_connected; 472 473enum 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 487enum 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 682unsigned int desired_output_groups = 0; 683 684typedef 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 696netperf_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 704enum 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 710int want_use_pktinfo = 0; 711int use_pktinfo = 0; 712int have_pktinfo = 0; 713#ifdef IP_PKTINFO 714struct in_pktinfo in_pktinfo; 715#endif 716 717char *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 727static unsigned short 728get_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 */ 754static int 755is_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 781static void 782set_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 */ 815static void 816join_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 888static void 889extract_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 912void 913pick_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 */ 965char * 966netperf_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 1324void 1325print_netperf_output_entry(FILE *where, enum netperf_output_name what) 1326{ 1327} 1328 1329void print_omni_init_list(); 1330 1331void 1332dump_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 1346void 1347dump_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 1364void 1365dump_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 1411enum netperf_output_name 1412match_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 1422enum netperf_output_name 1423match_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 1468void 1469set_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 1508void 1509parse_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 1579void 1580parse_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 1639void 1640parse_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 1705void 1706set_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 1755void 1756parse_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 1786static void 1787set_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 1809void 1810print_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 2400void 2401print_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... */ 2442int 2443my_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 2490void 2491print_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 2609void 2610print_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 2645void 2646print_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 2775void 2776print_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 2810int 2811connect_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 2841static 2842int 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 2876int 2877send_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) 2967static int 2968recv_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 3082static 3083int 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 3136int 3137recv_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 3252int 3253close_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 3308int 3309disconnect_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 3392static void 3393dump_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 3416static int 3417get_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 3457static void 3458get_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 3497static void 3498get_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 3516static void 3517set_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 3527static void 3528set_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 3549static SOCKET 3550omni_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 3585static int 3586choose_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 3610void 3611print_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 */ 3626static void 3627enable_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 3645void 3646set_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 3701void 3702send_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 4940void 4941send_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? */ 4952const char * 4953inet_ntop(int af, const void *src, char *dst, size_t size); 4954#endif 4955#endif 4956 4957static void 4958set_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 4969/* the name is something of a misnomer since this test could send, or 4970 receive, or both, but it matches the historical netperf routine 4971 naming convention for what runs in the netserver context. */ 4972void 4973recv_omni() 4974{ 4975 4976 struct addrinfo *local_res; 4977 char local_name[BUFSIZ]; 4978 char port_buffer[PORTBUFSIZE]; 4979 4980 struct sockaddr_storage myaddr_in, peeraddr_in; 4981 int peeraddr_set = 0; 4982 SOCKET s_listen, data_socket; 4983 netperf_socklen_t addrlen; 4984 4985 struct ring_elt *send_ring; 4986 struct ring_elt *recv_ring; 4987 4988 int timed_out = 0; 4989 int pad_time = 0; 4990 int need_to_connect = 0; 4991 int need_to_accept; 4992 int connected; 4993 int ret; 4994 uint32_t temp_recvs; 4995 4996 struct omni_request_struct *omni_request; 4997 struct omni_response_struct *omni_response; 4998 struct omni_results_struct *omni_results; 4999 5000 omni_request = 5001 (struct omni_request_struct *)netperf_request.content.test_specific_data; 5002 omni_response = 5003 (struct omni_response_struct *)netperf_response.content.test_specific_data; 5004 omni_results = 5005 (struct omni_results_struct *)netperf_response.content.test_specific_data; 5006 5007 if (debug) { 5008 fprintf(where,"netserver: %s: entered...\n",__FUNCTION__); 5009 fflush(where); 5010 } 5011 5012 /* netserver has no good way of knowing where the conversion cutoff 5013 point is, so we have to fix it after the fact */ 5014 fixup_request_n(OMNI_REQUEST_CONV_CUTOFF); 5015 5016 /* thus fixed-up, we can extract the requested congestion control 5017 algorithm */ 5018 strncpy(local_cong_control_req, 5019 omni_request->cong_control, 5020 sizeof(local_cong_control_req)); 5021 5022 /* based on what we have been told by the remote netperf, we want to 5023 setup our endpoint for the "data connection" and let the remote 5024 netperf know the situation. */ 5025 5026 if (debug) { 5027 fprintf(where,"%s: setting the response type...\n",__FUNCTION__); 5028 fflush(where); 5029 } 5030 5031 netperf_response.content.response_type = OMNI_RESPONSE; 5032 5033 if (debug) { 5034 fprintf(where,"%s: the response type is set...\n",__FUNCTION__); 5035 fflush(where); 5036 } 5037 5038 /* Grab a socket to listen on, and then listen on it. */ 5039 5040 if (debug) { 5041 fprintf(where,"%s: grabbing a socket...\n",__FUNCTION__); 5042 fflush(where); 5043 } 5044 5045 /* create_data_socket expects to find some things in the global 5046 variables, so set the globals based on the values in the request. 5047 once the socket has been created, we will set the response values 5048 based on the updated value of those globals. raj 7/94 */ 5049 lss_size_req = omni_request->send_buf_size; 5050 lsr_size_req = omni_request->recv_buf_size; 5051 loc_nodelay = (omni_request->flags) & OMNI_NO_DELAY; 5052 loc_rcvavoid = omni_request->so_rcvavoid; 5053 loc_sndavoid = omni_request->so_sndavoid; 5054 routing_allowed = (omni_request->flags) & OMNI_ROUTING_ALLOWED; 5055 want_keepalive = (omni_request->flags) & OMNI_WANT_KEEPALIVE; 5056 local_socket_prio = omni_request->socket_prio; 5057 local_socket_tos = omni_request->socket_tos; 5058 want_defer_accept = omni_request->flags & OMNI_WANT_DEFER_ACCEPT; 5059 5060#ifdef WANT_INTERVALS 5061 interval_usecs = omni_request->interval_usecs; 5062 interval_wate = interval_usecs / 1000; 5063 interval_burst = omni_request->interval_burst; 5064#else 5065 interval_usecs = 0; 5066 interval_wate = 1; 5067 interval_burst = 0; 5068#endif 5069 5070 connection_test = omni_request->flags & OMNI_CONNECT_TEST; 5071#ifdef TCP_FASTOPEN 5072 use_fastopen = omni_request->flags & OMNI_FASTOPEN; 5073#endif 5074 direction = omni_request->direction; 5075 use_pktinfo = (omni_request->flags) & OMNI_USE_PKTINFO; 5076 5077 /* let's be quite certain the fill file string is null terminated */ 5078 omni_request->fill_file[sizeof(omni_request->fill_file) - 1] = '\0'; 5079 strncpy(local_fill_file, 5080 omni_request->fill_file, 5081 sizeof(local_fill_file)); 5082 5083 /* kludgy, because I have no way at present to say how many bytes 5084 needed to be swapped around for the request from which this is 5085 pulled, and it is probably all wrong for IPv6 :( */ 5086 switch (nf_to_af(omni_request->ipfamily)) { 5087 case AF_INET6: 5088 /* yes indeed it is, do nothing, bz */ 5089 break; 5090 case AF_INET: 5091 default: 5092 for (ret=0; ret < 4; ret++) { 5093 omni_request->netserver_ip[ret] = htonl(omni_request->netserver_ip[ret]); 5094 omni_request->netperf_ip[ret] = htonl(omni_request->netperf_ip[ret]); 5095 } 5096 break; 5097 } 5098 5099 set_hostname_and_port_2(omni_request->netserver_ip, 5100 local_name, 5101 port_buffer, 5102 nf_to_af(omni_request->ipfamily), 5103 omni_request->data_port); 5104 5105 local_res = complete_addrinfo(local_name, 5106 local_name, 5107 port_buffer, 5108 nf_to_af(omni_request->ipfamily), 5109 nst_to_hst(omni_request->socket_type), 5110 omni_request->protocol, 5111 0); 5112 5113 s_listen = omni_create_data_socket(local_res); 5114 5115 if (s_listen == INVALID_SOCKET) { 5116 netperf_response.content.serv_errno = errno; 5117 send_response(); 5118 if (debug) { 5119 fprintf(where,"could not create data socket\n"); 5120 fflush(where); 5121 } 5122 exit(-1); 5123 } 5124 5125 /* We now alter the message_ptr variables to be at the desired */ 5126 /* alignments with the desired offsets. */ 5127 5128 if (debug) { 5129 fprintf(where, 5130 "recv_omni: requested recv alignment of %d offset %d\n" 5131 "recv_omni: requested send alignment of %d offset %d\n", 5132 omni_request->recv_alignment, 5133 omni_request->recv_offset, 5134 omni_request->send_alignment, 5135 omni_request->send_offset); 5136 fflush(where); 5137 } 5138 5139 omni_response->send_size = omni_request->send_size; 5140 omni_response->send_width = omni_request->send_width; 5141 omni_response->socket_prio = local_socket_prio; 5142 omni_response->socket_tos = local_socket_tos; 5143 5144 if (omni_request->direction & NETPERF_XMIT) { 5145#ifdef fo 5146 /* do we need to set multicast ttl? */ 5147 if (is_multicast_addr(remote_res)) { 5148 /* yes, s_listen - for a UDP test we will be copying it to 5149 data_socket but that hasn't happened yet. raj 20100315 */ 5150 set_multicast_ttl(s_listen); 5151 } 5152#endif 5153 5154 if (omni_request->response_size > 0) { 5155 /* request/response_test */ 5156 bytes_to_send = omni_request->response_size; 5157 if (omni_request->send_width == 0) send_width = 1; 5158 else send_width = omni_request->send_width; 5159 } 5160 else { 5161 if (omni_request->send_size == -1) { 5162 bytes_to_send = choose_send_size(lss_size,omni_request->protocol); 5163 } 5164 else bytes_to_send = omni_request->send_size; 5165 /* set the send_width */ 5166 if (omni_request->send_width == 0) { 5167 send_width = (lss_size/bytes_to_send) + 1; 5168 if (send_width == 1) send_width++; 5169 } 5170 else 5171 send_width = omni_request->send_width; 5172 } 5173 send_ring = allocate_buffer_ring(send_width, 5174 bytes_to_send, 5175 omni_request->send_alignment, 5176 omni_request->send_offset); 5177 5178 omni_response->send_width = send_width; 5179 omni_response->send_size = bytes_to_send; 5180 } 5181 5182 omni_response->receive_size = omni_request->receive_size; 5183 omni_response->recv_width = omni_request->recv_width; 5184 if (omni_request->direction & NETPERF_RECV) { 5185 5186 /* do we need to join a multicast group? */ 5187 if (is_multicast_addr(local_res)) { 5188 /* yes, s_listen - for a UDP test we will be copying it to 5189 data_socket but that hasn't happened yet. raj 20100315 */ 5190 join_multicast_addr(s_listen, local_res); 5191 } 5192 5193 if (omni_request->request_size > 0) { 5194 /* request/response test */ 5195 bytes_to_recv = omni_request->request_size; 5196 if (omni_request->recv_width == 0) recv_width = 1; 5197 else recv_width = omni_request->recv_width; 5198 } 5199 else { 5200 if (omni_request->receive_size == -1) { 5201 if (lsr_size > 0) bytes_to_recv = lsr_size; 5202 else bytes_to_recv = 4096; 5203 } 5204 else { 5205 bytes_to_recv = omni_request->receive_size; 5206 } 5207 /* set the recv_width */ 5208 if (omni_request->recv_width == 0) { 5209 recv_width = (lsr_size/bytes_to_recv) + 1; 5210 if (recv_width == 1) recv_width++; 5211 } 5212 else 5213 recv_width = omni_request->recv_width; 5214 } 5215 recv_ring = allocate_buffer_ring(recv_width, 5216 bytes_to_recv, 5217 omni_request->recv_alignment, 5218 omni_request->recv_offset); 5219 5220 omni_response->receive_size = bytes_to_recv; 5221 omni_response->recv_width = recv_width; 5222 } 5223 5224#ifdef WIN32 5225 /* The test timer can fire during operations on the listening socket, 5226 so to make the start_timer below work we have to move 5227 it to close s_listen while we are blocked on accept. */ 5228 win_kludge_socket2 = s_listen; 5229#endif 5230 5231 need_to_accept = (omni_request->protocol != IPPROTO_UDP); 5232 5233 /* we need to hang a listen for everything that needs at least one 5234 accept. the age-old constant of 5 is probably OK for our purposes 5235 but does not necessarily represent best practice */ 5236 if (need_to_accept) { 5237 int backlog = 5; 5238#ifdef TCP_FASTOPEN 5239 /* one of these days I will have to go find-out what the backlog 5240 is supposed to be here. until then, I'll just set it to five 5241 like the listen() call does - it is classic, and was what was 5242 used in the online example I found */ 5243 if (use_fastopen && 5244 (setsockopt(s_listen,IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog)) == 5245 SOCKET_ERROR)) { 5246 netperf_response.content.serv_errno = errno; 5247 close(s_listen); 5248 send_response(); 5249 if (debug) { 5250 fprintf(where,"netperfserver: %s could not fastopen\n",__FUNCTION__); 5251 fflush(where); 5252 } 5253 exit(1); 5254 } 5255#endif /* TCP_FASTOPEN */ 5256#ifdef TCP_DEFER_ACCEPT 5257 if (want_defer_accept && 5258 (setsockopt(s_listen, IPPROTO_TCP, TCP_DEFER_ACCEPT, &backlog, sizeof(backlog)) == SOCKET_ERROR)) { 5259 netperf_response.content.serv_errno = errno; 5260 close(s_listen); 5261 send_response(); 5262 if (debug) { 5263 fprintf(where, 5264 "netperfserver: %s could not defer accept\n",__FUNCTION__); 5265 fflush(where); 5266 } 5267 exit(1); 5268 } 5269#endif /* TCP_DEFER_ACCEPT */ 5270 if (listen(s_listen, backlog) == SOCKET_ERROR) { 5271 netperf_response.content.serv_errno = errno; 5272 close(s_listen); 5273 send_response(); 5274 if (debug) { 5275 fprintf(where,"netperfserver: %s could not listen\n",__FUNCTION__); 5276 fflush(where); 5277 } 5278 exit(1); 5279 } 5280 } 5281 5282 /* now get the port number assigned by the system */ 5283 addrlen = sizeof(myaddr_in); 5284 if (getsockname(s_listen, 5285 (struct sockaddr *)&myaddr_in, 5286 &addrlen) == SOCKET_ERROR){ 5287 netperf_response.content.serv_errno = errno; 5288 close(s_listen); 5289 send_response(); 5290 if (debug) { 5291 fprintf(where,"could not getsockname\n"); 5292 fflush(where); 5293 } 5294 exit(-1); 5295 } 5296 5297 /* Now myaddr_in contains the port and the internet address this is 5298 returned to the sender also implicitly telling the sender that 5299 the socket buffer sizing has been done. likely as not, the IP 5300 address will be the wildcard - so we only really need to extract 5301 the port number. since send_response is going to call htonl on 5302 all the fields, we want to initially put the port number in there 5303 in host order. */ 5304 5305 omni_response->data_port = 5306 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 5307 if (debug) { 5308 fprintf(where,"telling the remote to call me at %d\n", 5309 omni_response->data_port); 5310 fflush(where); 5311 } 5312 netperf_response.content.serv_errno = 0; 5313 5314 /* But wait, there's more. If the initiator wanted cpu measurements, */ 5315 /* then we must call the calibrate routine, which will return the max */ 5316 /* rate back to the initiator. If the CPU was not to be measured, or */ 5317 /* something went wrong with the calibration, we will return a 0.0 to */ 5318 /* the initiator. */ 5319 5320 omni_response->cpu_rate = (float)0.0; /* assume no cpu */ 5321 omni_response->flags &= ~OMNI_MEASURE_CPU; 5322 if (omni_request->flags & OMNI_MEASURE_CPU) { 5323 omni_response->flags |= OMNI_MEASURE_CPU; 5324 omni_response->cpu_rate = 5325 calibrate_local_cpu(omni_request->cpu_rate); 5326 } 5327 5328 /* before we send the response back to the initiator, pull some of */ 5329 /* the socket parms from the globals */ 5330 omni_response->send_buf_size = lss_size; 5331 omni_response->recv_buf_size = lsr_size; 5332 if (loc_nodelay) 5333 omni_response->flags |= OMNI_NO_DELAY; 5334 else 5335 omni_response->flags &= ~OMNI_NO_DELAY; 5336 5337 omni_response->so_rcvavoid = loc_rcvavoid; 5338 omni_response->so_sndavoid = loc_sndavoid; 5339 omni_response->interval_usecs = interval_usecs; 5340 omni_response->interval_burst = interval_burst; 5341 5342 send_response_n(OMNI_RESPONSE_CONV_CUTOFF); /* brittle, but functional */ 5343 5344 local_send_calls = 0; 5345 local_receive_calls = 0; 5346 5347 addrlen = sizeof(peeraddr_in); 5348 memset(&peeraddr_in,0,sizeof(peeraddr_in)); 5349 5350 /* Now it's time to start receiving data on the connection. We will */ 5351 /* first grab the apropriate counters and then start grabbing. */ 5352 5353 cpu_start(omni_request->flags & OMNI_MEASURE_CPU); 5354 5355 /* if the test is timed, set a timer of suitable length. if the 5356 test is by byte/transaction count, we don't need a timer - or 5357 rather we rely on the netperf to only ask us to do transaction 5358 counts over "reliable" protocols. perhaps at some point we 5359 should add a check herebouts to verify that... */ 5360 5361 if (omni_request->test_length >= 0) { 5362 times_up = 0; 5363 units_remaining = 0; 5364 test_time=omni_request->test_length; 5365 /* if we are the sender and only sending, then we don't need/want 5366 the padding, otherwise, we need the padding */ 5367 if (!(NETPERF_XMIT_ONLY(omni_request->direction)) && 5368 (omni_request->test_length > 0)) 5369 pad_time = PAD_TIME; 5370 start_timer(omni_request->test_length + pad_time); 5371 } 5372 else { 5373 times_up = 1; 5374 units_remaining = omni_request->test_length * -1; 5375 } 5376 5377#if defined(WANT_INTERVALS) 5378 INTERVALS_INIT(); 5379#endif /* WANT_INTERVALS */ 5380 5381 5382 trans_completed = 0; 5383 bytes_sent = 0; 5384 bytes_received = 0; 5385 connected = 0; 5386 5387 while ((!times_up) || (units_remaining > 0)) { 5388 5389 if (need_to_accept) { 5390 /* accept a connection from the remote */ 5391#ifdef WIN32 5392 /* The test timer will probably fire during this accept, 5393 so to make the start_timer above work we have to move 5394 it to close s_listen while we are blocked on accept. */ 5395 win_kludge_socket = s_listen; 5396#endif 5397 if ((data_socket=accept(s_listen, 5398 (struct sockaddr *)&peeraddr_in, 5399 &addrlen)) == INVALID_SOCKET) { 5400 if (errno == EINTR) { 5401 /* the timer popped */ 5402 times_up = 1; /* ostensibly the signal hander dealt with this?*/ 5403 timed_out = 1; 5404 break; 5405 } 5406 netperf_response.content.serv_errno = errno; 5407 send_response(); 5408 fprintf(where,"%s: accept: errno = %d\n",__FUNCTION__,errno); 5409 fflush(where); 5410 close(s_listen); 5411 5412 exit(-1); 5413 } 5414 5415 if (debug) { 5416 fprintf(where,"%s: accepted data connection.\n",__FUNCTION__); 5417 fflush(where); 5418 } 5419 need_to_accept = 0; 5420 connected = 1; 5421 5422#ifdef KLUDGE_SOCKET_OPTIONS 5423 /* this is for those systems which *INCORRECTLY* fail to pass 5424 attributes across an accept() call. Including this goes 5425 against my better judgement :( raj 11/95 */ 5426 5427 kludge_socket_options(data_socket); 5428 5429#endif /* KLUDGE_SOCKET_OPTIONS */ 5430 5431 } 5432 else { 5433 /* I wonder if duping would be better here? we also need to set 5434 peeraddr_in so we can send to netperf if this isn't a 5435 request/response test or if we are going to connect() the 5436 socket, but we only need to do it once. */ 5437 if ((omni_request->protocol == IPPROTO_UDP) && 5438 (!peeraddr_set)) { 5439 peeraddr_set = 1; 5440 data_socket = s_listen; 5441 set_sockaddr_family_addr_port(&peeraddr_in, 5442 nf_to_af(omni_request->ipfamily), 5443 omni_request->netperf_ip, 5444 omni_request->netperf_port); 5445 } 5446 } 5447 5448#ifdef WIN32 5449 /* this is used so the timer thread can close the socket out from 5450 under us, which to date is the easiest/cleanest/least 5451 Windows-specific way I can find to force the winsock calls to 5452 return WSAEINTR with the test is over. anything that will run on 5453 95 and NT and is closer to what netperf expects from Unix signals 5454 and such would be appreciated raj 1/96 */ 5455 win_kludge_socket = data_socket; 5456#endif /* WIN32 */ 5457 5458 /* in recv_omni, we check recv first, and _then_ send, otherwise, 5459 a request/response test will be all messed-up :) and that then 5460 is why there are two routines to rule them all rather than just 5461 one :) */ 5462 if ((omni_request->direction & NETPERF_RECV) && 5463 ((!times_up) || (units_remaining > 0))) { 5464 ret = recv_data(data_socket, 5465 recv_ring, 5466 bytes_to_recv, 5467 (connected) ? NULL : (struct sockaddr *)&peeraddr_in, 5468 &addrlen, 5469 /* if XMIT also, then this is RR test so waitall */ 5470 (direction & NETPERF_XMIT) ? NETPERF_WAITALL: 0, 5471 &temp_recvs); 5472 if (ret > 0) { 5473 /* if this is a recv-only test controlled by byte count we 5474 decrement the units_remaining by the bytes received */ 5475 if (!(direction & NETPERF_XMIT) && (units_remaining > 0)) { 5476 units_remaining -= ret; 5477 } 5478 bytes_received += ret; 5479 local_receive_calls += temp_recvs; 5480 } 5481 else if (ret == 0) { 5482 /* is this the end of a test, just a zero-byte recv, or 5483 something else? that is an exceedingly good question and 5484 one for which I don't presently have a good answer, but 5485 that won't stop me from guessing :) raj 2008-01-09 */ 5486 if (!((connection_test) || (null_message_ok))) { 5487 /* if it is neither a connection_test nor null_message_ok it 5488 must be the end of the test */ 5489 times_up = 1; 5490 break; 5491 } 5492 local_receive_calls += temp_recvs; 5493 } 5494 else if (ret == -1) { 5495 /* test timed-out */ 5496 times_up = 1; 5497 timed_out = 1; 5498 break; 5499 } 5500 else { 5501 /* presently at least, -2 and -3 are equally bad on recv */ 5502 /* we need a response message here for the control connection 5503 before we exit! */ 5504 netperf_response.content.serv_errno = errno; 5505 send_response(); 5506 exit(-1); 5507 } 5508 recv_ring = recv_ring->next; 5509 } 5510 5511 /* if we should try to send something, then by all means, let us 5512 try to send something. */ 5513 if ((omni_request->direction & NETPERF_XMIT) && 5514 ((!times_up) || (units_remaining > 0))) { 5515 5516 /* there used to be some code here looking sched_yield() until 5517 there was no more queued, unsent data on the socket but 5518 frankly, I've no idea what that was all about so I have 5519 removed it. It may have been part of a kludge to try to avoid 5520 coalescing requests and responses */ 5521 5522 if (omni_request->protocol == IPPROTO_UDP && need_to_connect && 5523 !connected) { 5524 if (connect(data_socket, 5525 (struct sockaddr*)&peeraddr_in, 5526 addrlen) == INVALID_SOCKET) { 5527 netperf_response.content.serv_errno = errno; 5528 send_response(); 5529 close(data_socket); 5530 exit(-1); 5531 } 5532 connected = 1; 5533 } 5534 5535 ret = send_data(data_socket, 5536 send_ring, 5537 bytes_to_send, 5538 (connected) ? NULL : (struct sockaddr *)&peeraddr_in, 5539 addrlen, 5540 omni_request->protocol); 5541 5542 /* the order of these if's will seem a triffle strange, but they 5543 are my best guess as to order of probabilty and/or importance 5544 to the overhead raj 2008-01-09*/ 5545 if (ret == bytes_to_send) { 5546 /* if this is a send-only test controlled by byte count we 5547 decrement units_remaining by the bytes sent */ 5548 if (!(direction & NETPERF_RECV) && (units_remaining > 0)) { 5549 units_remaining -= ret; 5550 } 5551 bytes_sent += ret; 5552 send_ring = send_ring->next; 5553 local_send_calls++; 5554 } 5555 else if (ret == -2) { 5556 /* what to do here -2 means a non-fatal error - probably 5557 ENOBUFS and so our send didn't happen. in the old code for 5558 UDP_STREAM we would just continue in the while loop. it 5559 isn't clear that is what to do here, so we will simply 5560 increment the failed_sends stat and fall-through. If this 5561 is a UDP_STREAM style of test, the net effect should be the 5562 same. if this is a UDP_RR with a really-big burst count, I 5563 don't think we were checking for ENOBUFS there anyway and 5564 so would have failed. Here we can just let things 5565 slide. */ 5566 failed_sends++; 5567 } 5568 else if (ret == 0) { 5569 /* was this a zero-byte send? if it was, then ostensibly we 5570 would hit the ret == bytes_to_send case which means we'd 5571 never get here as we are using blocking semantics */ 5572 } 5573 else if (ret == -1) { 5574 times_up = 1; 5575 timed_out = 1; 5576 break; 5577 } 5578 else { 5579 /* we need a response message back to netperf here before we 5580 exit */ 5581 /* NEED RESPONSE; */ 5582 netperf_response.content.serv_errno = errno; 5583 send_response(); 5584 exit(-1); 5585 } 5586 5587 } 5588 5589 if (connection_test) { 5590#ifdef __linux 5591 /* so, "Linux" with autotuning likes to alter the socket buffer 5592 sizes over the life of the connection, but only does so when 5593 one takes the defaults at time of socket creation. if we 5594 took those defaults, we should inquire as to what the values 5595 ultimately became. raj 2008-01-15 */ 5596 /* but as annoying as it is to have to make these calls, don't 5597 penalize linux by calling them over and over again. instead 5598 we will simply ass-u-me that it will become the same value 5599 over and over again. raj 20100917 */ 5600 if ((lsr_size_req < 0) && (-1 == lsr_size_end)) 5601 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 5602 else 5603 lsr_size_end = lsr_size; 5604 if ((lss_size_req < 0) && (-1 == lss_size_end)) 5605 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 5606 else 5607 lss_size_end = lss_size; 5608#else 5609 lsr_size_end = lsr_size; 5610 lss_size_end = lss_size; 5611#endif 5612 ret = close_data_socket(data_socket,NULL,0,omni_request->protocol); 5613 if (ret == -1) { 5614 times_up = 1; 5615 timed_out = 1; 5616 break; 5617 } 5618 else if (ret < 0) { 5619 netperf_response.content.serv_errno = errno; 5620 send_response(); 5621 perror("netperf: recv_omni: close_data_socket failed"); 5622 fflush(where); 5623 exit(-1); 5624 } 5625 /* we will need a new connection to be established */ 5626 need_to_accept = 1; 5627 connected = 0; 5628 } 5629 5630#if defined(WANT_INTERVALS) 5631 INTERVALS_WAIT(); 5632#endif /* WANT_INTERVALS */ 5633 5634 /* was this a "transaction" test? don't for get that a TCP_CC 5635 style test will have no xmit or recv :) so, we check for either 5636 both XMIT and RECV set, or neither XMIT nor RECV set */ 5637 if (NETPERF_IS_RR(omni_request->direction)) { 5638 trans_completed++; 5639 if (units_remaining) { 5640 units_remaining--; 5641 } 5642 } 5643 } 5644 5645 /* The current iteration loop now exits due to timeout or unit count 5646 being reached */ 5647 stop_timer(); 5648 cpu_stop(omni_request->flags & OMNI_MEASURE_CPU,&elapsed_time); 5649 close(s_listen); 5650 5651#if defined(WANT_INTERVALS) 5652#ifdef WIN32 5653 stop_itimer(); 5654#endif 5655#endif /* WANT_INTERVALS */ 5656 5657 if (timed_out) { 5658 /* we ended the test by time, which may have been PAD_TIME seconds 5659 longer than we wanted to run. so, we want to subtract pad_time 5660 from the elapsed_time. if we didn't pad the timer pad_time will 5661 be 0 so we can just subtract it anyway :) */ 5662 if (debug) { 5663 fprintf(where,"Adjusting elapsed time by %d seconds\n",pad_time); 5664 fflush(where); 5665 } 5666 elapsed_time -= pad_time; 5667 } 5668 5669 remote_transport_retrans = get_transport_retrans(data_socket, 5670 omni_request->protocol); 5671 5672 if (connected) { 5673#ifdef __linux 5674 /* so, "Linux" with autotuning likes to alter the socket buffer 5675 sizes over the life of the connection, but only does so when 5676 one takes the defaults at time of socket creation. if we took 5677 those defaults, we should inquire as to what the values 5678 ultimately became. raj 2008-01-15 */ 5679 if (lsr_size_req < 0) 5680 get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end); 5681 else 5682 lsr_size_end = lsr_size; 5683 if (lss_size_req < 0) 5684 get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end); 5685 else 5686 lss_size_end = lss_size; 5687#else 5688 lsr_size_end = lsr_size; 5689 lss_size_end = lss_size; 5690#endif 5691 if (omni_request->flags & OMNI_WANT_REM_CONG) { 5692 get_transport_cong_control(data_socket, 5693 local_res->ai_protocol, 5694 omni_results->cong_control, 5695 sizeof(omni_results->cong_control)); 5696 } 5697 else { 5698 strncpy(omni_results->cong_control,"",sizeof(omni_results->cong_control)); 5699 } 5700 5701 5702 close_data_socket(data_socket,NULL,0,omni_request->protocol); 5703 } 5704 else { 5705 close_data_socket(data_socket,(struct sockaddr *)&peeraddr_in,addrlen,omni_request->protocol); 5706 lsr_size_end = lsr_size; 5707 lss_size_end = lss_size; 5708 } 5709 5710 /* send the results to the sender */ 5711 5712 omni_results->send_calls = (uint32_t) local_send_calls; 5713 omni_results->bytes_received_lo = bytes_received & 0x00000000FFFFFFFFULL; 5714 omni_results->bytes_received_hi = (bytes_received & 0xFFFFFFFF00000000ULL) >> 32; 5715 omni_results->recv_buf_size = lsr_size_end; 5716 omni_results->recv_calls = (uint32_t) local_receive_calls; 5717 omni_results->bytes_sent_lo = bytes_sent & 0x00000000FFFFFFFFULL; 5718 omni_results->bytes_sent_hi = (bytes_sent & 0xFFFFFFFF00000000ULL) >> 32; 5719 omni_results->send_buf_size = lss_size_end; 5720 omni_results->trans_received = (uint32_t) trans_completed; 5721 omni_results->elapsed_time = elapsed_time; 5722 omni_results->transport_retrans = remote_transport_retrans; 5723 omni_results->cpu_method = cpu_method; 5724 omni_results->num_cpus = lib_num_loc_cpus; 5725 if (omni_request->flags & OMNI_MEASURE_CPU) { 5726 omni_results->cpu_util = calc_cpu_util(elapsed_time); 5727 omni_results->cpu_percent_user = lib_local_cpu_stats.cpu_user; 5728 omni_results->cpu_percent_system = lib_local_cpu_stats.cpu_system; 5729 omni_results->cpu_percent_iowait = lib_local_cpu_stats.cpu_iowait; 5730 omni_results->cpu_percent_irq = lib_local_cpu_stats.cpu_irq; 5731 omni_results->cpu_percent_swintr = lib_local_cpu_stats.cpu_swintr; 5732 omni_results->peak_cpu_util = lib_local_cpu_stats.peak_cpu_util; 5733 omni_results->peak_cpu_id = lib_local_cpu_stats.peak_cpu_id; 5734 } 5735 5736#if defined(WANT_INTERVALS) 5737#ifdef WIN32 5738 stop_itimer(); 5739#endif 5740#endif /* WANT_INTERVALS */ 5741 5742 if (debug) { 5743 fprintf(where, 5744 "%s: test complete, sending results.\n", 5745 __FUNCTION__); 5746 fflush(where); 5747 } 5748 5749 send_response_n(OMNI_RESULTS_CONV_CUTOFF); 5750 5751} 5752 5753 5754#ifdef WANT_MIGRATION 5755void 5756send_tcp_stream(char remote_host[]) 5757{ 5758 5759 char *tput_title = "\ 5760Recv Send Send \n\ 5761Socket Socket Message Elapsed \n\ 5762Size Size Size Time Throughput \n\ 5763bytes bytes bytes secs. %s/sec \n\n"; 5764 5765 char *tput_fmt_0 = 5766 "%7.2f %s\n"; 5767 5768 char *tput_fmt_1 = 5769 "%6d %6d %6d %-6.2f %7.2f %s\n"; 5770 5771 char *cpu_title = "\ 5772Recv Send Send Utilization Service Demand\n\ 5773Socket Socket Message Elapsed Send Recv Send Recv\n\ 5774Size Size Size Time Throughput local remote local remote\n\ 5775bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 5776 5777 char *cpu_fmt_0 = 5778 "%6.3f %c %s\n"; 5779 5780 char *cpu_fmt_1 = 5781 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 5782 5783 char *ksink_fmt = "\n\ 5784Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 5785Local Remote Local Remote Xfered Per Per\n\ 5786Send Recv Send Recv Send (avg) Recv (avg)\n\ 5787%5d %5d %5d %5d %6"PRId64" %6.2f %6"PRId64" %6.2f %6"PRId64"\n"; 5788 5789 char *ksink_fmt2 = "\n\ 5790Maximum\n\ 5791Segment\n\ 5792Size (bytes)\n\ 5793%6d\n"; 5794 5795 send_omni_inner(remote_host, legacy, "MIGRATED TCP STREAM TEST"); 5796 5797 5798 if (legacy) { 5799 5800 /* We are now ready to print all the information, but only if we 5801 are truly acting as a legacy test. If the user has specified 5802 zero-level verbosity, we will just print the local service 5803 demand, or the remote service demand. If the user has requested 5804 verbosity level 1, he will get the basic "streamperf" 5805 numbers. If the user has specified a verbosity of greater than 5806 1, we will display a veritable plethora of background 5807 information from outside of this block as it it not 5808 cpu_measurement specific... */ 5809 5810 if (confidence < 0) { 5811 /* we did not hit confidence, but were we asked to look for it? */ 5812 if (iteration_max > 1) { 5813 display_confidence(); 5814 } 5815 } 5816 5817 if (local_cpu_usage || remote_cpu_usage) { 5818 5819 switch (verbosity) { 5820 case 0: 5821 if (local_cpu_usage) { 5822 fprintf(where, 5823 cpu_fmt_0, 5824 local_service_demand, 5825 local_cpu_method, 5826 ((print_headers) || 5827 (result_brand == NULL)) ? "" : result_brand); 5828 } 5829 else { 5830 fprintf(where, 5831 cpu_fmt_0, 5832 remote_service_demand, 5833 remote_cpu_method, 5834 ((print_headers) || 5835 (result_brand == NULL)) ? "" : result_brand); 5836 } 5837 break; 5838 case 1: 5839 case 2: 5840 if (print_headers) { 5841 fprintf(where, 5842 cpu_title, 5843 format_units(), 5844 local_cpu_method, 5845 remote_cpu_method); 5846 } 5847 5848 fprintf(where, 5849 cpu_fmt_1, /* the format string */ 5850 rsr_size, /* remote recvbuf size */ 5851 lss_size, /* local sendbuf size */ 5852 send_size, /* how large were the sends */ 5853 elapsed_time, /* how long was the test */ 5854 thruput, /* what was the xfer rate */ 5855 local_cpu_utilization, /* local cpu */ 5856 remote_cpu_utilization, /* remote cpu */ 5857 local_service_demand, /* local service demand */ 5858 remote_service_demand, /* remote service demand */ 5859 ((print_headers) || 5860 (result_brand == NULL)) ? "" : result_brand); 5861 break; 5862 } 5863 } 5864 else { 5865 /* The tester did not wish to measure service demand. */ 5866 5867 switch (verbosity) { 5868 case 0: 5869 fprintf(where, 5870 tput_fmt_0, 5871 thruput, 5872 ((print_headers) || 5873 (result_brand == NULL)) ? "" : result_brand); 5874 break; 5875 case 1: 5876 case 2: 5877 if (print_headers) { 5878 fprintf(where,tput_title,format_units()); 5879 } 5880 fprintf(where, 5881 tput_fmt_1, /* the format string */ 5882 rsr_size, /* remote recvbuf size */ 5883 lss_size, /* local sendbuf size */ 5884 send_size, /* how large were the sends */ 5885 elapsed_time, /* how long did it take */ 5886 thruput, /* how fast did it go */ 5887 ((print_headers) || 5888 (result_brand == NULL)) ? "" : result_brand); 5889 break; 5890 } 5891 } 5892 5893 /* it would be a good thing to include information about some of the */ 5894 /* other parameters that may have been set for this test, but at the */ 5895 /* moment, I do not wish to figure-out all the formatting, so I will */ 5896 /* just put this comment here to help remind me that it is something */ 5897 /* that should be done at a later time. */ 5898 5899 if (verbosity > 1) { 5900 /* The user wanted to know it all, so we will give it to him. */ 5901 /* This information will include as much as we can find about */ 5902 /* TCP statistics, the alignments of the sends and receives */ 5903 /* and all that sort of rot... */ 5904 5905 /* this stuff needs to be worked-out in the presence of confidence */ 5906 /* intervals and multiple iterations of the test... raj 11/94 */ 5907 5908 fprintf(where, 5909 ksink_fmt, 5910 "Bytes", 5911 "Bytes", 5912 "Bytes", 5913 local_send_align, 5914 remote_recv_align, 5915 local_send_offset, 5916 remote_recv_offset, 5917 bytes_sent, 5918 bytes_sent / (double)local_send_calls, 5919 local_send_calls, 5920 bytes_sent / (double)remote_receive_calls, 5921 remote_receive_calls); 5922 fprintf(where, 5923 ksink_fmt2, 5924 transport_mss); 5925#ifdef WANT_HISTOGRAM 5926 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 5927 HIST_report(time_hist); 5928#endif /* WANT_HISTOGRAM */ 5929 fflush(where); 5930 } 5931 5932 } 5933} 5934 5935void 5936send_tcp_maerts(char remote_host[]) 5937{ 5938 5939 char *tput_title = "\ 5940Recv Send Send \n\ 5941Socket Socket Message Elapsed \n\ 5942Size Size Size Time Throughput \n\ 5943bytes bytes bytes secs. %s/sec \n\n"; 5944 5945 char *tput_fmt_0 = 5946 "%7.2f %s\n"; 5947 5948 char *tput_fmt_1 = 5949 "%6d %6d %6d %-6.2f %7.2f %s\n"; 5950 5951 char *cpu_title = "\ 5952Recv Send Send Utilization Service Demand\n\ 5953Socket Socket Message Elapsed Recv Send Recv Send\n\ 5954Size Size Size Time Throughput local remote local remote\n\ 5955bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 5956 5957 char *cpu_fmt_0 = 5958 "%6.3f %c %s\n"; 5959 5960 char *cpu_fmt_1 = 5961 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 5962 5963 char *ksink_fmt = "\n\ 5964Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\ 5965Local Remote Local Remote Xfered Per Per\n\ 5966Recv Send Recv Send Recv (avg) Send (avg)\n\ 5967%5d %5d %5d %5d %6"PRId64" %6.2f %6d %6.2f %6d\n"; 5968 5969 char *ksink_fmt2 = "\n\ 5970Maximum\n\ 5971Segment\n\ 5972Size (bytes)\n\ 5973%6d\n"; 5974 5975 send_omni_inner(remote_host, legacy, "MIGRATED TCP MAERTS TEST"); 5976 5977 5978 /* We are now ready to print all the information, but only if we are 5979 truly acting as a leacy test. If the user has specified 5980 zero-level verbosity, we will just print the local service 5981 demand, or the remote service demand. If the user has requested 5982 verbosity level 1, he will get the basic "streamperf" numbers. If 5983 the user has specified a verbosity of greater than 1, we will 5984 display a veritable plethora of background information from 5985 outside of this block as it it not cpu_measurement 5986 specific... */ 5987 5988 if (legacy) { 5989 5990 if (confidence < 0) { 5991 /* we did not hit confidence, but were we asked to look for it? */ 5992 if (iteration_max > 1) { 5993 display_confidence(); 5994 } 5995 } 5996 5997 if (local_cpu_usage || remote_cpu_usage) { 5998 5999 switch (verbosity) { 6000 case 0: 6001 if (local_cpu_usage) { 6002 fprintf(where, 6003 cpu_fmt_0, 6004 local_service_demand, 6005 local_cpu_method, 6006 ((print_headers) || 6007 (result_brand == NULL)) ? "" : result_brand); 6008 } 6009 else { 6010 fprintf(where, 6011 cpu_fmt_0, 6012 remote_service_demand, 6013 remote_cpu_method, 6014 ((print_headers) || 6015 (result_brand == NULL)) ? "" : result_brand); 6016 } 6017 break; 6018 case 1: 6019 case 2: 6020 if (print_headers) { 6021 fprintf(where, 6022 cpu_title, 6023 format_units(), 6024 local_cpu_method, 6025 remote_cpu_method); 6026 } 6027 6028 fprintf(where, 6029 cpu_fmt_1, /* the format string */ 6030 rsr_size, /* remote recvbuf size */ 6031 lss_size, /* local sendbuf size */ 6032 remote_send_size, /* how large were the recvs */ 6033 elapsed_time, /* how long was the test */ 6034 thruput, /* what was the xfer rate */ 6035 local_cpu_utilization, /* local cpu */ 6036 remote_cpu_utilization, /* remote cpu */ 6037 local_service_demand, /* local service demand */ 6038 remote_service_demand, /* remote service demand */ 6039 ((print_headers) || 6040 (result_brand == NULL)) ? "" : result_brand); 6041 break; 6042 } 6043 } 6044 else { 6045 /* The tester did not wish to measure service demand. */ 6046 6047 switch (verbosity) { 6048 case 0: 6049 fprintf(where, 6050 tput_fmt_0, 6051 thruput, 6052 ((print_headers) || 6053 (result_brand == NULL)) ? "" : result_brand); 6054 break; 6055 case 1: 6056 case 2: 6057 if (print_headers) { 6058 fprintf(where,tput_title,format_units()); 6059 } 6060 fprintf(where, 6061 tput_fmt_1, /* the format string */ 6062 lsr_size, /* local recvbuf size */ 6063 rss_size, /* remot sendbuf size */ 6064 remote_send_size, /* how large were the recvs */ 6065 elapsed_time, /* how long did it take */ 6066 thruput, /* how fast did it go */ 6067 ((print_headers) || 6068 (result_brand == NULL)) ? "" : result_brand); 6069 break; 6070 } 6071 } 6072 6073 /* it would be a good thing to include information about some of the */ 6074 /* other parameters that may have been set for this test, but at the */ 6075 /* moment, I do not wish to figure-out all the formatting, so I will */ 6076 /* just put this comment here to help remind me that it is something */ 6077 /* that should be done at a later time. */ 6078 6079 if (verbosity > 1) { 6080 /* The user wanted to know it all, so we will give it to him. */ 6081 /* This information will include as much as we can find about */ 6082 /* TCP statistics, the alignments of the sends and receives */ 6083 /* and all that sort of rot... */ 6084 6085 /* this stuff needs to be worked-out in the presence of confidence */ 6086 /* intervals and multiple iterations of the test... raj 11/94 */ 6087 6088 fprintf(where, 6089 ksink_fmt, 6090 "Bytes", 6091 "Bytes", 6092 "Bytes", 6093 local_recv_align, 6094 remote_recv_align, 6095 local_recv_offset, 6096 remote_recv_offset, 6097 bytes_received, 6098 bytes_received / (double)local_receive_calls, 6099 local_receive_calls, 6100 remote_bytes_sent / (double)remote_send_calls, 6101 remote_send_calls); 6102 fprintf(where, 6103 ksink_fmt2, 6104 transport_mss); 6105 6106#ifdef WANT_HISTOGRAM 6107 fprintf(where,"\n\nHistogram of time spent in recv() call.\n"); 6108 HIST_report(time_hist); 6109#endif /* WANT_HISTOGRAM */ 6110 fflush(where); 6111 } 6112 } 6113} 6114 6115 6116void 6117send_tcp_rr(char remote_host[]) { 6118 6119 char *tput_title = "\ 6120Local /Remote\n\ 6121Socket Size Request Resp. Elapsed Trans.\n\ 6122Send Recv Size Size Time Rate \n\ 6123bytes Bytes bytes bytes secs. per sec \n\n"; 6124 6125 char *tput_title_band = "\ 6126Local /Remote\n\ 6127Socket Size Request Resp. Elapsed \n\ 6128Send Recv Size Size Time Throughput \n\ 6129bytes Bytes bytes bytes secs. %s/sec \n\n"; 6130 6131 char *tput_fmt_0 = 6132 "%7.2f %s\n"; 6133 6134 char *tput_fmt_1_line_1 = "\ 6135%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 6136 char *tput_fmt_1_line_2 = "\ 6137%-6d %-6d\n"; 6138 6139 char *cpu_title = "\ 6140Local /Remote\n\ 6141Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6142Send Recv Size Size Time Rate local remote local remote\n\ 6143bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 6144 6145 char *cpu_title_tput = "\ 6146Local /Remote\n\ 6147Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 6148Send Recv Size Size Time %-8.8s local remote local remote\n\ 6149bytes bytes bytes bytes secs. per sec %% %c %% %c us/KB us/KB\n\n"; 6150 6151 char *cpu_title_latency = "\ 6152Local /Remote\n\ 6153Socket Size Request Resp. Elapsed Latency CPU CPU S.dem S.dem\n\ 6154Send Recv Size Size Time usecs local remote local remote\n\ 6155bytes bytes bytes bytes secs. per tran %% %c %% %c us/Tr us/Tr\n\n"; 6156 6157 char *cpu_fmt_0 = 6158 "%6.3f %c %s\n"; 6159 6160 char *cpu_fmt_1_line_1 = "\ 6161%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 6162 6163 char *cpu_fmt_1_line_2 = "\ 6164%-6d %-6d\n"; 6165 6166 char *ksink_fmt = "\ 6167Alignment Offset RoundTrip Trans Throughput\n\ 6168Local Remote Local Remote Latency Rate %-8.8s/s\n\ 6169Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\ 6170%5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n"; 6171 6172 send_omni_inner(remote_host, legacy, "MIGRATED TCP REQUEST/RESPONSE TEST"); 6173 6174 if (legacy) { 6175 /* We are now ready to print all the information. If the user has 6176 specified zero-level verbosity, we will just print the local 6177 service demand, or the remote service demand. If the user has 6178 requested verbosity level 1, he will get the basic "streamperf" 6179 numbers. If the user has specified a verbosity of greater than 1, 6180 we will display a veritable plethora of background information 6181 from outside of this block as it it not cpu_measurement 6182 specific... */ 6183 6184 if (confidence < 0) { 6185 /* we did not hit confidence, but were we asked to look for it? */ 6186 if (iteration_max > 1) { 6187 display_confidence(); 6188 } 6189 } 6190 6191 if (local_cpu_usage || remote_cpu_usage) { 6192 6193 switch (verbosity) { 6194 case 0: 6195 if (local_cpu_usage) { 6196 fprintf(where, 6197 cpu_fmt_0, 6198 local_service_demand, 6199 local_cpu_method, 6200 ((print_headers) || 6201 (result_brand == NULL)) ? "" : result_brand); 6202 } 6203 else { 6204 fprintf(where, 6205 cpu_fmt_0, 6206 remote_service_demand, 6207 remote_cpu_method, 6208 ((print_headers) || 6209 (result_brand == NULL)) ? "" : result_brand); 6210 } 6211 break; 6212 case 1: 6213 case 2: 6214 if (print_headers) { 6215 if ('x' == libfmt) { 6216 fprintf(where, 6217 cpu_title, 6218 local_cpu_method, 6219 remote_cpu_method); 6220 } 6221 else { 6222 fprintf(where, 6223 cpu_title_tput, 6224 format_units(), 6225 local_cpu_method, 6226 remote_cpu_method); 6227 } 6228 } 6229 6230 fprintf(where, 6231 cpu_fmt_1_line_1, /* the format string */ 6232 lss_size, /* local sendbuf size */ 6233 lsr_size, 6234 req_size, /* how large were the requests */ 6235 rsp_size, /* guess */ 6236 elapsed_time, /* how long was the test */ 6237 thruput, 6238 local_cpu_utilization, /* local cpu */ 6239 remote_cpu_utilization, /* remote cpu */ 6240 local_service_demand, /* local service demand */ 6241 remote_service_demand, /* remote service demand */ 6242 ((print_headers) || 6243 (result_brand == NULL)) ? "" : result_brand); 6244 fprintf(where, 6245 cpu_fmt_1_line_2, 6246 rss_size, 6247 rsr_size); 6248 break; 6249 } 6250 } 6251 else { 6252 /* The tester did not wish to measure service demand. */ 6253 6254 switch (verbosity) { 6255 case 0: 6256 fprintf(where, 6257 tput_fmt_0, 6258 thruput, 6259 ((print_headers) || 6260 (result_brand == NULL)) ? "" : result_brand); 6261 break; 6262 case 1: 6263 case 2: 6264 if (print_headers) { 6265 fprintf(where, 6266 ('x' == libfmt) ? tput_title : tput_title_band, 6267 format_units()); 6268 } 6269 6270 fprintf(where, 6271 tput_fmt_1_line_1, /* the format string */ 6272 lss_size, 6273 lsr_size, 6274 req_size, /* how large were the requests */ 6275 rsp_size, /* how large were the responses */ 6276 elapsed_time, /* how long did it take */ 6277 /* are we trans or do we need to convert to bytes then 6278 bits? at this point, thruput is in our "confident" 6279 transactions per second. we can convert to a 6280 bidirectional bitrate by multiplying that by the sum 6281 of the req_size and rsp_size. we pass that to 6282 calc_thruput_interval_omni with an elapsed time of 6283 1.0 s to get it converted to [kmg]bits/s or 6284 [KMG]Bytes/s */ 6285 thruput, 6286 ((print_headers) || 6287 (result_brand == NULL)) ? "" : result_brand); 6288 fprintf(where, 6289 tput_fmt_1_line_2, 6290 rss_size, /* remote recvbuf size */ 6291 rsr_size); 6292 6293 break; 6294 } 6295 } 6296 6297 /* it would be a good thing to include information about some of the */ 6298 /* other parameters that may have been set for this test, but at the */ 6299 /* moment, I do not wish to figure-out all the formatting, so I will */ 6300 /* just put this comment here to help remind me that it is something */ 6301 /* that should be done at a later time. */ 6302 6303 /* how to handle the verbose information in the presence of */ 6304 /* confidence intervals is yet to be determined... raj 11/94 */ 6305 if (verbosity > 1) { 6306 /* The user wanted to know it all, so we will give it to him. */ 6307 /* This information will include as much as we can find about */ 6308 /* TCP statistics, the alignments of the sends and receives */ 6309 /* and all that sort of rot... */ 6310 6311 /* normally, you might think that if we were messing about with 6312 the value of libfmt we would need to put it back again, but 6313 since this is basically the last thing we are going to do with 6314 it, it does not matter. so there :) raj 2007-06-08 */ 6315 /* if the user was asking for transactions, then we report 6316 megabits per second for the unidirectional throughput, 6317 otherwise we use the desired units. */ 6318 if ('x' == libfmt) { 6319 libfmt = 'm'; 6320 } 6321 6322 fprintf(where, 6323 ksink_fmt, 6324 format_units(), 6325 local_send_align, 6326 remote_recv_offset, 6327 local_send_offset, 6328 remote_recv_offset, 6329 /* if the user has enable burst mode, we have to remember 6330 to account for that in the number of transactions 6331 outstanding at any one time. otherwise we will 6332 underreport the latency of individual 6333 transactions. learned from saf by raj 2007-06-08 */ 6334 (((double)1.0/transaction_rate)*(double)1000000.0) * 6335 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)), 6336 transaction_rate, 6337 calc_thruput_interval_omni(transaction_rate * (double)req_size, 6338 1.0), 6339 calc_thruput_interval_omni(transaction_rate * (double)rsp_size, 6340 1.0)); 6341 6342#ifdef WANT_HISTOGRAM 6343 fprintf(where,"\nHistogram of request/response times\n"); 6344 HIST_report(time_hist); 6345#endif /* WANT_HISTOGRAM */ 6346 fflush(where); 6347 } 6348 } 6349} 6350 6351 6352void 6353send_tcp_conn_rr(char remote_host[]) 6354{ 6355 6356 char *tput_title = "\ 6357Local /Remote\n\ 6358Socket Size Request Resp. Elapsed Trans.\n\ 6359Send Recv Size Size Time Rate \n\ 6360bytes Bytes bytes bytes secs. per sec \n\n"; 6361 6362 char *tput_fmt_0 = 6363 "%7.2f\n"; 6364 6365 char *tput_fmt_1_line_1 = "\ 6366%-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 6367 char *tput_fmt_1_line_2 = "\ 6368%-6d %-6d\n"; 6369 6370 char *cpu_title = "\ 6371Local /Remote\n\ 6372Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6373Send Recv Size Size Time Rate local remote local remote\n\ 6374bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 6375 6376 char *cpu_fmt_0 = 6377 "%6.3f\n"; 6378 6379 char *cpu_fmt_1_line_1 = "\ 6380%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 6381 6382 char *cpu_fmt_1_line_2 = "\ 6383%-6d %-6d\n"; 6384 6385 char *ksink_fmt = "\n\ 6386Alignment Offset\n\ 6387Local Remote Local Remote\n\ 6388Send Recv Send Recv\n\ 6389%5d %5d %5d %5d\n"; 6390 6391 send_omni_inner(remote_host, 6392 legacy, 6393 "MIGRATED TCP Connect/Request/Response TEST"); 6394 6395 /* We are now ready to print all the information. If the user */ 6396 /* has specified zero-level verbosity, we will just print the */ 6397 /* local service demand, or the remote service demand. If the */ 6398 /* user has requested verbosity level 1, he will get the basic */ 6399 /* "streamperf" numbers. If the user has specified a verbosity */ 6400 /* of greater than 1, we will display a veritable plethora of */ 6401 /* background information from outside of this block as it it */ 6402 /* not cpu_measurement specific... */ 6403 6404 if (legacy) { 6405 if (confidence < 0) { 6406 /* we did not hit confidence, but were we asked to look for it? */ 6407 if (iteration_max > 1) { 6408 display_confidence(); 6409 } 6410 } 6411 6412 if (local_cpu_usage || remote_cpu_usage) { 6413 6414 switch (verbosity) { 6415 case 0: 6416 if (local_cpu_usage) { 6417 fprintf(where, 6418 cpu_fmt_0, 6419 local_service_demand, 6420 local_cpu_method); 6421 } 6422 else { 6423 fprintf(where, 6424 cpu_fmt_0, 6425 remote_service_demand, 6426 remote_cpu_method); 6427 } 6428 break; 6429 case 1: 6430 case 2: 6431 if (print_headers) { 6432 fprintf(where, 6433 cpu_title, 6434 local_cpu_method, 6435 remote_cpu_method); 6436 } 6437 6438 fprintf(where, 6439 cpu_fmt_1_line_1, /* the format string */ 6440 lss_size, /* local sendbuf size */ 6441 lsr_size, 6442 req_size, /* how large were the requests */ 6443 rsp_size, /* guess */ 6444 elapsed_time, /* how long was the test */ 6445 thruput, 6446 local_cpu_utilization, /* local cpu */ 6447 remote_cpu_utilization, /* remote cpu */ 6448 local_service_demand, /* local service demand */ 6449 remote_service_demand); /* remote service demand */ 6450 fprintf(where, 6451 cpu_fmt_1_line_2, 6452 rss_size, 6453 rsr_size); 6454 break; 6455 } 6456 } 6457 else { 6458 /* The tester did not wish to measure service demand. */ 6459 6460 switch (verbosity) { 6461 case 0: 6462 fprintf(where, 6463 tput_fmt_0, 6464 thruput); 6465 break; 6466 case 1: 6467 case 2: 6468 if (print_headers) { 6469 fprintf(where,tput_title,format_units()); 6470 } 6471 6472 fprintf(where, 6473 tput_fmt_1_line_1, /* the format string */ 6474 lss_size, 6475 lsr_size, 6476 req_size, /* how large were the requests */ 6477 rsp_size, /* how large were the responses */ 6478 elapsed_time, /* how long did it take */ 6479 thruput); 6480 fprintf(where, 6481 tput_fmt_1_line_2, 6482 rss_size, /* remote recvbuf size */ 6483 rsr_size); 6484 6485 break; 6486 } 6487 } 6488 6489 /* it would be a good thing to include information about some of the */ 6490 /* other parameters that may have been set for this test, but at the */ 6491 /* moment, I do not wish to figure-out all the formatting, so I will */ 6492 /* just put this comment here to help remind me that it is something */ 6493 /* that should be done at a later time. */ 6494 6495 /* how to handle the verbose information in the presence of */ 6496 /* confidence intervals is yet to be determined... raj 11/94 */ 6497 if (verbosity > 1) { 6498 /* The user wanted to know it all, so we will give it to him. */ 6499 /* This information will include as much as we can find about */ 6500 /* TCP statistics, the alignments of the sends and receives */ 6501 /* and all that sort of rot... */ 6502 6503 fprintf(where, 6504 ksink_fmt, 6505 local_send_align, 6506 remote_recv_align, 6507 local_send_offset, 6508 remote_recv_offset); 6509 6510#ifdef WANT_HISTOGRAM 6511 fprintf(where,"\nHistogram of request/response times\n"); 6512 HIST_report(time_hist); 6513#endif /* WANT_HISTOGRAM */ 6514 fflush(where); 6515 } 6516 } 6517} 6518 6519void 6520send_udp_stream(char remote_host[]) 6521{ 6522 /**********************************************************************/ 6523 /* */ 6524 /* UDP Unidirectional Send Test */ 6525 /* */ 6526 /**********************************************************************/ 6527 6528 char *tput_title = "\ 6529Socket Message Elapsed Messages \n\ 6530Size Size Time Okay Errors Throughput\n\ 6531bytes bytes secs # # %s/sec\n\n"; 6532 6533 char *tput_fmt_0 = 6534 "%7.2f\n"; 6535 6536 char *tput_fmt_1 = "\ 6537%6d %6d %-7.2f %7"PRIu64" %6d %7.2f\n\ 6538%6d %-7.2f %7"PRIu64" %7.2f\n\n"; 6539 6540 6541 char *cpu_title = "\ 6542Socket Message Elapsed Messages CPU Service\n\ 6543Size Size Time Okay Errors Throughput Util Demand\n\ 6544bytes bytes secs # # %s/sec %% %c%c us/KB\n\n"; 6545 6546 char *cpu_fmt_0 = 6547 "%6.2f %c\n"; 6548 6549 char *cpu_fmt_1 = "\ 6550%6d %6d %-7.2f %7"PRIu64" %6d %7.1f %-6.2f %-6.3f\n\ 6551%6d %-7.2f %7"PRIu64" %7.1f %-6.2f %-6.3f\n\n"; 6552 6553 6554 send_omni_inner(remote_host, legacy, "MIGRATED UDP STREAM TEST"); 6555 6556 if (legacy) { 6557 /* We are now ready to print all the information. If the user has 6558 specified zero-level verbosity, we will just print the local 6559 service demand, or the remote service demand. If the user has 6560 requested verbosity level 1, he will get the basic "streamperf" 6561 numbers. If the user has specified a verbosity of greater than 6562 1, we will display a veritable plethora of background 6563 information from outside of this block as it it not 6564 cpu_measurement specific... */ 6565 6566 6567 if (confidence < 0) { 6568 /* we did not hit confidence, but were we asked to look for it? */ 6569 if (iteration_max > 1) { 6570 display_confidence(); 6571 } 6572 } 6573 6574 if (local_cpu_usage || remote_cpu_usage) { 6575 6576 switch (verbosity) { 6577 case 0: 6578 if (local_cpu_usage) { 6579 fprintf(where, 6580 cpu_fmt_0, 6581 local_service_demand, 6582 local_cpu_method); 6583 } 6584 else { 6585 fprintf(where, 6586 cpu_fmt_0, 6587 remote_service_demand, 6588 local_cpu_method); 6589 } 6590 break; 6591 case 1: 6592 case 2: 6593 if (print_headers) { 6594 fprintf(where, 6595 cpu_title, 6596 format_units(), 6597 local_cpu_method, 6598 remote_cpu_method); 6599 } 6600 6601 fprintf(where, 6602 cpu_fmt_1, /* the format string */ 6603 lss_size, /* local sendbuf size */ 6604 send_size, /* how large were the sends */ 6605 elapsed_time, /* how long was the test */ 6606 local_send_calls, 6607 failed_sends, 6608 local_send_thruput, /* what was the xfer rate */ 6609 local_cpu_utilization, /* local cpu */ 6610 local_service_demand, /* local service demand */ 6611 rsr_size, 6612 elapsed_time, 6613 remote_receive_calls, 6614 remote_recv_thruput, 6615 remote_cpu_utilization, /* remote cpu */ 6616 remote_service_demand); /* remote service demand */ 6617 break; 6618 } 6619 } 6620 else { 6621 /* The tester did not wish to measure service demand. */ 6622 switch (verbosity) { 6623 case 0: 6624 fprintf(where, 6625 tput_fmt_0, 6626 local_send_thruput); 6627 break; 6628 case 1: 6629 case 2: 6630 if (print_headers) { 6631 fprintf(where,tput_title,format_units()); 6632 } 6633 fprintf(where, 6634 tput_fmt_1, /* the format string */ 6635 lss_size, /* local sendbuf size */ 6636 send_size, /* how large were the sends */ 6637 elapsed_time, /* how long did it take */ 6638 local_send_calls, 6639 failed_sends, 6640 local_send_thruput, 6641 rsr_size, /* remote recvbuf size */ 6642 elapsed_time, 6643 remote_receive_calls, 6644 remote_recv_thruput); 6645 break; 6646 } 6647 } 6648 6649#ifdef WANT_HISTOGRAM 6650 if (verbosity > 1) { 6651 fprintf(where,"\nHistogram of time spent in send() call\n"); 6652 HIST_report(time_hist); 6653 } 6654#endif /* WANT_HISTOGRAM */ 6655 fflush(where); 6656 } 6657} 6658 6659void 6660send_udp_rr(char remote_host[]) 6661{ 6662 6663 char *tput_title = "\ 6664Local /Remote\n\ 6665Socket Size Request Resp. Elapsed Trans.\n\ 6666Send Recv Size Size Time Rate \n\ 6667bytes Bytes bytes bytes secs. per sec \n\n"; 6668 6669 char *tput_title_band = "\ 6670Local /Remote\n\ 6671Socket Size Request Resp. Elapsed \n\ 6672Send Recv Size Size Time Throughput \n\ 6673bytes Bytes bytes bytes secs. %s/sec \n\n"; 6674 6675 char *tput_fmt_0 = 6676 "%7.2f %s\n"; 6677 6678 char *tput_fmt_1_line_1 = "\ 6679%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 6680 6681 char *tput_fmt_1_line_2 = "\ 6682%-6d %-6d\n"; 6683 6684 char *cpu_title = "\ 6685Local /Remote\n\ 6686Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6687Send Recv Size Size Time Rate local remote local remote\n\ 6688bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 6689 6690 char *cpu_title_tput = "\ 6691Local /Remote\n\ 6692Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 6693Send Recv Size Size Time %-8.8s local remote local remote\n\ 6694bytes bytes bytes bytes secs. per sec %% %c %% %c us/KB us/KB\n\n"; 6695 6696 char *cpu_fmt_0 = 6697 "%6.3f %c %s\n"; 6698 6699 char *cpu_fmt_1_line_1 = "\ 6700%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 6701 6702 char *cpu_fmt_1_line_2 = "\ 6703%-6d %-6d\n"; 6704 6705 send_omni_inner(remote_host, legacy, "MIGRATED UDP REQUEST/RESPONSE TEST"); 6706 6707 if (legacy) { 6708 /* We are now ready to print all the information. If the user has 6709 specified zero-level verbosity, we will just print the local 6710 service demand, or the remote service demand. If the user has 6711 requested verbosity level 1, he will get the basic "streamperf" 6712 numbers. If the user has specified a verbosity of greater than 6713 1, we will display a veritable plethora of background 6714 information from outside of this block as it it not 6715 cpu_measurement specific... */ 6716 6717 if (confidence < 0) { 6718 /* we did not hit confidence, but were we asked to look for it? */ 6719 if (iteration_max > 1) { 6720 display_confidence(); 6721 } 6722 } 6723 6724 if (local_cpu_usage || remote_cpu_usage) { 6725 6726 switch (verbosity) { 6727 case 0: 6728 if (local_cpu_usage) { 6729 fprintf(where, 6730 cpu_fmt_0, 6731 local_service_demand, 6732 local_cpu_method, 6733 ((print_headers) || 6734 (result_brand == NULL)) ? "" : result_brand); 6735 6736 } 6737 else { 6738 fprintf(where, 6739 cpu_fmt_0, 6740 remote_service_demand, 6741 remote_cpu_method, 6742 ((print_headers) || 6743 (result_brand == NULL)) ? "" : result_brand); 6744 6745 } 6746 break; 6747 case 1: 6748 case 2: 6749 if (print_headers) { 6750 if ('x' == libfmt) { 6751 fprintf(where, 6752 cpu_title, 6753 local_cpu_method, 6754 remote_cpu_method); 6755 } 6756 else { 6757 fprintf(where, 6758 cpu_title_tput, 6759 format_units(), 6760 local_cpu_method, 6761 remote_cpu_method); 6762 } 6763 } 6764 6765 fprintf(where, 6766 cpu_fmt_1_line_1, /* the format string */ 6767 lss_size, /* local sendbuf size */ 6768 lsr_size, 6769 req_size, /* how large were the requests */ 6770 rsp_size, /* guess */ 6771 elapsed_time, /* how long was the test */ 6772 thruput, 6773 local_cpu_utilization, /* local cpu */ 6774 remote_cpu_utilization, /* remote cpu */ 6775 local_service_demand, /* local service demand */ 6776 remote_service_demand, /* remote service demand */ 6777 ((print_headers) || 6778 (result_brand == NULL)) ? "" : result_brand); 6779 fprintf(where, 6780 cpu_fmt_1_line_2, 6781 rss_size, 6782 rsr_size); 6783 break; 6784 } 6785 } 6786 else { 6787 /* The tester did not wish to measure service demand. */ 6788 switch (verbosity) { 6789 case 0: 6790 fprintf(where, 6791 tput_fmt_0, 6792 thruput, 6793 ((print_headers) || 6794 (result_brand == NULL)) ? "" : result_brand); 6795 break; 6796 case 1: 6797 case 2: 6798 if (print_headers) { 6799 fprintf(where, 6800 ('x' == libfmt) ? tput_title : tput_title_band, 6801 format_units()); 6802 } 6803 6804 fprintf(where, 6805 tput_fmt_1_line_1, /* the format string */ 6806 lss_size, 6807 lsr_size, 6808 req_size, /* how large were the requests */ 6809 rsp_size, /* how large were the responses */ 6810 elapsed_time, /* how long did it take */ 6811 thruput, 6812 ((print_headers) || 6813 (result_brand == NULL)) ? "" : result_brand); 6814 fprintf(where, 6815 tput_fmt_1_line_2, 6816 rss_size, /* remote recvbuf size */ 6817 rsr_size); 6818 6819 break; 6820 } 6821 } 6822 6823 /* it would be a good thing to include information about some of the */ 6824 /* other parameters that may have been set for this test, but at the */ 6825 /* moment, I do not wish to figure-out all the formatting, so I will */ 6826 /* just put this comment here to help remind me that it is something */ 6827 /* that should be done at a later time. */ 6828 6829 /* how to handle the verbose information in the presence of */ 6830 /* confidence intervals is yet to be determined... raj 11/94 */ 6831 6832 if (verbosity > 1) { 6833 /* The user wanted to know it all, so we will give it to him. */ 6834 /* This information will include as much as we can find about */ 6835 /* UDP statistics, the alignments of the sends and receives */ 6836 /* and all that sort of rot... */ 6837 6838#ifdef WANT_HISTOGRAM 6839 fprintf(where,"\nHistogram of request/reponse times.\n"); 6840 HIST_report(time_hist); 6841#endif /* WANT_HISTOGRAM */ 6842 } 6843 fflush(where); 6844 } 6845} 6846 6847 6848#endif /* WANT_MIGRATION */ 6849 6850 6851/* using legacy test names will cause certain default settings to be 6852 made before we scan the test-specific arguments. raj 2010-07-20 */ 6853static void 6854set_omni_defaults_by_legacy_testname() { 6855 6856 /* the uber defaults are for a unidirectional test using TCP */ 6857 protocol = IPPROTO_TCP; 6858 socket_type = SOCK_STREAM; 6859 connection_test = 0; 6860 req_size = rsp_size = -1; 6861 was_legacy = 1; 6862 legacy = 1; 6863 implicit_direction = 0; /* do we allow certain options to 6864 implicitly affect the test direction? */ 6865 if (strcasecmp(test_name,"TCP_STREAM") == 0) { 6866 direction = NETPERF_XMIT; 6867 } 6868 else if (strcasecmp(test_name,"TCP_MAERTS") == 0) { 6869 direction = NETPERF_RECV; 6870 } 6871 else if (strcasecmp(test_name,"TCP_RR") == 0) { 6872 req_size = rsp_size = 1; 6873 direction = 0; 6874 direction |= NETPERF_XMIT; 6875 direction |= NETPERF_RECV; 6876 } 6877 else if (strcasecmp(test_name,"UDP_STREAM") == 0) { 6878 protocol = IPPROTO_UDP; 6879 socket_type = SOCK_DGRAM; 6880 } 6881 else if (strcasecmp(test_name,"UDP_RR") == 0) { 6882 protocol = IPPROTO_UDP; 6883 socket_type = SOCK_DGRAM; 6884 direction = 0; 6885 direction |= NETPERF_XMIT; 6886 direction |= NETPERF_RECV; 6887 req_size = rsp_size = 1; 6888 } 6889 else if (strcasecmp(test_name,"TCP_CC") == 0) { 6890 direction = 0; 6891 connection_test = 1; 6892 } 6893 else if (strcasecmp(test_name,"TCP_CRR") == 0) { 6894 direction = 0; 6895 direction |= NETPERF_XMIT; 6896 direction |= NETPERF_RECV; 6897 req_size = rsp_size = 1; 6898 connection_test = 1; 6899 } 6900 else if (strcasecmp(test_name,"omni") == 0) { 6901 /* there is not much to do here but clear the legacy flag */ 6902 was_legacy = 0; 6903 legacy = 0; 6904 implicit_direction = 1; 6905 } 6906 socket_type_str = hst_to_str(socket_type); 6907} 6908 6909char omni_usage[] = "\n\ 6910Usage: netperf [global options] -- [test options] \n\ 6911\n\ 6912OMNI and Migrated BSD Sockets Test Options:\n\ 6913 -b number Send number requests at start of _RR tests\n\ 6914 -c Explicitly declare this a connection test such as\n\ 6915 TCP_CRR or TCP_CC\n\ 6916 -C Set TCP_CORK when available\n\ 6917 -d direction Explicitly set test direction based on bitwise OR\n\ 6918 of 0x2 for transmit and 0x4 for receive. Default:\n\ 6919 based on test type\n\ 6920 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\ 6921 -h Display this text\n\ 6922 -H name[/mask],fam Use name (or IP) and family as target of data connection\n\ 6923 A mask value will cause randomization of the IP used\n\ 6924 -k [file] Generate keyval output optionally based on file\n\ 6925 Use filename of '?' to get the list of choices\n\ 6926 -K loc[,rem] Set the local and/or remote congestion control\n\ 6927 algorithm to use on those platforms where it can\n\ 6928 be set.\n\ 6929 -L name[/mask],fam Use name (or IP) and family as source of data connection\n\ 6930 A mask value will cause randomization of the IP used\n\ 6931 -m local,remote Set the send size for _STREAM/_MAERTS tests\n\ 6932 -M local,remote Set the recv size for _STREAM/_MAERTS tests\n\ 6933 -n Use the connected socket for UDP locally\n\ 6934 -N Use the connected socket for UDP remotely\n\ 6935 -o [file] Generate CSV output optionally based on file\n\ 6936 Use filename of '?' to get the list of choices\n\ 6937 -O [file] Generate classic-style output based on file\n\ 6938 Use filename of '?' to get the list of choices\n\ 6939 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\ 6940 -P local[,remote] Set the local/remote port for the data socket\n\ 6941 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\ 6942 -R 0/1 Allow routing of traffic on data connection.\n\ 6943 Default: 0 (off) for UDP_STREAM, 1 (on) otherwise\n\ 6944 -s send[,recv] Set local socket send/recv buffer sizes\n\ 6945 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 6946 -t type Explicitly set socket type. Default is implicit\n\ 6947 based on other settings\n\ 6948 -T protocol Explicitly set data connection protocol. Default is\n\ 6949 implicit based on other settings\n\ 6950 -u uuid Use the supplied string as the UUID for this test.\n\ 6951 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 6952 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 6953\n\ 6954For those options taking two parms, at least one must be specified;\n\ 6955specifying one value without a comma will set both parms to that\n\ 6956value, specifying a value with a leading comma will set just the second\n\ 6957parm, a value with a trailing comma will set just the first. To set\n\ 6958each parm to unique values, specify both and separate them with a\n\ 6959comma.\n"; 6960 6961void 6962print_omni_usage() 6963{ 6964 6965 fwrite(omni_usage, sizeof(char), strlen(omni_usage), stdout); 6966 exit(1); 6967 6968} 6969 6970 6971void 6972scan_omni_args(int argc, char *argv[]) 6973 6974{ 6975 6976#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" 6977 6978 extern char *optarg; /* pointer to option string */ 6979 6980 int c; 6981 int have_uuid = 0; 6982 int have_R_option = 0; 6983 6984 char 6985 arg1[BUFSIZ], /* argument holders */ 6986 arg2[BUFSIZ], 6987 arg3[BUFSIZ]; 6988 6989 if (debug) { 6990 int i; 6991 printf("%s called with the following argument vector\n", 6992 __FUNCTION__); 6993 for (i = 0; i< argc; i++) { 6994 printf("%s ",argv[i]); 6995 } 6996 printf("\n"); 6997 } 6998 6999 /* double-check struct sizes */ 7000 { 7001 const union netperf_request_struct * u = (const union netperf_request_struct *)0; 7002 if (debug) { 7003 fprintf(where, "sizeof(omni_request_struct)=%d/%d\n", 7004 (int)sizeof(struct omni_request_struct), 7005 (int)sizeof(u->content.test_specific_data)); 7006 fprintf(where, "sizeof(omni_response_struct)=%d/%d\n", 7007 (int)sizeof(struct omni_response_struct), 7008 (int)sizeof(u->content.test_specific_data)); 7009 fprintf(where, "sizeof(omni_results_struct)=%d/%d\n", 7010 (int)sizeof(struct omni_results_struct), 7011 (int)sizeof(u->content.test_specific_data)); 7012 } 7013 assert(sizeof(struct omni_request_struct) 7014 <= sizeof(u->content.test_specific_data)); 7015 assert(sizeof(struct omni_response_struct) 7016 <= sizeof(u->content.test_specific_data)); 7017 assert(sizeof(struct omni_results_struct) 7018 <= sizeof(u->content.test_specific_data)); 7019 } 7020 7021 strncpy(local_data_port,"0",sizeof(local_data_port)); 7022 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 7023 7024 /* this will handle setting default settings based on test name */ 7025 set_omni_defaults_by_legacy_testname(); 7026 7027 /* Go through all the command line arguments and break them out. For 7028 those options that take two parms, specifying only the first will 7029 set both to that value. Specifying only the second will leave the 7030 first untouched. To change only the first, use the form "first," 7031 (see the routine break_args.. */ 7032 7033 while ((c= getopt(argc, argv, OMNI_ARGS)) != EOF) { 7034 switch (c) { 7035 case '?': 7036 case '4': 7037 remote_data_family = AF_INET; 7038 local_data_family = AF_INET; 7039 break; 7040 case '6': 7041#if defined(AF_INET6) 7042 remote_data_family = AF_INET6; 7043 local_data_family = AF_INET6; 7044#else 7045 fprintf(stderr, 7046 "This netperf was not compiled on an IPv6 capable host!\n"); 7047 fflush(stderr); 7048 exit(-1); 7049#endif 7050 break; 7051 case 'h': 7052 print_omni_usage(); 7053 exit(1); 7054 case 'a': 7055 want_defer_accept = 1; 7056 break; 7057 case 'B': 7058 want_use_pktinfo = 1; 7059 break; 7060 case 'b': 7061#ifdef WANT_FIRST_BURST 7062 first_burst_size = atoi(optarg); 7063#else /* WANT_FIRST_BURST */ 7064 printf("Initial request burst functionality not compiled-in!\n"); 7065#endif /* WANT_FIRST_BURST */ 7066 break; 7067 case 'c': 7068 /* this is a connection test */ 7069 connection_test = 1; 7070 break; 7071 case 'C': 7072#ifdef TCP_CORK 7073 /* set TCP_CORK */ 7074 loc_tcpcork = 1; 7075 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */ 7076#else 7077 printf("WARNING: TCP_CORK not available on this platform!\n"); 7078#endif /* TCP_CORK */ 7079 break; 7080 case 'd': 7081 /* arbitrarily set the direction variable, but only for an 7082 actual omni test and then disable implicit setting of 7083 direction */ 7084 if (!was_legacy) { 7085 direction = parse_direction(optarg); 7086 implicit_direction = 0; 7087 } 7088 break; 7089 case 'D': 7090 /* set the TCP nodelay flag */ 7091 loc_nodelay = 1; 7092 rem_nodelay = 1; 7093 break; 7094 case 'F': 7095#if defined(MSG_FASTOPEN) 7096 use_fastopen = 1; 7097#else 7098 printf("WARNING: TCP FASTOPEN not available on this platform!\n"); 7099#endif 7100 break; 7101 case 'e': 7102 /* set the rEceive timeout */ 7103 receive_timeout = atoi(optarg); 7104 break; 7105 case 'g': 7106 /* enable SO_DEBUG, or at least make the attempt, on the data socket */ 7107 socket_debug = 1; 7108 break; 7109 case 'G': 7110 /* set the value for a tcp_maxseG call*/ 7111 transport_mss_req = atoi(optarg); 7112 break; 7113 case 'H': 7114 break_args_explicit_sep(optarg,',',arg1,arg2); 7115 if (arg1[0]) { 7116 /* check to see if there was a width, which we would want to 7117 be arg3. for simplicities sake, we will assume the width 7118 must follow the address and not the address family - ie 7119 1.2.3.4/24,inet. This means we can just pass optarg again 7120 as the source rather than have to shuffle arg values. */ 7121 break_args_explicit_sep(optarg,'/',arg1,arg3); 7122 if (arg1[0]) { 7123 remote_data_address = malloc(strlen(arg1)+1); 7124 strcpy(remote_data_address,arg1); 7125 explicit_data_address = 1; 7126 } 7127 if (arg3[0]) { 7128 remote_mask_len = convert(arg3); 7129 } 7130 } 7131 if (arg2[0]) { 7132 remote_data_family = parse_address_family(arg2); 7133 } 7134 break; 7135 case 'i': 7136 fprintf(stderr,"The support for check_interval has been removed because the contributing editor no longer knew what it was for\n"); 7137 fflush(stderr); 7138 break; 7139 case 'I': 7140 use_write = 1; 7141 break; 7142 case 'j': 7143 parallel_connections = atoi(optarg); 7144 break; 7145 case 'k': 7146 netperf_output_mode = KEYVAL; 7147 legacy = 0; 7148 /* obliterate any previous file name */ 7149 if (output_selection_spec) { 7150 free(output_selection_spec); 7151 output_selection_spec = NULL; 7152 } 7153 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7154 /* we assume that what follows is the name of a file with the 7155 list of desired output values. */ 7156 output_selection_spec = strdup(argv[optind]); 7157 optind++; 7158 /* special case - if the file name is "?" then we will emit a 7159 list of the available outputs */ 7160 if (strcmp(output_selection_spec,"?") == 0) { 7161 dump_netperf_output_choices(stdout,1); 7162 exit(1); 7163 } 7164 } 7165 break; 7166 case 'K': 7167 /* "Kongestion Kontrol */ 7168 break_args(optarg,arg1,arg2); 7169 if (arg1[0]) 7170 strncpy(local_cong_control_req,arg1,sizeof(local_cong_control_req)); 7171 if (arg2[2]) 7172 strncpy(remote_cong_control_req,arg2,sizeof(remote_cong_control_req)); 7173 break; 7174 case 'l': 7175 multicast_ttl = atoi(optarg); 7176 break; 7177 case 'L': 7178 break_args_explicit_sep(optarg,',',arg1,arg2); 7179 if (arg1[0]) { 7180 /* check to see if there was a width, which we would want to 7181 be arg3. for simplicities sake, we will assume the width 7182 must follow the address and not the address family - ie 7183 1.2.3.4/24,inet. This means we can just pass optarg again 7184 as the source rather than have to shuffle arg values. */ 7185 break_args_explicit_sep(optarg,'/',arg1,arg3); 7186 if (arg1[0]) { 7187 local_data_address = malloc(strlen(arg1)+1); 7188 strcpy(local_data_address,arg1); 7189 } 7190 if (arg3[0]) { 7191 local_mask_len = convert(arg3); 7192 } 7193 } 7194 if (arg2[0]) { 7195 local_data_family = parse_address_family(arg2); 7196 } 7197 break; 7198 case 'm': 7199 /* set the send size. if we set the local send size it will add 7200 XMIT to direction. if we set the remote send size it will 7201 add RECV to the direction. likely as not this will need some 7202 additional throught */ 7203 break_args_explicit(optarg,arg1,arg2); 7204 if (arg1[0]) { 7205 send_size = convert(arg1); 7206 if (implicit_direction) 7207 direction |= NETPERF_XMIT; 7208 } 7209 if (arg2[0]) { 7210 remote_send_size_req = convert(arg2); 7211 if (implicit_direction) 7212 direction |= NETPERF_RECV; 7213 } 7214 break; 7215 case 'M': 7216 /* set the recv sizes. if we set the local recv size it will 7217 add RECV to direction. if we set the remote recv size it 7218 will add XMIT to direction */ 7219 break_args_explicit(optarg,arg1,arg2); 7220 if (arg1[0]) { 7221 remote_recv_size_req = convert(arg1); 7222 if (implicit_direction) 7223 direction |= NETPERF_XMIT; 7224 } 7225 if (arg2[0]) { 7226 recv_size = convert(arg2); 7227 if (implicit_direction) 7228 direction |= NETPERF_RECV; 7229 } 7230 break; 7231 case 'n': 7232 /* set the local socket type */ 7233 local_connected = 1; 7234 break; 7235 case 'N': 7236 /* set the remote socket type */ 7237 remote_connected = 1; 7238 break; 7239 case 'o': 7240 netperf_output_mode = CSV; 7241 legacy = 0; 7242 /* obliterate any previous file name */ 7243 if (output_selection_spec) { 7244 free(output_selection_spec); 7245 output_selection_spec = NULL; 7246 } 7247 if (output_selection_spec) { 7248 free(output_selection_spec); 7249 output_selection_spec = NULL; 7250 } 7251 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7252 /* we assume that what follows is the name of a file with the 7253 list of desired output values. */ 7254 output_selection_spec = strdup(argv[optind]); 7255 optind++; 7256 /* special case - if the file name is "?" then we will emit a 7257 list of the available outputs */ 7258 if (strcmp(output_selection_spec,"?") == 0) { 7259 dump_netperf_output_choices(stdout,1); 7260 exit(1); 7261 } 7262 } 7263 break; 7264 case 'O': 7265 netperf_output_mode = HUMAN; 7266 legacy = 0; 7267 /* obliterate any previous file name */ 7268 if (output_selection_spec) { 7269 free(output_selection_spec); 7270 output_selection_spec = NULL; 7271 } 7272 if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) { 7273 /* we assume that what follows is the name of a file with the 7274 list of desired output values */ 7275 output_selection_spec = strdup(argv[optind]); 7276 optind++; 7277 if (strcmp(output_selection_spec,"?") == 0) { 7278 dump_netperf_output_choices(stdout,0); 7279 exit(1); 7280 } 7281 } 7282 break; 7283 case 'p': 7284 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */ 7285 /* tests. */ 7286 break_args(optarg,arg1,arg2); 7287 if (arg1[0]) 7288 client_port_min = atoi(arg1); 7289 if (arg2[0]) 7290 client_port_max = atoi(arg2); 7291 break; 7292 case 'P': 7293 /* set the local and remote data port numbers for the tests to 7294 allow them to run through those blankety blank end-to-end 7295 breaking firewalls. raj 2004-06-15 */ 7296 break_args(optarg,arg1,arg2); 7297 if (arg1[0]) 7298 strncpy(local_data_port,arg1,sizeof(local_data_port)); 7299 if (arg2[0]) 7300 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 7301 break; 7302 case 'r': 7303 /* set the request/response sizes. setting request/response 7304 sizes implicitly sets direction to XMIT and RECV */ 7305 if (implicit_direction) { 7306 direction |= NETPERF_XMIT; 7307 direction |= NETPERF_RECV; 7308 } 7309 break_args(optarg,arg1,arg2); 7310 if (arg1[0]) 7311 req_size = convert(arg1); 7312 if (arg2[0]) 7313 rsp_size = convert(arg2); 7314 break; 7315 case 'R': 7316 routing_allowed = atoi(optarg); 7317 have_R_option = 1; 7318 break; 7319 case 's': 7320 /* set local socket sizes */ 7321 break_args(optarg,arg1,arg2); 7322 if (arg1[0]) 7323 lss_size_req = convert(arg1); 7324 if (arg2[0]) 7325 lsr_size_req = convert(arg2); 7326 break; 7327 case 'S': 7328 /* set remote socket sizes */ 7329 break_args(optarg,arg1,arg2); 7330 if (arg1[0]) 7331 rss_size_req = convert(arg1); 7332 if (arg2[0]) 7333 rsr_size_req = convert(arg2); 7334 break; 7335 case 't': 7336 /* set the socket type */ 7337 socket_type = parse_socket_type(optarg); 7338 break; 7339 case 'T': 7340 /* set the protocol - aka "Transport" */ 7341 protocol = parse_protocol(optarg); 7342 break; 7343 case 'u': 7344 /* use the supplied string as the UUID for this test. at some 7345 point we may want to sanity check the string we are given but 7346 for now we won't worry about it */ 7347 strncpy(test_uuid,optarg,sizeof(test_uuid)); 7348 /* strncpy may leave us with a string without a null at the end */ 7349 test_uuid[sizeof(test_uuid) - 1] = 0; 7350 have_uuid = 1; 7351 break; 7352 case 'U': 7353 /* we don't want to give-up on the failure of a connect() call */ 7354 dont_give_up = 1; 7355 break; 7356 case 'W': 7357 /* set the "width" of the user space data */ 7358 /* buffer. This will be the number of */ 7359 /* send_size buffers malloc'd in the */ 7360 /* *_STREAM test. It may be enhanced to set */ 7361 /* both send and receive "widths" but for now */ 7362 /* it is just the sending *_STREAM. */ 7363 send_width = convert(optarg); 7364 break; 7365 case 'V' : 7366 /* we want to do copy avoidance and will set */ 7367 /* it for everything, everywhere, if we really */ 7368 /* can. of course, we don't know anything */ 7369 /* about the remote... */ 7370 loc_sndavoid = 1; 7371 loc_rcvavoid = 1; 7372 rem_sndavoid = 1; 7373 rem_rcvavoid = 1; 7374 break; 7375 }; 7376 } 7377 7378 /* generate the UUID for this test if the user has not supplied it */ 7379 if (!have_uuid) 7380 get_uuid_string(test_uuid,sizeof(test_uuid)); 7381 7382 protocol_str = protocol_to_str(protocol); 7383 /* ok, if we have gone through all that, and direction is still 7384 zero, let us see if it needs to be set to something else. */ 7385 if ((0 == direction) && (!connection_test)) direction = NETPERF_XMIT; 7386 direction_str = direction_to_str(direction); 7387 7388 /* to cover the backside of blithering idiots who run unidirectional 7389 UDP tests on test setups where they might trash their corporate 7390 WAN, we grudgingly provide a safety latch. unless explicitly 7391 enabled, UDP_STREAM/UDP_MAERTS sockets will not allow themselves 7392 to be routed via a gateway. raj 20091026 */ 7393 7394 if ((!have_R_option) && 7395 (protocol == IPPROTO_UDP) && 7396 (!NETPERF_IS_RR(direction))) { 7397 routing_allowed = 0; 7398 } 7399 7400 /* some other sanity checks we need to make would include stuff when 7401 the user has set -m and -M such that both XMIT and RECV are set 7402 and has not set -r. initially we will not allow that. at some 7403 point we might allow that if the user has also set -r, but until 7404 then the code will simply ignore the values from -m and -M when 7405 -r is set. */ 7406 7407#if defined(WANT_HISTOGRAM) 7408 if (verbosity > 1) keep_histogram = 1; 7409#endif 7410 7411 /* did the user use -d 6 but not set -r? */ 7412 if (NETPERF_IS_RR(direction) && !NETPERF_CC(direction)) { 7413 if (req_size == -1) 7414 req_size = 1; 7415 if (rsp_size == -1) 7416 rsp_size = 1; 7417 } 7418 7419 /* ok, time to sanity check the output units */ 7420 if ('?' == libfmt) { 7421 /* if this is a RR test then set it to 'x' for transactions */ 7422 if (NETPERF_IS_RR(direction)) { 7423 libfmt = 'x'; 7424 } 7425 else { 7426 libfmt = 'm'; 7427 } 7428 } 7429 else if ('x' == libfmt) { 7430 /* now, a format of 'x' makes no sense for anything other than 7431 an RR test. if someone has been silly enough to try to set 7432 that, we will reset it silently to default - namely 'm' */ 7433 if (!NETPERF_IS_RR(direction)) { 7434 libfmt = 'm'; 7435 } 7436 } 7437 7438 /* this needs to be strdup :) */ 7439 thruput_format_str = strdup(format_units()); 7440 7441 /* so, if there is to be no control connection, we want to have some 7442 different settings for a few things */ 7443 7444 if (no_control) { 7445 if (strcmp(remote_data_port,"0") == 0) { 7446 /* we need to select either the discard port, echo port or 7447 chargen port dedepending on the test direction. raj 7448 20101220 */ 7449 if (NETPERF_XMIT_ONLY(direction)) { 7450 strncpy(remote_data_port,"discard",sizeof(remote_data_port)); 7451 recv_size = -1; 7452 } 7453 else if (NETPERF_RECV_ONLY(direction)) { 7454 strncpy(remote_data_port,"chargen",sizeof(remote_data_port)); 7455 send_size = -1; 7456 } 7457 else if (NETPERF_IS_RR(direction) || NETPERF_CC(direction)) { 7458 strncpy(remote_data_port,"echo",sizeof(remote_data_port)); 7459 rsp_size = req_size; 7460 } 7461 else { 7462 printf("No default port known for the %s test, please set one yourself\n",test_name); 7463 exit(-1); 7464 } 7465 } 7466 remote_data_port[sizeof(remote_data_port) - 1] = '\0'; 7467 7468 /* I go back and forth on whether these should become -1 or if 7469 they should become 0 for a no_control test. what do you think? 7470 raj 2006-02-08 */ 7471 7472 rem_rcvavoid = -1; 7473 rem_sndavoid = -1; 7474 rss_size_req = -1; 7475 rsr_size_req = -1; 7476 rem_nodelay = -1; 7477 7478 } 7479 /* so, did the user request a few things implicitly via output selection? */ 7480 if (!legacy) 7481 print_omni_init(); 7482 7483 if (desired_output_groups & OMNI_WANT_STATS) { 7484 keep_statistics = 1; 7485 keep_histogram = 1; 7486 } 7487 7488} 7489 7490#endif /* WANT_OMNI */ 7491