1 char netlib_id[]="\ 2 @(#)netlib.c (c) Copyright 1993-2012 Hewlett-Packard Company. Version 2.6.0"; 3 4 5 /****************************************************************/ 6 /* */ 7 /* netlib.c */ 8 /* */ 9 /* the common utility routines available to all... */ 10 /* */ 11 /* establish_control() establish the control socket */ 12 /* calibrate_local_cpu() do local cpu calibration */ 13 /* calibrate_remote_cpu() do remote cpu calibration */ 14 /* send_request() send a request to the remote */ 15 /* recv_response() receive a response from remote */ 16 /* send_response() send a response to the remote */ 17 /* recv_request() recv a request from the remote */ 18 /* dump_request() dump request contents */ 19 /* dump_response() dump response contents */ 20 /* cpu_start() start measuring cpu */ 21 /* cpu_stop() stop measuring cpu */ 22 /* calc_cpu_util() calculate the cpu utilization */ 23 /* calc_service_demand() calculate the service demand */ 24 /* calc_thruput() calulate the tput in units */ 25 /* calibrate() really calibrate local cpu */ 26 /* identify_local() print local host information */ 27 /* identify_remote() print remote host information */ 28 /* format_number() format the number (KB, MB,etc) */ 29 /* format_units() return the format in english */ 30 /* msec_sleep() sleep for some msecs */ 31 /* start_timer() start a timer */ 32 /* random_ip_address() select a random IP address from */ 33 /* specified range */ 34 /* */ 35 /* the routines you get when WANT_DLPI is defined... */ 36 /* ...all moved to src/nettest_dlpi.c */ 37 /* */ 38 /* dl_open() open a file descriptor and */ 39 /* attach to the card */ 40 /* dl_mtu() find the MTU of the card */ 41 /* dl_bind() bind the sap do the card */ 42 /* dl_connect() sender's have of connect */ 43 /* dl_accpet() receiver's half of connect */ 44 /* dl_set_window() set the window size */ 45 /* dl_stats() retrieve statistics */ 46 /* dl_send_disc() initiate disconnect (sender) */ 47 /* dl_recv_disc() accept disconnect (receiver) */ 48 /****************************************************************/ 49 50 /****************************************************************/ 51 /* */ 52 /* Global include files */ 53 /* */ 54 /****************************************************************/ 55 56 #ifdef HAVE_CONFIG_H 57 #include <config.h> 58 #endif 59 60 /* It would seem that most of the includes being done here from 61 "sys/" actually have higher-level wrappers at just /usr/include. 62 This is based on a spot-check of a couple systems at my disposal. 63 If you have trouble compiling you may want to add "sys/" raj 64 10/95 */ 65 #include <limits.h> 66 #include <signal.h> 67 #ifdef HAVE_SYSCALL_H 68 #include <syscall.h> 69 #endif 70 #ifdef MPE 71 # define NSIG _NSIG 72 #endif /* MPE */ 73 #include <sys/types.h> 74 #include <fcntl.h> 75 #include <stdio.h> 76 #include <stdlib.h> 77 #include <math.h> 78 #include <string.h> 79 #include <assert.h> 80 #ifdef HAVE_ENDIAN_H 81 #include <endian.h> 82 #endif 83 84 85 #ifndef WIN32 86 /* at some point, I would like to get rid of all these "sys/" 87 includes where appropriate. if you have a system that requires/ 88 them, speak now, or your system may not compile later revisions of 89 netperf. raj 1/96 */ 90 #include <unistd.h> 91 #include <sys/stat.h> 92 #include <sys/times.h> 93 #ifndef MPE 94 #include <time.h> 95 #include <sys/time.h> 96 #endif /* MPE */ 97 #include <sys/socket.h> 98 #include <netinet/in.h> 99 #include <arpa/inet.h> 100 #include <netdb.h> 101 #include <errno.h> 102 #include <sys/utsname.h> 103 #if !defined(MPE) && !defined(__VMS) 104 #include <sys/param.h> 105 #endif /* MPE */ 106 107 #else /* WIN32 */ 108 109 #include <process.h> 110 #include <time.h> 111 #include <winsock2.h> 112 #define netperf_socklen_t socklen_t 113 #include <windows.h> 114 #include <mmsystem.h> 115 /* the only time someone should need to define DONT_IPV6 in the 116 "sources" file is if they are trying to compile on Windows 2000 or 117 NT4 and I suspect this may not be their only problem :) */ 118 #ifndef DONT_IPV6 119 #include <ws2tcpip.h> 120 #endif 121 122 #include <windows.h> 123 124 #define SIGALRM (14) 125 #define sleep(x) Sleep((x)*1000) 126 127 #endif /* WIN32 */ 128 129 #ifdef HAVE_UNAME 130 #include <sys/utsname.h> 131 #endif 132 133 #ifdef _AIX 134 #include <sys/select.h> 135 #include <sys/sched.h> 136 #include <sys/pri.h> 137 #define PRIORITY PRI_LOW 138 #else/* _AIX */ 139 #ifdef __sgi 140 #include <sys/prctl.h> 141 #include <sys/schedctl.h> 142 #define PRIORITY NDPLOMIN 143 #endif /* __sgi */ 144 #endif /* _AIX */ 145 146 147 #ifdef HAVE_MPCTL 148 #include <sys/mpctl.h> 149 #endif 150 151 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) 152 # include "missing/getaddrinfo.h" 153 #endif 154 155 156 #include "hist.h" 157 158 /****************************************************************/ 159 /* */ 160 /* Local Include Files */ 161 /* */ 162 /****************************************************************/ 163 #define NETLIB 164 #include "netlib.h" 165 #include "netsh.h" 166 #include "netcpu.h" 167 #include "netperf_version.h" 168 169 /****************************************************************/ 170 /* */ 171 /* Global constants, macros and variables */ 172 /* */ 173 /****************************************************************/ 174 175 #if defined(WIN32) || defined(__VMS) 176 struct timezone { 177 int dummy ; 178 } ; 179 #ifndef __VMS 180 SOCKET win_kludge_socket = INVALID_SOCKET; 181 SOCKET win_kludge_socket2 = INVALID_SOCKET; 182 #endif /* __VMS */ 183 #endif /* WIN32 || __VMS */ 184 185 #ifndef LONG_LONG_MAX 186 #define LONG_LONG_MAX 9223372036854775807LL 187 #endif /* LONG_LONG_MAX */ 188 189 /* older versions of netperf knew about the HP kernel IDLE counter. 190 this is now obsolete - in favor of either pstat(), times, or a 191 process-level looper process. we also now require support for the 192 "long" integer type. raj 4/95. */ 193 194 int 195 lib_num_loc_cpus, /* the number of cpus in the system */ 196 lib_num_rem_cpus; /* how many we think are in the remote */ 197 198 struct cpu_stats_struct 199 lib_local_cpu_stats, 200 lib_remote_cpu_stats; 201 202 #define PAGES_PER_CHILD 2 203 204 int lib_use_idle; 205 int cpu_method; 206 207 struct timeval time1, time2; 208 struct timezone tz; 209 float lib_elapsed, 210 lib_local_maxrate, 211 lib_remote_maxrate; 212 213 float lib_local_per_cpu_util[MAXCPUS]; 214 int lib_cpu_map[MAXCPUS]; 215 216 int *request_array; 217 int *response_array; 218 219 /* INVALID_SOCKET == INVALID_HANDLE_VALUE == (unsigned int)(~0) == -1 */ 220 SOCKET netlib_control = INVALID_SOCKET; 221 SOCKET server_sock = INVALID_SOCKET; 222 int control_family = AF_UNSPEC; 223 224 /* global variables to hold the value for processor affinity */ 225 int local_proc_affinity = -1,remote_proc_affinity = -1; 226 227 /* these are to allow netperf to be run easily through those evil, 228 end-to-end breaking things known as firewalls */ 229 char local_data_port[10]; 230 char remote_data_port[10]; 231 232 char *local_data_address=NULL; 233 char *remote_data_address=NULL; 234 235 char *local_sysname, *remote_sysname; 236 char *local_release, *remote_release; 237 char *local_version, *remote_version; 238 char *local_machine, *remote_machine; 239 240 int local_data_family=AF_UNSPEC; 241 int remote_data_family=AF_UNSPEC; 242 243 char *netperf_version; 244 245 enum netperf_output_modes netperf_output_mode = HUMAN; 246 247 /* in the past, I was overlaying a structure on an array of ints. now 248 I am going to have a "real" structure, and point an array of ints 249 at it. the real structure will be forced to the same alignment as 250 the type "double." this change will mean that pre-2.1 netperfs 251 cannot be mixed with 2.1 and later. raj 11/95 */ 252 253 union netperf_request_struct netperf_request; 254 union netperf_response_struct netperf_response; 255 256 FILE *where; 257 258 char libfmt = '?'; 259 260 #ifdef WIN32 261 HANDLE hAlarm = INVALID_HANDLE_VALUE; 262 int timed_out=0; 263 #endif 264 265 int times_up; 266 267 #ifdef WIN32 268 /* we use a getopt implementation from net.sources */ 269 /* 270 * get option letter from argument vector 271 */ 272 int 273 opterr = 1, /* should error messages be printed? */ 274 optind = 1, /* index into parent argv vector */ 275 optopt; /* character checked for validity */ 276 char 277 *optarg; /* argument associated with option */ 278 279 #define EMSG "" 280 281 #endif /* WIN32 */ 282 283 static int measuring_cpu; 284 int 285 netlib_get_page_size(void) { 286 287 /* not all systems seem to have the sysconf for page size. for 288 those which do not, we will assume that the page size is 8192 289 bytes. this should be more than enough to be sure that there is 290 no page or cache thrashing by looper processes on MP 291 systems. otherwise that's really just too bad - such systems 292 should define _SC_PAGE_SIZE - raj 4/95 */ 293 294 #ifndef _SC_PAGE_SIZE 295 #ifdef WIN32 296 297 SYSTEM_INFO SystemInfo; 298 299 GetSystemInfo(&SystemInfo); 300 301 return SystemInfo.dwPageSize; 302 #else 303 return(8192L); 304 #endif /* WIN32 */ 305 #else 306 return(sysconf(_SC_PAGE_SIZE)); 307 #endif /* _SC_PAGE_SIZE */ 308 309 } 310 311 312 314 #ifdef WANT_INTERVALS 315 #ifdef WIN32 316 HANDLE WinTimer; 317 UINT timerRes; 318 void stop_itimer() 319 { 320 CancelWaitableTimer(WinTimer); 321 CloseHandle(WinTimer); 322 timeEndPeriod(timerRes); 323 } 324 #else 325 static unsigned int usec_per_itvl; 326 327 328 void 329 stop_itimer() 330 331 { 332 333 struct itimerval new_interval; 334 struct itimerval old_interval; 335 336 new_interval.it_interval.tv_sec = 0; 337 new_interval.it_interval.tv_usec = 0; 338 new_interval.it_value.tv_sec = 0; 339 new_interval.it_value.tv_usec = 0; 340 if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) { 341 /* there was a problem arming the interval timer */ 342 perror("netperf: setitimer"); 343 exit(1); 344 } 345 return; 346 } 347 #endif /* WIN32 */ 348 #endif /* WANT_INTERVALS */ 349 350 352 353 #ifdef WIN32 355 static void 356 error(char *pch) 357 { 358 if (!opterr) { 359 return; /* without printing */ 360 } 361 fprintf(stderr, "%s: %s: %c\n", 362 (NULL != program) ? program : "getopt", pch, optopt); 363 } 364 365 int 366 getopt(int argc, char **argv, char *ostr) 367 { 368 static char *place = EMSG; /* option letter processing */ 369 register char *oli; /* option letter list index */ 370 371 if (!*place) { 372 /* update scanning pointer */ 373 if (optind >= argc || *(place = argv[optind]) != '-' || !*++place) { 374 return EOF; 375 } 376 if (*place == '-') { 377 /* found "--" */ 378 ++optind; 379 place = EMSG ; /* Added by shiva for Netperf */ 380 return EOF; 381 } 382 } 383 384 /* option letter okay? */ 385 if ((optopt = (int)*place++) == (int)':' 386 || !(oli = strchr(ostr, optopt))) { 387 if (!*place) { 388 ++optind; 389 } 390 error("illegal option"); 391 return BADCH; 392 } 393 if (*++oli != ':') { 394 /* don't need argument */ 395 optarg = NULL; 396 if (!*place) 397 ++optind; 398 } else { 399 /* need an argument */ 400 if (*place) { 401 optarg = place; /* no white space */ 402 } else if (argc <= ++optind) { 403 /* no arg */ 404 place = EMSG; 405 error("option requires an argument"); 406 return BADCH; 407 } else { 408 optarg = argv[optind]; /* white space */ 409 } 410 place = EMSG; 411 ++optind; 412 } 413 return optopt; /* return option letter */ 414 } 415 #endif /* WIN32 */ 416 417 /*---------------------------------------------------------------------------- 418 * WIN32 implementation of perror, does not deal very well with WSA errors 419 * The stdlib.h version of perror only deals with the ancient XENIX error codes. 420 * 421 * +*+SAF Why can't all WSA errors go through GetLastError? Most seem to... 422 *--------------------------------------------------------------------------*/ 423 424 #ifdef WIN32 425 void PrintWin32Error(FILE *stream, LPSTR text) 426 { 427 LPSTR szTemp; 428 DWORD dwResult; 429 DWORD dwError; 430 431 dwError = GetLastError(); 432 dwResult = FormatMessage( 433 FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY, 434 NULL, 435 dwError, 436 LANG_NEUTRAL, 437 (LPTSTR)&szTemp, 438 0, 439 NULL ); 440 441 if (dwResult) 442 fprintf(stream, "%s: %s\n", text, szTemp); 443 else 444 fprintf(stream, "%s: error 0x%x\n", text, dwError); 445 fflush(stream); 446 447 if (szTemp) 448 LocalFree((HLOCAL)szTemp); 449 } 450 #endif /* WIN32 */ 451 452 char * 453 nsec_enabled_to_str(int enabled) { 454 switch (enabled) { 455 case NSEC_UNKNOWN: 456 return("Unknown"); 457 case NSEC_DISABLED: 458 return("Disabled"); 459 case NSEC_PERMISSIVE: 460 return("Permissive"); 461 case NSEC_ENFORCING: 462 return("Enforcing"); 463 default: 464 return("UNKNOWN MODE"); 465 } 466 } 467 468 char * nsec_type_to_str(int type) { 469 switch (type) { 470 case NSEC_TYPE_UNKNOWN: 471 return("Unknown"); 472 case NSEC_TYPE_SELINUX: 473 return("SELinux"); 474 default: 475 return("UNKNOWN TYPE"); 476 } 477 } 478 479 480 char * 482 inet_ttos(int type) 483 { 484 switch (type) { 485 case SOCK_DGRAM: 486 return("SOCK_DGRAM"); 487 break; 488 case SOCK_STREAM: 489 return("SOCK_STREAM"); 490 break; 491 #ifdef SOCK_DCCP 492 case SOCK_DCCP: 493 return("SOCK_DCCP"); 494 #endif 495 #ifdef SOCK_SEQPACKET 496 case SOCK_SEQPACKET: 497 return("SOCK_SEQPACKET"); 498 #endif 499 default: 500 return("SOCK_UNKNOWN"); 501 } 502 } 503 504 505 506 508 char unknown[32]; 509 510 char * 511 inet_ptos(int protocol) { 512 switch (protocol) { 513 case IPPROTO_TCP: 514 return("IPPROTO_TCP"); 515 break; 516 case IPPROTO_UDP: 517 return("IPPROTO_UDP"); 518 break; 519 #if defined(IPPROTO_SCTP) 520 case IPPROTO_SCTP: 521 return("IPPROTO_SCTP"); 522 break; 523 #endif 524 #if defined(IPPROTO_DCCP) 525 case IPPROTO_DCCP: 526 return "IPPROTO_DCCP"; 527 break; 528 #endif 529 #if defined(IPPROTO_UDPLITE) 530 case IPPROTO_UDPLITE: 531 return "IPPROTO_UDPLITE"; 532 break; 533 #endif 534 default: 535 snprintf(unknown,sizeof(unknown),"IPPROTO_UNKNOWN(%d)",protocol); 536 return(unknown); 537 } 538 } 539 540 /* one of these days, this should not be required */ 541 #ifndef AF_INET_SDP 542 #define AF_INET_SDP 27 543 #define PF_INET_SDP AF_INET_SDP 544 #endif 545 546 char * 547 inet_ftos(int family) 548 { 549 switch(family) { 550 case AF_INET: 551 return("AF_INET"); 552 #if defined(AF_INET6) 553 case AF_INET6: 554 return("AF_INET6"); 555 #endif 556 #if defined(AF_INET_SDP) 557 case AF_INET_SDP: 558 return("AF_INET_SDP"); 559 #endif 560 #if defined(AF_RDS) 561 case AF_RDS: 562 return("AF_RDS"); 563 #endif 564 default: 565 return("AF_UNSPEC"); 566 } 567 } 568 569 int 570 inet_nton(int af, const void *src, char *dst, int cnt) 571 572 { 573 574 switch (af) { 575 case AF_INET: 576 /* magic constants again... :) */ 577 if (cnt >= 4) { 578 memcpy(dst,src,4); 579 return 4; 580 } 581 else { 582 Set_errno(ENOSPC); 583 return(-1); 584 } 585 break; 586 #if defined(AF_INET6) 587 case AF_INET6: 588 if (cnt >= 16) { 589 memcpy(dst,src,16); 590 return(16); 591 } 592 else { 593 Set_errno(ENOSPC); 594 return(-1); 595 } 596 break; 597 #endif 598 #if defined(AF_RDS) 599 case AF_RDS: 600 if (cnt >= 4) { 601 memcpy(dst,src,4); 602 return 4; 603 } 604 #endif 605 default: 606 Set_errno(EAFNOSUPPORT); 607 return(-1); 608 } 609 } 610 611 double 612 ntohd(double net_double) 613 614 { 615 /* we rely on things being nicely packed */ 616 union { 617 double whole_thing; 618 unsigned int words[2]; 619 unsigned char bytes[8]; 620 } conv_rec; 621 622 unsigned char scratch; 623 int i; 624 625 /* on those systems where ntohl is a no-op, we want to return the 626 original value, unchanged */ 627 628 if (ntohl(1L) == 1L) { 629 return(net_double); 630 } 631 632 conv_rec.whole_thing = net_double; 633 634 /* we know that in the message passing routines that ntohl will have 635 been called on the 32 bit quantities. we need to put those back 636 the way they belong before we swap */ 637 conv_rec.words[0] = htonl(conv_rec.words[0]); 638 conv_rec.words[1] = htonl(conv_rec.words[1]); 639 640 /* now swap */ 641 for (i=0; i<= 3; i++) { 642 scratch = conv_rec.bytes[i]; 643 conv_rec.bytes[i] = conv_rec.bytes[7-i]; 644 conv_rec.bytes[7-i] = scratch; 645 } 646 647 #if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER) 648 if (__FLOAT_WORD_ORDER != __BYTE_ORDER) { 649 /* Fixup mixed endian floating point machines */ 650 unsigned int scratch = conv_rec.words[0]; 651 conv_rec.words[0] = conv_rec.words[1]; 652 conv_rec.words[1] = scratch; 653 } 654 #endif 655 656 return(conv_rec.whole_thing); 657 658 } 659 660 double 661 htond(double host_double) 662 663 { 664 /* we rely on things being nicely packed */ 665 union { 666 double whole_thing; 667 unsigned int words[2]; 668 unsigned char bytes[8]; 669 } conv_rec; 670 671 unsigned char scratch; 672 int i; 673 674 /* on those systems where ntohl is a no-op, we want to return the 675 original value, unchanged */ 676 677 if (ntohl(1L) == 1L) { 678 return(host_double); 679 } 680 681 conv_rec.whole_thing = host_double; 682 683 /* now swap */ 684 for (i=0; i<= 3; i++) { 685 scratch = conv_rec.bytes[i]; 686 conv_rec.bytes[i] = conv_rec.bytes[7-i]; 687 conv_rec.bytes[7-i] = scratch; 688 } 689 690 #if defined(__FLOAT_WORD_ORDER) && defined(__BYTE_ORDER) 691 if (__FLOAT_WORD_ORDER != __BYTE_ORDER) { 692 /* Fixup mixed endian floating point machines */ 693 unsigned int scratch = conv_rec.words[0]; 694 conv_rec.words[0] = conv_rec.words[1]; 695 conv_rec.words[1] = scratch; 696 } 697 #endif 698 699 /* we know that in the message passing routines htonl will be called 700 on the 32 bit quantities. we need to set things up so that when 701 this happens, the proper order will go out on the network */ 702 conv_rec.words[0] = htonl(conv_rec.words[0]); 703 conv_rec.words[1] = htonl(conv_rec.words[1]); 704 705 return(conv_rec.whole_thing); 706 707 } 708 709 710 712 /* The original patch from Google used lrand48, but I have been 713 informed that is not easily available under Windows. So, rather 714 than have some #ifdefs here I'll just simplistically replace 715 lrand48 with rand(), which should be "good enough" at some point it 716 may be sufficient to just call rand() directly rather than call 717 this raj 20101130 */ 718 719 unsigned int 720 rand32(){ 721 return (unsigned int)rand() * 2 + rand() % 2; 722 } 723 724 /* this routine will set the ip address of the sockaddr in the 725 addrinfo to a random number in range, based on the address 726 family. for grins, we will sanity check the value of mask_len 727 against the address family. initial version from google, 728 enhancements by raj 20101129 */ 729 void 730 random_ip_address(struct addrinfo *res, int mask_len) 731 { 732 switch(res->ai_family) { 733 case AF_INET: { 734 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 735 unsigned int addr = ntohl(foo->sin_addr.s_addr); 736 unsigned int mask = ((unsigned int)1 << (32 - mask_len)) - 1; 737 738 if ((mask_len < 0) || (mask_len > 32)) { 739 fprintf(where, 740 "Mask length must be between 0 and 32 inclusive for AF_INET\n"); 741 fflush(where); 742 exit(-1); 743 } 744 745 addr = ntohl(foo->sin_addr.s_addr); 746 do { 747 addr = (addr & ~mask) | (rand32() & mask); 748 } while ((addr & 0xff) == 0xff); 749 foo->sin_addr.s_addr = htonl(addr); 750 break; 751 } 752 #if defined(AF_INET6) 753 case AF_INET6: { 754 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 755 756 unsigned int i, len; 757 unsigned int *addr = (unsigned int *)&(foo->sin6_addr.s6_addr); 758 unsigned int mask; 759 760 if ((mask_len < 0) || (mask_len > 128)) { 761 fprintf(where, 762 "Mask length must be between 0 and 128 inclusive for AF_INET\n"); 763 fflush(where); 764 exit(-1); 765 } 766 767 for (i = 0; i < 4; i ++){ 768 addr[i] = ntohl(addr[i]); 769 len = mask_len - i * 32; 770 len = ((len < 32) ? len : 32); 771 len = ((len > 0) ? len : 0); 772 mask = ((unsigned int)1 << (32 - len)) - 1; 773 addr[i] = (addr[i] & ~mask) | (rand32() & mask); 774 addr[i] = htonl(addr[i]); 775 } 776 break; 777 } 778 #endif 779 default: 780 fprintf(where, 781 "Unexpected Address Family of %u\n",res->ai_family); 782 fflush(where); 783 exit(-1); 784 } 785 } 786 787 #if defined(HAVE_SENDFILE) 789 int netperf_sendfile(SOCKET send_socket, struct ring_elt *send_ring) { 790 791 int len; 792 int ret = 0; 793 794 #if defined(__linux) || defined(__sun) 795 off_t scratch_offset; /* the linux sendfile() call will update 796 the offset variable, which is 797 something we do _not_ want to happen 798 to the value in the send_ring! so, we 799 have to use a scratch variable. */ 800 #endif /* __linux || defined(__sun) */ 801 802 #if defined (__sun) 803 size_t scratch_len; /* the sun sendfilev() needs a place to 804 tell us how many bytes were written, 805 even though it also returns the value */ 806 sendfilevec_t sv; 807 #endif /* __sun */ 808 809 /* you can look at netlib.h for a description of the fields we 810 are passing to sendfile(). 08/2000 */ 811 #if defined(__linux) 812 scratch_offset = send_ring->offset; 813 len=sendfile(send_socket, 814 send_ring->fildes, 815 &scratch_offset, /* modified after the call! */ 816 send_ring->length); 817 #elif defined (__sun) 818 /* We must call with SFV_NOWAIT and a large file size (>= 16MB) 819 to get zero-copy, as well as compiling with 820 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 */ 821 sv.sfv_fd = send_ring->fildes; 822 sv.sfv_flag = SFV_NOWAIT; 823 sv.sfv_off = send_ring->offset; 824 sv.sfv_len = send_ring->length; 825 len = sendfilev(send_socket, &sv, 1, &scratch_len); 826 #elif defined(__FreeBSD__) 827 /* so close to HP-UX and yet so far away... :) */ 828 ret = sendfile(send_ring->fildes, 829 send_socket, 830 send_ring->offset, 831 send_ring->length, 832 NULL, 833 (off_t *)&len, 834 send_ring->flags); 835 #elif defined(USE_OSX) 836 len = send_ring->length; 837 ret = sendfile(send_ring->fildes, 838 send_socket, 839 send_ring->offset, 840 (off_t *)&len, 841 NULL, 842 send_ring->flags); 843 #else /* original sendile HP-UX */ 844 len=sendfile(send_socket, 845 send_ring->fildes, 846 send_ring->offset, 847 send_ring->length, 848 send_ring->hdtrl, 849 send_ring->flags); 850 #endif 851 852 /* for OSX and FreeBSD, a non-zero ret means something failed. 853 I would hope that the length fields are set to -1 or the 854 like, but at the moment I do not know I can count on 855 that. for other platforms, ret will be set to zero and we can 856 rely directly on len. raj 2013-05-01 */ 857 if (ret != 0) 858 return -1; 859 else 860 return len; 861 862 } 863 #endif 864 865 867 /* one of these days, this should be abstracted-out just like the CPU 868 util stuff. raj 2005-01-27 */ 869 int 870 get_num_cpus() 871 872 { 873 874 /* on HP-UX, even when we use the looper procs we need the pstat */ 875 /* call */ 876 877 int temp_cpus; 878 879 #ifdef __hpux 880 #include <sys/pstat.h> 881 882 struct pst_dynamic psd; 883 884 if (pstat_getdynamic((struct pst_dynamic *)&psd, 885 (size_t)sizeof(psd), (size_t)1, 0) != -1) { 886 temp_cpus = psd.psd_proc_cnt; 887 } 888 else { 889 temp_cpus = 1; 890 } 891 892 #else 893 /* MW: <unistd.h> was included for non-Windows systems above. */ 894 /* Thus if _SC_NPROC_ONLN is defined, we should be able to use sysconf. */ 895 #ifdef _SC_NPROCESSORS_ONLN 896 temp_cpus = sysconf(_SC_NPROCESSORS_ONLN); 897 898 #ifdef USE_PERFSTAT 899 temp_cpus = perfstat_cpu(NULL,NULL, sizeof(perfstat_cpu_t), 0); 900 #endif /* USE_PERFSTAT */ 901 902 #else /* no _SC_NPROCESSORS_ONLN */ 903 904 #ifdef WIN32 905 SYSTEM_INFO SystemInfo; 906 GetSystemInfo(&SystemInfo); 907 908 temp_cpus = SystemInfo.dwNumberOfProcessors; 909 #else 910 /* we need to know some other ways to do this, or just fall-back on 911 a global command line option - raj 4/95 */ 912 temp_cpus = shell_num_cpus; 913 #endif /* WIN32 */ 914 #endif /* _SC_NPROCESSORS_ONLN */ 915 #endif /* __hpux */ 916 917 if (temp_cpus > MAXCPUS) { 918 fprintf(where, 919 "Sorry, this system has more CPUs (%d) than I can handle (%d).\n" 920 "Please alter MAXCPUS in netlib.h and recompile.\n", 921 temp_cpus, 922 MAXCPUS); 923 fflush(where); 924 exit(1); 925 } 926 927 return(temp_cpus); 928 929 } 930 931 #ifdef WIN32 932 #ifdef __GNUC__ 933 #define S64_SUFFIX(x) x##LL 934 #else 935 #define S64_SUFFIX(x) x##i64 936 #endif 937 938 /* 939 * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970 940 */ 941 #define EPOCH_BIAS S64_SUFFIX(116444736000000000) 942 943 /* 944 * Union to facilitate converting from FILETIME to unsigned __int64 945 */ 946 typedef union { 947 unsigned __int64 ft_scalar; 948 FILETIME ft_struct; 949 } FT; 950 951 void 952 gettimeofday( struct timeval *tv , struct timezone *not_used ) 953 { 954 FT nt_time; 955 __int64 UnixTime; /* microseconds since 1/1/1970 */ 956 957 GetSystemTimeAsFileTime( &(nt_time.ft_struct) ); 958 959 UnixTime = ((nt_time.ft_scalar - EPOCH_BIAS) / S64_SUFFIX(10)); 960 tv->tv_sec = (long)(time_t)(UnixTime / S64_SUFFIX(1000000)); 961 tv->tv_usec = (unsigned long)(UnixTime % S64_SUFFIX(1000000)); 962 } 963 #endif /* WIN32 */ 964 965 966 /* this routine will disable any running timer */ 968 void 969 stop_timer() 970 { 971 #ifndef WIN32 972 alarm(0); 973 #else 974 /* at some point we may need some win32 equivalent */ 975 if (hAlarm != (HANDLE) INVALID_HANDLE_VALUE) { 976 SetEvent(hAlarm); 977 } 978 #endif /* WIN32 */ 979 980 } 981 982 983 985 /************************************************************************/ 986 /* */ 987 /* signal catcher */ 988 /* */ 989 /************************************************************************/ 990 #ifndef WIN32 991 void 992 #if defined(__hpux) 993 catcher(sig, code, scp) 994 int sig; 995 int code; 996 struct sigcontext *scp; 997 #else 998 catcher(int sig) 999 #endif /* __hpux || __VMS */ 1000 { 1001 1002 #ifdef __hpux 1003 if (debug > 2) { 1004 fprintf(where,"caught signal %d ",sig); 1005 if (scp) { 1006 fprintf(where,"while in syscall %d\n", 1007 scp->sc_syscall); 1008 } 1009 else { 1010 fprintf(where,"null scp\n"); 1011 } 1012 fflush(where); 1013 } 1014 #endif /* RAJ_DEBUG */ 1015 1016 switch(sig) { 1017 1018 case SIGINT: 1019 times_up = 1; 1020 break; 1021 case SIGALRM: 1022 if (--test_len_ticks == 0) { 1023 /* the test is over */ 1024 if (times_up != 0) { 1025 fprintf(where,"catcher: timer popped with times_up != 0\n"); 1026 fflush(where); 1027 } 1028 times_up = 1; 1029 #if defined(WANT_INTERVALS) && !defined(WANT_SPIN) 1030 stop_itimer(); 1031 /* we should also stop the normal test timer lest it fire at an 1032 inopportune moment - we do not know if we got here off the 1033 interval timer or the test timer... */ 1034 stop_timer(); 1035 #endif /* WANT_INTERVALS */ 1036 break; 1037 } 1038 else { 1039 #ifdef WANT_INTERVALS 1040 #ifdef __hpux 1041 /* the test is not over yet and we must have been using the 1042 interval timer. if we were in SYS_SIGSUSPEND we want to 1043 re-start the system call. Otherwise, we want to get out of 1044 the sigsuspend call. I NEED TO KNOW HOW TO DO THIS FOR OTHER 1045 OPERATING SYSTEMS. If you know how, please let me know. rick 1046 jones <rick.jones2 (at) hp.com> */ 1047 if (scp->sc_syscall != SYS_SIGSUSPEND) { 1048 if (debug > 2) { 1049 fprintf(where, 1050 "catcher: Time to send burst > interval!\n"); 1051 fflush(where); 1052 } 1053 scp->sc_syscall_action = SIG_RESTART; 1054 } 1055 #endif /* __hpux */ 1056 #else /* WANT_INTERVALS */ 1057 fprintf(where, 1058 "catcher: interval timer running unexpectedly!\n"); 1059 fflush(where); 1060 times_up = 1; 1061 #endif /* WANT_INTERVALS */ 1062 break; 1063 } 1064 } 1065 return; 1066 } 1067 #endif /* WIN32 */ 1068 1069 void 1070 install_signal_catchers() 1071 1072 { 1073 /* just a simple little routine to catch a bunch of signals */ 1074 1075 #ifndef WIN32 1076 struct sigaction action; 1077 int i; 1078 1079 fprintf(where,"installing catcher for all signals\n"); 1080 fflush(where); 1081 1082 sigemptyset(&(action.sa_mask)); 1083 action.sa_handler = catcher; 1084 1085 #ifdef SA_INTERRUPT 1086 action.sa_flags = SA_INTERRUPT; 1087 #else /* SA_INTERRUPT */ 1088 action.sa_flags = 0; 1089 #endif /* SA_INTERRUPT */ 1090 1091 1092 for (i = 1; i <= NSIG; i++) { 1093 switch (i) { 1094 case SIGALRM: 1095 case SIGPROF: 1096 case SIGSTOP: 1097 case SIGKILL: 1098 break; 1099 default: 1100 if (sigaction(i,&action,NULL) != 0) { 1101 fprintf(where, 1102 "Could not install signal catcher for sig %d, errno %d\n", 1103 i, 1104 errno); 1105 fflush(where); 1106 1107 } 1108 } 1109 } 1110 #else 1111 return; 1112 #endif /* WIN32 */ 1113 } 1114 1115 1117 #ifdef WIN32 1118 #define SIGALRM (14) 1119 void 1120 emulate_alarm( int seconds ) 1121 { 1122 DWORD ErrorCode; 1123 DWORD HandlesClosedFlags = 0; 1124 1125 /* Wait on this event for parm seconds. */ 1126 1127 ErrorCode = WaitForSingleObject(hAlarm, seconds*1000); 1128 if (ErrorCode == WAIT_FAILED) 1129 { 1130 perror("WaitForSingleObject failed"); 1131 exit(1); 1132 } 1133 1134 if (ErrorCode == WAIT_TIMEOUT) 1135 { 1136 /* WaitForSingleObject timed out; this means the timer 1137 wasn't canceled. */ 1138 1139 times_up = 1; 1140 1141 /* Give the other threads time to notice that times_up has 1142 changed state before taking the harsh step of closing the 1143 sockets. */ 1144 timed_out=0; 1145 if (WaitForSingleObject(hAlarm, PAD_TIME/2*1000) == 1146 WAIT_TIMEOUT) { 1147 timed_out=1; 1148 /* We have yet to find a good way to fully emulate 1149 the effects of signals and getting EINTR from 1150 system calls under winsock, so what we do here is 1151 close the socket out from under the other thread. 1152 It is rather kludgy, but should be sufficient to 1153 get this puppy shipped. The concept can be 1154 attributed/blamed :) on Robin raj 1/96 */ 1155 1156 if (win_kludge_socket != INVALID_SOCKET) { 1157 HandlesClosedFlags |= 1; 1158 closesocket(win_kludge_socket); 1159 } 1160 if (win_kludge_socket2 != INVALID_SOCKET) { 1161 HandlesClosedFlags |= 2; 1162 closesocket(win_kludge_socket2); 1163 } 1164 } 1165 if(debug) { 1166 fprintf(where, 1167 "emulate_alarm - HandlesClosedFlags: %x\n", 1168 HandlesClosedFlags); 1169 fflush(where); 1170 } 1171 } 1172 } 1173 1174 1175 #endif /* WIN32 */ 1176 1177 void 1178 start_timer(int time) 1179 { 1180 1181 #ifdef WIN32 1182 /*+*+SAF What if StartTimer is called twice without the first timer */ 1183 /*+*+SAF expiring? */ 1184 1185 DWORD thread_id ; 1186 HANDLE tHandle; 1187 1188 if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE) 1189 { 1190 /* Create the Alarm event object */ 1191 hAlarm = CreateEvent( 1192 (LPSECURITY_ATTRIBUTES) NULL, /* no security */ 1193 FALSE, /* auto reset event */ 1194 FALSE, /* init. state = reset */ 1195 (void *)NULL); /* unnamed event object */ 1196 if (hAlarm == (HANDLE) INVALID_HANDLE_VALUE) 1197 { 1198 perror("CreateEvent failure"); 1199 exit(1); 1200 } 1201 } 1202 else 1203 { 1204 ResetEvent(hAlarm); 1205 } 1206 1207 1208 tHandle = CreateThread(0, 1209 0, 1210 (LPTHREAD_START_ROUTINE)emulate_alarm, 1211 (LPVOID)(ULONG_PTR)time, 1212 0, 1213 &thread_id ) ; 1214 CloseHandle(tHandle); 1215 1216 #else /* not WIN32 */ 1217 1218 struct sigaction action; 1219 int ret; 1220 1221 if (debug) { 1222 fprintf(where,"About to start a timer for %d seconds.\n",time); 1223 fflush(where); 1224 } 1225 1226 action.sa_handler = catcher; 1227 1228 #ifdef SA_INTERRUPT 1229 /* on some systems (SunOS 4.blah), system calls are restarted. we do */ 1230 /* not want that */ 1231 action.sa_flags = SA_INTERRUPT; 1232 #else /* SA_INTERRUPT */ 1233 action.sa_flags = 0; 1234 #endif /* SA_INTERRUPT */ 1235 1236 sigemptyset(&(action.sa_mask)); 1237 sigaddset(&(action.sa_mask),SIGALRM); 1238 if (sigaction(SIGALRM, &action, NULL) < 0) { 1239 fprintf(where, 1240 "start_timer: error installing alarm handler errno %d\n", 1241 errno); 1242 fflush(where); 1243 exit(-1); 1244 } 1245 1246 sigemptyset(&(action.sa_mask)); 1247 sigaddset(&(action.sa_mask),SIGINT); 1248 if (sigaction(SIGINT, &action, NULL) < 0) { 1249 fprintf(where, 1250 "start_timer: error installing SIGINT handler errno %d\n", 1251 errno); 1252 fflush(where); 1253 exit(-1); 1254 } 1255 1256 /* this is the easy case - just set the timer for so many seconds */ 1257 ret = alarm(time); 1258 if (ret != 0) { 1259 fprintf(where, 1260 "error starting alarm timer, ret %d errno %d\n", 1261 ret, 1262 errno); 1263 fflush(where); 1264 exit(-1); 1265 } 1266 #endif /* WIN32 */ 1267 1268 test_len_ticks = 1; 1269 1270 } 1271 1272 1273 1274 #ifdef WANT_INTERVALS 1276 /* this routine will enable the interval timer and set things up so 1277 that for a timed test the test will end at the proper time. it 1278 should detect the presence of POSIX.4 timer_* routines one of these 1279 days */ 1280 void 1281 start_itimer(unsigned int interval_len_msec ) 1282 { 1283 #ifdef WIN32 1284 LARGE_INTEGER liDueTime; 1285 TIMECAPS ptc; 1286 MMRESULT mmr; 1287 1288 /* make sure timer resolution is at least as small as interval length */ 1289 timerRes=interval_len_msec; 1290 mmr=timeGetDevCaps(&ptc, sizeof (ptc)); 1291 if (mmr==TIMERR_NOERROR){ 1292 if (interval_len_msec<ptc.wPeriodMin){ 1293 timerRes=ptc.wPeriodMin; 1294 fprintf(where, "Timer cannot be set to %dmsec. Minimum timer resolution: %d\n", interval_len_msec, ptc.wPeriodMin); 1295 fflush(where); 1296 } 1297 } 1298 /* timeBeginPeriod() affects a global Windows setting. 1299 Windows uses the lowest value (that is, highest resolution) requested by any process. */ 1300 mmr=timeBeginPeriod(timerRes); 1301 /* Create a waitable timer. */ 1302 WinTimer = CreateWaitableTimer(NULL, FALSE, "IntervalTimer"); 1303 if (NULL == WinTimer) 1304 { 1305 fprintf(where, "CreateWaitableTimer failed (%d)\n", GetLastError()); 1306 fflush(where); 1307 exit(1); 1308 } 1309 /*The time after which the state of the timer is to be set to signaled the first time, 1310 in 100 nanosecond intervals. Negative values indicate relative time. */ 1311 liDueTime.QuadPart=-10000LL*interval_len_msec; 1312 /* Set the timer to wait for interval_len_msec and periodically signal every interval_len_msec */ 1313 if (!SetWaitableTimer(WinTimer, &liDueTime, interval_len_msec, NULL, NULL, TRUE)) 1314 { 1315 fprintf(where,"SetWaitableTimer failed (%d)\n", GetLastError()); 1316 fflush(where); 1317 exit(1); 1318 } 1319 #else 1320 unsigned int ticks_per_itvl; 1321 1322 struct itimerval new_interval; 1323 struct itimerval old_interval; 1324 1325 /* if -DWANT_INTERVALS was used, we will use the ticking of the 1326 itimer to tell us when the test is over. while the user will be 1327 specifying some number of milliseconds, we know that the interval 1328 timer is really in units of 1/HZ. so, to prevent the test from 1329 running "long" it would be necessary to keep this in mind when 1330 calculating the number of itimer events */ 1331 1332 ticks_per_itvl = ((interval_wate * sysconf(_SC_CLK_TCK) * 1000) / 1333 1000000); 1334 1335 if (ticks_per_itvl == 0) ticks_per_itvl = 1; 1336 1337 /* how many usecs in each interval? */ 1338 usec_per_itvl = ticks_per_itvl * (1000000 / sysconf(_SC_CLK_TCK)); 1339 1340 /* how many times will the timer pop before the test is over? */ 1341 if (test_time > 0) { 1342 /* this was a timed test */ 1343 test_len_ticks = (test_time * 1000000) / usec_per_itvl; 1344 } 1345 else { 1346 /* this was not a timed test, use MAXINT */ 1347 test_len_ticks = INT_MAX; 1348 } 1349 1350 if (debug) { 1351 fprintf(where, 1352 "setting the interval timer to %d sec %d usec test len %d ticks\n", 1353 usec_per_itvl / 1000000, 1354 usec_per_itvl % 1000000, 1355 test_len_ticks); 1356 fflush(where); 1357 } 1358 1359 /* if this was not a timed test, then we really aught to enable the 1360 signal catcher raj 2/95 */ 1361 1362 new_interval.it_interval.tv_sec = usec_per_itvl / 1000000; 1363 new_interval.it_interval.tv_usec = usec_per_itvl % 1000000; 1364 new_interval.it_value.tv_sec = usec_per_itvl / 1000000; 1365 new_interval.it_value.tv_usec = usec_per_itvl % 1000000; 1366 if (setitimer(ITIMER_REAL,&new_interval,&old_interval) != 0) { 1367 /* there was a problem arming the interval timer */ 1368 perror("netperf: setitimer"); 1369 exit(1); 1370 } 1371 #endif /* WIN32*/ 1372 } 1373 #endif /* WANT_INTERVALS */ 1374 1375 void 1376 netlib_init_cpu_map() { 1377 1378 int i; 1379 #ifdef HAVE_MPCTL 1380 int num; 1381 i = 0; 1382 /* I go back and forth on whether this should be the system-wide set 1383 of calls, or if the processor set versions (sans the _SYS) should 1384 be used. at the moment I believe that the system-wide version 1385 should be used. raj 2006-04-03 */ 1386 num = mpctl(MPC_GETNUMSPUS_SYS,0,0); 1387 lib_cpu_map[i] = mpctl(MPC_GETFIRSTSPU_SYS,0,0); 1388 for (i = 1;((i < num) && (i < MAXCPUS)); i++) { 1389 lib_cpu_map[i] = mpctl(MPC_GETNEXTSPU_SYS,lib_cpu_map[i-1],0); 1390 } 1391 /* from here, we set them all to -1 because if we launch more 1392 loopers than actual CPUs, well, I'm not sure why :) */ 1393 for (; i < MAXCPUS; i++) { 1394 lib_cpu_map[i] = -1; 1395 } 1396 1397 #else 1398 /* we assume that there is indeed a contiguous mapping */ 1399 for (i = 0; i < MAXCPUS; i++) { 1400 lib_cpu_map[i] = i; 1401 } 1402 #endif 1403 } 1404 1405 1406 1407 /****************************************************************/ 1409 /* */ 1410 /* netlib_init() */ 1411 /* */ 1412 /* initialize the performance library... */ 1413 /* */ 1414 /****************************************************************/ 1415 1416 void 1417 netlib_init() 1418 { 1419 int i; 1420 1421 where = stdout; 1422 1423 request_array = (int *)(&netperf_request); 1424 response_array = (int *)(&netperf_response); 1425 1426 for (i = 0; i < MAXCPUS; i++) { 1427 lib_local_per_cpu_util[i] = -1.0; 1428 } 1429 1430 lib_local_cpu_stats.peak_cpu_id = -1; 1431 lib_local_cpu_stats.peak_cpu_util = -1.0; 1432 lib_remote_cpu_stats.peak_cpu_id = -1; 1433 lib_remote_cpu_stats.peak_cpu_util = -1.0; 1434 1435 netperf_version = strdup(NETPERF_VERSION); 1436 1437 /* on those systems where we know that CPU numbers may not start at 1438 zero and be contiguous, we provide a way to map from a 1439 contiguous, starting from 0 CPU id space to the actual CPU ids. 1440 at present this is only used for the netcpu_looper stuff because 1441 we ass-u-me that someone setting processor affinity from the 1442 netperf commandline will provide a "proper" CPU identifier. raj 1443 2006-04-03 */ 1444 1445 netlib_init_cpu_map(); 1446 1447 if (debug) { 1448 fprintf(where, 1449 "netlib_init: request_array at %p\n" 1450 "netlib_init: response_array at %p\n", 1451 request_array, 1452 response_array); 1453 fflush(where); 1454 } 1455 1456 /* some functionality might want to use random numbers, so we should 1457 initialize the random number generator */ 1458 srand(getpid()); 1459 1460 } 1461 1462 /* this routine will conver the string into an unsigned integer. it is 1464 used primarily for the command-line options taking a number (such 1465 as the socket size) which could be rather large. If someone enters 1466 32M, then the number will be converted to 32 * 1024 * 1024. If 1467 they inter 32m, the number will be converted to 32 * 1000 * 1000 */ 1468 unsigned int 1469 convert(char *string) 1470 1471 { 1472 unsigned int base; 1473 base = atoi(string); 1474 if (strstr(string,"K")) { 1475 base *= 1024; 1476 } 1477 if (strstr(string,"M")) { 1478 base *= (1024 * 1024); 1479 } 1480 if (strstr(string,"G")) { 1481 base *= (1024 * 1024 * 1024); 1482 } 1483 if (strstr(string,"k")) { 1484 base *= (1000); 1485 } 1486 if (strstr(string,"m")) { 1487 base *= (1000 * 1000); 1488 } 1489 if (strstr(string,"g")) { 1490 base *= (1000 * 1000 * 1000); 1491 } 1492 return(base); 1493 } 1494 1495 /* this routine is like convert, but it is used for an interval time 1496 specification instead of stuff like socket buffer or send sizes. 1497 it converts everything to microseconds for internal use. if there 1498 is an 'm' at the end it assumes the user provided milliseconds, s 1499 will imply seconds, u will imply microseconds. in the future n 1500 will imply nanoseconds but for now it will be ignored. if there is 1501 no suffix or an unrecognized suffix, it will be assumed the user 1502 provided milliseconds, which was the long-time netperf default. one 1503 of these days, we should probably revisit that nanosecond business 1504 wrt the return value being just an int rather than a uint64_t or 1505 something. raj 2006-02-06 */ 1506 1507 unsigned int 1508 convert_timespec(char *string) { 1509 1510 unsigned int base; 1511 base = atoi(string); 1512 if (strstr(string,"m")) { 1513 base *= 1000; 1514 } 1515 else if (strstr(string,"u")) { 1516 base *= (1); 1517 } 1518 else if (strstr(string,"s")) { 1519 base *= (1000 * 1000); 1520 } 1521 else { 1522 base *= (1000); 1523 } 1524 return(base); 1525 } 1526 1527 1528 /* this routine will allocate a circular list of buffers for either 1530 send or receive operations. each of these buffers will be aligned 1531 and offset as per the users request. the circumference of this ring 1532 will be controlled by the setting of width. the buffers will be 1533 filled with data from the file specified in fill_file. if fill_file 1534 is an empty string, the buffers will be filled from "default_fill" 1535 which will be "netperf" so anyone sniffing the traffic will have a 1536 better idea what this traffic happens to be. */ 1537 1538 struct ring_elt * 1539 allocate_buffer_ring(int width, int buffer_size, int alignment, int offset) 1540 { 1541 1542 struct ring_elt *first_link = NULL; 1543 struct ring_elt *temp_link = NULL; 1544 struct ring_elt *prev_link; 1545 1546 int i; 1547 int malloc_size; 1548 int bytes_left; 1549 int bytes_read; 1550 int do_fill; 1551 1552 FILE *fill_source; 1553 char default_fill[] = "netperf"; 1554 int fill_cursor = 0; 1555 1556 malloc_size = buffer_size + alignment + offset; 1557 1558 /* did the user wish to have the buffers pre-filled with data from a */ 1559 /* particular source? */ 1560 if (strcmp(local_fill_file,"") == 0) { 1561 do_fill = 0; 1562 fill_source = NULL; 1563 } 1564 else { 1565 do_fill = 1; 1566 fill_source = (FILE *)fopen(local_fill_file,"r"); 1567 if (fill_source == (FILE *)NULL) { 1568 fprintf(where,"Could not open requested fill file: %s\n", 1569 strerror(errno)); 1570 fflush(where); 1571 } 1572 } 1573 1574 assert(width >= 1); 1575 1576 prev_link = NULL; 1577 for (i = 1; i <= width; i++) { 1578 /* get the ring element */ 1579 temp_link = (struct ring_elt *)malloc(sizeof(struct ring_elt)); 1580 if (temp_link == NULL) { 1581 fprintf(where, 1582 "malloc(%u) failed!\n", 1583 (unsigned int)sizeof(struct ring_elt)); 1584 exit(-1); 1585 } 1586 temp_link->completion_ptr = NULL; 1587 /* remember the first one so we can close the ring at the end */ 1588 if (i == 1) { 1589 first_link = temp_link; 1590 } 1591 temp_link->buffer_base = (char *)malloc(malloc_size); 1592 if (temp_link->buffer_base == NULL) { 1593 fprintf(where, 1594 "malloc(%d) failed!\n", 1595 malloc_size); 1596 exit(-1); 1597 } 1598 1599 #ifndef WIN32 1600 temp_link->buffer_ptr = (char *)(( (long)(temp_link->buffer_base) + 1601 (long)alignment - 1) & 1602 ~((long)alignment - 1)); 1603 #else 1604 temp_link->buffer_ptr = (char *)(( (ULONG_PTR)(temp_link->buffer_base) + 1605 (ULONG_PTR)alignment - 1) & 1606 ~((ULONG_PTR)alignment - 1)); 1607 #endif 1608 temp_link->buffer_ptr += offset; 1609 /* is where the buffer fill code goes. */ 1610 if (do_fill) { 1611 char *bufptr = temp_link->buffer_ptr; 1612 bytes_left = buffer_size; 1613 while (bytes_left) { 1614 if (((bytes_read = (int)fread(bufptr, 1615 1, 1616 bytes_left, 1617 fill_source)) == 0) && 1618 (feof(fill_source))){ 1619 rewind(fill_source); 1620 } 1621 bufptr += bytes_read; 1622 bytes_left -= bytes_read; 1623 } 1624 } 1625 else { 1626 /* use the default fill to ID our data traffic on the 1627 network. it ain't exactly pretty, but it should work */ 1628 int j; 1629 char *bufptr = temp_link->buffer_ptr; 1630 for (j = 0; j < buffer_size; j++) { 1631 bufptr[j] = default_fill[fill_cursor]; 1632 fill_cursor += 1; 1633 /* the Windows DDK compiler with an x86_64 target wants a cast 1634 here */ 1635 if (fill_cursor > (int)strlen(default_fill)) { 1636 fill_cursor = 0; 1637 } 1638 } 1639 1640 } 1641 temp_link->next = prev_link; 1642 prev_link = temp_link; 1643 } 1644 if (first_link) { /* SAF Prefast made me do it... */ 1645 first_link->next = temp_link; 1646 } 1647 1648 return(first_link); /* it's a circle, doesn't matter which we return */ 1649 } 1650 1651 /* this routine will dirty the first dirty_count bytes of the 1652 specified buffer and/or read clean_count bytes from the buffer. it 1653 will go N bytes at a time, the only question is how large should N 1654 be and if we should be going continguously, or based on some 1655 assumption of cache line size */ 1656 1657 void 1658 access_buffer(char *buffer_ptr,int length, int dirty_count, int clean_count) { 1659 1660 char *temp_buffer; 1661 char *limit; 1662 int i, dirty_totals; 1663 1664 temp_buffer = buffer_ptr; 1665 limit = temp_buffer + length; 1666 dirty_totals = 0; 1667 1668 for (i = 0; 1669 ((i < dirty_count) && (temp_buffer < limit)); 1670 i++) { 1671 *temp_buffer += (char)i; 1672 dirty_totals += *temp_buffer; 1673 temp_buffer++; 1674 } 1675 1676 for (i = 0; 1677 ((i < clean_count) && (temp_buffer < limit)); 1678 i++) { 1679 dirty_totals += *temp_buffer; 1680 temp_buffer++; 1681 } 1682 1683 if (debug > 100) { 1684 fprintf(where, 1685 "This was here to try to avoid dead-code elimination %d\n", 1686 dirty_totals); 1687 fflush(where); 1688 } 1689 } 1690 1691 1693 #ifdef HAVE_ICSC_EXS 1694 1695 #include <sys/mman.h> 1696 #include <sys/exs.h> 1697 1698 /* this routine will allocate a circular list of buffers for either 1699 send or receive operations. each of these buffers will be aligned 1700 and offset as per the users request. the circumference of this ring 1701 will be controlled by the setting of send_width. the buffers will 1702 be filled with data from the file specified in local_fill_file. if 1703 local_fill_file is an empty string, the buffers will not be filled with 1704 any particular data */ 1705 1706 struct ring_elt * 1707 allocate_exs_buffer_ring (int width, int buffer_size, int alignment, int offset, exs_mhandle_t *mhandlep) 1708 { 1709 1710 struct ring_elt *first_link; 1711 struct ring_elt *temp_link; 1712 struct ring_elt *prev_link; 1713 1714 int i; 1715 int malloc_size; 1716 int bytes_left; 1717 int bytes_read; 1718 int do_fill; 1719 1720 FILE *fill_source; 1721 1722 int mmap_size; 1723 char *mmap_buffer, *mmap_buffer_aligned; 1724 1725 malloc_size = buffer_size + alignment + offset; 1726 1727 /* did the user wish to have the buffers pre-filled with data from a */ 1728 /* particular source? */ 1729 if (strcmp (local_fill_file, "") == 0) { 1730 do_fill = 0; 1731 fill_source = NULL; 1732 } else { 1733 do_fill = 1; 1734 fill_source = (FILE *) fopen (local_fill_file, "r"); 1735 if (fill_source == (FILE *) NULL) { 1736 perror ("Could not open requested fill file"); 1737 exit (1); 1738 } 1739 } 1740 1741 assert (width >= 1); 1742 1743 if (debug) { 1744 fprintf (where, 1745 "allocate_exs_buffer_ring: " 1746 "width=%d buffer_size=%d alignment=%d offset=%d\n", 1747 width, buffer_size, alignment, offset); 1748 } 1749 1750 /* allocate shared memory */ 1751 mmap_size = width * malloc_size; 1752 mmap_buffer = (char *) mmap ((caddr_t)NULL, mmap_size+NBPG-1, 1753 PROT_READ|PROT_WRITE, 1754 MAP_SHARED|MAP_ANONYMOUS, -1, 0); 1755 if (mmap_buffer == NULL) { 1756 perror ("allocate_exs_buffer_ring: mmap failed"); 1757 exit (1); 1758 } 1759 mmap_buffer_aligned = (char *) ((uintptr_t)mmap_buffer & ~(NBPG-1)); 1760 if (debug) { 1761 fprintf (where, 1762 "allocate_exs_buffer_ring: " 1763 "mmap buffer size=%d address=0x%p aligned=0x%p\n", 1764 mmap_size, mmap_buffer, mmap_buffer_aligned); 1765 } 1766 1767 /* register shared memory */ 1768 *mhandlep = exs_mregister ((void *)mmap_buffer_aligned, (size_t)mmap_size, 0); 1769 if (*mhandlep == EXS_MHANDLE_INVALID) { 1770 perror ("allocate_exs_buffer_ring: exs_mregister failed"); 1771 exit (1); 1772 } 1773 if (debug) { 1774 fprintf (where, "allocate_exs_buffer_ring: mhandle=%d\n", 1775 *mhandlep); 1776 } 1777 1778 /* allocate ring elements */ 1779 first_link = (struct ring_elt *) malloc (width * sizeof (struct ring_elt)); 1780 if (first_link == NULL) { 1781 printf ("malloc(%d) failed!\n", width * sizeof (struct ring_elt)); 1782 exit (1); 1783 } 1784 1785 /* initialize buffer ring */ 1786 prev_link = first_link + width - 1; 1787 1788 for (i = 0, temp_link = first_link; i < width; i++, temp_link++) { 1789 1790 temp_link->buffer_base = (char *) mmap_buffer_aligned + (i*malloc_size); 1791 #ifndef WIN32 1792 temp_link->buffer_ptr = (char *) 1793 (((long)temp_link->buffer_base + (long)alignment - 1) & 1794 ~((long)alignment - 1)); 1795 #else 1796 temp_link->buffer_ptr = (char *) 1797 (((ULONG_PTR)temp_link->buffer_base + (ULONG_PTR)alignment - 1) & 1798 ~((ULONG_PTR)alignment - 1)); 1799 #endif 1800 temp_link->buffer_ptr += offset; 1801 1802 if (debug) { 1803 fprintf (where, "allocate_exs_buffer_ring: " 1804 "buffer: index=%d base=0x%p ptr=0x%p\n", 1805 i, temp_link->buffer_base, temp_link->buffer_ptr); 1806 } 1807 1808 /* is where the buffer fill code goes. */ 1809 if (do_fill) { 1810 bytes_left = buffer_size; 1811 while (bytes_left) { 1812 if (((bytes_read = (int) fread (temp_link->buffer_ptr, 1813 1, 1814 bytes_left, 1815 fill_source)) == 0) && 1816 (feof (fill_source))) { 1817 rewind (fill_source); 1818 } 1819 bytes_left -= bytes_read; 1820 } 1821 } 1822 1823 /* do linking */ 1824 prev_link->next = temp_link; 1825 prev_link = temp_link; 1826 } 1827 1828 return (first_link); /* it is a circle, doesn't matter which we return */ 1829 } 1830 1831 #endif /* HAVE_ICSC_EXS */ 1832 1833 1834 1836 #ifdef HAVE_SENDFILE 1837 /* this routine will construct a ring of sendfile_ring_elt structs 1838 that the routine sendfile_tcp_stream() will use to get parameters 1839 to its calls to sendfile(). It will setup the ring to point at the 1840 file specified in the global -F option that is already used to 1841 pre-fill buffers in the send() case. 08/2000 1842 1843 if there is no file specified in a global -F option, we will create 1844 a tempoarary file and fill it with random data and use that 1845 instead. raj 2007-08-09 */ 1846 1847 struct ring_elt * 1848 alloc_sendfile_buf_ring(int width, 1849 int buffer_size, 1850 int alignment, 1851 int offset) 1852 1853 { 1854 1855 struct ring_elt *first_link = NULL; 1856 struct ring_elt *temp_link = NULL; 1857 struct ring_elt *prev_link; 1858 1859 int i; 1860 int fildes; 1861 struct stat statbuf; 1862 1863 /* if the user has not specified a file with the -F option, we will 1864 fail the test. otherwise, go ahead and try to open the 1865 file. 08/2000 */ 1866 if (strcmp(local_fill_file,"") == 0) { 1867 /* use an temp file for the fill file */ 1868 char temp_file[] = {"netperfXXXXXX\0"}; 1869 int *temp_buffer; 1870 1871 /* make sure we have at least an ints worth, even if the user is 1872 using an insane buffer size for a sendfile test. we are 1873 ass-u-me-ing that malloc will return something at least aligned 1874 on an int boundary... */ 1875 temp_buffer = (int *) malloc(buffer_size + sizeof(int)); 1876 if (temp_buffer) { 1877 /* ok, we have the buffer we are going to write, lets get a 1878 temporary filename */ 1879 fildes = mkstemp(temp_file); 1880 /* no need to call open because mkstemp did it */ 1881 if (-1 != fildes) { 1882 int count; 1883 int *int_ptr; 1884 1885 /* we initialize the random number generator in 1886 netlib_init() now. raj 20110111 */ 1887 1888 /* unlink the file so it goes poof when we 1889 exit. unless/until shown to be a problem we will 1890 blissfully ignore the return value. raj 2007-08-09 */ 1891 unlink(temp_file); 1892 1893 /* now fill-out the file with at least buffer_size * width bytes */ 1894 for (count = 0; count < width; count++) { 1895 /* fill the buffer with random data. it doesn't have to be 1896 really random, just "random enough" :) we do this here rather 1897 than up above because we want each write to the file to be 1898 different random data */ 1899 int_ptr = temp_buffer; 1900 for (i = 0; i <= buffer_size/sizeof(int); i++) { 1901 *int_ptr = rand(); 1902 int_ptr++; 1903 } 1904 if (write(fildes,temp_buffer,buffer_size+sizeof(int)) != 1905 buffer_size + sizeof(int)) { 1906 perror("allocate_sendfile_buf_ring: incomplete write"); 1907 exit(-1); 1908 } 1909 } 1910 } 1911 else { 1912 perror("alloc_sendfile_buf_ring: could not allocate temp name"); 1913 exit(-1); 1914 } 1915 } 1916 else { 1917 perror("alloc_sendfile_buf_ring: could not allocate buffer for file"); 1918 exit(-1); 1919 } 1920 } 1921 else { 1922 /* the user pointed us at a file, so try it */ 1923 fildes = open(local_fill_file , O_RDONLY); 1924 if (fildes == -1){ 1925 perror("alloc_sendfile_buf_ring: Could not open requested file"); 1926 exit(1); 1927 } 1928 /* make sure there is enough file there to allow us to make a 1929 complete ring. that way we do not need additional logic in the 1930 ring setup to deal with wrap-around issues. we might want that 1931 someday, but not just now. 08/2000 */ 1932 if (stat(local_fill_file,&statbuf) != 0) { 1933 perror("alloc_sendfile_buf_ring: could not stat file"); 1934 exit(1); 1935 } 1936 if (statbuf.st_size < (width * buffer_size)) { 1937 /* the file is too short */ 1938 fprintf(stderr, 1939 "alloc_sendfile_buf_ring: specified file too small.\n" 1940 "file must be larger than send_width * send_size\n"); 1941 fflush(stderr); 1942 exit(1); 1943 } 1944 } 1945 1946 /* so, at this point we know that fildes is a descriptor which 1947 references a file of sufficient size for our nefarious 1948 porpoises. raj 2007-08-09 */ 1949 1950 prev_link = NULL; 1951 for (i = 1; i <= width; i++) { 1952 /* get the ring element. we should probably make sure the malloc() 1953 was successful, but for now we'll just let the code bomb 1954 mysteriously. 08/2000 */ 1955 1956 temp_link = (struct ring_elt *) 1957 malloc(sizeof(struct ring_elt)); 1958 if (temp_link == NULL) { 1959 fprintf(where, 1960 "malloc(%u) failed!\n", 1961 (unsigned int) sizeof(struct ring_elt)); 1962 exit(1); 1963 } 1964 1965 /* remember the first one so we can close the ring at the end */ 1966 1967 if (i == 1) { 1968 first_link = temp_link; 1969 } 1970 1971 /* now fill-in the fields of the structure with the apropriate 1972 stuff. just how should we deal with alignment and offset I 1973 wonder? until something better comes-up, I think we will just 1974 ignore them. 08/2000 */ 1975 1976 temp_link->fildes = fildes; /* from which file do we send? */ 1977 temp_link->offset = offset; /* starting at which offset? */ 1978 offset += buffer_size; /* get ready for the next elt */ 1979 temp_link->length = buffer_size; /* how many bytes to send */ 1980 temp_link->hdtrl = NULL; /* no header or trailer */ 1981 temp_link->flags = 0; /* no flags */ 1982 1983 /* is where the buffer fill code went. */ 1984 1985 temp_link->next = prev_link; 1986 prev_link = temp_link; 1987 } 1988 /* close the ring */ 1989 first_link->next = temp_link; 1990 1991 return(first_link); /* it's a dummy ring */ 1992 } 1993 1994 #endif /* HAVE_SENDFILE */ 1995 1996 1997 /***********************************************************************/ 1999 /* */ 2000 /* dump_request() */ 2001 /* */ 2002 /* display the contents of the request array to the user. it will */ 2003 /* display the contents in decimal, hex, and ascii, with four bytes */ 2004 /* per line. */ 2005 /* */ 2006 /***********************************************************************/ 2007 2008 void 2009 dump_request() 2010 { 2011 int counter = 0; 2012 fprintf(where,"request contents:\n"); 2013 for (counter = 0; counter < ((sizeof(netperf_request)/4)-3); counter += 4) { 2014 fprintf(where,"%d:\t%8x %8x %8x %8x \t|%4.4s| |%4.4s| |%4.4s| |%4.4s|\n", 2015 counter, 2016 request_array[counter], 2017 request_array[counter+1], 2018 request_array[counter+2], 2019 request_array[counter+3], 2020 (char *)&request_array[counter], 2021 (char *)&request_array[counter+1], 2022 (char *)&request_array[counter+2], 2023 (char *)&request_array[counter+3]); 2024 } 2025 fflush(where); 2026 } 2027 2028 2029 /***********************************************************************/ 2030 /* */ 2031 /* dump_response() */ 2032 /* */ 2033 /* display the content of the response array to the user. it will */ 2034 /* display the contents in decimal, hex, and ascii, with four bytes */ 2035 /* per line. */ 2036 /* */ 2037 /***********************************************************************/ 2038 2039 void 2040 dump_response() 2041 { 2042 int counter = 0; 2043 2044 fprintf(where,"response contents\n"); 2045 for (counter = 0; counter < ((sizeof(netperf_response)/4)-3); counter += 4) { 2046 fprintf(where,"%d:\t%8x %8x %8x %8x \t>%4.4s< >%4.4s< >%4.4s< >%4.4s<\n", 2047 counter, 2048 response_array[counter], 2049 response_array[counter+1], 2050 response_array[counter+2], 2051 response_array[counter+3], 2052 (char *)&response_array[counter], 2053 (char *)&response_array[counter+1], 2054 (char *)&response_array[counter+2], 2055 (char *)&response_array[counter+3]); 2056 } 2057 fflush(where); 2058 } 2059 2060 /* 2061 2062 format_number() 2063 2064 return a pointer to a formatted string containing the value passed 2065 translated into the units specified. It assumes that the base units 2066 are bytes. If the format calls for bits, it will use SI units (10^) 2067 if the format calls for bytes, it will use CS units (2^)... This 2068 routine should look familiar to uses of the latest ttcp... 2069 2070 we would like to use "t" or "T" for transactions, but probably 2071 should leave those for terabits and terabytes respectively, so for 2072 transactions, we will use "x" which will, by default, do absolutely 2073 nothing to the result. why? so we don't have to special case code 2074 elsewhere such as in the TCP_RR-as-bidirectional test case. 2075 2076 */ 2077 2078 2079 char * 2080 format_number(double number) 2081 { 2082 static char fmtbuf[64]; 2083 2084 switch (libfmt) { 2085 case 'B': 2086 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f" , number); 2087 break; 2088 case 'K': 2089 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f" , number / 1024.0); 2090 break; 2091 case 'M': 2092 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0 / 1024.0); 2093 break; 2094 case 'G': 2095 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0 / 1024.0 / 1024.0); 2096 break; 2097 case 'b': 2098 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f" , number * 8); 2099 break; 2100 case 'k': 2101 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0); 2102 break; 2103 case 'm': 2104 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0 / 1000.0); 2105 break; 2106 case 'g': 2107 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number * 8 / 1000.0 / 1000.0 / 1000.0); 2108 break; 2109 case 'x': 2110 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number); 2111 break; 2112 default: 2113 snprintf(fmtbuf, sizeof(fmtbuf), "%-7.2f", number / 1024.0); 2114 } 2115 2116 return fmtbuf; 2117 } 2118 2119 char 2120 format_cpu_method(int method) 2121 { 2122 2123 char method_char; 2124 2125 switch (method) { 2126 case CPU_UNKNOWN: 2127 method_char = 'U'; 2128 break; 2129 case HP_IDLE_COUNTER: 2130 method_char = 'I'; 2131 break; 2132 case PSTAT: 2133 method_char = 'P'; 2134 break; 2135 case KSTAT: 2136 method_char = 'K'; 2137 break; 2138 case KSTAT_10: 2139 method_char = 'M'; 2140 break; 2141 case PERFSTAT: 2142 method_char = 'E'; 2143 break; 2144 case TIMES: /* historical only, completely unsuitable 2145 for netperf's purposes */ 2146 method_char = 'T'; 2147 break; 2148 case GETRUSAGE: /* historical only, completely unsuitable 2149 for netperf;s purposes */ 2150 method_char = 'R'; 2151 break; 2152 case LOOPER: 2153 method_char = 'L'; 2154 break; 2155 case NT_METHOD: 2156 method_char = 'N'; 2157 break; 2158 case PROC_STAT: 2159 method_char = 'S'; 2160 break; 2161 case SYSCTL: 2162 method_char = 'C'; 2163 break; 2164 case OSX: 2165 method_char = 'O'; 2166 break; 2167 default: 2168 method_char = '?'; 2169 } 2170 2171 return method_char; 2172 2173 } 2174 2175 char * 2176 format_units() 2177 { 2178 static char unitbuf[64]; 2179 2180 switch (libfmt) { 2181 case 'B': 2182 strcpy(unitbuf, "Bytes"); 2183 break; 2184 case 'K': 2185 strcpy(unitbuf, "KBytes"); 2186 break; 2187 case 'M': 2188 strcpy(unitbuf, "MBytes"); 2189 break; 2190 case 'G': 2191 strcpy(unitbuf, "GBytes"); 2192 break; 2193 case 'b': 2194 strcpy(unitbuf, "10^0bits"); 2195 break; 2196 case 'k': 2197 strcpy(unitbuf, "10^3bits"); 2198 break; 2199 case 'm': 2200 strcpy(unitbuf, "10^6bits"); 2201 break; 2202 case 'g': 2203 strcpy(unitbuf, "10^9bits"); 2204 break; 2205 case 'x': 2206 strcpy(unitbuf, "Trans"); 2207 break; 2208 case 'u': 2209 strcpy(unitbuf,"Usec"); 2210 break; 2211 2212 default: 2213 strcpy(unitbuf, "KBytes"); 2214 } 2215 2216 return unitbuf; 2217 } 2218 2219 2221 /****************************************************************/ 2222 /* */ 2223 /* shutdown_control() */ 2224 /* */ 2225 /* tear-down the control connection between me and the server. */ 2226 /****************************************************************/ 2227 2228 void 2229 shutdown_control() 2230 { 2231 2232 char *buf = (char *)&netperf_response; 2233 int buflen = sizeof(netperf_response); 2234 2235 /* stuff for select, use fd_set for better compliance */ 2236 fd_set readfds; 2237 struct timeval timeout; 2238 2239 if (debug) { 2240 fprintf(where, 2241 "shutdown_control: shutdown of control connection requested.\n"); 2242 fflush(where); 2243 } 2244 2245 /* first, we say that we will be sending no more data on the */ 2246 /* connection */ 2247 if (shutdown(netlib_control,1) == SOCKET_ERROR) { 2248 Print_errno(where, 2249 "shutdown_control: error in shutdown"); 2250 fflush(where); 2251 exit(1); 2252 } 2253 2254 /* Now, we hang on a select waiting for the socket to become 2255 readable to receive the shutdown indication from the remote. this 2256 will be "just" like the recv_response() code 2257 2258 we only select once. it is assumed that if the response is split 2259 (which should not be happening, that we will receive the whole 2260 thing and not have a problem ;-) */ 2261 2262 FD_ZERO(&readfds); 2263 FD_SET(netlib_control,&readfds); 2264 timeout.tv_sec = 60; /* wait one minute then punt */ 2265 timeout.tv_usec = 0; 2266 2267 /* select had better return one, or there was either a problem or a 2268 timeout... */ 2269 if (select(FD_SETSIZE, 2270 &readfds, 2271 0, 2272 0, 2273 &timeout) != 1) { 2274 Print_errno(where, 2275 "shutdown_control: no response received"); 2276 fflush(where); 2277 exit(1); 2278 } 2279 2280 /* we now assume that the socket has come ready for reading */ 2281 recv(netlib_control, buf, buflen,0); 2282 2283 } 2284 2285 /* 2286 bind_to_specific_processor will bind the calling process to the 2287 processor in "processor" It has lots of ugly ifdefs to deal with 2288 all the different ways systems do processor affinity. this is a 2289 generalization of work initially done by stephen burger. raj 2290 2004/12/13 */ 2291 2292 void 2293 bind_to_specific_processor(int processor_affinity, int use_cpu_map) 2294 { 2295 2296 int mapped_affinity; 2297 2298 /* this is in place because the netcpu_looper processor affinity 2299 ass-u-me-s a contiguous CPU id space starting with 0. for the 2300 regular netperf/netserver affinity, we ass-u-me the user has used 2301 a suitable CPU id even when the space is not contiguous and 2302 starting from zero */ 2303 if (use_cpu_map) { 2304 mapped_affinity = lib_cpu_map[processor_affinity]; 2305 } 2306 else { 2307 mapped_affinity = processor_affinity; 2308 } 2309 2310 #ifdef HAVE_MPCTL 2311 /* indeed, at some point it would be a good idea to check the return 2312 status and pass-along notification of error... raj 2004/12/13 */ 2313 mpctl(MPC_SETPROCESS_FORCE, mapped_affinity, getpid()); 2314 #elif HAVE_PROCESSOR_BIND 2315 #include <sys/types.h> 2316 #include <sys/processor.h> 2317 #include <sys/procset.h> 2318 processor_bind(P_PID,P_MYID,mapped_affinity,NULL); 2319 #elif HAVE_BINDPROCESSOR 2320 #include <sys/processor.h> 2321 /* this is the call on AIX. It takes a "what" of BINDPROCESS or 2322 BINDTHRAD, then "who" and finally "where" which is a CPU number 2323 or it seems PROCESSOR_CLASS_ANY there also seems to be a mycpu() 2324 call to return the current CPU assignment. this is all based on 2325 the sys/processor.h include file. from empirical testing, it 2326 would seem that the my_cpu() call returns the current CPU on 2327 which we are running rather than the CPU binding, so it's return 2328 value will not tell you if you are bound vs unbound. */ 2329 bindprocessor(BINDPROCESS,getpid(),(cpu_t)mapped_affinity); 2330 #elif HAVE_SCHED_SETAFFINITY 2331 #include <sched.h> 2332 /* in theory this should cover systems with more CPUs than bits in a 2333 long, without having to specify __USE_GNU. we "cheat" by taking 2334 defines from /usr/include/bits/sched.h, which we ass-u-me is 2335 included by <sched.h>. If they are not there we will just 2336 fall-back on what we had before, which is to use just the size of 2337 an unsigned long. raj 2006-09-14 */ 2338 2339 #if defined(__CPU_SETSIZE) 2340 #define NETPERF_CPU_SETSIZE __CPU_SETSIZE 2341 #if defined(__CPU_SET_S) 2342 #define NETPERF_CPU_SET(cpu, cpusetp) __CPU_SET_S(cpu, sizeof (cpu_set_t), cpusetp) 2343 #define NETPERF_CPU_ZERO(cpusetp) __CPU_ZERO_S (sizeof (cpu_set_t), cpusetp) 2344 #else 2345 #define NETPERF_CPU_SET(cpu, cpusetp) __CPU_SET(cpu, cpusetp) 2346 #define NETPERF_CPU_ZERO(cpusetp) __CPU_ZERO (cpusetp) 2347 #endif 2348 typedef cpu_set_t netperf_cpu_set_t; 2349 #else 2350 #define NETPERF_CPU_SETSIZE sizeof(unsigned long) 2351 #define NETPERF_CPU_SET(cpu, cpusetp) *cpusetp = 1 << cpu 2352 #define NETPERF_CPU_ZERO(cpusetp) *cpusetp = (unsigned long)0 2353 typedef unsigned long netperf_cpu_set_t; 2354 #endif 2355 2356 netperf_cpu_set_t netperf_cpu_set; 2357 unsigned int len = sizeof(netperf_cpu_set); 2358 2359 if (mapped_affinity < 8*sizeof(netperf_cpu_set)) { 2360 NETPERF_CPU_ZERO(&netperf_cpu_set); 2361 NETPERF_CPU_SET(mapped_affinity,&netperf_cpu_set); 2362 2363 if (sched_setaffinity(getpid(), len, &netperf_cpu_set)) { 2364 if (debug) { 2365 fprintf(stderr, "failed to set PID %d's CPU affinity errno %d\n", 2366 getpid(),errno); 2367 fflush(stderr); 2368 } 2369 } 2370 } 2371 else { 2372 if (debug) { 2373 fprintf(stderr, 2374 "CPU number larger than pre-compiled limits. Consider a recompile.\n"); 2375 fflush(stderr); 2376 } 2377 } 2378 2379 #elif HAVE_BIND_TO_CPU_ID 2380 /* this is the one for Tru64 */ 2381 #include <sys/types.h> 2382 #include <sys/resource.h> 2383 #include <sys/processor.h> 2384 2385 /* really should be checking a return code one of these days. raj 2386 2005/08/31 */ 2387 2388 bind_to_cpu_id(getpid(), mapped_affinity,0); 2389 2390 #elif WIN32 2391 2392 { 2393 ULONG_PTR AffinityMask; 2394 ULONG_PTR ProcessAffinityMask; 2395 ULONG_PTR SystemAffinityMask; 2396 2397 if ((mapped_affinity < 0) || 2398 (mapped_affinity > MAXIMUM_PROCESSORS)) { 2399 fprintf(where, 2400 "Invalid processor_affinity specified: %d\n", mapped_affinity); fflush(where); 2401 return; 2402 } 2403 2404 if (!GetProcessAffinityMask( 2405 GetCurrentProcess(), 2406 &ProcessAffinityMask, 2407 &SystemAffinityMask)) 2408 { 2409 perror("GetProcessAffinityMask failed"); 2410 fflush(stderr); 2411 exit(1); 2412 } 2413 2414 AffinityMask = (ULONG_PTR)1 << mapped_affinity; 2415 2416 if (AffinityMask & ProcessAffinityMask) { 2417 if (!SetThreadAffinityMask( GetCurrentThread(), AffinityMask)) { 2418 perror("SetThreadAffinityMask failed"); 2419 fflush(stderr); 2420 } 2421 } else if (debug) { 2422 fprintf(where, 2423 "Processor affinity set to CPU# %d\n", mapped_affinity); 2424 fflush(where); 2425 } 2426 } 2427 2428 #else 2429 if (debug) { 2430 fprintf(where, 2431 "Processor affinity not available for this platform!\n"); 2432 fflush(where); 2433 } 2434 #endif 2435 } 2436 2437 2438 /* 2440 * Sets a socket to non-blocking operation. 2441 */ 2442 int 2443 set_nonblock (SOCKET sock) 2444 { 2445 #ifdef WIN32 2446 unsigned long flags = 1; 2447 return (ioctlsocket(sock, FIONBIO, &flags) != SOCKET_ERROR); 2448 #else 2449 return (fcntl(sock, F_SETFL, O_NONBLOCK) != -1); 2450 #endif 2451 } 2452 2453 2454 2456 /* send a request, only converting the first n ints-worth of the 2457 test-specific data via htonl() before sending on the 2458 connection. the first two ints, which are before the test-specific 2459 portion are always converted. raj 2008-02-05 */ 2460 2461 void 2462 send_request_n(int n) 2463 { 2464 2465 int counter,count; 2466 2467 if (n < 0) count = sizeof(netperf_request)/4; 2468 else count = 2 + n; 2469 2470 /* silently truncate if the caller called for more than we have */ 2471 if (count > sizeof(netperf_request)/4) { 2472 if (debug > 1) { 2473 fprintf(where, 2474 "WARNING, htonl conversion count of %d was larger than netperf_request\n", 2475 count - 2); 2476 fflush(where); 2477 } 2478 count = sizeof(netperf_request)/4; 2479 } 2480 2481 /* display the contents of the request if the debug level is high 2482 enough. otherwise, just send the darned thing ;-) */ 2483 2484 if (debug > 1) { 2485 fprintf(where, 2486 "entered send_request_n...contents before %d htonls:\n", 2487 count); 2488 dump_request(); 2489 } 2490 2491 /* pass the processor affinity request value to netserver this is a 2492 kludge and I know it. sgb 8/11/04. we keep this here to deal 2493 with there being two paths to this place - direct and via 2494 send_request() */ 2495 2496 netperf_request.content.dummy = remote_proc_affinity; 2497 2498 /* put the entire request array into network order. We do this 2499 arbitrarily rather than trying to figure-out just how much of the 2500 request array contains real information. this should be simpler, 2501 and at any rate, the performance of sending control messages for 2502 this benchmark is not of any real concern. */ 2503 2504 for (counter = 0; counter < count; counter++) { 2505 request_array[counter] = htonl(request_array[counter]); 2506 } 2507 2508 if (debug > 1) { 2509 fprintf(where,"send_request_n...contents after %d htonls:\n", 2510 count); 2511 dump_request(); 2512 2513 fprintf(where, 2514 "\nsend_request: about to send %u bytes from %p\n", 2515 (unsigned int) sizeof(netperf_request), 2516 &netperf_request); 2517 fflush(where); 2518 } 2519 2520 if (send(netlib_control, 2521 (char *)&netperf_request, 2522 sizeof(netperf_request), 2523 0) != sizeof(netperf_request)) { 2524 perror("send_request: send call failure"); 2525 2526 exit(1); 2527 } 2528 } 2529 2530 /***********************************************************************/ 2531 /* */ 2532 /* send_request() */ 2533 /* */ 2534 /* send a netperf request on the control socket to the remote half of */ 2535 /* the connection. to get us closer to intervendor interoperability, */ 2536 /* we will call htonl on each of the int that compose the message to */ 2537 /* be sent. the server-half of the connection will call the ntohl */ 2538 /* routine to undo any changes that may have been made... */ 2539 /* */ 2540 /***********************************************************************/ 2541 2542 void 2543 send_request() 2544 { 2545 2546 /* pass the processor affinity request value to netserver this is a 2547 kludge and I know it. sgb 8/11/04 */ 2548 2549 netperf_request.content.dummy = remote_proc_affinity; 2550 2551 /* call send_request_n telling it to convert everything */ 2552 2553 send_request_n(-1); 2554 2555 } 2556 2557 /* send a response, only converting the first n ints-worth of the 2558 test-specific data via htonl() before sending on the 2559 connection. the first two ints, which are before the test-specific 2560 portion are always converted. raj 2008-02-05 */ 2561 2562 void 2563 send_response_n(int n) 2564 { 2565 int counter, count; 2566 int bytes_sent; 2567 2568 if (n < 0) count = sizeof(netperf_request)/4; 2569 else count = 2 + n; 2570 2571 /* silently truncate if the caller called for more than we have */ 2572 if (count > sizeof(netperf_request)/4) { 2573 if (debug > 1) { 2574 fprintf(where, 2575 "WARNING, htonl conversion count of %d was larger than netperf_request\n", 2576 count - 2); 2577 fflush(where); 2578 } 2579 count = sizeof(netperf_request)/4; 2580 } 2581 2582 /* display the contents of the request if the debug level is high */ 2583 /* enough. otherwise, just send the darned thing ;-) */ 2584 2585 if (debug > 1) { 2586 fprintf(where, 2587 "send_response_n: contents of %u ints before %d htonl,\n", 2588 (unsigned int) sizeof(netperf_response)/4, 2589 count); 2590 dump_response(); 2591 } 2592 2593 /* put the entire response_array into network order. We do this 2594 arbitrarily rather than trying to figure-out just how much of the 2595 request array contains real information. this should be simpler, 2596 and at any rate, the performance of sending control messages for 2597 this benchmark is not of any real concern. */ 2598 2599 for (counter = 0; counter < count; counter++) { 2600 response_array[counter] = htonl(response_array[counter]); 2601 } 2602 2603 if (debug > 1) { 2604 fprintf(where, 2605 "send_response_n: contents after htonl\n"); 2606 dump_response(); 2607 fprintf(where, 2608 "about to send %u bytes from %p\n", 2609 (unsigned int) sizeof(netperf_response), 2610 &netperf_response); 2611 fflush(where); 2612 } 2613 2614 /*KC*/ 2615 if ((bytes_sent = send(server_sock, 2616 (char *)&netperf_response, 2617 sizeof(netperf_response), 2618 0)) != sizeof(netperf_response)) { 2619 perror("send_response_n: send call failure"); 2620 fprintf(where, "BytesSent: %d\n", bytes_sent); 2621 exit(1); 2622 } 2623 2624 } 2625 2626 /***********************************************************************/ 2627 /* */ 2628 /* send_response() */ 2629 /* */ 2630 /* send a netperf response on the control socket to the remote half of */ 2631 /* the connection. to get us closer to intervendor interoperability, */ 2632 /* we will call htonl on each of the int that compose the message to */ 2633 /* be sent. the other half of the connection will call the ntohl */ 2634 /* routine to undo any changes that may have been made... */ 2635 /* */ 2636 /***********************************************************************/ 2637 2638 void 2639 send_response() 2640 { 2641 2642 send_response_n(-1); 2643 2644 } 2645 2646 /* go back and "undo" the ntohl that recv_request() did, starting with 2647 the specified point and going to the end of the request array */ 2648 void 2649 fixup_request_n(int n) 2650 { 2651 int i; 2652 int limit; 2653 2654 limit = sizeof(netperf_request) / 4; 2655 /* we must remember that the request_array also contains two ints of 2656 "other" stuff, so we start the fixup two in - at least I think we 2657 should. raj 2012-04-02 */ 2658 for (i = n + 2; i < limit; i++) { 2659 request_array[i] = htonl(request_array[i]); 2660 } 2661 if (debug > 1) { 2662 fprintf(where, 2663 "%s: request contents after fixup at the %d th int\n", 2664 __FUNCTION__, 2665 n); 2666 dump_request(); 2667 fflush(where); 2668 } 2669 } 2670 2671 /* receive a request, only converting the first n ints-worth of the 2672 test-specific data via htonl() before sending on the 2673 connection. the first two ints, which are before the test-specific 2674 portion are always converted. raj 2008-02-05 */ 2675 2676 int 2677 recv_request_timed_n(int n, int seconds) 2678 { 2679 int tot_bytes_recvd, 2680 bytes_recvd, 2681 bytes_left; 2682 char *buf = (char *)&netperf_request; 2683 int buflen = sizeof(netperf_request); 2684 int counter,count; 2685 2686 fd_set readfds; 2687 struct timeval timeout; 2688 2689 if (n < 0) count = sizeof(netperf_request)/4; 2690 else count = 2 + n; 2691 2692 /* silently truncate if the caller called for more than we have */ 2693 if (count > sizeof(netperf_request)/4) { 2694 if (debug > 1) { 2695 fprintf(where, 2696 "WARNING, htonl conversion count of %d was larger than netperf_request\n", 2697 count - 2); 2698 fflush(where); 2699 } 2700 count = sizeof(netperf_request)/4; 2701 } 2702 2703 /* for the time being, we rather rely on select decrementing timeout 2704 each time to preclude someone with nefarious intent from just 2705 dribbling data to us piecemeal. of course, who knows what 2706 someone with nefarious intent might come-up with. raj 2012-01-23 */ 2707 tot_bytes_recvd = 0; 2708 bytes_recvd = 0; /* nt_lint; bytes_recvd uninitialized if buflen == 0 */ 2709 bytes_left = buflen; 2710 timeout.tv_sec = seconds; 2711 timeout.tv_usec = 0; 2712 do { 2713 FD_ZERO(&readfds); 2714 FD_SET(server_sock,&readfds); 2715 if (select(FD_SETSIZE, 2716 &readfds, 2717 0, 2718 0, 2719 (seconds > 0) ? &timeout : NULL) != 1) { 2720 fprintf(where, 2721 "Issue receiving request on control connection. Errno %d (%s)\n", 2722 errno, 2723 strerror(errno)); 2724 fflush(where); 2725 close(server_sock); 2726 return -1; 2727 } 2728 2729 if ((bytes_recvd = recv(server_sock, buf, bytes_left, 0)) > 0) { 2730 tot_bytes_recvd += bytes_recvd; 2731 buf += bytes_recvd; 2732 bytes_left -= bytes_recvd; 2733 } 2734 } while ((tot_bytes_recvd != buflen) && 2735 (bytes_recvd > 0 )); 2736 2737 /* put the request into host order */ 2738 2739 for (counter = 0; counter < count; counter++) { 2740 request_array[counter] = ntohl(request_array[counter]); 2741 } 2742 2743 if (debug) { 2744 fprintf(where, 2745 "recv_request: received %d bytes of request.\n", 2746 tot_bytes_recvd); 2747 fflush(where); 2748 } 2749 2750 if (bytes_recvd == SOCKET_ERROR) { 2751 Print_errno(where, 2752 "recv_request: error on recv"); 2753 fflush(where); 2754 close(server_sock); 2755 return -1; 2756 } 2757 2758 if (bytes_recvd == 0) { 2759 /* the remote has shutdown the control connection, we should shut 2760 it down as well and return */ 2761 if (debug) { 2762 fprintf(where, 2763 "recv_request: remote requested shutdown of control\n"); 2764 fflush(where); 2765 } 2766 2767 close(server_sock); 2768 return 0; 2769 } 2770 2771 if (tot_bytes_recvd < buflen) { 2772 if (debug > 1) 2773 dump_request(); 2774 2775 fprintf(where, 2776 "recv_request: partial request received of %d bytes\n", 2777 tot_bytes_recvd); 2778 fflush(where); 2779 close(server_sock); 2780 return -1; 2781 } 2782 2783 if (debug > 1) { 2784 dump_request(); 2785 } 2786 2787 /* get the processor affinity request value from netperf this is a 2788 kludge and I know it. sgb 8/11/04 */ 2789 2790 local_proc_affinity = netperf_request.content.dummy; 2791 2792 if (local_proc_affinity != -1) { 2793 bind_to_specific_processor(local_proc_affinity,0); 2794 } 2795 2796 return buflen; 2797 } 2798 2799 /* receive a request, only converting the first n ints-worth of the 2800 test-specific data via htonl() before sending on the 2801 connection. the first two ints, which are before the test-specific 2802 portion are always converted. raj 2008-02-05 */ 2803 2804 int 2805 recv_request_n(int n) 2806 { 2807 2808 return recv_request_timed_n(n,0); 2809 2810 } 2811 2812 /***********************************************************************/ 2813 /* */ 2814 /* recv_request() */ 2815 /* */ 2816 /* receive the remote's request on the control socket. we will put */ 2817 /* the entire response into host order before giving it to the */ 2818 /* calling routine. hopefully, this will go most of the way to */ 2819 /* insuring intervendor interoperability. if there are any problems, */ 2820 /* we will just punt the entire situation. */ 2821 /* */ 2822 /***********************************************************************/ 2823 2824 int 2825 recv_request() 2826 { 2827 2828 return recv_request_n(-1); 2829 2830 } 2831 2832 void 2833 recv_response_timed_n(int addl_time, int n) 2834 { 2835 int tot_bytes_recvd, 2836 bytes_recvd = 0, 2837 bytes_left; 2838 char *buf = (char *)&netperf_response; 2839 int buflen = sizeof(netperf_response); 2840 int counter,count; 2841 2842 /* stuff for select, use fd_set for better compliance */ 2843 fd_set readfds; 2844 struct timeval timeout; 2845 2846 tot_bytes_recvd = 0; 2847 bytes_left = buflen; 2848 2849 if (n < 0) count = sizeof(netperf_request)/4; 2850 else count = 2 + n; 2851 2852 /* silently truncate if the caller called for more than we have */ 2853 if (count > sizeof(netperf_request)/4) { 2854 if (debug > 1) { 2855 fprintf(where, 2856 "WARNING, htonl conversion count of %d was larger than netperf_response\n", 2857 count - 2); 2858 fflush(where); 2859 } 2860 count = sizeof(netperf_request)/4; 2861 } 2862 2863 /* zero out the response structure */ 2864 2865 /* BUG FIX SJB 2/4/93 - should be < not <= */ 2866 for (counter = 0; 2867 counter < sizeof(netperf_response)/sizeof(int); 2868 counter++) { 2869 response_array[counter] = 0; 2870 } 2871 2872 /* we only select once. it is assumed that if the response is split 2873 (which should not be happening, that we will receive the whole 2874 thing and not have a problem ;-) */ 2875 2876 FD_ZERO(&readfds); 2877 FD_SET(netlib_control,&readfds); 2878 timeout.tv_sec = 120 + addl_time; /* wait at least two minutes 2879 before punting - the 2880 USE_LOOPER CPU stuff may 2881 cause remote's to have a bit 2882 longer time of it than 60 2883 seconds would allow. 2884 triggered by fix from Jeff 2885 Dwork. */ 2886 timeout.tv_usec = 0; 2887 2888 /* select had better return one, or there was either a problem or a */ 2889 /* timeout... */ 2890 2891 if ((counter = select(FD_SETSIZE, 2892 &readfds, 2893 0, 2894 0, 2895 &timeout)) != 1) { 2896 fprintf(where, 2897 "%s: no response received. errno %d counter %d\n", 2898 __FUNCTION__, 2899 errno, 2900 counter); 2901 exit(1); 2902 } 2903 2904 while ((tot_bytes_recvd != buflen) && 2905 ((bytes_recvd = recv(netlib_control, buf, bytes_left,0)) > 0 )) { 2906 tot_bytes_recvd += bytes_recvd; 2907 buf += bytes_recvd; 2908 bytes_left -= bytes_recvd; 2909 } 2910 2911 if (debug) { 2912 fprintf(where,"recv_response: received a %d byte response\n", 2913 tot_bytes_recvd); 2914 fflush(where); 2915 } 2916 2917 /* put the desired quantity of the response into host order */ 2918 2919 for (counter = 0; counter < count; counter++) { 2920 response_array[counter] = ntohl(response_array[counter]); 2921 } 2922 2923 if (bytes_recvd == SOCKET_ERROR) { 2924 perror("recv_response"); 2925 exit(1); 2926 } 2927 if (tot_bytes_recvd < buflen) { 2928 fprintf(stderr, 2929 "recv_response: partial response received: %d bytes\n", 2930 tot_bytes_recvd); 2931 fflush(stderr); 2932 if (debug > 1) 2933 dump_response(); 2934 exit(1); 2935 } 2936 if (debug > 1) { 2937 dump_response(); 2938 } 2939 } 2940 2941 /* 2942 2943 recv_response_timed() 2944 2945 receive the remote's response on the control socket. we will put the 2946 entire response into host order before giving it to the calling 2947 routine. hopefully, this will go most of the way to insuring 2948 intervendor interoperability. if there are any problems, we will 2949 just punt the entire situation. 2950 2951 The call to select at the beginning is to get us out of hang 2952 situations where the remote gives-up but we don't find-out about 2953 it. This seems to happen only rarely, but it would be nice to be 2954 somewhat robust ;-) 2955 2956 The "_timed" part is to allow the caller to add (or I suppose 2957 subtract) from the length of timeout on the select call. this was 2958 added since not all the CPU utilization mechanisms require a 40 2959 second calibration, and we used to have an aribtrary 40 second sleep 2960 in "calibrate_remote_cpu" - since we don't _always_ need that, we 2961 want to simply add 40 seconds to the select() timeout from that 2962 call, but don't want to change all the "recv_response" calls in the 2963 code right away. sooo, we push the functionality of the old 2964 recv_response() into a new recv_response_timed(addl_timout) call, 2965 and have recv_response() call recv_response_timed(0). raj 2966 2005-05-16 2967 2968 */ 2969 2970 2971 void 2972 recv_response_timed(int addl_time) 2973 { 2974 2975 /* -1 => convert all the test-specific data via ntohl */ 2976 recv_response_timed_n(addl_time,-1); 2977 2978 } 2979 2980 void 2981 recv_response() 2982 { 2983 /* 0 => no additional time, -1 => convert all test-specific data */ 2984 recv_response_timed_n(0,-1); 2985 } 2986 2987 void 2988 recv_response_n(int n) 2989 { 2990 recv_response_timed_n(0,n); 2991 } 2992 2993 2994 2995 2997 #if defined(USE_PSTAT) || defined (USE_SYSCTL) 2998 int 2999 hi_32(big_int) 3000 long long *big_int; 3001 { 3002 union overlay_u { 3003 long long dword; 3004 long words[2]; 3005 } *overlay; 3006 3007 overlay = (union overlay_u *)big_int; 3008 /* on those systems which are byte swapped, we really wish to return 3009 words[1] - at least I think so - raj 4/95 */ 3010 if (htonl(1L) == 1L) { 3011 /* we are a "normal" :) machine */ 3012 return(overlay->words[0]); 3013 } 3014 else { 3015 return(overlay->words[1]); 3016 } 3017 } 3018 3019 int 3020 lo_32(big_int) 3021 long long *big_int; 3022 { 3023 union overlay_u { 3024 long long dword; 3025 long words[2]; 3026 } *overlay; 3027 3028 overlay = (union overlay_u *)big_int; 3029 /* on those systems which are byte swapped, we really wish to return 3030 words[0] - at least I think so - raj 4/95 */ 3031 if (htonl(1L) == 1L) { 3032 /* we are a "normal" :) machine */ 3033 return(overlay->words[1]); 3034 } 3035 else { 3036 return(overlay->words[0]); 3037 } 3038 } 3039 3040 #endif /* USE_PSTAT || USE_SYSCTL */ 3041 3042 3044 void libmain() 3045 { 3046 fprintf(where,"hello world\n"); 3047 fprintf(where,"debug: %d\n",debug); 3048 } 3049 3050 3051 void 3053 get_sock_buffer (SOCKET sd, enum sock_buffer which, int *effective_sizep) 3054 { 3055 #ifdef SO_SNDBUF 3056 int optname = (which == SEND_BUFFER) ? SO_SNDBUF : SO_RCVBUF; 3057 netperf_socklen_t sock_opt_len; 3058 3059 sock_opt_len = sizeof(*effective_sizep); 3060 if (getsockopt(sd, SOL_SOCKET, optname, (char *)effective_sizep, 3061 &sock_opt_len) < 0) { 3062 fprintf(where, "netperf: get_sock_buffer: getsockopt %s: errno %d\n", 3063 (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF", errno); 3064 fflush(where); 3065 *effective_sizep = -1; 3066 } 3067 3068 if (debug) { 3069 fprintf(where, "netperf: get_sock_buffer: " 3070 "%s socket size determined to be %d\n", 3071 (which == SEND_BUFFER) ? "send" : "receive", *effective_sizep); 3072 fflush(where); 3073 } 3074 3075 #else 3076 *effective_sizep = -1; 3077 #endif 3078 } 3079 3080 void 3081 set_sock_buffer (SOCKET sd, enum sock_buffer which, int requested_size, int *effective_sizep) 3082 { 3083 #ifdef SO_SNDBUF 3084 3085 int optname = (which == SEND_BUFFER) ? SO_SNDBUF : SO_RCVBUF; 3086 3087 /* seems that under Windows, setting a value of zero is how one 3088 tells the stack you wish to enable copy-avoidance. Knuth only 3089 knows what it will do on other stacks, but it might be 3090 interesting to find-out, so we won't bother #ifdef'ing the change 3091 to allow asking for 0 bytes. Courtesy of SAF, 2007-05 raj 3092 2007-05-31 */ 3093 if (requested_size >= 0) { 3094 if (setsockopt(sd, SOL_SOCKET, optname, 3095 (char *)&requested_size, sizeof(int)) < 0) { 3096 fprintf(where, "netperf: set_sock_buffer: %s option: errno %d (%s)\n", 3097 (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF", 3098 errno, 3099 strerror(errno)); 3100 fflush(where); 3101 exit(1); 3102 } 3103 if (debug > 1) { 3104 fprintf(where, "netperf: set_sock_buffer: %s of %d requested.\n", 3105 (which == SEND_BUFFER) ? "SO_SNDBUF" : "SO_RCVBUF", 3106 requested_size); 3107 fflush(where); 3108 } 3109 } 3110 3111 /* the getsockopt() call that used to be here has been hoisted into 3112 its own routine to be used on those platforms where the socket 3113 buffer sizes might change from the beginning to the end of the 3114 run. raj 2008-01-15 */ 3115 3116 get_sock_buffer(sd, which, effective_sizep); 3117 3118 #else /* SO_SNDBUF */ 3119 *effective_sizep = -1; 3120 #endif /* SO_SNDBUF */ 3121 } 3122 3123 void 3124 dump_addrinfo(FILE *dumploc, struct addrinfo *info, 3125 const char *host, char *port, int family) 3126 { 3127 struct sockaddr *ai_addr; 3128 struct addrinfo *temp; 3129 temp=info; 3130 3131 fprintf(dumploc, 3132 "getaddrinfo returned the following for host '%s' port '%s' " 3133 " family %s\n", 3134 host, 3135 port, 3136 inet_ftos(family)); 3137 3138 while (temp) { 3139 /* seems that Solaris 10 GA bits will not give a canonical name 3140 for ::0 or 0.0.0.0, and their fprintf() cannot deal with a null 3141 pointer, so we have to check for a null pointer. probably a 3142 safe thing to do anyway, eventhough it was not necessary on 3143 linux or hp-ux. raj 2005-02-09 */ 3144 fprintf(dumploc, 3145 "\tcannonical name: '%s'\n" 3146 "\tflags: %x family: %s: socktype: %s protocol %s addrlen %d\n", 3147 (temp->ai_canonname) ? temp->ai_canonname : "(nil)", 3148 temp->ai_flags, 3149 inet_ftos(temp->ai_family), 3150 inet_ttos(temp->ai_socktype), 3151 inet_ptos(temp->ai_protocol), 3152 temp->ai_addrlen); 3153 ai_addr = temp->ai_addr; 3154 if (ai_addr != NULL) { 3155 int i; 3156 fprintf(dumploc, 3157 "\tsa_family: %s sadata:", 3158 inet_ftos(ai_addr->sa_family)); 3159 for (i = 0; i < (int) temp->ai_addrlen; i++) { 3160 fprintf(dumploc, 3161 (temp->ai_family == AF_INET) ? " %d" : " %.2x", 3162 (u_char)ai_addr->sa_data[i]); 3163 } 3164 fprintf(dumploc,"\n"); 3165 } 3166 temp = temp->ai_next; 3167 } 3168 fflush(dumploc); 3169 } 3170 3171 struct addrinfo * 3172 resolve_host(char *hostname, 3173 char *port, 3174 int family) 3175 { 3176 struct addrinfo hints; 3177 struct addrinfo *ai; 3178 int count; 3179 int error; 3180 3181 if (debug) { 3182 fprintf(where, 3183 "resolve_host called with host '%s' port '%s' family %s\n", 3184 hostname, 3185 port, 3186 inet_ftos(family)); 3187 fflush(where); 3188 } 3189 3190 memset(&hints, 0, sizeof(hints)); 3191 hints.ai_family = family; 3192 hints.ai_socktype = SOCK_STREAM; 3193 hints.ai_protocol = IPPROTO_TCP; 3194 hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; 3195 count = 0; 3196 do { 3197 error = getaddrinfo((char *)hostname, 3198 (char *)port, 3199 &hints, 3200 &ai); 3201 count += 1; 3202 if (error == EAI_AGAIN) { 3203 if (debug) { 3204 fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n"); 3205 fflush(where); 3206 } 3207 sleep(1); 3208 } 3209 } while ((error == EAI_AGAIN) && (count <= 5)); 3210 3211 if (error) { 3212 printf("%s: could not resolve host '%s' port '%s' af %s" 3213 "\n\tgetaddrinfo returned %d %s\n", 3214 __FUNCTION__, 3215 hostname, 3216 port, 3217 inet_ftos(family), 3218 error, 3219 gai_strerror(error)); 3220 return(NULL); 3221 } 3222 3223 if (debug) { 3224 dump_addrinfo(where, ai, hostname, port, family); 3225 } 3226 3227 return (ai); 3228 } 3229 3230 /* 3231 establish_control() 3232 3233 set-up the control connection between netperf and the netserver so 3234 we can actually run some tests. if we cannot establish the control 3235 connection, that may or may not be a good thing, so we will let the 3236 caller decide what to do. 3237 3238 to assist with pesky end-to-end-unfriendly things like firewalls, we 3239 allow the caller to specify both the remote hostname and port, and 3240 the local addressing info. i believe that in theory it is possible 3241 3242 another, but for the time being, we are only going to take-in one 3243 requested address family parameter. this means that the only way 3244 (iirc) that we might get a mixed-mode connection would be if the 3245 address family is specified as AF_UNSPEC, and getaddrinfo() returns 3246 different families for the local and server names. 3247 3248 the "names" can also be IP addresses in ASCII string form. 3249 3250 raj 2003-02-27 */ 3251 3252 SOCKET 3253 establish_control_internal(char *hostname, 3254 char *port, 3255 int remfam, 3256 char *localhost, 3257 char *localport, 3258 int locfam) 3259 { 3260 int not_connected; 3261 SOCKET control_sock; 3262 3263 struct addrinfo *local_res; 3264 struct addrinfo *remote_res; 3265 struct addrinfo *local_res_temp; 3266 struct addrinfo *remote_res_temp; 3267 3268 remote_res = resolve_host(hostname, port, remfam); 3269 if (!remote_res) 3270 return(INVALID_SOCKET); 3271 3272 local_res = resolve_host(localhost, localport, locfam); 3273 if (!local_res) 3274 return(INVALID_SOCKET); 3275 3276 if (debug) { 3277 fprintf(where, 3278 "establish_control called with host '%s' port '%s' remfam %s\n" 3279 "\t\tlocal '%s' port '%s' locfam %s\n", 3280 hostname, 3281 port, 3282 inet_ftos(remfam), 3283 localhost, 3284 localport, 3285 inet_ftos(locfam)); 3286 fflush(where); 3287 } 3288 3289 not_connected = 1; 3290 local_res_temp = local_res; 3291 remote_res_temp = remote_res; 3292 /* we want to loop through all the possibilities. looping on the 3293 local addresses will be handled within the while loop. I suppose 3294 these is some more "C-expert" way to code this, but it has not 3295 lept to mind just yet :) raj 2003-02024 */ 3296 3297 while (remote_res_temp != NULL) { 3298 3299 /* I am guessing that we should use the address family of the 3300 local endpoint, and we will not worry about mixed family types 3301 - presumeably the stack or other transition mechanisms will be 3302 able to deal with that for us. famous last words :) raj 3303 2003-02-26 */ 3304 control_sock = socket(local_res_temp->ai_family, 3305 SOCK_STREAM, 3306 0); 3307 if (control_sock == INVALID_SOCKET) { 3308 /* at some point we'll need a more generic "display error" 3309 message for when/if we use GUIs and the like. unlike a bind 3310 or connect failure, failure to allocate a socket is 3311 "immediately fatal" and so we return to the caller. raj 3312 2003-02-24 */ 3313 if (debug) { 3314 perror("establish_control: unable to allocate control socket"); 3315 } 3316 return(INVALID_SOCKET); 3317 } 3318 3319 /* if we are going to control the local enpoint addressing, we 3320 need to call bind. of course, we should probably be setting one 3321 of the SO_REUSEmumble socket options? raj 2005-02-04 */ 3322 if (bind(control_sock, 3323 local_res_temp->ai_addr, 3324 local_res_temp->ai_addrlen) == 0) { 3325 if (debug) { 3326 fprintf(where, 3327 "bound control socket to %s and %s\n", 3328 localhost, 3329 localport); 3330 } 3331 3332 if (connect(control_sock, 3333 remote_res_temp->ai_addr, 3334 remote_res_temp->ai_addrlen) == 0) { 3335 /* we have successfully connected to the remote netserver */ 3336 if (debug) { 3337 fprintf(where, 3338 "successful connection to remote netserver at %s and %s\n", 3339 hostname, 3340 port); 3341 } 3342 not_connected = 0; 3343 /* this should get us out of the while loop */ 3344 break; 3345 } else { 3346 /* the connect call failed */ 3347 if (debug) { 3348 fprintf(where, 3349 "establish_control: connect failed, errno %d %s\n" 3350 " trying next address combination\n", 3351 errno, 3352 strerror(errno)); 3353 fflush(where); 3354 } 3355 } 3356 } 3357 else { 3358 /* the bind failed */ 3359 if (debug) { 3360 fprintf(where, 3361 "establish_control: bind failed, errno %d %s\n" 3362 " trying next address combination\n", 3363 errno, 3364 strerror(errno)); 3365 fflush(where); 3366 } 3367 } 3368 3369 if ((local_res_temp = local_res_temp->ai_next) == NULL) { 3370 /* wrap the local and move to the next server, don't forget to 3371 close the current control socket. raj 2003-02-24 */ 3372 local_res_temp = local_res; 3373 /* the outer while conditions will deal with the case when we 3374 get to the end of all the possible remote addresses. */ 3375 remote_res_temp = remote_res_temp->ai_next; 3376 /* it is simplest here to just close the control sock. since 3377 this is not a performance critical section of code, we 3378 don't worry about overheads for socket allocation or 3379 close. raj 2003-02-24 */ 3380 } 3381 close(control_sock); 3382 } 3383 3384 control_family = local_res_temp->ai_family; 3385 3386 /* we no longer need the addrinfo stuff */ 3387 freeaddrinfo(local_res); 3388 freeaddrinfo(remote_res); 3389 3390 /* so, we are either connected or not */ 3391 if (not_connected) { 3392 fprintf(where, 3393 "establish control: are you sure there is a netserver " 3394 "listening on %s at port %s?\n", 3395 hostname, 3396 port); 3397 fflush(where); 3398 control_family = AF_UNSPEC; 3399 return(INVALID_SOCKET); 3400 } 3401 /* at this point, we are connected. we probably want some sort of 3402 version check with the remote at some point. raj 2003-02-24 */ 3403 return(control_sock); 3404 } 3405 3406 void 3407 establish_control(char *hostname, 3408 char *port, 3409 int remfam, 3410 char *localhost, 3411 char *localport, 3412 int locfam) 3413 3414 { 3415 3416 netlib_control = establish_control_internal(hostname, 3417 port, 3418 remfam, 3419 localhost, 3420 localport, 3421 locfam); 3422 if (netlib_control == INVALID_SOCKET) { 3423 fprintf(where, 3424 "establish_control could not establish the control" 3425 " connection from %s port %s address family %s to %s" 3426 " port %s address family %s\n", 3427 localhost,localport,inet_ftos(locfam), 3428 hostname,port,inet_ftos(remfam)); 3429 fflush(where); 3430 exit(INVALID_SOCKET); 3431 } 3432 } 3433 3434 3435 3437 3438 /***********************************************************************/ 3439 /* */ 3440 /* get_id() */ 3441 /* */ 3442 /* Return a string to the calling routine that contains the */ 3443 /* identifying information for the host we are running on. This */ 3444 /* information will then either be displayed locally, or returned to */ 3445 /* a remote caller for display there. */ 3446 /* */ 3447 /***********************************************************************/ 3448 3449 char * 3450 get_id() 3451 { 3452 static char id_string[80]; 3453 #ifdef WIN32 3454 char system_name[MAX_COMPUTERNAME_LENGTH+1] ; 3455 DWORD name_len = MAX_COMPUTERNAME_LENGTH + 1 ; 3456 #else 3457 struct utsname system_name; 3458 #endif /* WIN32 */ 3459 3460 #ifdef WIN32 3461 SYSTEM_INFO SystemInfo; 3462 GetSystemInfo( &SystemInfo ) ; 3463 if ( !GetComputerName(system_name , &name_len) ) 3464 strcpy(system_name , "no_name") ; 3465 #else 3466 if (uname(&system_name) <0) { 3467 perror("identify_local: uname"); 3468 exit(1); 3469 } 3470 #endif /* WIN32 */ 3471 3472 snprintf(id_string, sizeof(id_string), 3473 #ifdef WIN32 3474 "%-15s%-15s%d.%d%d", 3475 "Windows NT", 3476 system_name , 3477 GetVersion() & 0xFF , 3478 GetVersion() & 0xFF00 , 3479 SystemInfo.dwProcessorType 3480 3481 #else 3482 "%-15s%-15s%-15s%-15s%-15s", 3483 system_name.sysname, 3484 system_name.nodename, 3485 system_name.release, 3486 system_name.version, 3487 system_name.machine 3488 #endif /* WIN32 */ 3489 ); 3490 return (id_string); 3491 } 3492 3493 3494 /***********************************************************************/ 3495 /* */ 3496 /* identify_local() */ 3497 /* */ 3498 /* Display identifying information about the local host to the user. */ 3499 /* At first release, this information will be the same as that which */ 3500 /* is returned by the uname -a command, with the exception of the */ 3501 /* idnumber field, which seems to be a non-POSIX item, and hence */ 3502 /* non-portable. */ 3503 /* */ 3504 /***********************************************************************/ 3505 3506 void 3507 identify_local() 3508 { 3509 3510 char *local_id; 3511 3512 local_id = get_id(); 3513 3514 fprintf(where,"Local Information \n\ 3515 Sysname Nodename Release Version Machine\n"); 3516 3517 fprintf(where,"%s\n", 3518 local_id); 3519 3520 } 3521 3522 3523 /***********************************************************************/ 3524 /* */ 3525 /* identify_remote() */ 3526 /* */ 3527 /* Display identifying information about the remote host to the user. */ 3528 /* At first release, this information will be the same as that which */ 3529 /* is returned by the uname -a command, with the exception of the */ 3530 /* idnumber field, which seems to be a non-POSIX item, and hence */ 3531 /* non-portable. A request is sent to the remote side, which will */ 3532 /* return a string containing the utsname information in a */ 3533 /* pre-formatted form, which is then displayed after the header. */ 3534 /* */ 3535 /***********************************************************************/ 3536 3537 void 3538 identify_remote() 3539 { 3540 3541 char *remote_id=""; 3542 3543 /* send a request for node info to the remote */ 3544 netperf_request.content.request_type = NODE_IDENTIFY; 3545 3546 send_request(); 3547 3548 /* and now wait for the reply to come back */ 3549 3550 recv_response(); 3551 3552 if (netperf_response.content.serv_errno) { 3553 Set_errno(netperf_response.content.serv_errno); 3554 perror("identify_remote: on remote"); 3555 exit(1); 3556 } 3557 3558 fprintf(where,"Remote Information \n\ 3559 Sysname Nodename Release Version Machine\n"); 3560 3561 fprintf(where,"%s", 3562 remote_id); 3563 } 3564 3565 void 3566 cpu_start(int measure_cpu) 3567 { 3568 3569 gettimeofday(&time1, 3570 &tz); 3571 3572 if (measure_cpu) { 3573 cpu_util_init(); 3574 measuring_cpu = 1; 3575 cpu_method = get_cpu_method(); 3576 cpu_start_internal(); 3577 } 3578 } 3579 3580 3581 void 3583 cpu_stop(int measure_cpu, float *elapsed) 3584 3585 { 3586 3587 int sec, 3588 usec; 3589 3590 if (measure_cpu) { 3591 cpu_stop_internal(); 3592 cpu_util_terminate(); 3593 } 3594 3595 gettimeofday(&time2, 3596 &tz); 3597 3598 if (time2.tv_usec < time1.tv_usec) { 3599 time2.tv_usec += 1000000; 3600 time2.tv_sec -= 1; 3601 } 3602 3603 sec = time2.tv_sec - time1.tv_sec; 3604 usec = time2.tv_usec - time1.tv_usec; 3605 lib_elapsed = (float)sec + ((float)usec/(float)1000000.0); 3606 #ifdef WIN32 3607 if (timed_out) lib_elapsed-=PAD_TIME/2; 3608 #endif 3609 *elapsed = lib_elapsed; 3610 3611 } 3612 3613 3614 double 3615 calc_thruput_interval(double units_received,double elapsed) 3616 3617 { 3618 double divisor; 3619 3620 /* We will calculate the thruput in libfmt units/second */ 3621 switch (libfmt) { 3622 case 'K': 3623 divisor = 1024.0; 3624 break; 3625 case 'M': 3626 divisor = 1024.0 * 1024.0; 3627 break; 3628 case 'G': 3629 divisor = 1024.0 * 1024.0 * 1024.0; 3630 break; 3631 case 'k': 3632 divisor = 1000.0 / 8.0; 3633 break; 3634 case 'm': 3635 divisor = 1000.0 * 1000.0 / 8.0; 3636 break; 3637 case 'g': 3638 divisor = 1000.0 * 1000.0 * 1000.0 / 8.0; 3639 break; 3640 case 'x': 3641 case 'b': 3642 case 'B': 3643 divisor = 1.0; 3644 break; 3645 case 'u': 3646 /* latency in microseconds a bit squirrely but we don't want to 3647 really muck with things for the default return statement. 3648 invert transactions per second and multiply to get microseconds 3649 per transaction */ 3650 return (1 / (units_received / elapsed)) * 1000000.0; 3651 3652 default: 3653 divisor = 1024.0; 3654 } 3655 3656 return (units_received / divisor / elapsed); 3657 3658 } 3659 3660 double 3661 calc_thruput(double units_received) 3662 3663 { 3664 return(calc_thruput_interval(units_received,lib_elapsed)); 3665 } 3666 3667 /* these "_omni" versions are ones which understand 'x' as a unit, 3668 meaning transactions/s. we have a separate routine rather than 3669 convert the existing routine so we don't have to go and change 3670 _all_ the nettest_foo.c files at one time. raj 2007-06-08 */ 3671 3672 double 3673 calc_thruput_interval_omni(double units_received,double elapsed) 3674 3675 { 3676 double divisor; 3677 3678 /* We will calculate the thruput in libfmt units/second */ 3679 switch (libfmt) { 3680 case 'K': 3681 divisor = 1024.0; 3682 break; 3683 case 'M': 3684 divisor = 1024.0 * 1024.0; 3685 break; 3686 case 'G': 3687 divisor = 1024.0 * 1024.0 * 1024.0; 3688 break; 3689 case 'k': 3690 divisor = 1000.0 / 8.0; 3691 break; 3692 case 'm': 3693 divisor = 1000.0 * 1000.0 / 8.0; 3694 break; 3695 case 'g': 3696 divisor = 1000.0 * 1000.0 * 1000.0 / 8.0; 3697 break; 3698 case 'x': 3699 case 'b': 3700 case 'B': 3701 divisor = 1.0; 3702 break; 3703 case 'u': 3704 /* latency in microseconds a bit squirrely but we don't want to 3705 really muck with things for the default return statement. 3706 invert transactions per second and multiply to get microseconds 3707 per transaction */ 3708 return (1 / (units_received / elapsed)) * 1000000.0; 3709 3710 default: 3711 fprintf(where, 3712 "WARNING calc_throughput_internal_omni: unknown units %c\n", 3713 libfmt); 3714 fflush(where); 3715 divisor = 1024.0; 3716 } 3717 3718 return (units_received / divisor / elapsed); 3719 3720 } 3721 3722 double 3723 calc_thruput_omni(double units_received) 3724 3725 { 3726 return(calc_thruput_interval_omni(units_received,lib_elapsed)); 3727 } 3728 3729 3730 3732 3733 3734 float 3735 calc_cpu_util(float elapsed_time) 3736 { 3737 float temp_util; 3738 int i; 3739 temp_util = calc_cpu_util_internal(elapsed_time); 3740 3741 /* now, what was the most utilized CPU and its util? */ 3742 for (i = 0; i < MAXCPUS; i++) { 3743 if (lib_local_per_cpu_util[i] > lib_local_cpu_stats.peak_cpu_util) { 3744 lib_local_cpu_stats.peak_cpu_util = lib_local_per_cpu_util[i]; 3745 lib_local_cpu_stats.peak_cpu_id = lib_cpu_map[i]; 3746 } 3747 } 3748 3749 return temp_util; 3750 } 3751 3752 float 3753 calc_service_demand_internal(double unit_divisor, 3754 double units_sent, 3755 float elapsed_time, 3756 float cpu_utilization, 3757 int num_cpus) 3758 3759 { 3760 3761 double service_demand; 3762 double thruput; 3763 3764 if (debug) { 3765 fprintf(where, 3766 "calc_service_demand called: units_sent = %f\n" 3767 " elapsed_time = %f\n" 3768 " cpu_util = %f\n" 3769 " num cpu = %d\n", 3770 units_sent, 3771 elapsed_time, 3772 cpu_utilization, 3773 num_cpus); 3774 fflush(where); 3775 } 3776 3777 if (num_cpus == 0) num_cpus = lib_num_loc_cpus; 3778 3779 if (elapsed_time == 0.0) { 3780 elapsed_time = lib_elapsed; 3781 } 3782 if (cpu_utilization == 0.0) { 3783 cpu_utilization = lib_local_cpu_stats.cpu_util; 3784 } 3785 3786 thruput = (units_sent / 3787 (double) unit_divisor / 3788 (double) elapsed_time); 3789 3790 /* on MP systems, it is necessary to multiply the service demand by 3791 the number of CPU's. at least, I believe that to be the case:) 3792 raj 10/95 */ 3793 3794 /* thruput has a "per second" component. if we were using 100% ( 3795 100.0) of the CPU in a second, that would be 1 second, or 1 3796 millisecond, so we multiply cpu_utilization by 10 to go to 3797 milliseconds, or 10,000 to go to micro seconds. With revision 3798 2.1, the service demand measure goes to microseconds per unit. 3799 raj 12/95 */ 3800 service_demand = (cpu_utilization*10000.0/thruput) * 3801 (float) num_cpus; 3802 3803 if (debug) { 3804 fprintf(where, 3805 "calc_service_demand using: units_sent = %f\n" 3806 " elapsed_time = %f\n" 3807 " cpu_util = %f\n" 3808 " num cpu = %d\n" 3809 "calc_service_demand got: thruput = %f\n" 3810 " servdem = %f\n", 3811 units_sent, 3812 elapsed_time, 3813 cpu_utilization, 3814 num_cpus, 3815 thruput, 3816 service_demand); 3817 fflush(where); 3818 } 3819 return (float)service_demand; 3820 } 3821 3822 float calc_service_demand(double units_sent, 3823 float elapsed_time, 3824 float cpu_utilization, 3825 int num_cpus) 3826 3827 { 3828 3829 double unit_divisor = (double)1024.0; 3830 3831 return(calc_service_demand_internal(unit_divisor, 3832 units_sent, 3833 elapsed_time, 3834 cpu_utilization, 3835 num_cpus)); 3836 } 3837 3838 /* use the value of libfmt to determine the unit_divisor */ 3839 float calc_service_demand_fmt(double units_sent, 3840 float elapsed_time, 3841 float cpu_utilization, 3842 int num_cpus) 3843 3844 { 3845 double unit_divisor; 3846 3847 if ('x' == libfmt) unit_divisor = 1.0; 3848 else unit_divisor = 1024.0; 3849 3850 return(calc_service_demand_internal(unit_divisor, 3851 units_sent, 3852 elapsed_time, 3853 cpu_utilization, 3854 num_cpus)); 3855 } 3856 3857 3858 3860 float 3861 calibrate_local_cpu(float local_cpu_rate) 3862 { 3863 3864 lib_num_loc_cpus = get_num_cpus(); 3865 3866 lib_use_idle = 0; 3867 #ifdef USE_LOOPER 3868 cpu_util_init(); 3869 lib_use_idle = 1; 3870 #endif /* USE_LOOPER */ 3871 3872 if (local_cpu_rate > 0) { 3873 /* The user think that he knows what the cpu rate is. We assume 3874 that all the processors of an MP system are essentially the 3875 same - for this reason we do not have a per processor maxrate. 3876 if the machine has processors which are different in 3877 performance, the CPU utilization will be skewed. raj 4/95 */ 3878 lib_local_maxrate = local_cpu_rate; 3879 } 3880 else { 3881 /* if neither USE_LOOPER nor USE_PSTAT are defined, we return a 3882 0.0 to indicate that times or getrusage should be used. raj 3883 4/95 */ 3884 lib_local_maxrate = (float)0.0; 3885 #if defined(USE_PROC_STAT) || defined(USE_LOOPER) || defined(USE_PSTAT) || defined(USE_KSTAT) || defined(USE_PERFSTAT) || defined(USE_SYSCTL) 3886 lib_local_maxrate = calibrate_idle_rate(4,10); 3887 #endif 3888 } 3889 return lib_local_maxrate; 3890 } 3891 3892 3893 float 3894 calibrate_remote_cpu() 3895 { 3896 float remrate; 3897 3898 netperf_request.content.request_type = CPU_CALIBRATE; 3899 send_request(); 3900 /* we know that calibration will last at least 40 seconds, so go to 3901 sleep for that long so the 60 second select in recv_response will 3902 not pop. raj 7/95 */ 3903 3904 /* we know that CPU calibration may last as long as 40 seconds, so 3905 make sure we "select" for at least that long while looking for 3906 the response. raj 2005-05-16 */ 3907 recv_response_timed(40); 3908 3909 if (netperf_response.content.serv_errno) { 3910 /* initially, silently ignore remote errors and pass back a zero 3911 to the caller this should allow us to mix rev 1.0 and rev 1.1 3912 netperfs... */ 3913 return((float)0.0); 3914 } 3915 else { 3916 /* the rate is the first word of the test_specific data */ 3917 bcopy((char *)netperf_response.content.test_specific_data, 3918 (char *)&remrate, 3919 sizeof(remrate)); 3920 bcopy((char *)netperf_response.content.test_specific_data + sizeof(remrate), 3921 (char *)&lib_num_rem_cpus, 3922 sizeof(lib_num_rem_cpus)); 3923 /* remrate = (float) netperf_response.content.test_specific_data[0]; */ 3924 return(remrate); 3925 } 3926 } 3927 3928 3929 3930 #ifndef WIN32 3932 /* WIN32 requires that at least one of the file sets to select be 3933 non-null. Since msec_sleep routine is only called by nettest_dlpi 3934 & nettest_unix, let's duck this issue. */ 3935 3936 int 3937 msec_sleep( int msecs ) 3938 { 3939 int rval ; 3940 3941 struct timeval timeout; 3942 3943 timeout.tv_sec = msecs / 1000; 3944 timeout.tv_usec = (msecs - (msecs/1000) *1000) * 1000; 3945 if ((rval = select(0, 3946 0, 3947 0, 3948 0, 3949 &timeout))) { 3950 if ( SOCKET_EINTR(rval) ) { 3951 return(1); 3952 } 3953 perror("msec_sleep: select"); 3954 exit(1); 3955 } 3956 return(0); 3957 } 3958 #endif /* WIN32 */ 3959 3960 #if defined(WANT_INTERVALS) || defined(WANT_DEMO) 3961 3962 int demo_mode; /* are we actually in demo mode? = 0 3963 == not in demo mode; 1 == classic 3964 unit based demo mode; 2 == always 3965 timestamp demo mode */ 3966 double demo_interval = 1000000.0; /* what is the desired interval to 3967 display interval results. default 3968 is one second in units of 3969 microseconds */ 3970 double demo_units = 0.0; /* what is our current best guess as 3971 to how many work units must be 3972 done to be near the desired 3973 reporting interval? */ 3974 3975 double units_this_tick; 3976 #endif 3977 3978 #ifdef WANT_DEMO 3979 #ifdef HAVE_GETHRTIME 3980 static hrtime_t demo_one; 3981 static hrtime_t demo_two; 3982 static hrtime_t *demo_one_ptr = &demo_one; 3983 static hrtime_t *demo_two_ptr = &demo_two; 3984 static hrtime_t *temp_demo_ptr = &demo_one; 3985 #elif defined(WIN32) 3986 static LARGE_INTEGER demo_one; 3987 static LARGE_INTEGER demo_two; 3988 static LARGE_INTEGER *demo_one_ptr = &demo_one; 3989 static LARGE_INTEGER *demo_two_ptr = &demo_two; 3990 static LARGE_INTEGER *temp_demo_ptr = &demo_one; 3991 #else 3992 static struct timeval demo_one; 3993 static struct timeval demo_two; 3994 static struct timeval *demo_one_ptr = &demo_one; 3995 static struct timeval *demo_two_ptr = &demo_two; 3996 static struct timeval *temp_demo_ptr = &demo_one; 3997 #endif 3998 3999 void demo_first_timestamp() { 4000 HIST_timestamp(demo_one_ptr); 4001 } 4002 4003 void demo_reset() { 4004 if (debug) { 4005 fprintf(where, 4006 "Resetting interim results\n"); 4007 fflush(where); 4008 } 4009 units_this_tick = 0; 4010 demo_first_timestamp(); 4011 } 4012 4013 /* for a _STREAM test, "a" should be lss_size and "b" should be 4014 rsr_size. for a _MAERTS test, "a" should be lsr_size and "b" should 4015 be rss_size. raj 2005-04-06 */ 4016 void demo_stream_setup(uint32_t a, uint32_t b) { 4017 if ((demo_mode) && (demo_units == 0)) { 4018 /* take our default value of demo_units to be the larger of 4019 twice the remote's SO_RCVBUF or twice our SO_SNDBUF */ 4020 if (a > b) { 4021 demo_units = 2*a; 4022 } 4023 else { 4024 demo_units = 2*b; 4025 } 4026 } 4027 } 4028 4029 #ifdef WIN32 4030 __forceinline void demo_interval_display(double actual_interval) 4031 #else 4032 inline void demo_interval_display(double actual_interval) 4033 #endif 4034 { 4035 static int count = 0; 4036 struct timeval now; 4037 4038 gettimeofday(&now,NULL); 4039 switch (netperf_output_mode) { 4040 case HUMAN: 4041 fprintf(where, 4042 "Interim result: %7.2f %s/s over %.3f seconds ending at %ld.%.3ld\n", 4043 calc_thruput_interval(units_this_tick, 4044 actual_interval/1000000.0), 4045 format_units(), 4046 actual_interval/1000000.0, 4047 now.tv_sec, 4048 (long) now.tv_usec/1000); 4049 break; 4050 case CSV: 4051 fprintf(where, 4052 "%7.2f,%s/s,%.3f,%ld.%.3ld\n", 4053 calc_thruput_interval(units_this_tick, 4054 actual_interval/1000000.0), 4055 format_units(), 4056 actual_interval/1000000.0, 4057 now.tv_sec, 4058 (long) now.tv_usec/1000); 4059 break; 4060 case KEYVAL: 4061 fprintf(where, 4062 "NETPERF_INTERIM_RESULT[%d]=%.2f\n" 4063 "NETPERF_UNITS[%d]=%s/s\n" 4064 "NETPERF_INTERVAL[%d]=%.3f\n" 4065 "NETPERF_ENDING[%d]=%ld.%.3ld\n", 4066 count, 4067 calc_thruput_interval(units_this_tick, 4068 actual_interval/1000000.0), 4069 count, 4070 format_units(), 4071 count, 4072 actual_interval/1000000.0, 4073 count, 4074 now.tv_sec, 4075 (long) now.tv_usec/1000); 4076 count += 1; 4077 break; 4078 default: 4079 fprintf(where, 4080 "Hey Ricky you not fine, theres a bug at demo time. Hey Ricky!"); 4081 fflush(where); 4082 exit(-1); 4083 } 4084 fflush(where); 4085 } 4086 4087 /* this has gotten long enough to warrant being an inline function 4088 rather than a macro, and it has been enough years since all the 4089 important compilers have supported such a construct so it should 4090 not be a big deal. raj 2012-01-23 */ 4091 4092 #ifdef WIN32 4093 /* It would seem that the Microsoft compiler will not inline across 4094 source files. So there is little point in having an inline 4095 directive in that situation. Of course that makes me wonder if an 4096 inline directive has to appear in netlib.h... */ 4097 void demo_interval_tick(uint32_t units) 4098 #else 4099 inline void demo_interval_tick(uint32_t units) 4100 #endif 4101 { 4102 double actual_interval = 0.0; 4103 4104 switch (demo_mode) { 4105 case 0: 4106 return; 4107 case 1: /* use the unit accumulation first */ 4108 units_this_tick += units; 4109 if (units_this_tick >= demo_units) { 4110 /* time to possibly update demo_units and maybe output an 4111 interim result */ 4112 HIST_timestamp(demo_two_ptr); 4113 actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); 4114 /* we always want to fine-tune demo_units here whether we emit 4115 an interim result or not. if we are short, this will 4116 lengthen demo_units. if we are long, this will shorten it */ 4117 demo_units = demo_units * (demo_interval / actual_interval); 4118 } 4119 else 4120 return; 4121 break; 4122 case 2: /* Always timestamp */ 4123 units_this_tick += units; 4124 HIST_timestamp(demo_two_ptr); 4125 actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); 4126 4127 break; 4128 default: 4129 fprintf(where, 4130 "Unexpected value of demo_mode of %d. Please report this as a bug.\n", 4131 demo_mode); 4132 fflush(where); 4133 exit(-1); 4134 } 4135 4136 4137 4138 /* units == 0 will be when we have completed a test. we want to 4139 emit a final interim results if there is anything to report */ 4140 if (actual_interval >= demo_interval) { 4141 /* time to emit an interim result, giving the current time to the 4142 millisecond for compatability with RRD */ 4143 demo_interval_display(actual_interval); 4144 units_this_tick = 0.0; 4145 /* now get a new starting timestamp. we could be clever 4146 and swap pointers - the math we do probably does not 4147 take all that long, but for now this will suffice */ 4148 temp_demo_ptr = demo_one_ptr; 4149 demo_one_ptr = demo_two_ptr; 4150 demo_two_ptr = temp_demo_ptr; 4151 4152 } 4153 } 4154 4155 void demo_interval_final() { 4156 double actual_interval; 4157 4158 switch (demo_mode) { 4159 case 0: 4160 return; 4161 case 1: 4162 case 2: 4163 if (units_this_tick > 0.0) { 4164 HIST_timestamp(demo_two_ptr); 4165 actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); 4166 demo_interval_display(actual_interval); 4167 units_this_tick = 0.0; 4168 } 4169 } 4170 } 4171 4172 void demo_stream_interval(uint32_t units) { 4173 demo_interval_tick(units); 4174 } 4175 4176 void demo_rr_setup(uint32_t a) { 4177 if ((demo_mode) && (demo_units == 0)) { 4178 /* take whatever we are given */ 4179 demo_units = a; 4180 } 4181 } 4182 4183 void demo_rr_interval(uint32_t units) { 4184 demo_interval_tick(units); 4185 } 4186 4187 #endif 4188 4189 /* hist.c 4190 4191 Given a time difference in microseconds, increment one of 61 4192 different buckets: 4193 4194 0 - 9 in increments of 1 usec 4195 0 - 9 in increments of 10 usecs 4196 0 - 9 in increments of 100 usecs 4197 1 - 9 in increments of 1 msec 4198 1 - 9 in increments of 10 msecs 4199 1 - 9 in increments of 100 msecs 4200 1 - 9 in increments of 1 sec 4201 1 - 9 in increments of 10 sec 4202 > 100 secs 4203 4204 This will allow any time to be recorded to within an accuracy of 4205 10%, and provides a compact representation for capturing the 4206 distribution of a large number of time differences (e.g. 4207 request-response latencies). 4208 4209 Colin Low 10/6/93 4210 Rick Jones 2004-06-15 extend to unit and ten usecs 4211 */ 4212 4213 /* #include "sys.h" */ 4214 4215 /*#define HIST_TEST*/ 4216 4217 HIST 4218 HIST_new_n(int max_outstanding) { 4219 HIST h; 4220 4221 if((h = (HIST) malloc(sizeof(struct histogram_struct))) == NULL) { 4222 perror("HIST_new_n - histogram_struct malloc failed"); 4223 exit(1); 4224 } 4225 HIST_clear(h); 4226 4227 /* we never want to have a full queue, so will trade a little space 4228 for that. one day we may still have to check for a full queue */ 4229 h->limit = max_outstanding + 1; 4230 4231 /* now allocate the time_ones based on h->limit */ 4232 #ifdef HAVE_GETHRTIME 4233 h->time_ones = (hrtime_t *) malloc(h->limit * sizeof(hrtime_t)); 4234 #elif HAVE_GET_HRT 4235 h->time_ones = (hrt_t *) malloc(h->limit * sizeof(hrt_t)); 4236 #elif defined(WIN32) 4237 h->time_ones = (LARGE_INTEGER *) malloc(h->limit * 4238 sizeof(LARGE_INTEGER)); 4239 #else 4240 h->time_ones = (struct timeval *) malloc(h->limit * 4241 sizeof(struct timeval)); 4242 #endif /* HAVE_GETHRTIME */ 4243 if (h->time_ones == NULL) { 4244 perror("HIST_new_n - time_ones malloc failed"); 4245 exit(1); 4246 } 4247 4248 return h; 4249 } 4250 4251 HIST 4252 HIST_new(void){ 4253 return HIST_new_n(0); 4254 } 4255 4256 4257 void 4258 HIST_clear(HIST h){ 4259 int i; 4260 for(i = 0; i < HIST_NUM_OF_BUCKET; i++){ 4261 h->unit_usec[i] = 0; 4262 h->ten_usec[i] = 0; 4263 h->hundred_usec[i] = 0; 4264 h->unit_msec[i] = 0; 4265 h->ten_msec[i] = 0; 4266 h->hundred_msec[i] = 0; 4267 h->unit_sec[i] = 0; 4268 h->ten_sec[i] = 0; 4269 } 4270 h->ridiculous = 0; 4271 h->total = 0; 4272 h->sum = 0; 4273 h->sumsquare = 0; 4274 h->hmin = 0; 4275 h->hmax = 0; 4276 h->limit = 0; 4277 h->count = 0; 4278 h->producer = 0; 4279 h->consumer = 0; 4280 h->time_ones = NULL; 4281 } 4282 4283 void 4284 HIST_purge(HIST h) { 4285 h->count = 0; 4286 h->producer = 0; 4287 h->consumer = 0; 4288 } 4289 4290 void 4291 HIST_add(register HIST h, int time_delta){ 4292 register float val; 4293 register int base = HIST_NUM_OF_BUCKET / 10; 4294 4295 /* check for < 0 added via VMware ESX patches. */ 4296 4297 /* hoisted up to the top because we do not want to count any 4298 ridiculous values in the actual statistics. right? raj 4299 2011-07-28 */ 4300 if (time_delta < 0) { 4301 h->ridiculous++; 4302 return; 4303 } 4304 4305 if (!h->total) 4306 h->hmin = h->hmax = time_delta; 4307 h->total++; 4308 h->sum += time_delta; 4309 /* am I just being paranoid about the overhead of pow() when we 4310 aren't all that interested in the statistics derived from it? 4311 raj 20100914 */ 4312 if (keep_statistics) { 4313 h->sumsquare += pow(time_delta, 2); 4314 } 4315 h->hmin = ((h->hmin < time_delta) ? h->hmin : time_delta); 4316 h->hmax = ((h->hmax > time_delta) ? h->hmax : time_delta); 4317 val = (float) time_delta; 4318 if(val < 10) h->unit_usec[(int)(val * base)]++; 4319 else { 4320 val /= 10; 4321 if(val < 10) h->ten_usec[(int)(val * base)]++; 4322 else { 4323 val /= 10; 4324 if(val < 10) h->hundred_usec[(int)(val * base)]++; 4325 else { 4326 val /= 10; 4327 if(val < 10) h->unit_msec[(int)(val * base)]++; 4328 else { 4329 val /= 10; 4330 if(val < 10) h->ten_msec[(int)(val * base)]++; 4331 else { 4332 val /= 10; 4333 if(val < 10) h->hundred_msec[(int)(val * base)]++; 4334 else { 4335 val /= 10; 4336 if(val < 10) h->unit_sec[(int)(val * base)]++; 4337 else { 4338 val /= 10; 4339 if(val < 10) h->ten_sec[(int)(val * base)]++; 4340 else h->ridiculous++; 4341 } 4342 } 4343 } 4344 } 4345 } 4346 } 4347 } 4348 } 4349 4350 void 4351 output_row(FILE *fd, char *title, int *row){ 4352 register int i; 4353 register int j; 4354 register int base = HIST_NUM_OF_BUCKET / 10; 4355 register int sum; 4356 fprintf(where,"%s", title); 4357 for(i = 0; i < 10; i++){ 4358 sum = 0; 4359 for (j = i * base; j < (i + 1) * base; j++) { 4360 sum += row[j]; 4361 } 4362 fprintf(where,": %4d", sum); 4363 } 4364 fprintf(where,"\n"); 4365 } 4366 4367 int 4368 sum_row(int *row) { 4369 int sum = 0; 4370 int i; 4371 for (i = 0; i < HIST_NUM_OF_BUCKET; i++) sum += row[i]; 4372 return(sum); 4373 } 4374 4375 void 4376 HIST_report(HIST h){ 4377 #ifndef OLD_HISTOGRAM 4378 output_row(stdout, "UNIT_USEC ", h->unit_usec); 4379 output_row(stdout, "TEN_USEC ", h->ten_usec); 4380 output_row(stdout, "HUNDRED_USEC ", h->hundred_usec); 4381 #else 4382 h->hundred_usec[0] += sum_row(h->unit_usec); 4383 h->hundred_usec[0] += sum_row(h->ten_usec); 4384 output_row(stdout, "TENTH_MSEC ", h->hundred_usec); 4385 #endif 4386 output_row(stdout, "UNIT_MSEC ", h->unit_msec); 4387 output_row(stdout, "TEN_MSEC ", h->ten_msec); 4388 output_row(stdout, "HUNDRED_MSEC ", h->hundred_msec); 4389 output_row(stdout, "UNIT_SEC ", h->unit_sec); 4390 output_row(stdout, "TEN_SEC ", h->ten_sec); 4391 fprintf(where,">100_SECS: %d\n", h->ridiculous); 4392 fprintf(where,"HIST_TOTAL: %d\n", h->total); 4393 if (debug) { 4394 fprintf(where, 4395 "sum %"PRIi64", sumsquare %f, limit %d count %d\n", 4396 h->sum, 4397 h->sumsquare, 4398 h->limit, 4399 h->count); 4400 } 4401 } 4402 4403 /* search buckets for each unit */ 4404 int 4405 HIST_search_bucket(int *unit, int num, int *last, int *current, double scale){ 4406 int base = HIST_NUM_OF_BUCKET / 10; 4407 int i; 4408 for (i = 0; i < HIST_NUM_OF_BUCKET; i++){ 4409 *last = *current; 4410 *current += unit[i]; 4411 if (*current >= num) 4412 return (int)((i + (double)(num - *last)/(*current - *last)) * scale/base); 4413 } 4414 return 0; 4415 } 4416 4417 /* get percentile from histogram */ 4418 int 4419 HIST_get_percentile(HIST h, const double percentile){ 4420 double win_kludge = percentile * (double) h->total; 4421 int num = (int) win_kludge; 4422 int last = 0; 4423 int current = 0; 4424 int result; 4425 4426 if (!num) 4427 return 0; 4428 4429 /* search in unit usec range */ 4430 result = HIST_search_bucket(h->unit_usec, num, &last, ¤t, 1e0); 4431 if (result) 4432 return result; 4433 4434 /* search in ten usec range */ 4435 result = HIST_search_bucket(h->ten_usec, num, &last, ¤t, 1e1); 4436 if (result) 4437 return result; 4438 4439 /* search in ten hundred usec range */ 4440 result = HIST_search_bucket(h->hundred_usec, num, &last, ¤t, 1e2); 4441 if (result) 4442 return result; 4443 4444 /* search in unic msec range */ 4445 result = HIST_search_bucket(h->unit_msec, num, &last, ¤t, 1e3); 4446 if (result) 4447 return result; 4448 4449 /* search in ten msec range */ 4450 result = HIST_search_bucket(h->ten_msec, num, &last, ¤t, 1e4); 4451 if (result) 4452 return result; 4453 4454 /* search in hundred msec range */ 4455 result = HIST_search_bucket(h->hundred_msec, num, &last, ¤t, 1e5); 4456 if (result) 4457 return result; 4458 4459 /* search in unit sec range */ 4460 result = HIST_search_bucket(h->unit_sec, num, &last, ¤t, 1e6); 4461 if (result) 4462 return result; 4463 4464 /* search in ten sec range */ 4465 result = HIST_search_bucket(h->ten_sec, num, &last, ¤t, 1e7); 4466 if (result) 4467 return result; 4468 4469 return (int)(1e8); 4470 } 4471 4472 4473 /* get basic stats */ 4474 void 4475 HIST_get_stats(HIST h, int *min, int *max, double *mean, double *stddev){ 4476 *min = h->hmin; 4477 *max = h->hmax; 4478 if (h->total){ 4479 *mean = (double)h->sum / (double)h->total; 4480 *stddev = (h->sumsquare * h->total - pow((double)h->sum, 2)) / 4481 pow(h->total, 2); 4482 *stddev = sqrt(*stddev); 4483 } 4484 else{ 4485 *mean = 0; 4486 *stddev = 0; 4487 } 4488 } 4489 4490 4491 /* with the advent of sit-and-spin intervals support, we might as well 4492 make these things available all the time, not just for demo or 4493 histogram modes. raj 2006-02-06 */ 4494 #ifdef HAVE_GETHRTIME 4495 4496 void 4497 HIST_timestamp(hrtime_t *timestamp) 4498 { 4499 *timestamp = gethrtime(); 4500 } 4501 4502 int 4503 delta_micro(hrtime_t *begin, hrtime_t *end) 4504 { 4505 long nsecs; 4506 nsecs = (*end) - (*begin); 4507 return(nsecs/1000); 4508 } 4509 4510 #elif defined(HAVE_GET_HRT) 4511 #include "hrt.h" 4512 4513 void 4514 HIST_timestamp(hrt_t *timestamp) 4515 { 4516 *timestamp = get_hrt(); 4517 } 4518 4519 int 4520 delta_micro(hrt_t *begin, hrt_t *end) 4521 { 4522 4523 return((int)get_hrt_delta(*end,*begin)); 4524 4525 } 4526 #elif defined(WIN32) 4527 void HIST_timestamp(LARGE_INTEGER *timestamp) 4528 { 4529 QueryPerformanceCounter(timestamp); 4530 } 4531 4532 int delta_micro(LARGE_INTEGER *begin, LARGE_INTEGER *end) 4533 { 4534 LARGE_INTEGER DeltaTimestamp; 4535 static LARGE_INTEGER TickHz = {{0,0}}; 4536 4537 if (TickHz.QuadPart == 0) 4538 { 4539 QueryPerformanceFrequency(&TickHz); 4540 } 4541 4542 /*+*+ Rick; this will overflow after ~2000 seconds, is that 4543 good enough? Spencer: Yes, that should be more than good 4544 enough for histogram support */ 4545 4546 DeltaTimestamp.QuadPart = (end->QuadPart - begin->QuadPart) * 4547 1000000/TickHz.QuadPart; 4548 assert((DeltaTimestamp.HighPart == 0) && 4549 ((int)DeltaTimestamp.LowPart >= 0)); 4550 4551 return (int)DeltaTimestamp.LowPart; 4552 } 4553 4554 #else 4555 4556 void 4557 HIST_timestamp(struct timeval *timestamp) 4558 { 4559 gettimeofday(timestamp,NULL); 4560 } 4561 4562 /* return the difference (in micro seconds) between two timeval */ 4563 /* timestamps */ 4564 int 4565 delta_micro(struct timeval *begin,struct timeval *end) 4566 4567 { 4568 4569 int usecs, secs; 4570 4571 if (end->tv_usec < begin->tv_usec) { 4572 /* borrow a second from the tv_sec */ 4573 end->tv_usec += 1000000; 4574 end->tv_sec--; 4575 } 4576 usecs = end->tv_usec - begin->tv_usec; 4577 secs = end->tv_sec - begin->tv_sec; 4578 4579 usecs += (secs * 1000000); 4580 4581 return(usecs); 4582 4583 } 4584 #endif /* HAVE_GETHRTIME */ 4585 4586 void 4587 HIST_timestamp_start(HIST h) { 4588 4589 if (NULL == h) { 4590 fprintf(where,"HIST_timestamp_start called with NULL histogram\n"); 4591 fflush(where); 4592 exit(-1); 4593 } 4594 if (h->count == h->limit) { 4595 fprintf(where,"HIST_timestamp_start called with full time_ones\n"); 4596 } 4597 4598 HIST_timestamp(&(h->time_ones[h->producer])); 4599 h->producer += 1; 4600 h->producer %= h->limit; 4601 h->count += 1; 4602 4603 4604 } 4605 4606 /* snap an ending timestamp and add the delta to the histogram */ 4607 void 4608 HIST_timestamp_stop_add(HIST h) { 4609 4610 if (NULL == h) { 4611 fprintf(where,"HIST_timestamp_stop called with NULL histogram\n"); 4612 fflush(where); 4613 exit(-1); 4614 } 4615 4616 if (h->consumer == h->producer) { 4617 fprintf(where, 4618 "HIST_timestamp_stop called with empty time_ones consumer %d producer %d\n", 4619 h->consumer, 4620 h->producer); 4621 fflush(where); 4622 exit(-1); 4623 } 4624 /* take our stopping timestamp */ 4625 HIST_timestamp(&(h->time_two)); 4626 4627 /* now add it */ 4628 HIST_add(h,delta_micro(&(h->time_ones[h->consumer]),&(h->time_two))); 4629 h->consumer += 1; 4630 h->consumer %= h->limit; 4631 h->count -= 1; 4632 4633 } 4634 4635 4636 4638 /* these routines for confidence intervals are courtesy of IBM. They 4639 have been modified slightly for more general usage beyond TCP/UDP 4640 tests. raj 11/94 I would suspect that this code carries an IBM 4641 copyright that is much the same as that for the original HP netperf 4642 code */ 4643 int confidence_iterations; /* for iterations */ 4644 4645 double 4646 result_confid=-10.0, 4647 loc_cpu_confid=-10.0, 4648 rem_cpu_confid=-10.0, 4649 4650 measured_sum_result=0.0, 4651 measured_square_sum_result=0.0, 4652 measured_mean_result=0.0, 4653 measured_var_result=0.0, 4654 4655 measured_sum_local_cpu=0.0, 4656 measured_square_sum_local_cpu=0.0, 4657 measured_mean_local_cpu=0.0, 4658 measured_var_local_cpu=0.0, 4659 4660 measured_sum_remote_cpu=0.0, 4661 measured_square_sum_remote_cpu=0.0, 4662 measured_mean_remote_cpu=0.0, 4663 measured_var_remote_cpu=0.0, 4664 4665 measured_sum_local_service_demand=0.0, 4666 measured_square_sum_local_service_demand=0.0, 4667 measured_mean_local_service_demand=0.0, 4668 measured_var_local_service_demand=0.0, 4669 4670 measured_sum_remote_service_demand=0.0, 4671 measured_square_sum_remote_service_demand=0.0, 4672 measured_mean_remote_service_demand=0.0, 4673 measured_var_remote_service_demand=0.0, 4674 4675 measured_sum_local_time=0.0, 4676 measured_square_sum_local_time=0.0, 4677 measured_mean_local_time=0.0, 4678 measured_var_local_time=0.0, 4679 4680 measured_mean_remote_time=0.0, 4681 4682 measured_fails, 4683 measured_local_results, 4684 confidence=-10.0; 4685 /* interval=0.1; */ 4686 4687 /************************************************************************/ 4688 /* */ 4689 /* Constants for Confidence Intervals */ 4690 /* */ 4691 /************************************************************************/ 4692 void 4693 init_stat() 4694 { 4695 measured_sum_result=0.0; 4696 measured_square_sum_result=0.0; 4697 measured_mean_result=0.0; 4698 measured_var_result=0.0; 4699 4700 measured_sum_local_cpu=0.0; 4701 measured_square_sum_local_cpu=0.0; 4702 measured_mean_local_cpu=0.0; 4703 measured_var_local_cpu=0.0; 4704 4705 measured_sum_remote_cpu=0.0; 4706 measured_square_sum_remote_cpu=0.0; 4707 measured_mean_remote_cpu=0.0; 4708 measured_var_remote_cpu=0.0; 4709 4710 measured_sum_local_service_demand=0.0; 4711 measured_square_sum_local_service_demand=0.0; 4712 measured_mean_local_service_demand=0.0; 4713 measured_var_local_service_demand=0.0; 4714 4715 measured_sum_remote_service_demand=0.0; 4716 measured_square_sum_remote_service_demand=0.0; 4717 measured_mean_remote_service_demand=0.0; 4718 measured_var_remote_service_demand=0.0; 4719 4720 measured_sum_local_time=0.0; 4721 measured_square_sum_local_time=0.0; 4722 measured_mean_local_time=0.0; 4723 measured_var_local_time=0.0; 4724 4725 measured_mean_remote_time=0.0; 4726 4727 measured_fails = 0.0; 4728 measured_local_results=0.0, 4729 confidence=-10.0; 4730 } 4731 4732 /* this routine does a simple table lookup for some statistical 4733 function that I would remember if I stayed awake in my probstats 4734 class... raj 11/94 */ 4735 double 4736 confid(int level, int freedom) 4737 { 4738 double t99[35],t95[35]; 4739 4740 t95[1]=12.706; 4741 t95[2]= 4.303; 4742 t95[3]= 3.182; 4743 t95[4]= 2.776; 4744 t95[5]= 2.571; 4745 t95[6]= 2.447; 4746 t95[7]= 2.365; 4747 t95[8]= 2.306; 4748 t95[9]= 2.262; 4749 t95[10]= 2.228; 4750 t95[11]= 2.201; 4751 t95[12]= 2.179; 4752 t95[13]= 2.160; 4753 t95[14]= 2.145; 4754 t95[15]= 2.131; 4755 t95[16]= 2.120; 4756 t95[17]= 2.110; 4757 t95[18]= 2.101; 4758 t95[19]= 2.093; 4759 t95[20]= 2.086; 4760 t95[21]= 2.080; 4761 t95[22]= 2.074; 4762 t95[23]= 2.069; 4763 t95[24]= 2.064; 4764 t95[25]= 2.060; 4765 t95[26]= 2.056; 4766 t95[27]= 2.052; 4767 t95[28]= 2.048; 4768 t95[29]= 2.045; 4769 t95[30]= 2.042; 4770 4771 t99[1]=63.657; 4772 t99[2]= 9.925; 4773 t99[3]= 5.841; 4774 t99[4]= 4.604; 4775 t99[5]= 4.032; 4776 t99[6]= 3.707; 4777 t99[7]= 3.499; 4778 t99[8]= 3.355; 4779 t99[9]= 3.250; 4780 t99[10]= 3.169; 4781 t99[11]= 3.106; 4782 t99[12]= 3.055; 4783 t99[13]= 3.012; 4784 t99[14]= 2.977; 4785 t99[15]= 2.947; 4786 t99[16]= 2.921; 4787 t99[17]= 2.898; 4788 t99[18]= 2.878; 4789 t99[19]= 2.861; 4790 t99[20]= 2.845; 4791 t99[21]= 2.831; 4792 t99[22]= 2.819; 4793 t99[23]= 2.807; 4794 t99[24]= 2.797; 4795 t99[25]= 2.787; 4796 t99[26]= 2.779; 4797 t99[27]= 2.771; 4798 t99[28]= 2.763; 4799 t99[29]= 2.756; 4800 t99[30]= 2.750; 4801 4802 if(level==95){ 4803 return(t95[freedom]); 4804 } else if(level==99){ 4805 return(t99[freedom]); 4806 } else{ 4807 return(0); 4808 } 4809 } 4810 4811 void 4812 calculate_confidence(int confidence_iterations, 4813 float time, 4814 double result, 4815 float loc_cpu, 4816 float rem_cpu, 4817 float loc_sd, 4818 float rem_sd) 4819 { 4820 4821 if (debug) { 4822 fprintf(where, 4823 "calculate_confidence: itr %d; time %f; res %f\n" 4824 " lcpu %f; rcpu %f\n" 4825 " lsdm %f; rsdm %f\n", 4826 confidence_iterations, 4827 time, 4828 result, 4829 loc_cpu, 4830 rem_cpu, 4831 loc_sd, 4832 rem_sd); 4833 fflush(where); 4834 } 4835 4836 /* the test time */ 4837 measured_sum_local_time += 4838 (double) time; 4839 measured_square_sum_local_time += 4840 (double) time*time; 4841 measured_mean_local_time = 4842 (double) measured_sum_local_time/confidence_iterations; 4843 measured_var_local_time = 4844 (double) measured_square_sum_local_time/confidence_iterations 4845 -measured_mean_local_time*measured_mean_local_time; 4846 4847 /* the test result */ 4848 measured_sum_result += 4849 (double) result; 4850 measured_square_sum_result += 4851 (double) result*result; 4852 measured_mean_result = 4853 (double) measured_sum_result/confidence_iterations; 4854 measured_var_result = 4855 (double) measured_square_sum_result/confidence_iterations 4856 -measured_mean_result*measured_mean_result; 4857 4858 /* local cpu utilization */ 4859 measured_sum_local_cpu += 4860 (double) loc_cpu; 4861 measured_square_sum_local_cpu += 4862 (double) loc_cpu*loc_cpu; 4863 measured_mean_local_cpu = 4864 (double) measured_sum_local_cpu/confidence_iterations; 4865 measured_var_local_cpu = 4866 (double) measured_square_sum_local_cpu/confidence_iterations 4867 -measured_mean_local_cpu*measured_mean_local_cpu; 4868 4869 /* remote cpu util */ 4870 measured_sum_remote_cpu += 4871 (double) rem_cpu; 4872 measured_square_sum_remote_cpu+= 4873 (double) rem_cpu*rem_cpu; 4874 measured_mean_remote_cpu = 4875 (double) measured_sum_remote_cpu/confidence_iterations; 4876 measured_var_remote_cpu = 4877 (double) measured_square_sum_remote_cpu/confidence_iterations 4878 -measured_mean_remote_cpu*measured_mean_remote_cpu; 4879 4880 /* local service demand */ 4881 measured_sum_local_service_demand += 4882 (double) loc_sd; 4883 measured_square_sum_local_service_demand+= 4884 (double) loc_sd*loc_sd; 4885 measured_mean_local_service_demand = 4886 (double) measured_sum_local_service_demand/confidence_iterations; 4887 measured_var_local_service_demand = 4888 (double) measured_square_sum_local_service_demand/confidence_iterations 4889 -measured_mean_local_service_demand*measured_mean_local_service_demand; 4890 4891 /* remote service demand */ 4892 measured_sum_remote_service_demand += 4893 (double) rem_sd; 4894 measured_square_sum_remote_service_demand+= 4895 (double) rem_sd*rem_sd; 4896 measured_mean_remote_service_demand = 4897 (double) measured_sum_remote_service_demand/confidence_iterations; 4898 measured_var_remote_service_demand = 4899 (double) measured_square_sum_remote_service_demand/confidence_iterations 4900 -measured_mean_remote_service_demand*measured_mean_remote_service_demand; 4901 4902 if(confidence_iterations>1){ 4903 result_confid= (double) interval - 4904 2.0 * confid(confidence_level,confidence_iterations-1)* 4905 sqrt(measured_var_result/(confidence_iterations-1.0)) / 4906 measured_mean_result; 4907 4908 loc_cpu_confid= (double) interval - 4909 2.0 * confid(confidence_level,confidence_iterations-1)* 4910 sqrt(measured_var_local_cpu/(confidence_iterations-1.0)) / 4911 measured_mean_local_cpu; 4912 4913 rem_cpu_confid= (double) interval - 4914 2.0 * confid(confidence_level,confidence_iterations-1)* 4915 sqrt(measured_var_remote_cpu/(confidence_iterations-1.0)) / 4916 measured_mean_remote_cpu; 4917 4918 if(debug){ 4919 printf("Conf_itvl %2d: results:%4.1f%% loc_cpu:%4.1f%% rem_cpu:%4.1f%%\n", 4920 confidence_iterations, 4921 (interval-result_confid)*100.0, 4922 (interval-loc_cpu_confid)*100.0, 4923 (interval-rem_cpu_confid)*100.0); 4924 } 4925 4926 /* if the user has requested that we only wait for the result to 4927 be confident rather than the result and CPU util(s) then do 4928 so. raj 2007-08-08 */ 4929 if (!result_confidence_only) { 4930 confidence = min(min(result_confid,loc_cpu_confid),rem_cpu_confid); 4931 } 4932 else { 4933 confidence = result_confid; 4934 } 4935 } 4936 } 4937 4938 /* here ends the IBM code */ 4939 4940 void 4941 retrieve_confident_values(float *elapsed_time, 4942 double *thruput, 4943 float *local_cpu_utilization, 4944 float *remote_cpu_utilization, 4945 float *local_service_demand, 4946 float *remote_service_demand) 4947 4948 { 4949 *elapsed_time = (float)measured_mean_local_time; 4950 *thruput = measured_mean_result; 4951 *local_cpu_utilization = (float)measured_mean_local_cpu; 4952 *remote_cpu_utilization = (float)measured_mean_remote_cpu; 4953 *local_service_demand = (float)measured_mean_local_service_demand; 4954 *remote_service_demand = (float)measured_mean_remote_service_demand; 4955 } 4956 4957 double 4958 get_result_confid() 4959 { 4960 return (double) (100.0 * (interval - result_confid)); 4961 } 4962 4963 double 4964 get_loc_cpu_confid() 4965 { 4966 return (double) (100.0 * (interval - loc_cpu_confid)); 4967 } 4968 4969 double 4970 get_rem_cpu_confid() 4971 { 4972 return (double) (100.0 * (interval - rem_cpu_confid)); 4973 } 4974 4975 /* display_confidence() is called when we could not achieve the 4976 desired confidence in the results. it will print the achieved 4977 confidence to "where" raj 11/94 */ 4978 void 4979 display_confidence() 4980 4981 { 4982 fprintf(where, 4983 "!!! WARNING\n" 4984 "!!! Desired confidence was not achieved within " 4985 "the specified iterations.\n" 4986 "!!! This implies that there was variability in " 4987 "the test environment that\n" 4988 "!!! must be investigated before going further.\n" 4989 "!!! Confidence intervals: Throughput : %4.3f%%\n" 4990 "!!! Local CPU util : %4.3f%%\n" 4991 "!!! Remote CPU util : %4.3f%%\n\n", 4992 100.0 * (interval - result_confid), 4993 100.0 * (interval - loc_cpu_confid), 4994 100.0 * (interval - rem_cpu_confid)); 4995 } 4996