1 #ifndef lint 2 char nettest_id[]="\ 3 @(#)nettest_bsd.c (c) Copyright 1993-2012 Hewlett-Packard Co. Version 2.6.0"; 4 #endif /* lint */ 5 6 7 /****************************************************************/ 8 /* */ 9 /* nettest_bsd.c */ 10 /* */ 11 /* the BSD sockets parsing routine... */ 12 /* ...with the addition of Windows NT, this is now also */ 13 /* a Winsock test... sigh :) */ 14 /* */ 15 /* scan_sockets_args() */ 16 /* */ 17 /* the actual test routines... */ 18 /* */ 19 /* send_tcp_stream() perform a tcp stream test */ 20 /* recv_tcp_stream() */ 21 /* send_tcp_maerts() perform a tcp stream test */ 22 /* recv_tcp_maerts() in the other direction */ 23 /* send_tcp_rr() perform a tcp request/response */ 24 /* recv_tcp_rr() */ 25 /* send_tcp_conn_rr() an RR test including connect */ 26 /* recv_tcp_conn_rr() */ 27 /* send_tcp_cc() a connect/disconnect test with */ 28 /* recv_tcp_cc() no RR */ 29 /* send_tcp_mss() just report the mss */ 30 /* send_udp_stream() perform a udp stream test */ 31 /* recv_udp_stream() */ 32 /* send_udp_rr() perform a udp request/response */ 33 /* recv_udp_rr() */ 34 /* loc_cpu_rate() determine the local cpu maxrate */ 35 /* rem_cpu_rate() find the remote cpu maxrate */ 36 /* */ 37 /****************************************************************/ 38 39 #ifdef HAVE_CONFIG_H 40 #include <config.h> 41 #endif 42 43 #include <stdio.h> 44 #if HAVE_SYS_TYPES_H 45 # include <sys/types.h> 46 #endif 47 #if HAVE_SYS_STAT_H 48 # include <sys/stat.h> 49 #endif 50 #if STDC_HEADERS 51 # include <stdlib.h> 52 # include <stddef.h> 53 #else 54 # if HAVE_STDLIB_H 55 # include <stdlib.h> 56 # endif 57 #endif 58 #if HAVE_STRING_H 59 # if !STDC_HEADERS && HAVE_MEMORY_H 60 # include <memory.h> 61 # endif 62 # include <string.h> 63 #endif 64 #if HAVE_STRINGS_H 65 # include <strings.h> 66 #endif 67 #if HAVE_INTTYPES_H 68 # include <inttypes.h> 69 #else 70 # if HAVE_STDINT_H 71 # include <stdint.h> 72 # endif 73 #endif 74 #if HAVE_UNISTD_H 75 # include <unistd.h> 76 #endif 77 78 #include <fcntl.h> 79 #ifndef WIN32 80 #include <errno.h> 81 #include <signal.h> 82 #endif 83 84 #if TIME_WITH_SYS_TIME 85 # include <sys/time.h> 86 # include <time.h> 87 #else 88 # if HAVE_SYS_TIME_H 89 # include <sys/time.h> 90 # else 91 # include <time.h> 92 # endif 93 #endif 94 95 #ifdef NOSTDLIBH 96 #include <malloc.h> 97 #endif /* NOSTDLIBH */ 98 99 100 #ifndef WIN32 101 #if !defined(__VMS) 102 #include <sys/ipc.h> 103 #endif /* !__VMS */ 104 #include <sys/socket.h> 105 #include <netinet/in.h> 106 #include <netinet/tcp.h> 107 108 #ifdef HAVE_NETINET_SCTP_H 109 #include <netinet/sctp.h> 110 #endif 111 112 #include <arpa/inet.h> 113 #include <netdb.h> 114 #else /* WIN32 */ 115 #include <process.h> 116 #define netperf_socklen_t socklen_t 117 #include <winsock2.h> 118 #include "missing\stdint.h" 119 /* while it is unlikely that anyone running Windows 2000 or NT 4 is 120 going to be trying to compile this, if they are they will want to 121 define DONT_IPV6 in the sources file */ 122 #ifndef DONT_IPV6 123 #include <ws2tcpip.h> 124 #endif 125 #include <windows.h> 126 127 #define sleep(x) Sleep((x)*1000) 128 129 #define __func__ __FUNCTION__ 130 #endif /* WIN32 */ 131 132 /* We don't want to use bare constants in the shutdown() call. In the 133 extremely unlikely event that SHUT_WR isn't defined, we will define 134 it to the value we used to be passing to shutdown() anyway. raj 135 2007-02-08 */ 136 #if !defined(SHUT_WR) 137 #define SHUT_WR 1 138 #endif 139 140 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) 141 # include "missing/getaddrinfo.h" 142 #endif 143 144 #include "netlib.h" 145 #include "netsh.h" 146 #include "nettest_bsd.h" 147 148 #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO) 149 #include "hist.h" 150 #endif /* WANT_HISTOGRAM */ 151 152 153 /* make first_burst_size unconditional so we can use it easily enough 154 when calculating transaction latency for the TCP_RR test. raj 155 2007-06-08 however, change its default value so one can tell in 156 "omni" output whether or not WANT_BURST was enabled. raj 157 2008-01-28 */ 158 #if defined(WANT_FIRST_BURST) 159 int first_burst_size=0; 160 #else 161 int first_burst_size=-1; 162 #endif 163 164 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun)) 165 #include <sys/sendfile.h> 166 #endif /* HAVE_SENDFILE && (__linux || __sun) */ 167 168 169 171 /* these variables are specific to the BSD sockets tests, but can 172 * be used elsewhere if needed. They are externed through nettest_bsd.h 173 */ 174 175 int 176 socket_type, /* used initially by the "omni" tests */ 177 rss_size_req = -1, /* requested remote socket send buffer size */ 178 rsr_size_req = -1, /* requested remote socket recv buffer size */ 179 rss_size, /* initial remote socket send buffer size */ 180 rsr_size, /* initial remote socket recv buffer size */ 181 rss_size_end = -1, /* final remote socket send buffer size */ 182 rsr_size_end = -1, /* final remote socket recv buffer size */ 183 lss_size_req = -1, /* requested local socket send buffer size */ 184 lsr_size_req = -1, /* requested local socket recv buffer size */ 185 lss_size, /* local socket send buffer size */ 186 lsr_size, /* local socket recv buffer size */ 187 lss_size_end = -1, /* final local socket send buffer size */ 188 lsr_size_end = -1, /* final local socket recv buffer size */ 189 req_size = 1, /* request size */ 190 rsp_size = 1, /* response size */ 191 send_size, /* how big are individual sends */ 192 recv_size, /* how big are individual receives */ 193 transport_mss_req = -1; /* what maximum segment size is wanted */ 194 195 static int confidence_iteration; 196 static char local_cpu_method; 197 static char remote_cpu_method; 198 199 /* these will control the width of port numbers we try to use in the */ 200 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */ 201 static int client_port_min = 5000; 202 static int client_port_max = 65535; 203 204 /* different options for the sockets */ 205 206 int 207 loc_nodelay, /* don't/do use NODELAY locally */ 208 rem_nodelay, /* don't/do use NODELAY remotely */ 209 #ifdef TCP_CORK 210 loc_tcpcork=0, /* don't/do use TCP_CORK locally */ 211 rem_tcpcork=0, /* don't/do use TCP_CORK remotely */ 212 #else 213 loc_tcpcork=-1, 214 rem_tcpcork=-1, 215 #endif /* TCP_CORK */ 216 loc_sndavoid, /* avoid send copies locally */ 217 loc_rcvavoid, /* avoid recv copies locally */ 218 rem_sndavoid, /* avoid send copies remotely */ 219 rem_rcvavoid, /* avoid recv_copies remotely */ 220 local_connected = 0, /* local socket type, connected/non-connected */ 221 remote_connected = 0, /* remote socket type, connected/non-connected */ 222 routing_allowed = 1; /* set/clear SO_DONTROUTE on data socket */ 223 224 int multicast_ttl = -1; /* should we set the multicast TTL to a value? */ 225 226 int want_keepalive = 0; 227 228 #ifdef WANT_HISTOGRAM 229 #ifdef HAVE_GETHRTIME 230 static hrtime_t time_one; 231 static hrtime_t time_two; 232 #elif HAVE_GET_HRT 233 #include "hrt.h" 234 static hrt_t time_one; 235 static hrt_t time_two; 236 #elif defined(WIN32) 237 static LARGE_INTEGER time_one; 238 static LARGE_INTEGER time_two; 239 #else 240 static struct timeval time_one; 241 static struct timeval time_two; 242 #endif /* HAVE_GETHRTIME */ 243 static HIST time_hist; 244 #endif /* WANT_HISTOGRAM */ 245 246 #ifdef WANT_INTERVALS 247 int interval_count; 248 #ifndef WANT_SPIN 249 #ifdef WIN32 250 #define INTERVALS_INIT() \ 251 if (interval_burst) { \ 252 /* zero means that we never pause, so we never should need the \ 253 interval timer. we used to use it for demo mode, but we deal \ 254 with that with a variant on watching the clock rather than \ 255 waiting for a timer. raj 2006-02-06 */ \ 256 start_itimer(interval_wate); \ 257 } \ 258 interval_count = interval_burst; 259 #else 260 sigset_t signal_set; 261 #define INTERVALS_INIT() \ 262 if (interval_burst) { \ 263 /* zero means that we never pause, so we never should need the \ 264 interval timer. we used to use it for demo mode, but we deal \ 265 with that with a variant on watching the clock rather than \ 266 waiting for a timer. raj 2006-02-06 */ \ 267 start_itimer(interval_wate); \ 268 } \ 269 interval_count = interval_burst; \ 270 /* get the signal set for the call to sigsuspend */ \ 271 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \ 272 fprintf(where, \ 273 "%s: unable to get sigmask errno %d\n", \ 274 __func__, \ 275 errno); \ 276 fflush(where); \ 277 exit(1); \ 278 } 279 #endif /* WIN32 */ 280 281 #ifdef WIN32 282 #define INTERVALS_WAIT() \ 283 /* in this case, the interval count is the count-down counter \ 284 to decide to sleep for a little bit */ \ 285 if ((interval_burst) && (--interval_count == 0)) { \ 286 /* call WaitForSingleObject and wait for the interval timer to get us \ 287 out */ \ 288 if (debug > 1) { \ 289 fprintf(where,"about to suspend\n"); \ 290 fflush(where); \ 291 } \ 292 if (WaitForSingleObject(WinTimer, INFINITE) != WAIT_OBJECT_0) { \ 293 fprintf(where, "WaitForSingleObject failed (%d)\n", GetLastError()); \ 294 fflush(where); \ 295 exit(1); \ 296 } \ 297 interval_count = interval_burst; \ 298 } 299 #else 300 #define INTERVALS_WAIT() \ 301 /* in this case, the interval count is the count-down couter \ 302 to decide to sleep for a little bit */ \ 303 if ((interval_burst) && (--interval_count == 0)) { \ 304 /* call sigsuspend and wait for the interval timer to get us \ 305 out */ \ 306 if (debug > 1) { \ 307 fprintf(where,"about to suspend\n"); \ 308 fflush(where); \ 309 } \ 310 if (sigsuspend(&signal_set) == EFAULT) { \ 311 fprintf(where, \ 312 "%s: fault with sigsuspend.\n", \ 313 __func__); \ 314 fflush(where); \ 315 exit(1); \ 316 } \ 317 interval_count = interval_burst; \ 318 } 319 #endif /* WIN32 */ 320 #else 321 /* first out timestamp */ 322 #ifdef HAVE_GETHRTIME 323 static hrtime_t intvl_one; 324 static hrtime_t intvl_two; 325 static hrtime_t *intvl_one_ptr = &intvl_one; 326 static hrtime_t *intvl_two_ptr = &intvl_two; 327 static hrtime_t *temp_intvl_ptr = &intvl_one; 328 #elif defined(WIN32) 329 static LARGE_INTEGER intvl_one; 330 static LARGE_INTEGER intvl_two; 331 static LARGE_INTEGER *intvl_one_ptr = &intvl_one; 332 static LARGE_INTEGER *intvl_two_ptr = &intvl_two; 333 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one; 334 #else 335 static struct timeval intvl_one; 336 static struct timeval intvl_two; 337 static struct timeval *intvl_one_ptr = &intvl_one; 338 static struct timeval *intvl_two_ptr = &intvl_two; 339 static struct timeval *temp_intvl_ptr = &intvl_one; 340 #endif 341 342 #define INTERVALS_INIT() \ 343 if (interval_burst) { \ 344 HIST_timestamp(intvl_one_ptr); \ 345 } \ 346 interval_count = interval_burst; \ 347 348 #define INTERVALS_WAIT() \ 349 /* in this case, the interval count is the count-down couter \ 350 to decide to sleep for a little bit */ \ 351 if ((interval_burst) && (--interval_count == 0)) { \ 352 /* call sigsuspend and wait for the interval timer to get us \ 353 out */ \ 354 if (debug > 1) { \ 355 fprintf(where,"about to spin suspend\n"); \ 356 fflush(where); \ 357 } \ 358 HIST_timestamp(intvl_two_ptr); \ 359 while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \ 360 HIST_timestamp(intvl_two_ptr); \ 361 } \ 362 temp_intvl_ptr = intvl_one_ptr; \ 363 intvl_one_ptr = intvl_two_ptr; \ 364 intvl_two_ptr = temp_intvl_ptr; \ 365 interval_count = interval_burst; \ 366 } 367 #endif 368 #endif 369 370 371 char sockets_usage[] = "\n\ 372 Usage: netperf [global options] -- [test options] \n\ 373 \n\ 374 TCP/UDP BSD Sockets Test Options:\n\ 375 -b number Send number requests at start of _RR tests\n\ 376 -C Set TCP_CORK when available\n\ 377 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\ 378 -h Display this text\n\ 379 -H name,fam Use name (or IP) and family as target of data connection\n\ 380 -L name,fam Use name (or IP) and family as source of data connection\n\ 381 -m bytes Set the send size (TCP_STREAM, UDP_STREAM)\n\ 382 -M bytes Set the recv size (TCP_STREAM, UDP_STREAM)\n\ 383 -n Use the connected socket for UDP locally\n\ 384 -N Use the connected socket for UDP remotely\n\ 385 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\ 386 -P local[,remote] Set the local/remote port for the data socket\n\ 387 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\ 388 -s send[,recv] Set local socket send/recv buffer sizes\n\ 389 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 390 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 391 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 392 \n\ 393 For those options taking two parms, at least one must be specified;\n\ 394 specifying one value without a comma will set both parms to that\n\ 395 value, specifying a value with a leading comma will set just the second\n\ 396 parm, a value with a trailing comma will set just the first. To set\n\ 397 each parm to unique values, specify both and separate them with a\n\ 398 comma.\n"; 399 400 401 403 /* these routines convert between the AF address space and the NF 404 address space since the numeric values of AF_mumble are not the 405 same across the platforms. raj 2005-02-08 */ 406 407 int 408 nf_to_af(int nf) { 409 switch(nf) { 410 case NF_INET: 411 return AF_INET; 412 case NF_UNSPEC: 413 return AF_UNSPEC; 414 case NF_INET6: 415 #if defined(AF_INET6) 416 return AF_INET6; 417 #else 418 return AF_UNSPEC; 419 #endif 420 case NF_RDS: 421 #if defined(AF_RDS) 422 return AF_RDS; 423 #else 424 return AF_UNSPEC; 425 #endif 426 default: 427 return AF_UNSPEC; 428 } 429 } 430 431 int 432 af_to_nf(int af) { 433 434 switch(af) { 435 case AF_INET: 436 return NF_INET; 437 case AF_UNSPEC: 438 return NF_UNSPEC; 439 #if defined(AF_INET6) 440 case AF_INET6: 441 return NF_INET6; 442 #endif 443 #if defined(AF_RDS) 444 case AF_RDS: 445 return NF_RDS; 446 #endif 447 default: 448 return NF_UNSPEC; 449 } 450 } 451 452 453 /* these routines will convert between the hosts' socket types and 455 those netperf uses. we need this because different platforms can 456 have different values for SOCK_STREAM, SOCK_DGRAM and the 457 like... */ 458 459 int 460 nst_to_hst(int nst) { 461 switch(nst) { 462 #ifdef SOCK_STREAM 463 case NST_STREAM: 464 return SOCK_STREAM; 465 break; /* ok, this may not be necessary :) */ 466 #endif 467 #ifdef SOCK_DGRAM 468 case NST_DGRAM: 469 return SOCK_DGRAM; 470 break; 471 #endif 472 #ifdef SOCK_DCCP 473 case NST_DCCP: 474 return SOCK_DCCP; 475 break; 476 #endif 477 #ifdef SOCK_SEQPACKET 478 case NST_SEQPACKET: 479 return NST_SEQPACKET; 480 #endif 481 default: 482 return -1; 483 } 484 } 485 486 int 487 hst_to_nst(int hst) { 488 489 switch(hst) { 490 #ifdef SOCK_STREAM 491 case SOCK_STREAM: 492 return NST_STREAM; 493 break; 494 #endif 495 #ifdef SOCK_DGRAM 496 case SOCK_DGRAM: 497 return NST_DGRAM; 498 break; 499 #endif 500 #ifdef SOCK_DCCP 501 case SOCK_DCCP: 502 return NST_DCCP; 503 break; 504 #endif 505 #ifdef SOCK_SEQPACKET 506 case SOCK_SEQPACKET: 507 return NST_SEQPACKET; 508 #endif 509 default: 510 return NST_UNKN; 511 } 512 } 513 char * 514 hst_to_str(int hst) { 515 516 switch(hst) { 517 #ifdef SOCK_STREAM 518 case SOCK_STREAM: 519 return "Stream"; 520 break; 521 #endif 522 #ifdef SOCK_DGRAM 523 case SOCK_DGRAM: 524 return "Datagram"; 525 break; 526 #endif 527 #ifdef SOCK_DCCP 528 case SOCK_DCCP: 529 return "DCCP"; 530 break; 531 #endif 532 #ifdef SOCK_SEQPACKET 533 case SOCK_SEQPACKET: 534 return "Seqpacket"; 535 #endif 536 default: 537 return "Unknown"; 538 } 539 } 540 541 char * 542 protocol_to_str(int protocol) { 543 switch(protocol) { 544 /* ass-u-me that everyone has IPPROTO_TCP and IPPROTO_UDP */ 545 case IPPROTO_TCP: 546 return "TCP"; 547 case IPPROTO_UDP: 548 return "UDP"; 549 /* but do not assume that everyone has the others */ 550 #ifdef IPPROTO_UDPLITE 551 case IPPROTO_UDPLITE: 552 return "UDPLite"; 553 #endif 554 #ifdef IPPROTO_SCTP 555 case IPPROTO_SCTP: 556 return "SCTP"; 557 #endif 558 #ifdef IPPROTO_DCCP 559 case IPPROTO_DCCP: 560 return "DCCP"; 561 #endif 562 #ifdef IPPROTO_SDP 563 case IPPROTO_SDP: 564 return "SDP"; 565 #endif 566 #ifdef IPPROTO_IP 567 case IPPROTO_IP: 568 return "IP Default"; 569 #endif 570 default: 571 return "Unknown Protocol"; 572 } 573 } 574 575 576 /* This routine is intended to retrieve interesting aspects of tcp */ 578 /* for the data connection. at first, it attempts to retrieve the */ 579 /* maximum segment size. later, it might be modified to retrieve */ 580 /* other information, but it must be information that can be */ 581 /* retrieved quickly as it is called during the timing of the test. */ 582 /* for that reason, a second routine may be created that can be */ 583 /* called outside of the timing loop */ 584 static 585 void 586 get_tcp_info(SOCKET socket, int *mss) 587 { 588 589 #ifdef TCP_MAXSEG 590 netperf_socklen_t sock_opt_len; 591 592 sock_opt_len = sizeof(int); 593 if (getsockopt(socket, 594 getprotobyname("tcp")->p_proto, 595 TCP_MAXSEG, 596 (char *)mss, 597 &sock_opt_len) == SOCKET_ERROR) { 598 fprintf(where, 599 "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n", 600 errno); 601 fflush(where); 602 *mss = -1; 603 } 604 #else 605 *mss = -1; 606 #endif /* TCP_MAXSEG */ 607 } 608 609 static 610 void 611 set_tcp_mss(SOCKET socket, int mss) { 612 #ifdef TCP_MAXSEG 613 netperf_socklen_t sock_opt_len; 614 615 sock_opt_len = sizeof(int); 616 if ((setsockopt(socket, 617 getprotobyname("tcp")->p_proto, 618 TCP_MAXSEG, 619 (const char *)&mss, 620 sock_opt_len) == SOCKET_ERROR) && (debug)) { 621 fprintf(where, 622 "netperf: %s: setsockopt TCP_MAXSEG: %s (errno %d)\n", 623 __FUNCTION__, 624 strerror(errno), 625 errno); 626 fflush(where); 627 } 628 #else 629 if (debug) { 630 fprintf(where, 631 "netperf: %s platform does not know how to set TCP segment size\n", 632 __FUNCTION__); 633 fflush(where); 634 } 635 636 #endif /* TCP_MAXSEG */ 637 } 638 639 640 642 /* return a pointer to a completed addrinfo chain - prefer 643 data_address to controlhost and utilize the specified address 644 family */ 645 646 struct addrinfo * 647 complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags) 648 { 649 struct addrinfo hints; 650 struct addrinfo *res; 651 struct addrinfo *temp_res; 652 653 #define CHANGED_SOCK_TYPE 0x1 654 #define CHANGED_PROTOCOL 0x2 655 #define CHANGED_SCTP 0x4 656 #define CHANGED_DCCP 0x8 657 #define CHANGED_DCCP_SOCK 0x10 658 659 int change_info = 0; 660 static int change_warning_displayed = 0; 661 662 int count = 0; 663 int error = 0; 664 665 char *hostname; 666 667 /* take data-address over controlhost */ 668 if (data_address) 669 hostname = data_address; 670 else 671 hostname = controlhost; 672 673 if (debug) { 674 fprintf(where, 675 "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n", 676 hostname, 677 port, 678 inet_ftos(family), 679 inet_ttos(type), 680 inet_ptos(protocol), 681 flags); 682 fflush(where); 683 } 684 685 memset(&hints, 0, sizeof(hints)); 686 hints.ai_family = family; 687 hints.ai_socktype = type; 688 hints.ai_protocol = protocol; 689 hints.ai_flags = flags|AI_CANONNAME|AI_ADDRCONFIG; 690 691 count = 0; 692 do { 693 error = getaddrinfo((char *)hostname, 694 (char *)port, 695 &hints, 696 &res); 697 count += 1; 698 if (error == EAI_AGAIN) { 699 if (debug) { 700 fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n"); 701 fflush(where); 702 } 703 sleep(1); 704 } 705 /* while you see this kludge first, it is actually the second, the 706 first being the one for Solaris below. The need for this kludge 707 came after implementing the Solaris broken getaddrinfo kludge - 708 now we see a kludge in Linux getaddrinfo where if it is given 709 SOCK_STREAM and IPPROTO_SCTP it barfs with a -7 710 EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if 711 we were asking for IPPROTO_SCTP and if so, kludge, again... raj 712 200?-10-13 and of course, requiring the kludge for SCTP, it is 713 no surprise that linux needs a kludge for DCCP...actually not 714 only does it need the ai_protocol kludge, it needs an 715 ai_socktype kludge too... sigh raj 2008-02-01 */ 716 #if defined(IPPROTO_SCTP) || defined (IPPROTO_DCCP) 717 if (EAI_SOCKTYPE == error 718 #ifdef EAI_BADHINTS 719 || EAI_BADHINTS == error 720 #endif 721 ) { 722 /* we ass-u-me this is the Linux getaddrinfo bug, clear the 723 hints.ai_protocol field, and set some state "remembering" 724 that we did this so the code for the Solaris kludge can do 725 the fix-up for us. also flip error over to EAI_AGAIN and 726 make sure we don't "count" this time around the loop. */ 727 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) 728 /* only tweak on this one the second time around, after we've 729 kludged the ai_protocol field */ 730 if ((hints.ai_socktype == SOCK_DCCP) && 731 (hints.ai_protocol == 0)) { 732 change_info |= CHANGED_DCCP_SOCK; 733 hints.ai_socktype = 0; 734 /* we need to give it some sort of IPPROTO or it gets unhappy, 735 so for now, pick one from deep within the colon and use 736 IPPROTO_TCP */ 737 hints.ai_protocol = IPPROTO_TCP; 738 } 739 740 if (hints.ai_protocol == IPPROTO_DCCP) { 741 change_info |= CHANGED_DCCP; 742 hints.ai_protocol = 0; 743 } 744 745 #endif 746 #if defined(IPPROTO_SCTP) 747 if (hints.ai_protocol == IPPROTO_SCTP) { 748 change_info |= CHANGED_SCTP; 749 hints.ai_protocol = 0; 750 } 751 #endif 752 753 error = EAI_AGAIN; 754 count -= 1; 755 } 756 #endif 757 } while ((error == EAI_AGAIN) && (count <= 5)); 758 759 if (error) { 760 fprintf(where, 761 "complete_addrinfo: could not resolve '%s' port '%s' af %d" 762 "\n\tgetaddrinfo returned %d %s\n", 763 hostname, 764 port, 765 family, 766 error, 767 gai_strerror(error)); 768 fflush(where); 769 exit(-1); 770 } 771 772 /* there exists at least one platform - Solaris 10 - that does not 773 seem to completely honor the ai_protocol and/or ai_socktype one 774 sets in the hints parm to the getaddrinfo call. so, we need to 775 walk the list of entries returned and if either of those do not 776 match what we asked for, we need to go ahead and set them 777 "correctly" this is based in part on some earlier SCTP-only code 778 from previous revisions. raj 2006-10-09 */ 779 780 temp_res = res; 781 782 while (temp_res) { 783 784 if ((type) && 785 (temp_res->ai_socktype != type)) { 786 change_info |= CHANGED_SOCK_TYPE; 787 if (debug) { 788 fprintf(where, 789 "WARNING! Changed bogus getaddrinfo socket type %d to %d\n", 790 temp_res->ai_socktype, 791 type); 792 fflush(where); 793 } 794 temp_res->ai_socktype = type; 795 } 796 797 if ((protocol) && 798 (temp_res->ai_protocol != protocol)) { 799 change_info |= CHANGED_PROTOCOL; 800 if (debug) { 801 fprintf(where, 802 "WARNING! Changed bogus getaddrinfo protocol %d to %d\n", 803 temp_res->ai_protocol, 804 protocol); 805 fflush(where); 806 } 807 temp_res->ai_protocol = protocol; 808 } 809 temp_res = temp_res->ai_next; 810 } 811 812 if ((change_info & CHANGED_SOCK_TYPE) && 813 !(change_warning_displayed & CHANGED_SOCK_TYPE)) { 814 change_warning_displayed |= CHANGED_SOCK_TYPE; 815 fprintf(where, 816 "WARNING! getaddrinfo returned a socket type which did not\n" 817 "match the requested type. Please contact your vendor for\n" 818 "a fix to this bug in getaddrinfo()\n"); 819 fflush(where); 820 } 821 822 /* if we dropped the protocol hint, it would be for a protocol that 823 getaddrinfo() wasn't supporting yet, not for the bug that it took 824 our hint and still returned zero. raj 2006-10-16 */ 825 /* as there is now an open bug against (Open)Solaris (id 6847733) on 826 this behaviour we will only emit this warning if debug is set 827 under Solaris and will continue to emit it under any circumstance 828 on other platforms should it arise. raj 2009-06-03 */ 829 /* since it has now been two years since that bug was filed, it 830 should be resolved by now, so the "out" given to Sun should no 831 longer be necessary. either folks are running with the fix or 832 they need to get the fix. raj 2011-07-06 */ 833 if ((change_info & CHANGED_PROTOCOL) && 834 !(change_warning_displayed & CHANGED_PROTOCOL) && 835 (hints.ai_protocol != 0)) { 836 change_warning_displayed |= CHANGED_PROTOCOL; 837 fprintf(where, 838 "WARNING! getaddrinfo returned a protocol other than the\n" 839 "requested protocol. Please contact your vendor for\n" 840 "a fix to this bug in getaddrinfo()\n"); 841 fflush(where); 842 } 843 844 if ((change_info & CHANGED_SCTP) && 845 !(change_warning_displayed & CHANGED_SCTP)) { 846 change_warning_displayed |= CHANGED_SCTP; 847 fprintf(where, 848 "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n" 849 "Please contact your vendor for a fix to this bug in getaddrinfo().\n"); 850 fflush(where); 851 } 852 853 if ((change_info & CHANGED_DCCP) && 854 !(change_warning_displayed & CHANGED_DCCP)) { 855 change_warning_displayed |= CHANGED_DCCP; 856 fprintf(where, 857 "WARNING! getaddrinfo on this platform does not accept IPPROTO_DCCP!\n" 858 "Please contact your vendor for a fix to this bug in getaddrinfo().\n"); 859 fflush(where); 860 } 861 862 863 if (debug) { 864 dump_addrinfo(where, res, hostname, port, family); 865 } 866 867 return(res); 868 } 869 870 void 871 complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) { 872 873 if (remote_data_family == AF_UNSPEC) { 874 remote_data_family = control_family; 875 } 876 877 *remote = complete_addrinfo(remote_host, 878 remote_data_address, 879 remote_data_port, 880 remote_data_family, 881 type, 882 protocol, 883 flags); 884 885 /* OK, if the user has not specified a local data endpoint address 886 (test-specific -L), pick the local data endpoint address based on 887 the remote data family info (test-specific -H or -4 or -6 888 option). if the user has not specified remote data addressing 889 info (test-specific -H, -4 -6) pick something based on the local 890 control connection address (ie the global -L option). */ 891 892 if (NULL == local_data_address) { 893 local_data_address = malloc(HOSTNAMESIZE); 894 if (NULL == remote_data_address) { 895 if (debug) { 896 fprintf(where, 897 "local_data_address not set, using local_host_name of '%s'\n", 898 local_host_name); 899 fflush(where); 900 } 901 strcpy(local_data_address,local_host_name); 902 } 903 else { 904 if (debug) { 905 fprintf(where, 906 "local_data_address not set, using address family info\n"); 907 fflush(where); 908 } 909 /* by default, use 0.0.0.0 - assume IPv4 */ 910 strcpy(local_data_address,"0.0.0.0"); 911 #if defined(AF_INET6) 912 if ((AF_INET6 == local_data_family) || 913 ((AF_UNSPEC == local_data_family) && 914 (AF_INET6 == remote_data_family)) || 915 ((AF_UNSPEC == local_data_family) && 916 (AF_INET6 == (*remote)->ai_family))) { 917 strcpy(local_data_address,"::0"); 918 } 919 #endif 920 } 921 } 922 923 *local = complete_addrinfo("what to put here?", 924 local_data_address, 925 local_data_port, 926 local_data_family, 927 type, 928 protocol, 929 flags|AI_PASSIVE); 930 931 /* OK, at this point, if remote_data_address is NULL, we know that 932 we used the value of remote_host (the control connection) for the 933 remote, which means we can/should set remote_data_address to 934 remote_host so the "omni" output routines can use that global 935 variable. at least i think I can get away with that :) I'm sure 936 that at some point I'll find-out that I need to allocate 937 something for it rather than mess with the pointers, but that can 938 wait. famous last words of raj 2008-01-25 */ 939 if (remote_data_address == NULL) 940 remote_data_address = remote_host; 941 } 942 943 void 944 set_hostname_and_port(char *hostname, char *portstr, int family, int port) 945 { 946 strcpy(hostname,"0.0.0.0"); 947 #if defined AF_INET6 948 if (AF_INET6 == family) { 949 strcpy(hostname,"::0"); 950 } 951 #endif 952 953 sprintf(portstr, "%u", port); 954 955 } 956 957 static unsigned short 958 get_port_number(struct addrinfo *res) 959 { 960 switch(res->ai_family) { 961 case AF_INET: { 962 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 963 return(ntohs(foo->sin_port)); 964 break; 965 } 966 #if defined(AF_INET6) 967 case AF_INET6: { 968 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 969 return(ntohs(foo->sin6_port)); 970 break; 971 } 972 #endif 973 default: 974 fprintf(where, 975 "Given Unexpected Address Family of %u\n",res->ai_family); 976 fflush(where); 977 exit(-1); 978 } 979 } 980 981 static void 982 extract_inet_address_and_port(struct addrinfo *res, void *addr, int len, int *port) 983 { 984 switch(res->ai_family) { 985 case AF_INET: { 986 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 987 *port = foo->sin_port; 988 memcpy(addr,&(foo->sin_addr),min(len,sizeof(foo->sin_addr))); 989 break; 990 } 991 #if defined(AF_INET6) 992 case AF_INET6: { 993 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 994 *port = foo->sin6_port; 995 memcpy(addr,&(foo->sin6_addr),min(len,sizeof(foo->sin6_addr))); 996 break; 997 } 998 #endif 999 default: 1000 *port = 0xDEADBEEF; 1001 strncpy(addr,"UNKN FAMILY",len); 1002 } 1003 } 1004 1005 /* this routine will set the port number of the sockaddr in the 1006 addrinfo to the specified value, based on the address family */ 1007 void 1008 set_port_number(struct addrinfo *res, unsigned short port) 1009 { 1010 switch(res->ai_family) { 1011 case AF_INET: 1012 #if defined(AF_RDS) 1013 case AF_RDS: 1014 #endif 1015 { 1016 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 1017 foo->sin_port = htons(port); 1018 break; 1019 } 1020 #if defined(AF_INET6) 1021 case AF_INET6: { 1022 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 1023 foo->sin6_port = htons(port); 1024 break; 1025 } 1026 #endif 1027 default: 1028 fprintf(where, 1029 "set_port_number Unexpected Address Family of %u\n",res->ai_family); 1030 fflush(where); 1031 exit(-1); 1032 } 1033 } 1034 1035 /* stuff the address family, port number and address into a 1036 sockaddr. for now, we will go ahead and zero-out the sockaddr 1037 first */ 1038 void 1039 set_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int port) { 1040 1041 memset(sockaddr,0,sizeof(struct sockaddr_storage)); 1042 1043 switch (family) { 1044 #if defined(AF_RDS) 1045 case AF_RDS: 1046 #endif 1047 case AF_INET: { 1048 struct sockaddr_in *foo = (struct sockaddr_in *)sockaddr; 1049 foo->sin_port = htons((unsigned short) port); 1050 foo->sin_family = (unsigned short) family; 1051 memcpy(&(foo->sin_addr),addr,sizeof(foo->sin_addr)); 1052 *(int *)addr = htonl(*(int *)addr); 1053 break; 1054 } 1055 #if defined(AF_INET6) 1056 case AF_INET6: { 1057 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)sockaddr; 1058 foo->sin6_port = htons((unsigned short) port); 1059 foo->sin6_family = (unsigned short) family; 1060 memcpy(&(foo->sin6_addr),addr,sizeof(foo->sin6_addr)); 1061 break; 1062 } 1063 #endif 1064 default: 1065 fprintf(where, 1066 "set_sockaddr_family_addr_port Unexpected Address Family of %u\n",family); 1067 fflush(where); 1068 exit(-1); 1069 } 1070 } 1071 1072 /* pull the port and address out of the sockaddr in host format */ 1073 int 1074 get_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int *port) 1075 { 1076 struct sockaddr_in *sin = (struct sockaddr_in *)sockaddr; 1077 1078 int ret = 0; 1079 if (sin->sin_family != family) { 1080 fprintf(where, 1081 "get_sockaddr_family_addr_port family mismatch %d vs %d\n", 1082 sin->sin_family, 1083 family); 1084 fflush(where); 1085 return -1; 1086 } 1087 1088 switch(family) { 1089 #if defined(AF_RDS) 1090 case AF_RDS: 1091 #endif 1092 case AF_INET: { 1093 *port = ntohs(sin->sin_port); 1094 memcpy(addr,&(sin->sin_addr),sizeof(sin->sin_addr)); 1095 if (*(int *)addr == INADDR_ANY) ret = 1; 1096 *(int *)addr = ntohl(*(int *)addr); 1097 break; 1098 } 1099 #ifdef AF_INET6 1100 case AF_INET6: { 1101 int i; 1102 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sockaddr; 1103 *port = ntohs(sin6->sin6_port); 1104 ret = 1; 1105 for (i=0; i < sizeof(struct in6_addr); i++) 1106 if (sin6->sin6_addr.s6_addr[i] != 0) ret=0; 1107 memcpy(addr,&(sin6->sin6_addr), sizeof(sin6->sin6_addr)); 1108 break; 1109 } 1110 #endif 1111 default: 1112 fprintf(where, 1113 "get_sockaddr_family_addr_port: Unexpected Address Family of %u\n",family); 1114 fflush(where); 1115 exit(-1); 1116 } 1117 return ret; 1118 } 1119 1120 1121 int 1123 set_socket_tos(SOCKET sock, int family, int socket_tos) { 1124 1125 int my_tos = -3; 1126 netperf_socklen_t sock_opt_len; 1127 1128 switch (family) { 1129 #if defined(IP_TOS) 1130 case AF_INET: 1131 /* should I mask-away anything above the byte? */ 1132 my_tos = socket_tos; 1133 if (setsockopt(sock, 1134 IPPROTO_IP, 1135 IP_TOS, 1136 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) { 1137 fprintf(where, 1138 "%s ip_tos failed with %s (errno %d)\n", 1139 __FUNCTION__, 1140 strerror(errno), 1141 errno); 1142 fflush(where); 1143 my_tos = -2; 1144 } 1145 else { 1146 sock_opt_len = sizeof(my_tos); 1147 getsockopt(sock, 1148 IPPROTO_IP, 1149 IP_TOS, 1150 (char *)&my_tos, 1151 &sock_opt_len); 1152 } 1153 break; 1154 #endif 1155 #if defined(IPV6_TCLASS) 1156 case AF_INET6: 1157 /* should I mask-away anything above the byte? */ 1158 my_tos = socket_tos; 1159 if (setsockopt(sock, 1160 IPPROTO_IPV6, 1161 IPV6_TCLASS, 1162 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) { 1163 fprintf(where, 1164 "%s ip_tos failed with %s (errno %d)\n", 1165 __FUNCTION__, 1166 strerror(errno), 1167 errno); 1168 fflush(where); 1169 my_tos = -2; 1170 } 1171 else { 1172 sock_opt_len = sizeof(my_tos); 1173 getsockopt(sock, 1174 IPPROTO_IPV6, 1175 IPV6_TCLASS, 1176 (char *)&my_tos, 1177 &sock_opt_len); 1178 } 1179 break; 1180 #endif 1181 } 1182 return my_tos; 1183 } 1184 1185 1187 /* This routine will create a data (listen) socket with the 1188 apropriate options set and return it to the caller. this replaces 1189 all the duplicate code in each of the test routines and should help 1190 make things a little easier to understand. since this routine can be 1191 called by either the netperf or netserver programs, all output 1192 should be directed towards "where." family is generally AF_INET and 1193 type will be either SOCK_STREAM or SOCK_DGRAM. This routine will 1194 also be used by the "SCTP" tests, hence the slightly strange-looking 1195 SCTP stuff in the classic bsd sockets test file... vlad/raj 1196 2005-03-15 */ 1197 1198 SOCKET 1199 create_data_socket(struct addrinfo *res) 1200 { 1201 1202 SOCKET temp_socket; 1203 int one = 1; 1204 int on = 1; 1205 netperf_socklen_t sock_opt_len; 1206 1207 /*set up the data socket */ 1208 temp_socket = socket(res->ai_family, 1209 res->ai_socktype, 1210 res->ai_protocol); 1211 1212 if (temp_socket == INVALID_SOCKET){ 1213 fprintf(where, 1214 "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n", 1215 errno, 1216 inet_ftos(res->ai_family), 1217 inet_ttos(res->ai_socktype), 1218 inet_ptos(res->ai_protocol), 1219 strerror(errno)); 1220 fflush(where); 1221 exit(1); 1222 } 1223 1224 if (debug) { 1225 fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket); 1226 fflush(where); 1227 } 1228 1229 /* Modify the local socket size. The reason we alter the send buffer 1230 size here rather than when the connection is made is to take care 1231 of decreases in buffer size. Decreasing the window size after 1232 connection establishment is a TCP no-no. Also, by setting the 1233 buffer (window) size before the connection is established, we can 1234 control the TCP MSS (segment size). The MSS is never (well, should 1235 never be) more that 1/2 the minimum receive buffer size at each 1236 half of the connection. This is why we are altering the receive 1237 buffer size on the sending size of a unidirectional transfer. If 1238 the user has not requested that the socket buffers be altered, we 1239 will try to find-out what their values are. If we cannot touch the 1240 socket buffer in any way, we will set the values to -1 to indicate 1241 that. */ 1242 1243 /* all the oogy nitty gritty stuff moved from here into the routine 1244 being called below, per patches from davidm to workaround the bug 1245 in Linux getsockopt(). raj 2004-06-15 */ 1246 set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size); 1247 set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size); 1248 1249 /* now, we may wish to enable the copy avoidance features on the */ 1250 /* local system. of course, this may not be possible... */ 1251 1252 #ifdef SO_RCV_COPYAVOID 1253 /* this is ancient vestigial HP-UX code that should probably go away 1254 one day */ 1255 if (loc_rcvavoid) { 1256 if (setsockopt(temp_socket, 1257 SOL_SOCKET, 1258 SO_RCV_COPYAVOID, 1259 (const char *)&loc_rcvavoid, 1260 sizeof(int)) == SOCKET_ERROR) { 1261 fprintf(where, 1262 "netperf: create_data_socket: Could not enable receive copy avoidance"); 1263 fflush(where); 1264 loc_rcvavoid = 0; 1265 } 1266 } 1267 #endif 1268 1269 #ifdef SO_SND_COPYAVOID 1270 if (loc_sndavoid) { 1271 if (setsockopt(temp_socket, 1272 SOL_SOCKET, 1273 SO_SND_COPYAVOID, 1274 (const char *)&loc_sndavoid, 1275 sizeof(int)) == SOCKET_ERROR) { 1276 fprintf(where, 1277 "netperf: create_data_socket: Could not enable send copy avoidance"); 1278 fflush(where); 1279 loc_sndavoid = 0; 1280 } 1281 } 1282 #endif 1283 1284 /* Now, we will see about setting the TCP_NODELAY flag on the local */ 1285 /* socket. We will only do this for those systems that actually */ 1286 /* support the option. If it fails, note the fact, but keep going. */ 1287 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */ 1288 /* will cause an error to be displayed */ 1289 1290 /* well..... long ago and far away that would have happened, in 1291 particular because we would always use IPPROTO_TCP here. 1292 however, now we are using res->ai_protocol, which will be 1293 IPPROT_UDP, and while HP-UX, and I suspect no-one else on the 1294 planet has a UDP_mumble option that overlaps with TCP_NODELAY, 1295 sure as knuth made little green programs, linux has a UDP_CORK 1296 option that is defined as a value of 1, which is the same a 1297 TCP_NODELAY under Linux. So, when asking for -D and 1298 "TCP_NODELAY" under Linux, we are actually setting UDP_CORK 1299 instead of getting an error like every other OS on the 1300 planet. joy and rupture. this stops a UDP_RR test cold sooo we 1301 have to make sure that res->ai_protocol actually makes sense for 1302 a _NODELAY setsockopt() or a UDP_RR test on Linux where someone 1303 mistakenly sets -D will hang. raj 2005-04-21 */ 1304 1305 #if defined(TCP_NODELAY) || defined(SCTP_NODELAY) 1306 if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) { 1307 1308 /* strictly speaking, since the if defined above is an OR, we 1309 should probably check against TCP_NODELAY being defined here. 1310 however, the likelihood of SCTP_NODELAY being defined and 1311 TCP_NODELAY _NOT_ being defined is, probably :), epsilon. raj 1312 2005-03-15 */ 1313 1314 int option = TCP_NODELAY; 1315 1316 /* I suspect that WANT_SCTP would suffice here since that is the 1317 only time we would have called getaddrinfo with a hints asking 1318 for SCTP, but just in case there is an SCTP implementation out 1319 there _without_ SCTP_NODELAY... raj 2005-03-15 */ 1320 /* change this to IPPROTO_SCTP rather than WANT_SCTP to better fit 1321 with the modus operandi of the new "omni" tests. raj 1322 2008-02-04 */ 1323 #if defined(IPPROTO_SCTP) && defined(SCTP_NODELAY) 1324 if (IPPROTO_SCTP == res->ai_protocol) { 1325 option = SCTP_NODELAY; 1326 } 1327 #endif 1328 1329 one = 1; 1330 if(setsockopt(temp_socket, 1331 res->ai_protocol, 1332 option, 1333 (char *)&one, 1334 sizeof(one)) == SOCKET_ERROR) { 1335 fprintf(where, 1336 "netperf: create_data_socket: nodelay: errno %d\n", 1337 errno); 1338 fflush(where); 1339 } 1340 1341 if (debug > 1) { 1342 fprintf(where, 1343 "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n"); 1344 fflush(where); 1345 } 1346 } 1347 #else /* TCP_NODELAY */ 1348 1349 loc_nodelay = 0; 1350 1351 #endif /* TCP_NODELAY */ 1352 1353 if ((transport_mss_req != -1) && (IPPROTO_TCP == res->ai_protocol)) { 1354 set_tcp_mss(temp_socket,transport_mss_req); 1355 } 1356 1357 #if defined(TCP_CORK) 1358 1359 if (loc_tcpcork > 0) { 1360 /* the user wishes for us to set TCP_CORK on the socket */ 1361 if (setsockopt(temp_socket, 1362 getprotobyname("tcp")->p_proto, 1363 TCP_CORK, 1364 (char *)&one, 1365 sizeof(one)) == SOCKET_ERROR) { 1366 perror("netperf: create_data_socket: tcp_cork"); 1367 exit(1); 1368 } 1369 if (debug) { 1370 fprintf(where,"create_data_socket: tcp_cork...\n"); 1371 } 1372 } 1373 1374 #endif /* TCP_CORK */ 1375 1376 /* well, after Knuth only knows how many years, I have finally 1377 decided to enable setting SO_KEEPALIVE on the data socket. 99 1378 times out of 10 this should not be necessary, but that 100th time, 1379 perhaps when netperf is being (ab)used by functional testers, may 1380 benefit from it. And it may help clean-up some lingering 1381 netservers from time to time. raj 2011-06-29 */ 1382 1383 #if defined(SO_KEEPALIVE) 1384 1385 if (want_keepalive) { 1386 if (setsockopt(temp_socket, 1387 SOL_SOCKET, 1388 SO_KEEPALIVE, 1389 (const char *)&on, 1390 sizeof(on)) < 0) { 1391 if (debug) { 1392 fprintf(where, 1393 "%s: unable to set SO_KEEPALIVE on data socket: %s (errno %d)\n", 1394 __FUNCTION__, 1395 strerror(errno), 1396 errno); 1397 fflush(where); 1398 } 1399 } 1400 } 1401 1402 #endif /* SO_KEEPALIVE */ 1403 1404 /* since some of the UDP tests do not do anything to cause an 1405 implicit bind() call, we need to be rather explicit about our 1406 bind() call here. even if the address and/or the port are zero 1407 (INADDR_ANY etc). raj 2004-07-20 */ 1408 1409 if (setsockopt(temp_socket, 1410 #ifdef IPPROTO_DCCP 1411 /* it is REALLY SILLY THAT THIS SHOULD BE NEEDED!! I 1412 should be able to use SOL_SOCKET for this just 1413 like TCP and SCTP */ 1414 /* IT IS EVEN SILLIER THAT THERE COULD BE SYSTEMS 1415 WITH IPPROTO_DCCP and no SOL_DCCP */ 1416 #ifndef SOL_DCCP 1417 #define SOL_DCCP SOL_SOCKET 1418 #define NETPERF_NEED_CLEANUP 1 1419 #endif 1420 (res->ai_protocol == IPPROTO_DCCP) ? SOL_DCCP : SOL_SOCKET, 1421 #ifdef NETPERF_NEED_CLEANUP 1422 #undef SOL_DCCP 1423 #undef NETPERF_NEED_CLEANUP 1424 #endif 1425 1426 #else 1427 SOL_SOCKET, 1428 #endif 1429 SO_REUSEADDR, 1430 (const char *)&on, 1431 sizeof(on)) < 0) { 1432 fprintf(where, 1433 "netperf: create_data_socket: SO_REUSEADDR failed %d\n", 1434 errno); 1435 fflush(where); 1436 } 1437 1438 if (bind(temp_socket, 1439 res->ai_addr, 1440 res->ai_addrlen) < 0) { 1441 if (debug) { 1442 fprintf(where, 1443 "netperf: create_data_socket: data socket bind failed: %s (errno %d)\n", 1444 strerror(errno), 1445 errno); 1446 fprintf(where," port: %d\n",get_port_number(res)); 1447 fflush(where); 1448 } 1449 } 1450 1451 /* this one is a slightly grudgingly added backside covering for 1452 those folks who (ab)use netperf as a functional testing tool, and 1453 further compound that error by running tests on systems also 1454 connected to their site networks, and then compound it even 1455 further compound it by running UDP_STREAM tests over links that 1456 generate link-down events and so cause the traffic to be sent out 1457 the default route into their corporate network... frankly such 1458 people should not be allowed to run netperf in the first place 1459 but there we are... raj 20091026 */ 1460 1461 #if defined (SO_DONTROUTE) 1462 if (!routing_allowed) { 1463 if (setsockopt(temp_socket, 1464 SOL_SOCKET, 1465 SO_DONTROUTE, 1466 (char *)&one, 1467 sizeof(one)) == SOCKET_ERROR) { 1468 fprintf(where, 1469 "netperf: create_data_socket: so_dontroute: errno %d\n", 1470 errno); 1471 fflush(where); 1472 } 1473 } 1474 #endif 1475 1476 #if defined(SO_PRIORITY) 1477 if (local_socket_prio >= 0) { 1478 if (setsockopt(temp_socket, 1479 SOL_SOCKET, 1480 SO_PRIORITY, 1481 &local_socket_prio, 1482 sizeof(int)) == SOCKET_ERROR) { 1483 fprintf(where, 1484 "netperf: create_data_socket: so_priority: errno %d\n", 1485 errno); 1486 fflush(where); 1487 local_socket_prio = -2; 1488 } 1489 else { 1490 sock_opt_len = 4; 1491 getsockopt(temp_socket, 1492 SOL_SOCKET, 1493 SO_PRIORITY, 1494 &local_socket_prio, 1495 &sock_opt_len); 1496 } 1497 } 1498 #else 1499 local_socket_prio = -3; 1500 #endif 1501 1502 #if defined (IP_TOS) || defined(IPV6_TCLASS) 1503 if (local_socket_tos > 0) 1504 local_socket_tos = set_socket_tos(temp_socket,res->ai_family, local_socket_tos); 1505 #endif 1506 1507 return temp_socket; 1508 } 1509 1510 #ifdef KLUDGE_SOCKET_OPTIONS 1511 1512 1513 /* This routine is for those BROKEN systems which do not correctly */ 1515 /* pass socket attributes through calls such as accept(). It should */ 1516 /* only be called for those broken systems. I *really* don't want to */ 1517 /* have this, but even broken systems must be measured. raj 11/95 */ 1518 void 1519 kludge_socket_options(int temp_socket) 1520 { 1521 1522 set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size); 1523 set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size); 1524 1525 /* now, we may wish to enable the copy avoidance features on the */ 1526 /* local system. of course, this may not be possible... */ 1527 /* those calls were only valid for HP-UX, and I know that HP-UX is */ 1528 /* written correctly, and so we do not need to include those calls */ 1529 /* in this kludgy routine. raj 11/95 */ 1530 1531 1532 /* Now, we will see about setting the TCP_NODELAY flag on the local */ 1533 /* socket. We will only do this for those systems that actually */ 1534 /* support the option. If it fails, note the fact, but keep going. */ 1535 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */ 1536 /* will cause an error to be displayed */ 1537 1538 #ifdef TCP_NODELAY 1539 if (loc_nodelay) { 1540 one = 1; 1541 if(setsockopt(temp_socket, 1542 getprotobyname("tcp")->p_proto, 1543 TCP_NODELAY, 1544 (char *)&one, 1545 sizeof(one)) == SOCKET_ERROR) { 1546 fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n", 1547 errno); 1548 fflush(where); 1549 } 1550 1551 if (debug > 1) { 1552 fprintf(where, 1553 "netperf: kludge_socket_options: TCP_NODELAY requested...\n"); 1554 fflush(where); 1555 } 1556 } 1557 #else /* TCP_NODELAY */ 1558 1559 loc_nodelay = 0; 1560 1561 #endif /* TCP_NODELAY */ 1562 1563 } 1564 1565 #endif /* KLUDGE_SOCKET_OPTIONS */ 1566 1567 1569 static void * 1570 get_address_address(struct addrinfo *info) 1571 { 1572 struct sockaddr_in *sin; 1573 #if defined(AF_INET6) 1574 struct sockaddr_in6 *sin6; 1575 #endif 1576 1577 switch(info->ai_family) { 1578 case AF_INET: 1579 sin = (struct sockaddr_in *)info->ai_addr; 1580 return(&(sin->sin_addr)); 1581 break; 1582 #if defined(AF_INET6) 1583 case AF_INET6: 1584 sin6 = (struct sockaddr_in6 *)info->ai_addr; 1585 return(&(sin6->sin6_addr)); 1586 break; 1587 #endif 1588 default: 1589 fprintf(stderr,"we never expected to get here in get_address_address\n"); 1590 fflush(stderr); 1591 exit(-1); 1592 } 1593 } 1594 1595 #if defined(WIN32) 1596 #if !defined(InetNtop) 1597 /* +*+ Why isn't this in the winsock headers yet? */ 1598 const char * 1599 inet_ntop(int af, const void *src, char *dst, size_t size); 1600 #endif 1601 #endif 1602 1603 /* This routine is a generic test header printer for the topmost header */ 1604 void 1605 print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination) 1606 { 1607 1608 char *address_buf; 1609 1610 #ifdef AF_INET6 1611 address_buf = malloc(INET6_ADDRSTRLEN); 1612 #else 1613 address_buf = malloc(16); /* magic constant */ 1614 #endif 1615 1616 if (address_buf == NULL) { 1617 fprintf(where,"Unable to allocate address_buf\n"); 1618 fflush(where); 1619 exit(1); 1620 } 1621 1622 /* we want to have some additional, interesting information in the 1623 headers. we know some of it here, but not all, so we will only 1624 print the test title here and will print the results titles after 1625 the test is finished */ 1626 fprintf(where,"%s",test_name); 1627 1628 address_buf[0] = '\0'; 1629 inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf)); 1630 fprintf(where, 1631 " from %s (%s) port %u %s", 1632 source->ai_canonname, 1633 address_buf, 1634 get_port_number(source), 1635 inet_ftos(source->ai_family)); 1636 1637 address_buf[0] = '\0'; 1638 inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf)); 1639 fprintf(where, 1640 " to %s (%s) port %u %s", 1641 destination->ai_canonname, 1642 address_buf, 1643 get_port_number(destination), 1644 inet_ftos(destination->ai_family)); 1645 1646 if (iteration_max > 1) { 1647 fprintf(where, 1648 " : +/-%.3f%% @ %2d%% conf. %s", 1649 interval/0.02, 1650 confidence_level, 1651 result_confidence_only ? " on result only" : ""); 1652 } 1653 if ((loc_nodelay > 0) || (rem_nodelay > 0)) { 1654 fprintf(where," : nodelay"); 1655 } 1656 if ((loc_sndavoid > 0) || 1657 (loc_rcvavoid > 0) || 1658 (rem_sndavoid > 0) || 1659 (rem_rcvavoid > 0)) { 1660 fprintf(where," : copy avoidance"); 1661 } 1662 1663 if (no_control) { 1664 fprintf(where," : no control"); 1665 } 1666 1667 #ifdef WANT_HISTOGRAM 1668 fprintf(where," : histogram"); 1669 #endif /* WANT_HISTOGRAM */ 1670 1671 #ifdef WANT_INTERVALS 1672 #ifndef WANT_SPIN 1673 fprintf(where," : interval"); 1674 #else 1675 fprintf(where," : spin interval"); 1676 #endif 1677 #endif /* WANT_INTERVALS */ 1678 1679 #ifdef DIRTY 1680 fprintf(where," : dirty data"); 1681 #endif /* DIRTY */ 1682 #ifdef WANT_DEMO 1683 fprintf(where," : demo"); 1684 #endif 1685 #ifdef WANT_FIRST_BURST 1686 /* a little hokey perhaps, but we really only want this to be 1687 emitted for tests where it actually is used, which means a 1688 "REQUEST/RESPONSE" test. raj 2005-11-10 */ 1689 if (strstr(test_name,"REQUEST/RESPONSE")) { 1690 fprintf(where," : first burst %d",first_burst_size); 1691 } 1692 #endif 1693 if (cpu_binding_requested) { 1694 fprintf(where," : cpu bind"); 1695 } 1696 fprintf(where,"\n"); 1697 1698 free(address_buf); 1699 } 1700 1701 /* if WANT_MIGRATION is defined, we will use the send_tcp_stream() 1702 call in src/nettest_omni.c */ 1703 #ifndef WANT_MIGRATION 1704 1705 /* This routine implements the TCP unidirectional data transfer test */ 1706 /* (a.k.a. stream) for the sockets interface. It receives its */ 1707 /* parameters via global variables from the shell and writes its */ 1708 /* output to the standard output. */ 1709 1710 void 1711 send_tcp_stream(char remote_host[]) 1712 { 1713 1714 char *tput_title = "\ 1715 Recv Send Send \n\ 1716 Socket Socket Message Elapsed \n\ 1717 Size Size Size Time Throughput \n\ 1718 bytes bytes bytes secs. %s/sec \n\n"; 1719 1720 char *tput_fmt_0 = 1721 "%7.2f %s\n"; 1722 1723 char *tput_fmt_1 = 1724 "%6d %6d %6d %-6.2f %7.2f %s\n"; 1725 1726 char *cpu_title = "\ 1727 Recv Send Send Utilization Service Demand\n\ 1728 Socket Socket Message Elapsed Send Recv Send Recv\n\ 1729 Size Size Size Time Throughput local remote local remote\n\ 1730 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 1731 1732 char *cpu_fmt_0 = 1733 "%6.3f %c %s\n"; 1734 1735 char *cpu_fmt_1 = 1736 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 1737 1738 char *ksink_fmt = "\n\ 1739 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 1740 Local Remote Local Remote Xfered Per Per\n\ 1741 Send Recv Send Recv Send (avg) Recv (avg)\n\ 1742 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 1743 1744 char *ksink_fmt2 = "\n\ 1745 Maximum\n\ 1746 Segment\n\ 1747 Size (bytes)\n\ 1748 %6d\n"; 1749 1750 1751 float elapsed_time; 1752 1753 /* what we want is to have a buffer space that is at least one */ 1754 /* send-size greater than our send window. this will insure that we */ 1755 /* are never trying to re-use a buffer that may still be in the hands */ 1756 /* of the transport. This buffer will be malloc'd after we have found */ 1757 /* the size of the local senc socket buffer. We will want to deal */ 1758 /* with alignment and offset concerns as well. */ 1759 1760 struct ring_elt *send_ring; 1761 1762 int len; 1763 unsigned int nummessages = 0; 1764 SOCKET send_socket; 1765 int bytes_remaining; 1766 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 1767 1768 /* with links like fddi, one can send > 32 bits worth of bytes 1769 during a test... ;-) at some point, this should probably become a 1770 64bit integral type, but those are not entirely common 1771 yet... time passes, and 64 bit types do indeed become common. */ 1772 #if defined(WIN32) && _MSC_VER <= 1200 1773 __int64 local_bytes_sent = 0; 1774 #else 1775 unsigned long long local_bytes_sent = 0; 1776 #endif 1777 1778 double bytes_sent = 0.0; 1779 1780 float local_cpu_utilization; 1781 float local_service_demand; 1782 float remote_cpu_utilization; 1783 float remote_service_demand; 1784 1785 double thruput; 1786 1787 struct addrinfo *remote_res; 1788 struct addrinfo *local_res; 1789 1790 struct tcp_stream_request_struct *tcp_stream_request; 1791 struct tcp_stream_response_struct *tcp_stream_response; 1792 struct tcp_stream_results_struct *tcp_stream_result; 1793 1794 tcp_stream_request = 1795 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 1796 tcp_stream_response = 1797 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 1798 tcp_stream_result = 1799 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 1800 1801 #ifdef WANT_HISTOGRAM 1802 if (verbosity > 1) { 1803 time_hist = HIST_new(); 1804 } 1805 #endif /* WANT_HISTOGRAM */ 1806 /* since we are now disconnected from the code that established the */ 1807 /* control socket, and since we want to be able to use different */ 1808 /* protocols and such, we are passed the name of the remote host and */ 1809 /* must turn that into the test specific addressing information. */ 1810 1811 /* complete_addrinfos will either succede or exit the process */ 1812 complete_addrinfos(&remote_res, 1813 &local_res, 1814 remote_host, 1815 SOCK_STREAM, 1816 IPPROTO_TCP, 1817 0); 1818 1819 if ( print_headers ) { 1820 print_top_test_header("TCP STREAM TEST",local_res,remote_res); 1821 } 1822 1823 send_ring = NULL; 1824 confidence_iteration = 1; 1825 init_stat(); 1826 1827 /* we have a great-big while loop which controls the number of times */ 1828 /* we run a particular test. this is for the calculation of a */ 1829 /* confidence interval (I really should have stayed awake during */ 1830 /* probstats :). If the user did not request confidence measurement */ 1831 /* (no confidence is the default) then we will only go though the */ 1832 /* loop once. the confidence stuff originates from the folks at IBM */ 1833 1834 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 1835 (confidence_iteration <= iteration_min)) { 1836 1837 /* initialize a few counters. we have to remember that we might be */ 1838 /* going through the loop more than once. */ 1839 1840 nummessages = 0; 1841 bytes_sent = 0.0; 1842 times_up = 0; 1843 1844 /*set up the data socket */ 1845 send_socket = create_data_socket(local_res); 1846 1847 if (send_socket == INVALID_SOCKET){ 1848 perror("netperf: send_tcp_stream: tcp stream data socket"); 1849 exit(1); 1850 } 1851 1852 if (debug) { 1853 fprintf(where,"send_tcp_stream: send_socket obtained...\n"); 1854 } 1855 1856 /* at this point, we have either retrieved the socket buffer sizes, */ 1857 /* or have tried to set them, so now, we may want to set the send */ 1858 /* size based on that (because the user either did not use a -m */ 1859 /* option, or used one with an argument of 0). If the socket buffer */ 1860 /* size is not available, we will set the send size to 4KB - no */ 1861 /* particular reason, just arbitrary... */ 1862 if (send_size == 0) { 1863 if (lss_size > 0) { 1864 send_size = lss_size; 1865 } 1866 else { 1867 send_size = 4096; 1868 } 1869 } 1870 1871 /* set-up the data buffer ring with the requested alignment and offset. */ 1872 /* note also that we have allocated a quantity */ 1873 /* of memory that is at least one send-size greater than our socket */ 1874 /* buffer size. We want to be sure that there are at least two */ 1875 /* buffers allocated - this can be a bit of a problem when the */ 1876 /* send_size is bigger than the socket size, so we must check... the */ 1877 /* user may have wanted to explicitly set the "width" of our send */ 1878 /* buffers, we should respect that wish... */ 1879 if (send_width == 0) { 1880 send_width = (lss_size/send_size) + 1; 1881 if (send_width == 1) send_width++; 1882 } 1883 1884 if (send_ring == NULL) { 1885 /* only allocate the send ring once. this is a networking test, */ 1886 /* not a memory allocation test. this way, we do not need a */ 1887 /* deallocate_buffer_ring() routine, and I don't feel like */ 1888 /* writing one anyway :) raj 11/94 */ 1889 send_ring = allocate_buffer_ring(send_width, 1890 send_size, 1891 local_send_align, 1892 local_send_offset); 1893 } 1894 1895 /* If the user has requested cpu utilization measurements, we must */ 1896 /* calibrate the cpu(s). We will perform this task within the tests */ 1897 /* themselves. If the user has specified the cpu rate, then */ 1898 /* calibrate_local_cpu will return rather quickly as it will have */ 1899 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 1900 /* all the "normal" calibration stuff and return the rate back. */ 1901 1902 if (local_cpu_usage) { 1903 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 1904 } 1905 1906 if (!no_control) { 1907 /* Tell the remote end to do a listen. The server alters the 1908 socket paramters on the other side at this point, hence the 1909 reason for all the values being passed in the setup 1910 message. If the user did not specify any of the parameters, 1911 they will be passed as 0, which will indicate to the remote 1912 that no changes beyond the system's default should be 1913 used. Alignment is the exception, it will default to 1, which 1914 will be no alignment alterations. */ 1915 1916 netperf_request.content.request_type = DO_TCP_STREAM; 1917 tcp_stream_request->send_buf_size = rss_size_req; 1918 tcp_stream_request->recv_buf_size = rsr_size_req; 1919 tcp_stream_request->receive_size = recv_size; 1920 tcp_stream_request->no_delay = rem_nodelay; 1921 tcp_stream_request->recv_alignment = remote_recv_align; 1922 tcp_stream_request->recv_offset = remote_recv_offset; 1923 tcp_stream_request->measure_cpu = remote_cpu_usage; 1924 tcp_stream_request->cpu_rate = remote_cpu_rate; 1925 if (test_time) { 1926 tcp_stream_request->test_length = test_time; 1927 } 1928 else { 1929 tcp_stream_request->test_length = test_bytes; 1930 } 1931 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 1932 tcp_stream_request->so_sndavoid = rem_sndavoid; 1933 #ifdef DIRTY 1934 tcp_stream_request->dirty_count = rem_dirty_count; 1935 tcp_stream_request->clean_count = rem_clean_count; 1936 #endif /* DIRTY */ 1937 tcp_stream_request->port = atoi(remote_data_port); 1938 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 1939 if (debug > 1) { 1940 fprintf(where, 1941 "netperf: send_tcp_stream: requesting TCP stream test\n"); 1942 } 1943 1944 send_request(); 1945 1946 /* The response from the remote will contain all of the relevant 1947 socket parameters for this test type. We will put them back 1948 into the variables here so they can be displayed if desired. 1949 The remote will have calibrated CPU if necessary, and will 1950 have done all the needed set-up we will have calibrated the 1951 cpu locally before sending the request, and will grab the 1952 counter value right after the connect returns. The remote 1953 will grab the counter right after the accept call. This saves 1954 the hassle of extra messages being sent for the TCP 1955 tests. */ 1956 1957 recv_response(); 1958 1959 if (!netperf_response.content.serv_errno) { 1960 if (debug) 1961 fprintf(where,"remote listen done.\n"); 1962 rsr_size = tcp_stream_response->recv_buf_size; 1963 rss_size = tcp_stream_response->send_buf_size; 1964 rem_nodelay = tcp_stream_response->no_delay; 1965 remote_cpu_usage= tcp_stream_response->measure_cpu; 1966 remote_cpu_rate = tcp_stream_response->cpu_rate; 1967 1968 /* we have to make sure that the server port number is in 1969 network order */ 1970 set_port_number(remote_res, 1971 (short)tcp_stream_response->data_port_number); 1972 1973 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 1974 rem_sndavoid = tcp_stream_response->so_sndavoid; 1975 } 1976 else { 1977 Set_errno(netperf_response.content.serv_errno); 1978 fprintf(where, 1979 "netperf: remote error %d", 1980 netperf_response.content.serv_errno); 1981 perror(""); 1982 fflush(where); 1983 1984 exit(1); 1985 } 1986 } 1987 1988 #ifdef WANT_DEMO 1989 demo_stream_setup(lss_size,rsr_size); 1990 #endif 1991 1992 /*Connect up to the remote port on the data socket */ 1993 if (connect(send_socket, 1994 remote_res->ai_addr, 1995 remote_res->ai_addrlen) == INVALID_SOCKET){ 1996 perror("netperf: send_tcp_stream: data socket connect failed"); 1997 exit(1); 1998 } 1999 2000 #ifdef WIN32 2001 /* this is used so the timer thread can close the socket out from */ 2002 /* under us, which to date is the easiest/cleanest/least */ 2003 /* Windows-specific way I can find to force the winsock calls to */ 2004 /* return WSAEINTR with the test is over. anything that will run on */ 2005 /* 95 and NT and is closer to what netperf expects from Unix signals */ 2006 /* and such would be appreciated raj 1/96 */ 2007 win_kludge_socket = send_socket; 2008 #endif /* WIN32 */ 2009 2010 /* Data Socket set-up is finished. If there were problems, either */ 2011 /* the connect would have failed, or the previous response would */ 2012 /* have indicated a problem. I failed to see the value of the */ 2013 /* extra message after the accept on the remote. If it failed, */ 2014 /* we'll see it here. If it didn't, we might as well start pumping */ 2015 /* data. */ 2016 2017 /* Set-up the test end conditions. For a stream test, they can be */ 2018 /* either time or byte-count based. */ 2019 2020 if (test_time) { 2021 /* The user wanted to end the test after a period of time. */ 2022 times_up = 0; 2023 bytes_remaining = 0; 2024 /* in previous revisions, we had the same code repeated throught */ 2025 /* all the test suites. this was unnecessary, and meant more */ 2026 /* work for me when I wanted to switch to POSIX signals, so I */ 2027 /* have abstracted this out into a routine in netlib.c. if you */ 2028 /* are experiencing signal problems, you might want to look */ 2029 /* there. raj 11/94 */ 2030 start_timer(test_time); 2031 } 2032 else { 2033 /* The tester wanted to send a number of bytes. */ 2034 bytes_remaining = test_bytes; 2035 times_up = 1; 2036 } 2037 2038 /* The cpu_start routine will grab the current time and possibly */ 2039 /* value of the idle counter for later use in measuring cpu */ 2040 /* utilization and/or service demand and thruput. */ 2041 2042 cpu_start(local_cpu_usage); 2043 2044 /* we only start the interval timer if we are using the 2045 timer-timed intervals rather than the sit and spin ones. raj 2046 2006-02-06 */ 2047 #if defined(WANT_INTERVALS) 2048 INTERVALS_INIT(); 2049 #endif /* WANT_INTERVALS */ 2050 2051 /* before we start, initialize a few variables */ 2052 2053 #ifdef WANT_DEMO 2054 if (demo_mode) { 2055 demo_first_timestamp(); 2056 } 2057 #endif 2058 2059 2060 /* We use an "OR" to control test execution. When the test is */ 2061 /* controlled by time, the byte count check will always return false. */ 2062 /* When the test is controlled by byte count, the time test will */ 2063 /* always return false. When the test is finished, the whole */ 2064 /* expression will go false and we will stop sending data. */ 2065 2066 while ((!times_up) || (bytes_remaining > 0)) { 2067 2068 #ifdef DIRTY 2069 access_buffer(send_ring->buffer_ptr, 2070 send_size, 2071 loc_dirty_count, 2072 loc_clean_count); 2073 #endif /* DIRTY */ 2074 2075 #ifdef WANT_HISTOGRAM 2076 if (verbosity > 1) { 2077 /* timestamp just before we go into send and then again just 2078 after we come out raj 8/94 */ 2079 /* but lets only do this if there is going to be a histogram 2080 displayed */ 2081 HIST_timestamp(&time_one); 2082 } 2083 #endif /* WANT_HISTOGRAM */ 2084 2085 if((len=send(send_socket, 2086 send_ring->buffer_ptr, 2087 send_size, 2088 0)) != send_size) { 2089 if ((len >=0) || SOCKET_EINTR(len)) { 2090 /* the test was interrupted, must be the end of test */ 2091 break; 2092 } 2093 perror("netperf: data send error"); 2094 printf("len was %d\n",len); 2095 exit(1); 2096 } 2097 2098 local_bytes_sent += send_size; 2099 2100 #ifdef WANT_HISTOGRAM 2101 if (verbosity > 1) { 2102 /* timestamp the exit from the send call and update the histogram */ 2103 HIST_timestamp(&time_two); 2104 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 2105 } 2106 #endif /* WANT_HISTOGRAM */ 2107 2108 #ifdef WANT_DEMO 2109 demo_stream_interval(send_size); 2110 #endif 2111 2112 #if defined(WANT_INTERVALS) 2113 INTERVALS_WAIT(); 2114 #endif /* WANT_INTERVALS */ 2115 2116 /* now we want to move our pointer to the next position in the */ 2117 /* data buffer...we may also want to wrap back to the "beginning" */ 2118 /* of the bufferspace, so we will mod the number of messages sent */ 2119 /* by the send width, and use that to calculate the offset to add */ 2120 /* to the base pointer. */ 2121 nummessages++; 2122 send_ring = send_ring->next; 2123 if (bytes_remaining) { 2124 bytes_remaining -= send_size; 2125 } 2126 } 2127 2128 /* The test is over. Flush the buffers to the remote end. We do a */ 2129 /* graceful release to insure that all data has been taken by the */ 2130 /* remote. */ 2131 2132 /* but first, if the verbosity is greater than 1, find-out what */ 2133 /* the TCP maximum segment_size was (if possible) */ 2134 if (verbosity > 1) { 2135 tcp_mss = -1; 2136 get_tcp_info(send_socket,&tcp_mss); 2137 } 2138 2139 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR && !times_up) { 2140 perror("netperf: cannot shutdown tcp stream socket"); 2141 exit(1); 2142 } 2143 2144 /* hang a recv() off the socket to block until the remote has */ 2145 /* brought all the data up into the application. it will do a */ 2146 /* shutdown to cause a FIN to be sent our way. We will assume that */ 2147 /* any exit from the recv() call is good... raj 4/93 */ 2148 2149 recv(send_socket, send_ring->buffer_ptr, send_size, 0); 2150 2151 /* this call will always give us the elapsed time for the test, and */ 2152 /* will also store-away the necessaries for cpu utilization */ 2153 2154 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 2155 /* measured and how */ 2156 /* long did we really */ 2157 /* run? */ 2158 2159 /* we are finished with the socket, so close it to prevent hitting */ 2160 /* the limit on maximum open files. */ 2161 2162 close(send_socket); 2163 2164 #if defined(WANT_INTERVALS) 2165 #ifdef WIN32 2166 stop_itimer(); 2167 #endif 2168 #endif /* WANT_INTERVALS */ 2169 2170 if (!no_control) { 2171 /* Get the statistics from the remote end. The remote will have 2172 calculated service demand and all those interesting 2173 things. If it wasn't supposed to care, it will return obvious 2174 values. */ 2175 2176 recv_response(); 2177 if (!netperf_response.content.serv_errno) { 2178 if (debug) 2179 fprintf(where, 2180 "remote reporting results for %.2f seconds\n", 2181 tcp_stream_result->elapsed_time); 2182 } 2183 else { 2184 Set_errno(netperf_response.content.serv_errno); 2185 fprintf(where, 2186 "netperf: remote error %d", 2187 netperf_response.content.serv_errno); 2188 perror(""); 2189 fflush(where); 2190 2191 exit(1); 2192 } 2193 2194 /* We now calculate what our thruput was for the test. In the 2195 future, we may want to include a calculation of the thruput 2196 measured by the remote, but it should be the case that for a 2197 TCP stream test, that the two numbers should be *very* 2198 close... We calculate bytes_sent regardless of the way the 2199 test length was controlled. If it was time, we needed to, 2200 and if it was by bytes, the user may have specified a number 2201 of bytes that wasn't a multiple of the send_size, so we 2202 really didn't send what he asked for ;-) */ 2203 2204 bytes_sent = ntohd(tcp_stream_result->bytes_received); 2205 } 2206 else { 2207 bytes_sent = (double)local_bytes_sent; 2208 } 2209 2210 thruput = calc_thruput(bytes_sent); 2211 2212 if (local_cpu_usage || remote_cpu_usage) { 2213 /* We must now do a little math for service demand and cpu */ 2214 /* utilization for the system(s) */ 2215 /* Of course, some of the information might be bogus because */ 2216 /* there was no idle counter in the kernel(s). We need to make */ 2217 /* a note of this for the user's benefit...*/ 2218 if (local_cpu_usage) { 2219 2220 local_cpu_utilization = calc_cpu_util(0.0); 2221 local_service_demand = calc_service_demand(bytes_sent, 2222 0.0, 2223 0.0, 2224 0); 2225 } 2226 else { 2227 local_cpu_utilization = (float) -1.0; 2228 local_service_demand = (float) -1.0; 2229 } 2230 2231 if (remote_cpu_usage) { 2232 2233 remote_cpu_utilization = tcp_stream_result->cpu_util; 2234 remote_service_demand = calc_service_demand(bytes_sent, 2235 0.0, 2236 remote_cpu_utilization, 2237 tcp_stream_result->num_cpus); 2238 } 2239 else { 2240 remote_cpu_utilization = (float) -1.0; 2241 remote_service_demand = (float) -1.0; 2242 } 2243 } 2244 else { 2245 /* we were not measuring cpu, for the confidence stuff, we */ 2246 /* should make it -1.0 */ 2247 local_cpu_utilization = (float) -1.0; 2248 local_service_demand = (float) -1.0; 2249 remote_cpu_utilization = (float) -1.0; 2250 remote_service_demand = (float) -1.0; 2251 } 2252 2253 /* at this point, we want to calculate the confidence information. */ 2254 /* if debugging is on, calculate_confidence will print-out the */ 2255 /* parameters we pass it */ 2256 2257 calculate_confidence(confidence_iteration, 2258 elapsed_time, 2259 thruput, 2260 local_cpu_utilization, 2261 remote_cpu_utilization, 2262 local_service_demand, 2263 remote_service_demand); 2264 2265 2266 confidence_iteration++; 2267 } 2268 2269 /* at this point, we have finished making all the runs that we */ 2270 /* will be making. so, we should extract what the calcuated values */ 2271 /* are for all the confidence stuff. we could make the values */ 2272 /* global, but that seemed a little messy, and it did not seem worth */ 2273 /* all the mucking with header files. so, we create a routine much */ 2274 /* like calcualte_confidence, which just returns the mean values. */ 2275 /* raj 11/94 */ 2276 2277 retrieve_confident_values(&elapsed_time, 2278 &thruput, 2279 &local_cpu_utilization, 2280 &remote_cpu_utilization, 2281 &local_service_demand, 2282 &remote_service_demand); 2283 2284 /* We are now ready to print all the information. If the user */ 2285 /* has specified zero-level verbosity, we will just print the */ 2286 /* local service demand, or the remote service demand. If the */ 2287 /* user has requested verbosity level 1, he will get the basic */ 2288 /* "streamperf" numbers. If the user has specified a verbosity */ 2289 /* of greater than 1, we will display a veritable plethora of */ 2290 /* background information from outside of this block as it it */ 2291 /* not cpu_measurement specific... */ 2292 2293 if (confidence < 0) { 2294 /* we did not hit confidence, but were we asked to look for it? */ 2295 if (iteration_max > 1) { 2296 display_confidence(); 2297 } 2298 } 2299 2300 if (local_cpu_usage || remote_cpu_usage) { 2301 local_cpu_method = format_cpu_method(cpu_method); 2302 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 2303 2304 switch (verbosity) { 2305 case 0: 2306 if (local_cpu_usage) { 2307 fprintf(where, 2308 cpu_fmt_0, 2309 local_service_demand, 2310 local_cpu_method, 2311 ((print_headers) || 2312 (result_brand == NULL)) ? "" : result_brand); 2313 } 2314 else { 2315 fprintf(where, 2316 cpu_fmt_0, 2317 remote_service_demand, 2318 remote_cpu_method, 2319 ((print_headers) || 2320 (result_brand == NULL)) ? "" : result_brand); 2321 } 2322 break; 2323 case 1: 2324 case 2: 2325 if (print_headers) { 2326 fprintf(where, 2327 cpu_title, 2328 format_units(), 2329 local_cpu_method, 2330 remote_cpu_method); 2331 } 2332 2333 fprintf(where, 2334 cpu_fmt_1, /* the format string */ 2335 rsr_size, /* remote recvbuf size */ 2336 lss_size, /* local sendbuf size */ 2337 send_size, /* how large were the sends */ 2338 elapsed_time, /* how long was the test */ 2339 thruput, /* what was the xfer rate */ 2340 local_cpu_utilization, /* local cpu */ 2341 remote_cpu_utilization, /* remote cpu */ 2342 local_service_demand, /* local service demand */ 2343 remote_service_demand, /* remote service demand */ 2344 ((print_headers) || 2345 (result_brand == NULL)) ? "" : result_brand); 2346 break; 2347 } 2348 } 2349 else { 2350 /* The tester did not wish to measure service demand. */ 2351 2352 switch (verbosity) { 2353 case 0: 2354 fprintf(where, 2355 tput_fmt_0, 2356 thruput, 2357 ((print_headers) || 2358 (result_brand == NULL)) ? "" : result_brand); 2359 break; 2360 case 1: 2361 case 2: 2362 if (print_headers) { 2363 fprintf(where,tput_title,format_units()); 2364 } 2365 fprintf(where, 2366 tput_fmt_1, /* the format string */ 2367 rsr_size, /* remote recvbuf size */ 2368 lss_size, /* local sendbuf size */ 2369 send_size, /* how large were the sends */ 2370 elapsed_time, /* how long did it take */ 2371 thruput, /* how fast did it go */ 2372 ((print_headers) || 2373 (result_brand == NULL)) ? "" : result_brand); 2374 break; 2375 } 2376 } 2377 2378 /* it would be a good thing to include information about some of the */ 2379 /* other parameters that may have been set for this test, but at the */ 2380 /* moment, I do not wish to figure-out all the formatting, so I will */ 2381 /* just put this comment here to help remind me that it is something */ 2382 /* that should be done at a later time. */ 2383 2384 if (verbosity > 1) { 2385 /* The user wanted to know it all, so we will give it to him. */ 2386 /* This information will include as much as we can find about */ 2387 /* TCP statistics, the alignments of the sends and receives */ 2388 /* and all that sort of rot... */ 2389 2390 /* this stuff needs to be worked-out in the presence of confidence */ 2391 /* intervals and multiple iterations of the test... raj 11/94 */ 2392 2393 fprintf(where, 2394 ksink_fmt, 2395 "Bytes", 2396 "Bytes", 2397 "Bytes", 2398 local_send_align, 2399 remote_recv_align, 2400 local_send_offset, 2401 remote_recv_offset, 2402 bytes_sent, 2403 bytes_sent / (double)nummessages, 2404 nummessages, 2405 bytes_sent / (double)tcp_stream_result->recv_calls, 2406 tcp_stream_result->recv_calls); 2407 fprintf(where, 2408 ksink_fmt2, 2409 tcp_mss); 2410 fflush(where); 2411 #ifdef WANT_HISTOGRAM 2412 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 2413 fflush(where); 2414 HIST_report(time_hist); 2415 #endif /* WANT_HISTOGRAM */ 2416 } 2417 2418 } 2419 2420 2421 2423 /* This routine implements the netperf-side TCP unidirectional data 2424 transfer test (a.k.a. stream) for the sockets interface where the 2425 data flow is from the netserver to the netperf. It receives its 2426 parameters via global variables from the shell and writes its 2427 output to the standard output. */ 2428 2429 2430 void 2431 send_tcp_maerts(char remote_host[]) 2432 { 2433 2434 char *tput_title = "\ 2435 Recv Send Send \n\ 2436 Socket Socket Message Elapsed \n\ 2437 Size Size Size Time Throughput \n\ 2438 bytes bytes bytes secs. %s/sec \n\n"; 2439 2440 char *tput_fmt_0 = 2441 "%7.2f %s\n"; 2442 2443 char *tput_fmt_1 = 2444 "%6d %6d %6d %-6.2f %7.2f %s\n"; 2445 2446 char *cpu_title = "\ 2447 Recv Send Send Utilization Service Demand\n\ 2448 Socket Socket Message Elapsed Recv Send Recv Send\n\ 2449 Size Size Size Time Throughput local remote local remote\n\ 2450 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 2451 2452 char *cpu_fmt_0 = 2453 "%6.3f %c %s\n"; 2454 2455 char *cpu_fmt_1 = 2456 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 2457 2458 char *ksink_fmt = "\n\ 2459 Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\ 2460 Local Remote Local Remote Xfered Per Per\n\ 2461 Recv Send Recv Send Recv (avg) Send (avg)\n\ 2462 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 2463 2464 char *ksink_fmt2 = "\n\ 2465 Maximum\n\ 2466 Segment\n\ 2467 Size (bytes)\n\ 2468 %6d\n"; 2469 2470 2471 float elapsed_time; 2472 2473 /* what we want is to have a buffer space that is at least one */ 2474 /* recv-size greater than our recv window. this will insure that we */ 2475 /* are never trying to re-use a buffer that may still be in the hands */ 2476 /* of the transport. This buffer will be malloc'd after we have found */ 2477 /* the size of the local senc socket buffer. We will want to deal */ 2478 /* with alignment and offset concerns as well. */ 2479 2480 struct ring_elt *recv_ring; 2481 2482 int len; 2483 unsigned int nummessages = 0; 2484 SOCKET recv_socket; 2485 int bytes_remaining; 2486 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 2487 2488 /* with links like fddi, one can recv > 32 bits worth of bytes 2489 during a test... ;-) at some point, this should probably become a 2490 64bit integral type, but those are not entirely common yet. of 2491 course, time passes and they do become common. 2492 */ 2493 double bytes_sent = 0.0; 2494 2495 #if defined(WIN32) && (_MSC_VER < 1200) 2496 __int64 local_bytes_recvd = 0; 2497 #else 2498 unsigned long long local_bytes_recvd = 0; 2499 #endif 2500 2501 float local_cpu_utilization; 2502 float local_service_demand; 2503 float remote_cpu_utilization; 2504 float remote_service_demand; 2505 2506 double thruput; 2507 2508 struct addrinfo *remote_res; 2509 struct addrinfo *local_res; 2510 2511 struct tcp_maerts_request_struct *tcp_maerts_request; 2512 struct tcp_maerts_response_struct *tcp_maerts_response; 2513 struct tcp_maerts_results_struct *tcp_maerts_result; 2514 2515 tcp_maerts_request = 2516 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data; 2517 tcp_maerts_response = 2518 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data; 2519 tcp_maerts_result = 2520 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data; 2521 2522 #ifdef WANT_HISTOGRAM 2523 if (verbosity > 1) { 2524 time_hist = HIST_new(); 2525 } 2526 #endif /* WANT_HISTOGRAM */ 2527 /* since we are now disconnected from the code that established the */ 2528 /* control socket, and since we want to be able to use different */ 2529 /* protocols and such, we are passed the name of the remote host and */ 2530 /* must turn that into the test specific addressing information. */ 2531 2532 complete_addrinfos(&remote_res, 2533 &local_res, 2534 remote_host, 2535 SOCK_STREAM, 2536 IPPROTO_TCP, 2537 0); 2538 2539 if ( print_headers ) { 2540 print_top_test_header("TCP MAERTS TEST",local_res,remote_res); 2541 } 2542 2543 recv_ring = NULL; 2544 confidence_iteration = 1; 2545 init_stat(); 2546 2547 /* we have a great-big while loop which controls the number of times */ 2548 /* we run a particular test. this is for the calculation of a */ 2549 /* confidence interval (I really should have stayed awake during */ 2550 /* probstats :). If the user did not request confidence measurement */ 2551 /* (no confidence is the default) then we will only go though the */ 2552 /* loop once. the confidence stuff originates from the folks at IBM */ 2553 2554 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 2555 (confidence_iteration <= iteration_min)) { 2556 2557 /* initialize a few counters. we have to remember that we might be */ 2558 /* going through the loop more than once. */ 2559 2560 nummessages = 0; 2561 bytes_sent = 0.0; 2562 times_up = 0; 2563 2564 /*set up the data socket */ 2565 recv_socket = create_data_socket(local_res); 2566 2567 if (recv_socket == INVALID_SOCKET){ 2568 perror("netperf: send_tcp_maerts: tcp stream data socket"); 2569 exit(1); 2570 } 2571 2572 if (debug) { 2573 fprintf(where,"send_tcp_maerts: recv_socket obtained...\n"); 2574 } 2575 2576 /* at this point, we have either retrieved the socket buffer sizes, */ 2577 /* or have tried to set them, so now, we may want to set the recv */ 2578 /* size based on that (because the user either did not use a -m */ 2579 /* option, or used one with an argument of 0). If the socket buffer */ 2580 /* size is not available, we will set the recv size to 4KB - no */ 2581 /* particular reason, just arbitrary... */ 2582 if (recv_size == 0) { 2583 if (lsr_size > 0) { 2584 recv_size = lsr_size; 2585 } 2586 else { 2587 recv_size = 4096; 2588 } 2589 } 2590 2591 /* set-up the data buffer ring with the requested alignment and offset. */ 2592 /* note also that we have allocated a quantity */ 2593 /* of memory that is at least one recv-size greater than our socket */ 2594 /* buffer size. We want to be sure that there are at least two */ 2595 /* buffers allocated - this can be a bit of a problem when the */ 2596 /* recv_size is bigger than the socket size, so we must check... the */ 2597 /* user may have wanted to explicitly set the "width" of our recv */ 2598 /* buffers, we should respect that wish... */ 2599 if (recv_width == 0) { 2600 recv_width = (lsr_size/recv_size) + 1; 2601 if (recv_width == 1) recv_width++; 2602 } 2603 2604 if (recv_ring == NULL) { 2605 /* only allocate the recv ring once. this is a networking test, */ 2606 /* not a memory allocation test. this way, we do not need a */ 2607 /* deallocate_buffer_ring() routine, and I don't feel like */ 2608 /* writing one anyway :) raj 11/94 */ 2609 recv_ring = allocate_buffer_ring(recv_width, 2610 recv_size, 2611 local_recv_align, 2612 local_recv_offset); 2613 } 2614 2615 /* If the user has requested cpu utilization measurements, we must */ 2616 /* calibrate the cpu(s). We will perform this task within the tests */ 2617 /* themselves. If the user has specified the cpu rate, then */ 2618 /* calibrate_local_cpu will return rather quickly as it will have */ 2619 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 2620 /* all the "normal" calibration stuff and return the rate back. */ 2621 2622 if (local_cpu_usage) { 2623 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 2624 } 2625 2626 if (!no_control) { 2627 /* Tell the remote end to do a listen. The server alters the 2628 socket paramters on the other side at this point, hence the 2629 reason for all the values being passed in the setup 2630 message. If the user did not specify any of the parameters, 2631 they will be passed as 0, which will indicate to the remote 2632 that no changes beyond the system's default should be 2633 used. Alignment is the exception, it will default to 1, which 2634 will be no alignment alterations. */ 2635 2636 netperf_request.content.request_type = DO_TCP_MAERTS; 2637 tcp_maerts_request->send_buf_size = rss_size_req; 2638 tcp_maerts_request->recv_buf_size = rsr_size_req; 2639 tcp_maerts_request->send_size = send_size; 2640 tcp_maerts_request->no_delay = rem_nodelay; 2641 tcp_maerts_request->send_alignment = remote_send_align; 2642 tcp_maerts_request->send_offset = remote_send_offset; 2643 tcp_maerts_request->measure_cpu = remote_cpu_usage; 2644 tcp_maerts_request->cpu_rate = remote_cpu_rate; 2645 if (test_time) { 2646 tcp_maerts_request->test_length = test_time; 2647 } 2648 else { 2649 tcp_maerts_request->test_length = test_bytes; 2650 } 2651 tcp_maerts_request->so_rcvavoid = rem_rcvavoid; 2652 tcp_maerts_request->so_sndavoid = rem_sndavoid; 2653 #ifdef DIRTY 2654 tcp_maerts_request->dirty_count = rem_dirty_count; 2655 tcp_maerts_request->clean_count = rem_clean_count; 2656 #endif /* DIRTY */ 2657 tcp_maerts_request->port = atoi(remote_data_port); 2658 tcp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family); 2659 if (debug > 1) { 2660 fprintf(where, 2661 "netperf: send_tcp_maerts: requesting TCP maerts test\n"); 2662 } 2663 2664 send_request(); 2665 2666 /* The response from the remote will contain all of the relevant 2667 socket parameters for this test type. We will put them back 2668 into the variables here so they can be displayed if desired. 2669 The remote will have calibrated CPU if necessary, and will 2670 have done all the needed set-up we will have calibrated the 2671 cpu locally before sending the request, and will grab the 2672 counter value right after the connect returns. The remote 2673 will grab the counter right after the accept call. This saves 2674 the hassle of extra messages being sent for the TCP 2675 tests. */ 2676 2677 recv_response(); 2678 2679 if (!netperf_response.content.serv_errno) { 2680 if (debug) 2681 fprintf(where,"remote listen done.\n"); 2682 rsr_size = tcp_maerts_response->recv_buf_size; 2683 rss_size = tcp_maerts_response->send_buf_size; 2684 rem_nodelay = tcp_maerts_response->no_delay; 2685 remote_cpu_usage= tcp_maerts_response->measure_cpu; 2686 remote_cpu_rate = tcp_maerts_response->cpu_rate; 2687 send_size = tcp_maerts_response->send_size; 2688 2689 /* we have to make sure that the server port number is in 2690 network order */ 2691 set_port_number(remote_res, 2692 (short)tcp_maerts_response->data_port_number); 2693 rem_rcvavoid = tcp_maerts_response->so_rcvavoid; 2694 rem_sndavoid = tcp_maerts_response->so_sndavoid; 2695 } 2696 else { 2697 Set_errno(netperf_response.content.serv_errno); 2698 fprintf(where, 2699 "netperf: remote error %d", 2700 netperf_response.content.serv_errno); 2701 perror(""); 2702 fflush(where); 2703 2704 exit(1); 2705 } 2706 } 2707 2708 #ifdef WANT_DEMO 2709 demo_stream_setup(lsr_size,rss_size); 2710 #endif 2711 2712 /*Connect up to the remote port on the data socket */ 2713 if (connect(recv_socket, 2714 remote_res->ai_addr, 2715 remote_res->ai_addrlen) == INVALID_SOCKET){ 2716 perror("netperf: send_tcp_maerts: data socket connect failed"); 2717 exit(1); 2718 } 2719 2720 #ifdef WIN32 2721 /* this is used so the timer thread can close the socket out from */ 2722 /* under us, which to date is the easiest/cleanest/least */ 2723 /* Windows-specific way I can find to force the winsock calls to */ 2724 /* return WSAEINTR with the test is over. anything that will run on */ 2725 /* 95 and NT and is closer to what netperf expects from Unix signals */ 2726 /* and such would be appreciated raj 1/96 */ 2727 win_kludge_socket = recv_socket; 2728 #endif /* WIN32 */ 2729 2730 /* Data Socket set-up is finished. If there were problems, either */ 2731 /* the connect would have failed, or the previous response would */ 2732 /* have indicated a problem. I failed to see the value of the */ 2733 /* extra message after the accept on the remote. If it failed, */ 2734 /* we'll see it here. If it didn't, we might as well start pumping */ 2735 /* data. */ 2736 2737 /* Set-up the test end conditions. For a maerts test, they can be */ 2738 /* either time or byte-count based. */ 2739 2740 if (test_time) { 2741 /* The user wanted to end the test after a period of time. */ 2742 times_up = 0; 2743 bytes_remaining = 0; 2744 /* in previous revisions, we had the same code repeated throught */ 2745 /* all the test suites. this was unnecessary, and meant more */ 2746 /* work for me when I wanted to switch to POSIX signals, so I */ 2747 /* have abstracted this out into a routine in netlib.c. if you */ 2748 /* are experiencing signal problems, you might want to look */ 2749 /* there. raj 11/94 */ 2750 if (!no_control) { 2751 /* this is a netperf to netserver test, netserver will close 2752 to tell us the test is over, so use PAD_TIME to avoid 2753 causing the netserver fits. */ 2754 start_timer(test_time + PAD_TIME); 2755 } 2756 else { 2757 /* this is a netperf to data source test, no PAD_TIME */ 2758 start_timer(test_time); 2759 } 2760 } 2761 else { 2762 /* The tester wanted to recv a number of bytes. we don't do that 2763 in a TCP_MAERTS test. sorry. raj 2002-06-21 */ 2764 printf("netperf: send_tcp_maerts: test must be timed\n"); 2765 exit(1); 2766 } 2767 2768 /* The cpu_start routine will grab the current time and possibly */ 2769 /* value of the idle counter for later use in measuring cpu */ 2770 /* utilization and/or service demand and thruput. */ 2771 2772 cpu_start(local_cpu_usage); 2773 2774 #ifdef WANT_INTERVALS 2775 INTERVALS_INIT(); 2776 #endif /* WANT_INTERVALS */ 2777 2778 /* before we start, initialize a few variables */ 2779 2780 #ifdef WANT_DEMO 2781 if (demo_mode) { 2782 demo_first_timestamp(); 2783 } 2784 #endif 2785 2786 /* the test will continue until we either get a zero-byte recv() 2787 on the socket or our failsafe timer expires. most of the time 2788 we trust that we get a zero-byte recieve from the socket. raj 2789 2002-06-21 */ 2790 2791 #ifdef WANT_HISTOGRAM 2792 if (verbosity > 1) { 2793 /* timestamp just before we go into recv and then again just 2794 after we come out raj 8/94 */ 2795 /* but only if we are actually going to display a histogram. raj 2796 2006-02-07 */ 2797 HIST_timestamp(&time_one); 2798 } 2799 #endif /* WANT_HISTOGRAM */ 2800 2801 while ((!times_up) && (len=recv(recv_socket, 2802 recv_ring->buffer_ptr, 2803 recv_size, 2804 0)) > 0 ) { 2805 2806 #ifdef WANT_HISTOGRAM 2807 if (verbosity > 1) { 2808 /* timestamp the exit from the recv call and update the histogram */ 2809 HIST_timestamp(&time_two); 2810 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 2811 } 2812 #endif /* WANT_HISTOGRAM */ 2813 2814 #ifdef DIRTY 2815 access_buffer(recv_ring->buffer_ptr, 2816 recv_size, 2817 loc_dirty_count, 2818 loc_clean_count); 2819 #endif /* DIRTY */ 2820 2821 #ifdef WANT_DEMO 2822 demo_stream_interval(len); 2823 #endif 2824 2825 #ifdef WANT_INTERVALS 2826 INTERVALS_WAIT(); 2827 #endif /* WANT_INTERVALS */ 2828 2829 /* now we want to move our pointer to the next position in the */ 2830 /* data buffer...we may also want to wrap back to the "beginning" */ 2831 /* of the bufferspace, so we will mod the number of messages sent */ 2832 /* by the recv width, and use that to calculate the offset to add */ 2833 /* to the base pointer. */ 2834 nummessages++; 2835 recv_ring = recv_ring->next; 2836 if (bytes_remaining) { 2837 bytes_remaining -= len; 2838 } 2839 2840 local_bytes_recvd += len; 2841 2842 #ifdef WANT_HISTOGRAM 2843 if (verbosity > 1) { 2844 /* make sure we timestamp just before we go into recv */ 2845 /* raj 2004-06-15 */ 2846 HIST_timestamp(&time_one); 2847 } 2848 #endif /* WANT_HISTOGRAM */ 2849 2850 } 2851 2852 /* an EINTR is to be expected when this is a no_control test */ 2853 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) { 2854 perror("send_tcp_maerts: data recv error"); 2855 printf("len was %d\n",len); 2856 exit(1); 2857 } 2858 2859 /* if we get here, it must mean we had a recv return of 0 before 2860 the watchdog timer expired, or the watchdog timer expired and 2861 this was a no_control test */ 2862 2863 /* The test is over. Flush the buffers to the remote end. We do a 2864 graceful release to tell the remote we have all the data. */ 2865 2866 /* but first, if the verbosity is greater than 1, find-out what */ 2867 /* the TCP maximum segment_size was (if possible) */ 2868 if (verbosity > 1) { 2869 tcp_mss = -1; 2870 get_tcp_info(recv_socket,&tcp_mss); 2871 } 2872 2873 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) { 2874 perror("netperf: cannot shutdown tcp maerts socket"); 2875 exit(1); 2876 } 2877 2878 stop_timer(); 2879 2880 #if defined(WANT_INTERVALS) 2881 #ifdef WIN32 2882 stop_itimer(); 2883 #endif 2884 #endif /* WANT_INTERVALS */ 2885 2886 /* this call will always give us the local elapsed time for the 2887 test, and will also store-away the necessaries for cpu 2888 utilization */ 2889 2890 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 2891 /* measured and how */ 2892 /* long did we really */ 2893 /* run? */ 2894 2895 /* we are finished with the socket, so close it to prevent hitting */ 2896 /* the limit on maximum open files. */ 2897 2898 close(recv_socket); 2899 2900 if (!no_control) { 2901 /* Get the statistics from the remote end. The remote will have 2902 calculated service demand and all those interesting 2903 things. If it wasn't supposed to care, it will return obvious 2904 values. */ 2905 2906 recv_response(); 2907 if (!netperf_response.content.serv_errno) { 2908 if (debug) 2909 fprintf(where,"remote results obtained\n"); 2910 } 2911 else { 2912 Set_errno(netperf_response.content.serv_errno); 2913 fprintf(where, 2914 "netperf: remote error %d", 2915 netperf_response.content.serv_errno); 2916 perror(""); 2917 fflush(where); 2918 2919 exit(1); 2920 } 2921 2922 /* We now calculate what our thruput was for the test. In the 2923 future, we may want to include a calculation of the thruput 2924 measured by the remote, but it should be the case that for a 2925 TCP maerts test, that the two numbers should be *very* 2926 close... We calculate bytes_sent regardless of the way the 2927 test length was controlled. If it was time, we needed to, 2928 and if it was by bytes, the user may have specified a number 2929 of bytes that wasn't a multiple of the recv_size, so we 2930 really didn't recv what he asked for ;-) */ 2931 2932 bytes_sent = ntohd(tcp_maerts_result->bytes_sent); 2933 } 2934 else { 2935 bytes_sent = (double)local_bytes_recvd; 2936 } 2937 2938 2939 thruput = calc_thruput(bytes_sent); 2940 2941 if (local_cpu_usage || remote_cpu_usage) { 2942 /* We must now do a little math for service demand and cpu */ 2943 /* utilization for the system(s) */ 2944 /* Of course, some of the information might be bogus because */ 2945 /* there was no idle counter in the kernel(s). We need to make */ 2946 /* a note of this for the user's benefit...*/ 2947 if (local_cpu_usage) { 2948 2949 local_cpu_utilization = calc_cpu_util(0.0); 2950 local_service_demand = calc_service_demand(bytes_sent, 2951 0.0, 2952 0.0, 2953 0); 2954 } 2955 else { 2956 local_cpu_utilization = (float) -1.0; 2957 local_service_demand = (float) -1.0; 2958 } 2959 2960 if (remote_cpu_usage) { 2961 2962 remote_cpu_utilization = tcp_maerts_result->cpu_util; 2963 remote_service_demand = calc_service_demand(bytes_sent, 2964 0.0, 2965 remote_cpu_utilization, 2966 tcp_maerts_result->num_cpus); 2967 } 2968 else { 2969 remote_cpu_utilization = (float) -1.0; 2970 remote_service_demand = (float) -1.0; 2971 } 2972 } 2973 else { 2974 /* we were not measuring cpu, for the confidence stuff, we */ 2975 /* should make it -1.0 */ 2976 local_cpu_utilization = (float) -1.0; 2977 local_service_demand = (float) -1.0; 2978 remote_cpu_utilization = (float) -1.0; 2979 remote_service_demand = (float) -1.0; 2980 } 2981 2982 /* at this point, we want to calculate the confidence information. */ 2983 /* if debugging is on, calculate_confidence will print-out the */ 2984 /* parameters we pass it */ 2985 2986 calculate_confidence(confidence_iteration, 2987 elapsed_time, 2988 thruput, 2989 local_cpu_utilization, 2990 remote_cpu_utilization, 2991 local_service_demand, 2992 remote_service_demand); 2993 2994 2995 confidence_iteration++; 2996 } 2997 2998 /* at this point, we have finished making all the runs that we */ 2999 /* will be making. so, we should extract what the calcuated values */ 3000 /* are for all the confidence stuff. we could make the values */ 3001 /* global, but that seemed a little messy, and it did not seem worth */ 3002 /* all the mucking with header files. so, we create a routine much */ 3003 /* like calcualte_confidence, which just returns the mean values. */ 3004 /* raj 11/94 */ 3005 3006 retrieve_confident_values(&elapsed_time, 3007 &thruput, 3008 &local_cpu_utilization, 3009 &remote_cpu_utilization, 3010 &local_service_demand, 3011 &remote_service_demand); 3012 3013 /* We are now ready to print all the information. If the user */ 3014 /* has specified zero-level verbosity, we will just print the */ 3015 /* local service demand, or the remote service demand. If the */ 3016 /* user has requested verbosity level 1, he will get the basic */ 3017 /* "streamperf" numbers. If the user has specified a verbosity */ 3018 /* of greater than 1, we will display a veritable plethora of */ 3019 /* background information from outside of this block as it it */ 3020 /* not cpu_measurement specific... */ 3021 3022 if (confidence < 0) { 3023 /* we did not hit confidence, but were we asked to look for it? */ 3024 if (iteration_max > 1) { 3025 display_confidence(); 3026 } 3027 } 3028 3029 if (local_cpu_usage || remote_cpu_usage) { 3030 local_cpu_method = format_cpu_method(cpu_method); 3031 remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method); 3032 3033 switch (verbosity) { 3034 case 0: 3035 if (local_cpu_usage) { 3036 fprintf(where, 3037 cpu_fmt_0, 3038 local_service_demand, 3039 local_cpu_method, 3040 ((print_headers) || 3041 (result_brand == NULL)) ? "" : result_brand); 3042 } 3043 else { 3044 fprintf(where, 3045 cpu_fmt_0, 3046 remote_service_demand, 3047 remote_cpu_method, 3048 ((print_headers) || 3049 (result_brand == NULL)) ? "" : result_brand); 3050 } 3051 break; 3052 case 1: 3053 case 2: 3054 if (print_headers) { 3055 fprintf(where, 3056 cpu_title, 3057 format_units(), 3058 local_cpu_method, 3059 remote_cpu_method); 3060 } 3061 3062 fprintf(where, 3063 cpu_fmt_1, /* the format string */ 3064 rsr_size, /* remote recvbuf size */ 3065 lss_size, /* local sendbuf size */ 3066 send_size, /* how large were the recvs */ 3067 elapsed_time, /* how long was the test */ 3068 thruput, /* what was the xfer rate */ 3069 local_cpu_utilization, /* local cpu */ 3070 remote_cpu_utilization, /* remote cpu */ 3071 local_service_demand, /* local service demand */ 3072 remote_service_demand, /* remote service demand */ 3073 ((print_headers) || 3074 (result_brand == NULL)) ? "" : result_brand); 3075 break; 3076 } 3077 } 3078 else { 3079 /* The tester did not wish to measure service demand. */ 3080 3081 switch (verbosity) { 3082 case 0: 3083 fprintf(where, 3084 tput_fmt_0, 3085 thruput, 3086 ((print_headers) || 3087 (result_brand == NULL)) ? "" : result_brand); 3088 break; 3089 case 1: 3090 case 2: 3091 if (print_headers) { 3092 fprintf(where,tput_title,format_units()); 3093 } 3094 fprintf(where, 3095 tput_fmt_1, /* the format string */ 3096 lsr_size, /* local recvbuf size */ 3097 rss_size, /* remot sendbuf size */ 3098 send_size, /* how large were the recvs */ 3099 elapsed_time, /* how long did it take */ 3100 thruput, /* how fast did it go */ 3101 ((print_headers) || 3102 (result_brand == NULL)) ? "" : result_brand); 3103 break; 3104 } 3105 } 3106 3107 /* it would be a good thing to include information about some of the */ 3108 /* other parameters that may have been set for this test, but at the */ 3109 /* moment, I do not wish to figure-out all the formatting, so I will */ 3110 /* just put this comment here to help remind me that it is something */ 3111 /* that should be done at a later time. */ 3112 3113 if (verbosity > 1) { 3114 /* The user wanted to know it all, so we will give it to him. */ 3115 /* This information will include as much as we can find about */ 3116 /* TCP statistics, the alignments of the sends and receives */ 3117 /* and all that sort of rot... */ 3118 3119 /* this stuff needs to be worked-out in the presence of confidence */ 3120 /* intervals and multiple iterations of the test... raj 11/94 */ 3121 3122 fprintf(where, 3123 ksink_fmt, 3124 "Bytes", 3125 "Bytes", 3126 "Bytes", 3127 local_recv_align, 3128 remote_recv_align, 3129 local_recv_offset, 3130 remote_recv_offset, 3131 bytes_sent, 3132 bytes_sent / (double)nummessages, 3133 nummessages, 3134 bytes_sent / (double)tcp_maerts_result->send_calls, 3135 tcp_maerts_result->send_calls); 3136 fprintf(where, 3137 ksink_fmt2, 3138 tcp_mss); 3139 fflush(where); 3140 #ifdef WANT_HISTOGRAM 3141 fprintf(where,"\n\nHistogram of time spent in recv() call.\n"); 3142 fflush(where); 3143 HIST_report(time_hist); 3144 #endif /* WANT_HISTOGRAM */ 3145 } 3146 3147 } 3148 #endif /* WANT_MIGRATION */ 3149 3150 3152 /* this routine implements the TCP_MSS test. All it does is pretend 3153 to be a TCP_STREAM test and report the TCP_MSS for the data 3154 connection. No actual data is transferred. raj 2007-11-07 3155 */ 3156 void 3157 send_tcp_mss(char remote_host[]) 3158 { 3159 3160 char *mss_title = "\ 3161 Maximum\n\ 3162 Segment\n\ 3163 Size (bytes)\n\n"; 3164 3165 char *mss_fmt_0 = 3166 "%d %s\n"; 3167 3168 SOCKET send_socket; 3169 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 3170 3171 struct addrinfo *remote_res; 3172 struct addrinfo *local_res; 3173 3174 struct tcp_stream_request_struct *tcp_stream_request; 3175 struct tcp_stream_response_struct *tcp_stream_response; 3176 struct tcp_stream_results_struct *tcp_stream_result; 3177 3178 tcp_stream_request = 3179 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 3180 tcp_stream_response = 3181 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 3182 tcp_stream_result = 3183 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 3184 3185 /* since we are now disconnected from the code that established the */ 3186 /* control socket, and since we want to be able to use different */ 3187 /* protocols and such, we are passed the name of the remote host and */ 3188 /* must turn that into the test specific addressing information. */ 3189 3190 /* complete_addrinfos will either succede or exit the process */ 3191 complete_addrinfos(&remote_res, 3192 &local_res, 3193 remote_host, 3194 SOCK_STREAM, 3195 IPPROTO_TCP, 3196 0); 3197 3198 if ( print_headers ) { 3199 print_top_test_header("TCP MSS TEST",local_res,remote_res); 3200 } 3201 3202 /*set up the data socket */ 3203 send_socket = create_data_socket(local_res); 3204 3205 if (send_socket == INVALID_SOCKET){ 3206 perror("netperf: send_tcp_stream: tcp stream data socket"); 3207 exit(1); 3208 } 3209 3210 if (debug) { 3211 fprintf(where,"send_tcp_stream: send_socket obtained...\n"); 3212 } 3213 3214 3215 if (!no_control) { 3216 /* Tell the remote end to do a listen. The server alters the 3217 socket paramters on the other side at this point, hence the 3218 reason for all the values being passed in the setup 3219 message. If the user did not specify any of the parameters, 3220 they will be passed as 0, which will indicate to the remote 3221 that no changes beyond the system's default should be 3222 used. Alignment is the exception, it will default to 1, which 3223 will be no alignment alterations. */ 3224 3225 netperf_request.content.request_type = DO_TCP_STREAM; 3226 tcp_stream_request->send_buf_size = rss_size_req; 3227 tcp_stream_request->recv_buf_size = rsr_size_req; 3228 tcp_stream_request->receive_size = recv_size; 3229 tcp_stream_request->no_delay = rem_nodelay; 3230 tcp_stream_request->recv_alignment = remote_recv_align; 3231 tcp_stream_request->recv_offset = remote_recv_offset; 3232 tcp_stream_request->measure_cpu = remote_cpu_usage; 3233 tcp_stream_request->cpu_rate = remote_cpu_rate; 3234 if (test_time) { 3235 tcp_stream_request->test_length = test_time; 3236 } 3237 else { 3238 tcp_stream_request->test_length = test_bytes; 3239 } 3240 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 3241 tcp_stream_request->so_sndavoid = rem_sndavoid; 3242 #ifdef DIRTY 3243 tcp_stream_request->dirty_count = rem_dirty_count; 3244 tcp_stream_request->clean_count = rem_clean_count; 3245 #endif /* DIRTY */ 3246 tcp_stream_request->port = atoi(remote_data_port); 3247 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 3248 if (debug > 1) { 3249 fprintf(where, 3250 "netperf: send_tcp_mss: requesting TCP stream test\n"); 3251 } 3252 3253 send_request(); 3254 3255 /* The response from the remote will contain all of the relevant 3256 socket parameters for this test type. We will put them back 3257 into the variables here so they can be displayed if desired. 3258 The remote will have calibrated CPU if necessary, and will 3259 have done all the needed set-up we will have calibrated the 3260 cpu locally before sending the request, and will grab the 3261 counter value right after the connect returns. The remote 3262 will grab the counter right after the accept call. This saves 3263 the hassle of extra messages being sent for the TCP 3264 tests. */ 3265 3266 recv_response(); 3267 3268 if (!netperf_response.content.serv_errno) { 3269 if (debug) 3270 fprintf(where,"remote listen done.\n"); 3271 rsr_size = tcp_stream_response->recv_buf_size; 3272 rss_size = tcp_stream_response->send_buf_size; 3273 rem_nodelay = tcp_stream_response->no_delay; 3274 remote_cpu_usage= tcp_stream_response->measure_cpu; 3275 remote_cpu_rate = tcp_stream_response->cpu_rate; 3276 3277 /* we have to make sure that the server port number is in 3278 network order */ 3279 set_port_number(remote_res, 3280 (short)tcp_stream_response->data_port_number); 3281 3282 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 3283 rem_sndavoid = tcp_stream_response->so_sndavoid; 3284 } 3285 else { 3286 Set_errno(netperf_response.content.serv_errno); 3287 fprintf(where, 3288 "netperf: remote error %d", 3289 netperf_response.content.serv_errno); 3290 perror(""); 3291 fflush(where); 3292 3293 exit(1); 3294 } 3295 } 3296 3297 /*Connect up to the remote port on the data socket */ 3298 if (connect(send_socket, 3299 remote_res->ai_addr, 3300 remote_res->ai_addrlen) == INVALID_SOCKET){ 3301 perror("netperf: send_tcp_mss: data socket connect failed"); 3302 exit(1); 3303 } 3304 3305 3306 /* find-out what the TCP maximum segment_size was (if possible) */ 3307 tcp_mss = -1; 3308 get_tcp_info(send_socket,&tcp_mss); 3309 3310 /* just go ahead and close the socket, the remote should figure it 3311 out */ 3312 close(send_socket); 3313 3314 /* statistics? we don't need no stinking statistics */ 3315 3316 3317 switch (verbosity) { 3318 case 0: 3319 fprintf(where, 3320 mss_fmt_0, 3321 tcp_mss, 3322 ((print_headers) || 3323 (result_brand == NULL)) ? "" : result_brand); 3324 break; 3325 case 1: 3326 case 2: 3327 if (print_headers) { 3328 fprintf(where,"%s",mss_title); 3329 } 3330 fprintf(where, 3331 mss_fmt_0, /* the format string */ 3332 tcp_mss, 3333 ((print_headers) || 3334 (result_brand == NULL)) ? "" : result_brand); 3335 break; 3336 } 3337 3338 3339 } 3340 3341 3342 3344 #ifdef HAVE_ICSC_EXS 3345 3346 #include <sys/exs.h> 3347 3348 3349 /* This routine implements the TCP unidirectional data transfer test */ 3350 /* (a.k.a. stream) for the sockets interface. It receives its */ 3351 /* parameters via global variables from the shell and writes its */ 3352 /* output to the standard output. */ 3353 3354 void 3355 send_exs_tcp_stream(char remote_host[]) 3356 { 3357 3358 char *tput_title = "\ 3359 Recv Send Send \n\ 3360 Socket Socket Message Elapsed \n\ 3361 Size Size Size Time Throughput \n\ 3362 bytes bytes bytes secs. %s/sec \n\n"; 3363 3364 char *tput_fmt_0 = 3365 "%7.2f\n"; 3366 3367 char *tput_fmt_1 = 3368 "%6d %6d %6d %-6.2f %7.2f \n"; 3369 3370 char *cpu_title = "\ 3371 Recv Send Send Utilization Service Demand\n\ 3372 Socket Socket Message Elapsed Send Recv Send Recv\n\ 3373 Size Size Size Time Throughput local remote local remote\n\ 3374 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 3375 3376 char *cpu_fmt_0 = 3377 "%6.3f %c\n"; 3378 3379 char *cpu_fmt_1 = 3380 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 3381 3382 char *ksink_fmt = "\n\ 3383 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 3384 Local Remote Local Remote Xfered Per Per\n\ 3385 Send Recv Send Recv Send (avg) Recv (avg)\n\ 3386 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 3387 3388 char *ksink_fmt2 = "\n\ 3389 Maximum\n\ 3390 Segment\n\ 3391 Size (bytes)\n\ 3392 %6d\n"; 3393 3394 3395 float elapsed_time; 3396 3397 /* what we want is to have a buffer space that is at least one */ 3398 /* send-size greater than our send window. this will insure that we */ 3399 /* are never trying to re-use a buffer that may still be in the hands */ 3400 /* of the transport. This buffer will be malloc'd after we have found */ 3401 /* the size of the local senc socket buffer. We will want to deal */ 3402 /* with alignment and offset concerns as well. */ 3403 3404 struct ring_elt *send_ring; 3405 3406 int len; 3407 unsigned int nummessages = 0; 3408 SOCKET send_socket; 3409 int bytes_remaining; 3410 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 3411 3412 exs_mhandle_t exs_mhandle; 3413 exs_qhandle_t exs_qhandle; 3414 #define NETPERF_EXS_PENDING 16 3415 int exs_aio_pending; 3416 int exs_aio_eagain; 3417 int exs_aio_dequeued; 3418 int exs_aio_dequeuecnt; 3419 int exs_evtcnt; 3420 #define NETPERF_EXS_QSIZE 128 3421 exs_event_t exs_evtvec[NETPERF_EXS_QSIZE]; 3422 3423 /* with links like fddi, one can send > 32 bits worth of bytes */ 3424 /* during a test... ;-) at some point, this should probably become a */ 3425 /* 64bit integral type, but those are not entirely common yet */ 3426 3427 double bytes_sent = 0.0; 3428 3429 float local_cpu_utilization; 3430 float local_service_demand; 3431 float remote_cpu_utilization; 3432 float remote_service_demand; 3433 3434 double thruput; 3435 3436 struct addrinfo *remote_res; 3437 struct addrinfo *local_res; 3438 3439 struct tcp_stream_request_struct *tcp_stream_request; 3440 struct tcp_stream_response_struct *tcp_stream_response; 3441 struct tcp_stream_results_struct *tcp_stream_result; 3442 3443 tcp_stream_request = 3444 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 3445 tcp_stream_response = 3446 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 3447 tcp_stream_result = 3448 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 3449 3450 #if 0 /* def WANT_HISTOGRAM */ 3451 time_hist = HIST_new(); 3452 #endif /* WANT_HISTOGRAM */ 3453 /* since we are now disconnected from the code that established the */ 3454 /* control socket, and since we want to be able to use different */ 3455 /* protocols and such, we are passed the name of the remote host and */ 3456 /* must turn that into the test specific addressing information. */ 3457 3458 /* complete_addrinfos will either succede or exit the process */ 3459 complete_addrinfos(&remote_res, 3460 &local_res, 3461 remote_host, 3462 SOCK_STREAM, 3463 IPPROTO_TCP, 3464 0); 3465 3466 if ( print_headers ) { 3467 print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res); 3468 } 3469 3470 send_ring = NULL; 3471 confidence_iteration = 1; 3472 init_stat(); 3473 3474 /* initialize EXS API and create event queue */ 3475 if (exs_init (EXS_VERSION) == -1) { 3476 perror ("netperf: send_exs_tcp_stream: exs_init failed"); 3477 exit (1); 3478 } 3479 3480 if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) { 3481 perror ("netperf: send_exs_tcp_stream: exs_qcreate failed"); 3482 exit (1); 3483 } 3484 if (debug) { 3485 fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle); 3486 } 3487 3488 /* we have a great-big while loop which controls the number of times */ 3489 /* we run a particular test. this is for the calculation of a */ 3490 /* confidence interval (I really should have stayed awake during */ 3491 /* probstats :). If the user did not request confidence measurement */ 3492 /* (no confidence is the default) then we will only go though the */ 3493 /* loop once. the confidence stuff originates from the folks at IBM */ 3494 3495 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 3496 (confidence_iteration <= iteration_min)) { 3497 3498 /* initialize a few counters. we have to remember that we might be */ 3499 /* going through the loop more than once. */ 3500 3501 nummessages = 0; 3502 bytes_sent = 0.0; 3503 times_up = 0; 3504 3505 /*set up the data socket */ 3506 send_socket = create_data_socket(local_res); 3507 3508 if (send_socket == INVALID_SOCKET){ 3509 perror("netperf: send_tcp_stream: tcp stream data socket"); 3510 exit(1); 3511 } 3512 3513 if (debug) { 3514 fprintf(where,"send_tcp_stream: send_socket obtained...\n"); 3515 } 3516 3517 /* at this point, we have either retrieved the socket buffer sizes, */ 3518 /* or have tried to set them, so now, we may want to set the send */ 3519 /* size based on that (because the user either did not use a -m */ 3520 /* option, or used one with an argument of 0). If the socket buffer */ 3521 /* size is not available, we will set the send size to 4KB - no */ 3522 /* particular reason, just arbitrary... */ 3523 if (send_size == 0) { 3524 if (lss_size > 0) { 3525 send_size = lss_size; 3526 } 3527 else { 3528 send_size = 4096; 3529 } 3530 } 3531 3532 /* set-up the data buffer ring with the requested alignment and offset. */ 3533 /* note also that we have allocated a quantity */ 3534 /* of memory that is at least one send-size greater than our socket */ 3535 /* buffer size. We want to be sure that there are at least two */ 3536 /* buffers allocated - this can be a bit of a problem when the */ 3537 /* send_size is bigger than the socket size, so we must check... the */ 3538 /* user may have wanted to explicitly set the "width" of our send */ 3539 /* buffers, we should respect that wish... */ 3540 if (send_width == 0) { 3541 send_width = (lss_size/send_size) + 1; 3542 if (send_width == 1) send_width++; 3543 } 3544 3545 if (send_ring == NULL) { 3546 /* only allocate the send ring once. this is a networking test, */ 3547 /* not a memory allocation test. this way, we do not need a */ 3548 /* deallocate_buffer_ring() routine, and I don't feel like */ 3549 /* writing one anyway :) raj 11/94 */ 3550 send_ring = allocate_exs_buffer_ring(send_width, 3551 send_size, 3552 local_send_align, 3553 local_send_offset, 3554 &exs_mhandle); 3555 } 3556 3557 /* If the user has requested cpu utilization measurements, we must */ 3558 /* calibrate the cpu(s). We will perform this task within the tests */ 3559 /* themselves. If the user has specified the cpu rate, then */ 3560 /* calibrate_local_cpu will return rather quickly as it will have */ 3561 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 3562 /* all the "normal" calibration stuff and return the rate back. */ 3563 3564 if (local_cpu_usage) { 3565 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 3566 } 3567 3568 /* Tell the remote end to do a listen. The server alters the socket */ 3569 /* paramters on the other side at this point, hence the reason for */ 3570 /* all the values being passed in the setup message. If the user did */ 3571 /* not specify any of the parameters, they will be passed as 0, which */ 3572 /* will indicate to the remote that no changes beyond the system's */ 3573 /* default should be used. Alignment is the exception, it will */ 3574 /* default to 1, which will be no alignment alterations. */ 3575 3576 netperf_request.content.request_type = DO_TCP_STREAM; 3577 tcp_stream_request->send_buf_size = rss_size_req; 3578 tcp_stream_request->recv_buf_size = rsr_size_req; 3579 tcp_stream_request->receive_size = recv_size; 3580 tcp_stream_request->no_delay = rem_nodelay; 3581 tcp_stream_request->recv_alignment = remote_recv_align; 3582 tcp_stream_request->recv_offset = remote_recv_offset; 3583 tcp_stream_request->measure_cpu = remote_cpu_usage; 3584 tcp_stream_request->cpu_rate = remote_cpu_rate; 3585 if (test_time) { 3586 tcp_stream_request->test_length = test_time; 3587 } 3588 else { 3589 tcp_stream_request->test_length = test_bytes; 3590 } 3591 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 3592 tcp_stream_request->so_sndavoid = rem_sndavoid; 3593 #ifdef DIRTY 3594 tcp_stream_request->dirty_count = rem_dirty_count; 3595 tcp_stream_request->clean_count = rem_clean_count; 3596 #endif /* DIRTY */ 3597 tcp_stream_request->port = atoi(remote_data_port); 3598 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 3599 if (debug > 1) { 3600 fprintf(where, 3601 "netperf: send_tcp_stream: requesting TCP stream test\n"); 3602 } 3603 3604 send_request(); 3605 3606 /* The response from the remote will contain all of the relevant */ 3607 /* socket parameters for this test type. We will put them back into */ 3608 /* the variables here so they can be displayed if desired. The */ 3609 /* remote will have calibrated CPU if necessary, and will have done */ 3610 /* all the needed set-up we will have calibrated the cpu locally */ 3611 /* before sending the request, and will grab the counter value right*/ 3612 /* after the connect returns. The remote will grab the counter right*/ 3613 /* after the accept call. This saves the hassle of extra messages */ 3614 /* being sent for the TCP tests. */ 3615 3616 recv_response(); 3617 3618 if (!netperf_response.content.serv_errno) { 3619 if (debug) 3620 fprintf(where,"remote listen done.\n"); 3621 rsr_size = tcp_stream_response->recv_buf_size; 3622 rss_size = tcp_stream_response->send_buf_size; 3623 rem_nodelay = tcp_stream_response->no_delay; 3624 remote_cpu_usage= tcp_stream_response->measure_cpu; 3625 remote_cpu_rate = tcp_stream_response->cpu_rate; 3626 3627 /* we have to make sure that the server port number is in */ 3628 /* network order */ 3629 set_port_number(remote_res,(short)tcp_stream_response->data_port_number); 3630 3631 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 3632 rem_sndavoid = tcp_stream_response->so_sndavoid; 3633 } 3634 else { 3635 Set_errno(netperf_response.content.serv_errno); 3636 fprintf(where, 3637 "netperf: remote error %d", 3638 netperf_response.content.serv_errno); 3639 perror(""); 3640 fflush(where); 3641 3642 exit(1); 3643 } 3644 3645 #if 0 /* def WANT_DEMO */ 3646 demo_stream_setup(lss_size,rsr_size); 3647 #endif 3648 3649 /*Connect up to the remote port on the data socket */ 3650 if (connect(send_socket, 3651 remote_res->ai_addr, 3652 remote_res->ai_addrlen) == INVALID_SOCKET){ 3653 perror("netperf: send_tcp_stream: data socket connect failed"); 3654 exit(1); 3655 } 3656 3657 #ifdef WIN32 3658 /* this is used so the timer thread can close the socket out from */ 3659 /* under us, which to date is the easiest/cleanest/least */ 3660 /* Windows-specific way I can find to force the winsock calls to */ 3661 /* return WSAEINTR with the test is over. anything that will run on */ 3662 /* 95 and NT and is closer to what netperf expects from Unix signals */ 3663 /* and such would be appreciated raj 1/96 */ 3664 win_kludge_socket = send_socket; 3665 #endif /* WIN32 */ 3666 3667 /* Data Socket set-up is finished. If there were problems, either */ 3668 /* the connect would have failed, or the previous response would */ 3669 /* have indicated a problem. I failed to see the value of the */ 3670 /* extra message after the accept on the remote. If it failed, */ 3671 /* we'll see it here. If it didn't, we might as well start pumping */ 3672 /* data. */ 3673 3674 /* Set-up the test end conditions. For a stream test, they can be */ 3675 /* either time or byte-count based. */ 3676 3677 if (test_time) { 3678 /* The user wanted to end the test after a period of time. */ 3679 times_up = 0; 3680 bytes_remaining = 0; 3681 /* in previous revisions, we had the same code repeated throught */ 3682 /* all the test suites. this was unnecessary, and meant more */ 3683 /* work for me when I wanted to switch to POSIX signals, so I */ 3684 /* have abstracted this out into a routine in netlib.c. if you */ 3685 /* are experiencing signal problems, you might want to look */ 3686 /* there. raj 11/94 */ 3687 start_timer(test_time); 3688 } 3689 else { 3690 /* The tester wanted to send a number of bytes. */ 3691 bytes_remaining = test_bytes; 3692 times_up = 1; 3693 } 3694 3695 /* The cpu_start routine will grab the current time and possibly */ 3696 /* value of the idle counter for later use in measuring cpu */ 3697 /* utilization and/or service demand and thruput. */ 3698 3699 cpu_start(local_cpu_usage); 3700 3701 #if 0 /* def WANT_INTERVALS */ 3702 INTERVALS_INIT(); 3703 #endif /* WANT_INTERVALS */ 3704 3705 /* before we start, initialize a few variables */ 3706 3707 #if 0 /* def WANT_DEMO */ 3708 if (demo_mode) { 3709 demo_first_timestamp(); 3710 } 3711 #endif 3712 3713 3714 /* We use an "OR" to control test execution. When the test is */ 3715 /* controlled by time, the byte count check will always return false. */ 3716 /* When the test is controlled by byte count, the time test will */ 3717 /* always return false. When the test is finished, the whole */ 3718 /* expression will go false and we will stop sending data. */ 3719 3720 exs_aio_pending = 0; 3721 exs_aio_eagain = 0; 3722 exs_aio_dequeuecnt = 0; 3723 3724 while ((!times_up) || (bytes_remaining > 0)) { 3725 3726 #ifdef DIRTY 3727 access_buffer(send_ring->buffer_ptr, 3728 send_size, 3729 loc_dirty_count, 3730 loc_clean_count); 3731 #endif /* DIRTY */ 3732 3733 #if 0 /* def WANT_HISTOGRAM */ 3734 /* timestamp just before we go into send and then again just after */ 3735 /* we come out raj 8/94 */ 3736 HIST_timestamp(&time_one); 3737 #endif /* WANT_HISTOGRAM */ 3738 3739 3740 /* post up to NETPERF_EXS_PENDING I/Os */ 3741 while ((exs_aio_pending < NETPERF_EXS_PENDING) && 3742 (exs_send (send_socket, send_ring->buffer_ptr, send_size, 3743 0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) { 3744 exs_aio_pending++; 3745 3746 /* now we want to move our pointer to the next 3747 position in the data buffer...we may also want to 3748 wrap back to the "beginning" of the bufferspace, so 3749 we will mod the number of messages sent by the send 3750 width, and use that to calculate the offset to add 3751 to the base pointer. */ 3752 3753 nummessages++; 3754 send_ring = send_ring->next; 3755 if (bytes_remaining) { 3756 bytes_remaining -= send_size; 3757 } 3758 } 3759 3760 /* check exs_send result */ 3761 if (exs_aio_pending < NETPERF_EXS_PENDING) { 3762 /* standard flow control case */ 3763 if (errno == EAGAIN) 3764 exs_aio_eagain++; 3765 /* case of times_up */ 3766 else if (errno == EINTR) 3767 break; 3768 /* strange, let's stop */ 3769 else { 3770 perror ("netperf: exs_send error"); 3771 exit (1); 3772 } 3773 } 3774 3775 /* dequeue events with "threshold" on 1/2 posted */ 3776 exs_aio_dequeued = 3777 exs_qdequeue (exs_qhandle, exs_evtvec, 3778 -(exs_aio_pending>>1), NULL); 3779 exs_aio_dequeuecnt++; 3780 3781 /* check exs_dequeue result */ 3782 if (exs_aio_dequeued < 0) { 3783 /* case of times_up */ 3784 if (errno == EINTR) 3785 break; 3786 /* strange, let's stop */ 3787 else { 3788 perror ("netperf: exs_send error"); 3789 exit (1); 3790 } 3791 } 3792 /* update number of pending I/Os */ 3793 else { 3794 exs_aio_pending -= exs_aio_dequeued; 3795 } 3796 3797 3798 #if 0 /* def WANT_HISTOGRAM */ 3799 /* timestamp the exit from the send call and update the histogram */ 3800 HIST_timestamp(&time_two); 3801 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 3802 #endif /* WANT_HISTOGRAM */ 3803 3804 #if 0 /* def WANT_DEMO */ 3805 demo_stream_interval(send_size); 3806 #endif 3807 3808 #if 0 /* def WANT_INTERVALS */ 3809 INTERVALS_WAIT(); 3810 #endif /* WANT_INTERVALS */ 3811 3812 } 3813 3814 /* Collect the last completion events */ 3815 exs_aio_dequeued = 3816 exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL); 3817 exs_aio_dequeuecnt++; 3818 /* check exs_dequeue result and update number of pending I/Os */ 3819 if (exs_aio_dequeued < 0) { 3820 perror ("netperf: exs_send error"); 3821 exit (1); 3822 } 3823 exs_aio_pending -= exs_aio_dequeued; 3824 3825 /* Display some async I/O debug info */ 3826 if (debug) { 3827 fprintf (where, "send_exs_tcp_stream: " 3828 "aio sent=%d eagain=%d dequeue=%d pending=%d\n", 3829 nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending); 3830 } 3831 3832 /* The test is over. Flush the buffers to the remote end. We do a */ 3833 /* graceful release to insure that all data has been taken by the */ 3834 /* remote. */ 3835 3836 /* but first, if the verbosity is greater than 1, find-out what */ 3837 /* the TCP maximum segment_size was (if possible) */ 3838 if (verbosity > 1) { 3839 tcp_mss = -1; 3840 get_tcp_info(send_socket,&tcp_mss); 3841 } 3842 3843 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 3844 perror("netperf: cannot shutdown tcp stream socket"); 3845 exit(1); 3846 } 3847 3848 /* hang a recv() off the socket to block until the remote has */ 3849 /* brought all the data up into the application. it will do a */ 3850 /* shutdown to cause a FIN to be sent our way. We will assume that */ 3851 /* any exit from the recv() call is good... raj 4/93 */ 3852 3853 recv(send_socket, send_ring->buffer_ptr, send_size, 0); 3854 3855 /* this call will always give us the elapsed time for the test, and */ 3856 /* will also store-away the necessaries for cpu utilization */ 3857 3858 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 3859 /* measured and how */ 3860 /* long did we really */ 3861 /* run? */ 3862 3863 /* we are finished with the socket, so close it to prevent hitting */ 3864 /* the limit on maximum open files. */ 3865 3866 close(send_socket); 3867 3868 /* Get the statistics from the remote end. The remote will have */ 3869 /* calculated service demand and all those interesting things. If it */ 3870 /* wasn't supposed to care, it will return obvious values. */ 3871 3872 recv_response(); 3873 if (!netperf_response.content.serv_errno) { 3874 if (debug) 3875 fprintf(where,"remote results obtained\n"); 3876 } 3877 else { 3878 Set_errno(netperf_response.content.serv_errno); 3879 fprintf(where, 3880 "netperf: remote error %d", 3881 netperf_response.content.serv_errno); 3882 perror(""); 3883 fflush(where); 3884 3885 exit(1); 3886 } 3887 3888 /* We now calculate what our thruput was for the test. In the future, */ 3889 /* we may want to include a calculation of the thruput measured by */ 3890 /* the remote, but it should be the case that for a TCP stream test, */ 3891 /* that the two numbers should be *very* close... We calculate */ 3892 /* bytes_sent regardless of the way the test length was controlled. */ 3893 /* If it was time, we needed to, and if it was by bytes, the user may */ 3894 /* have specified a number of bytes that wasn't a multiple of the */ 3895 /* send_size, so we really didn't send what he asked for ;-) */ 3896 3897 bytes_sent = ntohd(tcp_stream_result->bytes_received); 3898 3899 thruput = calc_thruput(bytes_sent); 3900 3901 if (local_cpu_usage || remote_cpu_usage) { 3902 /* We must now do a little math for service demand and cpu */ 3903 /* utilization for the system(s) */ 3904 /* Of course, some of the information might be bogus because */ 3905 /* there was no idle counter in the kernel(s). We need to make */ 3906 /* a note of this for the user's benefit...*/ 3907 if (local_cpu_usage) { 3908 3909 local_cpu_utilization = calc_cpu_util(0.0); 3910 local_service_demand = calc_service_demand(bytes_sent, 3911 0.0, 3912 0.0, 3913 0); 3914 } 3915 else { 3916 local_cpu_utilization = (float) -1.0; 3917 local_service_demand = (float) -1.0; 3918 } 3919 3920 if (remote_cpu_usage) { 3921 3922 remote_cpu_utilization = tcp_stream_result->cpu_util; 3923 remote_service_demand = calc_service_demand(bytes_sent, 3924 0.0, 3925 remote_cpu_utilization, 3926 tcp_stream_result->num_cpus); 3927 } 3928 else { 3929 remote_cpu_utilization = (float) -1.0; 3930 remote_service_demand = (float) -1.0; 3931 } 3932 } 3933 else { 3934 /* we were not measuring cpu, for the confidence stuff, we */ 3935 /* should make it -1.0 */ 3936 local_cpu_utilization = (float) -1.0; 3937 local_service_demand = (float) -1.0; 3938 remote_cpu_utilization = (float) -1.0; 3939 remote_service_demand = (float) -1.0; 3940 } 3941 3942 /* at this point, we want to calculate the confidence information. */ 3943 /* if debugging is on, calculate_confidence will print-out the */ 3944 /* parameters we pass it */ 3945 3946 calculate_confidence(confidence_iteration, 3947 elapsed_time, 3948 thruput, 3949 local_cpu_utilization, 3950 remote_cpu_utilization, 3951 local_service_demand, 3952 remote_service_demand); 3953 3954 3955 confidence_iteration++; 3956 } 3957 3958 /* at this point, we have finished making all the runs that we */ 3959 /* will be making. so, we should extract what the calcuated values */ 3960 /* are for all the confidence stuff. we could make the values */ 3961 /* global, but that seemed a little messy, and it did not seem worth */ 3962 /* all the mucking with header files. so, we create a routine much */ 3963 /* like calcualte_confidence, which just returns the mean values. */ 3964 /* raj 11/94 */ 3965 3966 retrieve_confident_values(&elapsed_time, 3967 &thruput, 3968 &local_cpu_utilization, 3969 &remote_cpu_utilization, 3970 &local_service_demand, 3971 &remote_service_demand); 3972 3973 /* We are now ready to print all the information. If the user */ 3974 /* has specified zero-level verbosity, we will just print the */ 3975 /* local service demand, or the remote service demand. If the */ 3976 /* user has requested verbosity level 1, he will get the basic */ 3977 /* "streamperf" numbers. If the user has specified a verbosity */ 3978 /* of greater than 1, we will display a veritable plethora of */ 3979 /* background information from outside of this block as it it */ 3980 /* not cpu_measurement specific... */ 3981 3982 if (confidence < 0) { 3983 /* we did not hit confidence, but were we asked to look for it? */ 3984 if (iteration_max > 1) { 3985 display_confidence(); 3986 } 3987 } 3988 3989 if (local_cpu_usage || remote_cpu_usage) { 3990 local_cpu_method = format_cpu_method(cpu_method); 3991 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 3992 3993 switch (verbosity) { 3994 case 0: 3995 if (local_cpu_usage) { 3996 fprintf(where, 3997 cpu_fmt_0, 3998 local_service_demand, 3999 local_cpu_method); 4000 } 4001 else { 4002 fprintf(where, 4003 cpu_fmt_0, 4004 remote_service_demand, 4005 remote_cpu_method); 4006 } 4007 break; 4008 case 1: 4009 case 2: 4010 if (print_headers) { 4011 fprintf(where, 4012 cpu_title, 4013 format_units(), 4014 local_cpu_method, 4015 remote_cpu_method); 4016 } 4017 4018 fprintf(where, 4019 cpu_fmt_1, /* the format string */ 4020 rsr_size, /* remote recvbuf size */ 4021 lss_size, /* local sendbuf size */ 4022 send_size, /* how large were the sends */ 4023 elapsed_time, /* how long was the test */ 4024 thruput, /* what was the xfer rate */ 4025 local_cpu_utilization, /* local cpu */ 4026 remote_cpu_utilization, /* remote cpu */ 4027 local_service_demand, /* local service demand */ 4028 remote_service_demand); /* remote service demand */ 4029 break; 4030 } 4031 } 4032 else { 4033 /* The tester did not wish to measure service demand. */ 4034 4035 switch (verbosity) { 4036 case 0: 4037 fprintf(where, 4038 tput_fmt_0, 4039 thruput); 4040 break; 4041 case 1: 4042 case 2: 4043 if (print_headers) { 4044 fprintf(where,tput_title,format_units()); 4045 } 4046 fprintf(where, 4047 tput_fmt_1, /* the format string */ 4048 rsr_size, /* remote recvbuf size */ 4049 lss_size, /* local sendbuf size */ 4050 send_size, /* how large were the sends */ 4051 elapsed_time, /* how long did it take */ 4052 thruput);/* how fast did it go */ 4053 break; 4054 } 4055 } 4056 4057 /* it would be a good thing to include information about some of the */ 4058 /* other parameters that may have been set for this test, but at the */ 4059 /* moment, I do not wish to figure-out all the formatting, so I will */ 4060 /* just put this comment here to help remind me that it is something */ 4061 /* that should be done at a later time. */ 4062 4063 if (verbosity > 1) { 4064 /* The user wanted to know it all, so we will give it to him. */ 4065 /* This information will include as much as we can find about */ 4066 /* TCP statistics, the alignments of the sends and receives */ 4067 /* and all that sort of rot... */ 4068 4069 /* this stuff needs to be worked-out in the presence of confidence */ 4070 /* intervals and multiple iterations of the test... raj 11/94 */ 4071 4072 fprintf(where, 4073 ksink_fmt, 4074 "Bytes", 4075 "Bytes", 4076 "Bytes", 4077 local_send_align, 4078 remote_recv_align, 4079 local_send_offset, 4080 remote_recv_offset, 4081 bytes_sent, 4082 bytes_sent / (double)nummessages, 4083 nummessages, 4084 bytes_sent / (double)tcp_stream_result->recv_calls, 4085 tcp_stream_result->recv_calls); 4086 fprintf(where, 4087 ksink_fmt2, 4088 tcp_mss); 4089 fflush(where); 4090 #if 0 /* def WANT_HISTOGRAM */ 4091 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 4092 fflush(where); 4093 HIST_report(time_hist); 4094 #endif /* WANT_HISTOGRAM */ 4095 } 4096 4097 } 4098 4099 #endif /* HAVE_ICSC_EXS */ 4100 4101 4102 4104 #if defined(HAVE_SENDFILE) 4105 4106 4107 /* This routine implements the TCP unidirectional data transfer test 4108 (a.k.a. stream) for the sockets interface using the sendfile() 4109 system call - TCP_SENDFILE. It receives its parameters via global 4110 variables from the shell and writes its output to the standard 4111 output. Basically, this is the same test as the send_tcp_stream() 4112 logic and we even tell the remote to do a TCP_STREAM test since for 4113 all it knows, nothig is different. */ 4114 4115 void 4116 sendfile_tcp_stream(remote_host) 4117 char remote_host[]; 4118 { 4119 4120 char *tput_title = "\ 4121 Recv Send Send \n\ 4122 Socket Socket Message Elapsed \n\ 4123 Size Size Size Time Throughput \n\ 4124 bytes bytes bytes secs. %s/sec \n\n"; 4125 4126 char *tput_fmt_0 = 4127 "%7.2f %s\n"; 4128 4129 char *tput_fmt_1 = 4130 "%6d %6d %6d %-6.2f %7.2f %s\n"; 4131 4132 char *cpu_title = "\ 4133 Recv Send Send Utilization Service Demand\n\ 4134 Socket Socket Message Elapsed Send Recv Send Recv\n\ 4135 Size Size Size Time Throughput local remote local remote\n\ 4136 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 4137 4138 char *cpu_fmt_0 = 4139 "%6.3f %c %s\n"; 4140 char *cpu_fmt_1 = 4141 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 4142 4143 char *ksink_fmt = "\n\ 4144 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 4145 Local Remote Local Remote Xfered Per Per\n\ 4146 Send Recv Send Recv Send (avg) Recv (avg)\n\ 4147 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 4148 4149 char *ksink_fmt2 = "\n\ 4150 Maximum\n\ 4151 Segment\n\ 4152 Size (bytes)\n\ 4153 %6d\n"; 4154 4155 float elapsed_time; 4156 4157 /* what we want is to have a buffer space that is at least one */ 4158 /* send-size greater than our send window. this will insure that we */ 4159 /* are never trying to re-use a buffer that may still be in the hands */ 4160 /* of the transport. This buffer will be malloc'd after we have found */ 4161 /* the size of the local senc socket buffer. We will want to deal */ 4162 /* with alignment and offset concerns as well. */ 4163 4164 struct ring_elt *send_ring; 4165 4166 int len; 4167 unsigned int nummessages = 0; 4168 SOCKET send_socket; 4169 int bytes_remaining; 4170 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 4171 4172 /* with links like fddi, one can send > 32 bits worth of bytes */ 4173 /* during a test... ;-) at some point, this should probably become a */ 4174 /* 64bit integral type, but those are not entirely common yet */ 4175 double bytes_sent = 0.0; 4176 4177 float local_cpu_utilization; 4178 float local_service_demand; 4179 float remote_cpu_utilization; 4180 float remote_service_demand; 4181 4182 double thruput; 4183 4184 struct addrinfo *remote_res; 4185 struct addrinfo *local_res; 4186 struct sockaddr_in server; 4187 4188 #if defined(__linux) || defined(__sun) 4189 off_t scratch_offset; /* the linux sendfile() call will update 4190 the offset variable, which is 4191 something we do _not_ want to happen 4192 to the value in the send_ring! so, we 4193 have to use a scratch variable. */ 4194 #endif /* __linux || defined(__sun) */ 4195 #if defined (USE_OSX) 4196 off_t scratch_len; /* Darwin 9.x need a value-result parameter */ 4197 #endif 4198 #if defined (__sun) 4199 size_t scratch_len; /* the sun sendfilev() needs a place to 4200 tell us how many bytes were written, 4201 even though it also returns the value */ 4202 sendfilevec_t sv; 4203 #endif /* __sun */ 4204 4205 struct tcp_stream_request_struct *tcp_stream_request; 4206 struct tcp_stream_response_struct *tcp_stream_response; 4207 struct tcp_stream_results_struct *tcp_stream_result; 4208 4209 tcp_stream_request = 4210 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 4211 tcp_stream_response = 4212 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 4213 tcp_stream_result = 4214 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 4215 4216 #ifdef WANT_HISTOGRAM 4217 if (verbosity > 1) { 4218 time_hist = HIST_new(); 4219 } 4220 #endif /* WANT_HISTOGRAM */ 4221 4222 /* since we are now disconnected from the code that established the */ 4223 /* control socket, and since we want to be able to use different */ 4224 /* protocols and such, we are passed the name of the remote host and */ 4225 /* must turn that into the test specific addressing information. */ 4226 4227 bzero((char *)&server, 4228 sizeof(server)); 4229 4230 complete_addrinfos(&remote_res, 4231 &local_res, 4232 remote_host, 4233 SOCK_STREAM, 4234 IPPROTO_TCP, 4235 0); 4236 4237 if ( print_headers ) { 4238 /* we want to have some additional, interesting information in */ 4239 /* the headers. we know some of it here, but not all, so we will */ 4240 /* only print the test title here and will print the results */ 4241 /* titles after the test is finished */ 4242 print_top_test_header("TCP SENDFILE TEST",local_res,remote_res); 4243 } 4244 4245 send_ring = NULL; 4246 confidence_iteration = 1; 4247 init_stat(); 4248 4249 /* we have a great-big while loop which controls the number of times */ 4250 /* we run a particular test. this is for the calculation of a */ 4251 /* confidence interval (I really should have stayed awake during */ 4252 /* probstats :). If the user did not request confidence measurement */ 4253 /* (no confidence is the default) then we will only go though the */ 4254 /* loop once. the confidence stuff originates from the folks at IBM */ 4255 4256 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 4257 (confidence_iteration <= iteration_min)) { 4258 4259 /* initialize a few counters. we have to remember that we might be */ 4260 /* going through the loop more than once. */ 4261 4262 nummessages = 0; 4263 bytes_sent = 0.0; 4264 times_up = 0; 4265 4266 /* set up the data socket */ 4267 send_socket = create_data_socket(local_res); 4268 4269 if (send_socket == INVALID_SOCKET){ 4270 perror("netperf: sendfile_tcp_stream: tcp stream data socket"); 4271 exit(1); 4272 } 4273 4274 if (debug) { 4275 fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n"); 4276 } 4277 4278 #if defined(TCP_CORK) 4279 /* should this even be here?!? */ 4280 if (loc_tcpcork > 0) { 4281 /* the user wishes for us to set TCP_CORK on the socket */ 4282 int one = 1; 4283 if (setsockopt(send_socket, 4284 getprotobyname("tcp")->p_proto, 4285 TCP_CORK, 4286 (char *)&one, 4287 sizeof(one)) == SOCKET_ERROR) { 4288 perror("netperf: sendfile_tcp_stream: tcp_cork"); 4289 exit(1); 4290 } 4291 if (debug) { 4292 fprintf(where,"sendfile_tcp_stream: tcp_cork...\n"); 4293 } 4294 } 4295 4296 #endif /* TCP_CORK */ 4297 4298 /* at this point, we have either retrieved the socket buffer sizes, */ 4299 /* or have tried to set them, so now, we may want to set the send */ 4300 /* size based on that (because the user either did not use a -m */ 4301 /* option, or used one with an argument of 0). If the socket buffer */ 4302 /* size is not available, we will set the send size to 4KB - no */ 4303 /* particular reason, just arbitrary... */ 4304 4305 /*check for file size/ min file size here? create file here/ back out???*/ 4306 4307 if (send_size == 0) { 4308 if (lss_size > 0) { 4309 send_size = lss_size; 4310 } 4311 else { 4312 send_size = 4096; 4313 } 4314 } 4315 4316 /* set-up the data buffer ring with the requested alignment and 4317 offset. note also that we have allocated a quantity of memory 4318 that is at least one send-size greater than our socket buffer 4319 size. We want to be sure that there are at least two buffers 4320 allocated - this can be a bit of a problem when the send_size 4321 is bigger than the socket size, so we must check... the user 4322 may have wanted to explicitly set the "width" of our send 4323 buffers, we should respect that wish... */ 4324 4325 /*sendring -> an offset index that will shift the starting point of the*/ 4326 /*section of the file sent throughout the file*/ 4327 4328 if (send_width == 0) { 4329 send_width = (lss_size/send_size) + 1; 4330 if (send_width == 1) send_width++; 4331 } 4332 4333 if (send_ring == NULL) { 4334 4335 /* only allocate the send ring once. this is a networking test, 4336 not a memory allocation test. this way, we do not need a 4337 deallocate_buffer_ring() routine, and I don't feel like 4338 writing one anyway :) raj 11/94 */ 4339 4340 send_ring = alloc_sendfile_buf_ring(send_width, 4341 send_size, 4342 local_send_align, 4343 local_send_offset); 4344 } 4345 4346 /* If the user has requested cpu utilization measurements, we must 4347 calibrate the cpu(s). We will perform this task within the 4348 tests themselves. If the user has specified the cpu rate, then 4349 calibrate_local_cpu will return rather quickly as it will have 4350 nothing to do. If local_cpu_rate is zero, then we will go 4351 through all the "normal" calibration stuff and return the rate 4352 back. */ 4353 4354 if (local_cpu_usage) { 4355 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 4356 } 4357 4358 /* Tell the remote end to do a listen. The server alters the 4359 socket paramters on the other side at this point, hence the 4360 reason for all the values being passed in the setup 4361 message. If the user did not specify any of the parameters, 4362 they will be passed as 0, which will indicate to the remote 4363 that no changes beyond the system's default should be 4364 used. Alignment is the exception, it will default to 1, which 4365 will be no alignment alterations. */ 4366 4367 netperf_request.content.request_type = DO_TCP_STREAM; 4368 tcp_stream_request->send_buf_size = rss_size_req; 4369 tcp_stream_request->recv_buf_size = rsr_size_req; 4370 tcp_stream_request->receive_size = recv_size; 4371 tcp_stream_request->no_delay = rem_nodelay; 4372 tcp_stream_request->recv_alignment = remote_recv_align; 4373 tcp_stream_request->recv_offset = remote_recv_offset; 4374 tcp_stream_request->measure_cpu = remote_cpu_usage; 4375 tcp_stream_request->cpu_rate = remote_cpu_rate; 4376 4377 if (test_time) { 4378 tcp_stream_request->test_length = test_time; 4379 } 4380 else { 4381 tcp_stream_request->test_length = test_bytes; 4382 } 4383 4384 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 4385 tcp_stream_request->so_sndavoid = rem_sndavoid; 4386 4387 #ifdef DIRTY 4388 tcp_stream_request->dirty_count = rem_dirty_count; 4389 tcp_stream_request->clean_count = rem_clean_count; 4390 #endif /* DIRTY */ 4391 tcp_stream_request->port = atoi(remote_data_port); 4392 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 4393 4394 if (debug > 1) { 4395 fprintf(where, 4396 "netperf: send_tcp_stream: requesting TCP stream test\n"); 4397 } 4398 4399 send_request(); 4400 4401 /* The response from the remote will contain all of the relevant 4402 socket parameters for this test type. We will put them back 4403 into the variables here so they can be displayed if desired. 4404 The remote will have calibrated CPU if necessary, and will have 4405 done all the needed set-up we will have calibrated the cpu 4406 locally before sending the request, and will grab the counter 4407 value right after the connect returns. The remote will grab the 4408 counter right after the accept call. This saves the hassle of 4409 extra messages being sent for the TCP tests. */ 4410 4411 recv_response(); 4412 4413 if (!netperf_response.content.serv_errno) { 4414 if (debug) 4415 fprintf(where,"remote listen done.\n"); 4416 rsr_size = tcp_stream_response->recv_buf_size; 4417 rss_size = tcp_stream_response->send_buf_size; 4418 rem_nodelay = tcp_stream_response->no_delay; 4419 remote_cpu_usage= tcp_stream_response->measure_cpu; 4420 remote_cpu_rate = tcp_stream_response->cpu_rate; 4421 4422 /* we have to make sure that the server port number is in */ 4423 /* network order */ 4424 set_port_number(remote_res,(short)tcp_stream_response->data_port_number); 4425 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 4426 rem_sndavoid = tcp_stream_response->so_sndavoid; 4427 } 4428 else { 4429 Set_errno(netperf_response.content.serv_errno); 4430 fprintf(where, 4431 "netperf: remote error %d", 4432 netperf_response.content.serv_errno); 4433 perror(""); 4434 fflush(where); 4435 4436 exit(1); 4437 } 4438 4439 #ifdef WANT_DEMO 4440 demo_stream_setup(lss_size,rsr_size); 4441 #endif 4442 4443 /*Connect up to the remote port on the data socket */ 4444 if (connect(send_socket, 4445 remote_res->ai_addr, 4446 remote_res->ai_addrlen) == INVALID_SOCKET){ 4447 perror("netperf: send_tcp_stream: data socket connect failed"); 4448 printf(" port: %d\n",ntohs(server.sin_port)); 4449 exit(1); 4450 } 4451 4452 #ifdef WIN32 4453 /* this is used so the timer thread can close the socket out from */ 4454 /* under us, which to date is the easiest/cleanest/least */ 4455 /* Windows-specific way I can find to force the winsock calls to */ 4456 /* return WSAEINTR with the test is over. anything that will run on */ 4457 /* 95 and NT and is closer to what netperf expects from Unix signals */ 4458 /* and such would be appreciated raj 1/96 */ 4459 win_kludge_socket = send_socket; 4460 #endif /* WIN32 */ 4461 4462 /* Data Socket set-up is finished. If there were problems, either 4463 the connect would have failed, or the previous response would 4464 have indicated a problem. I failed to see the value of the 4465 extra message after the accept on the remote. If it failed, 4466 we'll see it here. If it didn't, we might as well start pumping 4467 data. */ 4468 4469 /* Set-up the test end conditions. For a stream test, they can be */ 4470 /* either time or byte-count based. */ 4471 4472 if (test_time) { 4473 /* The user wanted to end the test after a period of time. */ 4474 times_up = 0; 4475 bytes_remaining = 0; 4476 4477 /* in previous revisions, we had the same code repeated throught 4478 all the test suites. this was unnecessary, and meant more 4479 work for me when I wanted to switch to POSIX signals, so I 4480 have abstracted this out into a routine in netlib.c. if you 4481 are experiencing signal problems, you might want to look 4482 there. raj 11/94 */ 4483 4484 start_timer(test_time); 4485 } 4486 else { 4487 /* The tester wanted to send a number of bytes. */ 4488 bytes_remaining = test_bytes; 4489 times_up = 1; 4490 } 4491 4492 /* The cpu_start routine will grab the current time and possibly */ 4493 /* value of the idle counter for later use in measuring cpu */ 4494 /* utilization and/or service demand and thruput. */ 4495 4496 cpu_start(local_cpu_usage); 4497 4498 #ifdef WANT_INTERVALS 4499 INTERVALS_INIT(); 4500 #endif /* WANT_INTERVALS */ 4501 4502 4503 /* before we start, initialize a few variables */ 4504 4505 #ifdef WANT_DEMO 4506 if (demo_mode) { 4507 demo_first_timestamp(); 4508 } 4509 #endif 4510 4511 /* We use an "OR" to control test execution. When the test is 4512 controlled by time, the byte count check will always return 4513 false. When the test is controlled by byte count, the time test 4514 will always return false. When the test is finished, the whole 4515 expression will go false and we will stop sending data. */ 4516 4517 while ((!times_up) || (bytes_remaining > 0)) { 4518 4519 /* the sendfile_tcp_stream test does not support making the buffers 4520 dirty. 08/2000 */ 4521 4522 #ifdef WANT_HISTOGRAM 4523 if (verbosity > 1) { 4524 /* timestamp just before we go into sendfile() and then again 4525 just after we come out raj 08/2000 */ 4526 /* but only if we are actually going to display a histogram */ 4527 HIST_timestamp(&time_one); 4528 } 4529 #endif /* WANT_HISTOGRAM */ 4530 4531 /* you can look at netlib.h for a description of the fields we 4532 are passing to sendfile(). 08/2000 */ 4533 if (netperf_sendfile(send_socket, send_ring) != send_size) { 4534 /* the test was interrupted, must be the end of test. the 4535 send_tcp_stream code has some WIN32 ifdefs that we do not 4536 need here. */ 4537 if ((len >=0) || SOCKET_EINTR(len)) { 4538 break; 4539 } 4540 perror("netperf: data send error: sendfile"); 4541 fprintf(stderr, 4542 "len was %d send_size was %d\n", 4543 len, 4544 send_size); 4545 fflush(stderr); 4546 exit(1); 4547 } 4548 4549 #ifdef WANT_HISTOGRAM 4550 if (verbosity > 1) { 4551 /* timestamp the exit from the send call and update the 4552 histogram */ 4553 4554 HIST_timestamp(&time_two); 4555 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 4556 } 4557 #endif /* WANT_HISTOGRAM */ 4558 4559 #ifdef WANT_DEMO 4560 demo_stream_interval(send_size); 4561 #endif 4562 4563 #ifdef WANT_INTERVALS 4564 INTERVALS_WAIT(); 4565 #endif /* WANT_INTERVALS */ 4566 4567 /* now we want to move our pointer to the next position in the */ 4568 /* data buffer...we may also want to wrap back to the "beginning" */ 4569 /* of the bufferspace, so we will mod the number of messages sent */ 4570 /* by the send width, and use that to calculate the offset to add */ 4571 /* to the base pointer. */ 4572 4573 nummessages++; 4574 send_ring = send_ring->next; 4575 if (bytes_remaining) { 4576 bytes_remaining -= send_size; 4577 } 4578 } 4579 4580 /* The test is over. Flush the buffers to the remote end. We do a 4581 graceful release to insure that all data has been taken by the 4582 remote. */ 4583 4584 /* but first, if the verbosity is greater than 1, find-out what */ 4585 /* the TCP maximum segment_size was (if possible) */ 4586 if (verbosity > 1) { 4587 tcp_mss = -1; 4588 get_tcp_info(send_socket,&tcp_mss); 4589 } 4590 4591 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 4592 perror("netperf: cannot shutdown tcp stream socket"); 4593 exit(1); 4594 } 4595 4596 /* hang a recv() off the socket to block until the remote has */ 4597 /* brought all the data up into the application. it will do a */ 4598 /* shutdown to cause a FIN to be sent our way. We will assume that */ 4599 /* any exit from the recv() call is good... raj 4/93 */ 4600 4601 /* since we are using sendfile() instead of send, we have no 4602 scratch buffer from the send_ring to use for the 4603 receive. however, since we "know" that the recv should be 4604 returning zero bytes (not that we are making the checks we 4605 should) we can pass the address of the flags field. raj 08/2000 4606 */ 4607 4608 recv(send_socket, 4609 &(send_ring->flags), 4610 sizeof(send_ring->flags), 4611 0); 4612 4613 /* this call will always give us the elapsed time for the test, and */ 4614 /* will also store-away the necessaries for cpu utilization */ 4615 4616 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 4617 /* measured and how */ 4618 /* long did we really */ 4619 /* run? */ 4620 4621 /* we are finished with the socket, so close it to prevent hitting */ 4622 /* the limit on maximum open files. */ 4623 4624 close(send_socket); 4625 4626 #if defined(WANT_INTERVALS) 4627 #ifdef WIN32 4628 stop_itimer(); 4629 #endif 4630 #endif /* WANT_INTERVALS */ 4631 4632 /* Get the statistics from the remote end. The remote will have */ 4633 /* calculated service demand and all those interesting things. If it */ 4634 /* wasn't supposed to care, it will return obvious values. */ 4635 4636 recv_response(); 4637 4638 if (!netperf_response.content.serv_errno) { 4639 if (debug) 4640 fprintf(where,"remote results obtained\n"); 4641 } 4642 4643 else { 4644 Set_errno(netperf_response.content.serv_errno); 4645 fprintf(where, 4646 "netperf: remote error %d", 4647 netperf_response.content.serv_errno); 4648 perror(""); 4649 fflush(where); 4650 4651 exit(1); 4652 } 4653 4654 /* We now calculate what our thruput was for the test. In the future, */ 4655 /* we may want to include a calculation of the thruput measured by */ 4656 /* the remote, but it should be the case that for a TCP stream test, */ 4657 /* that the two numbers should be *very* close... We calculate */ 4658 /* bytes_sent regardless of the way the test length was controlled. */ 4659 /* If it was time, we needed to, and if it was by bytes, the user may */ 4660 /* have specified a number of bytes that wasn't a multiple of the */ 4661 /* send_size, so we really didn't send what he asked for ;-) */ 4662 4663 bytes_sent = ntohd(tcp_stream_result->bytes_received); 4664 4665 thruput = calc_thruput(bytes_sent); 4666 4667 if (local_cpu_usage || remote_cpu_usage) { 4668 4669 /* We must now do a little math for service demand and cpu */ 4670 /* utilization for the system(s) */ 4671 /* Of course, some of the information might be bogus because */ 4672 /* there was no idle counter in the kernel(s). We need to make */ 4673 /* a note of this for the user's benefit...*/ 4674 if (local_cpu_usage) { 4675 4676 local_cpu_utilization = calc_cpu_util(0.0); 4677 local_service_demand = calc_service_demand(bytes_sent, 4678 0.0, 4679 0.0, 4680 0); 4681 } 4682 else { 4683 local_cpu_utilization = (float) -1.0; 4684 local_service_demand = (float) -1.0; 4685 } 4686 4687 if (remote_cpu_usage) { 4688 4689 remote_cpu_utilization = tcp_stream_result->cpu_util; 4690 remote_service_demand = calc_service_demand(bytes_sent, 4691 0.0, 4692 remote_cpu_utilization, 4693 tcp_stream_result->num_cpus); 4694 } 4695 else { 4696 remote_cpu_utilization = (float) -1.0; 4697 remote_service_demand = (float) -1.0; 4698 } 4699 } 4700 else { 4701 /* we were not measuring cpu, for the confidence stuff, we */ 4702 /* should make it -1.0 */ 4703 local_cpu_utilization = (float) -1.0; 4704 local_service_demand = (float) -1.0; 4705 remote_cpu_utilization = (float) -1.0; 4706 remote_service_demand = (float) -1.0; 4707 } 4708 4709 /* at this point, we want to calculate the confidence information. */ 4710 /* if debugging is on, calculate_confidence will print-out the */ 4711 /* parameters we pass it */ 4712 4713 calculate_confidence(confidence_iteration, 4714 elapsed_time, 4715 thruput, 4716 local_cpu_utilization, 4717 remote_cpu_utilization, 4718 local_service_demand, 4719 remote_service_demand); 4720 4721 confidence_iteration++; 4722 } 4723 4724 /* at this point, we have finished making all the runs that we */ 4725 /* will be making. so, we should extract what the calcuated values */ 4726 /* are for all the confidence stuff. we could make the values */ 4727 /* global, but that seemed a little messy, and it did not seem worth */ 4728 /* all the mucking with header files. so, we create a routine much */ 4729 /* like calcualte_confidence, which just returns the mean values. */ 4730 /* raj 11/94 */ 4731 4732 retrieve_confident_values(&elapsed_time, 4733 &thruput, 4734 &local_cpu_utilization, 4735 &remote_cpu_utilization, 4736 &local_service_demand, 4737 &remote_service_demand); 4738 4739 /* We are now ready to print all the information. If the user */ 4740 /* has specified zero-level verbosity, we will just print the */ 4741 /* local service demand, or the remote service demand. If the */ 4742 /* user has requested verbosity level 1, he will get the basic */ 4743 /* "streamperf" numbers. If the user has specified a verbosity */ 4744 /* of greater than 1, we will display a veritable plethora of */ 4745 /* background information from outside of this block as it it */ 4746 /* not cpu_measurement specific... */ 4747 4748 if (confidence < 0) { 4749 /* we did not hit confidence, but were we asked to look for it? */ 4750 if (iteration_max > 1) { 4751 display_confidence(); 4752 } 4753 } 4754 4755 if (local_cpu_usage || remote_cpu_usage) { 4756 local_cpu_method = format_cpu_method(cpu_method); 4757 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 4758 4759 switch (verbosity) { 4760 case 0: 4761 4762 if (local_cpu_usage) { 4763 fprintf(where, 4764 cpu_fmt_0, 4765 local_service_demand, 4766 local_cpu_method, 4767 ((print_headers) || 4768 (result_brand == NULL)) ? "" : result_brand); 4769 } 4770 4771 else { 4772 fprintf(where, 4773 cpu_fmt_0, 4774 remote_service_demand, 4775 remote_cpu_method, 4776 ((print_headers) || 4777 (result_brand == NULL)) ? "" : result_brand); 4778 } 4779 4780 break; 4781 4782 case 1: 4783 case 2: 4784 if (print_headers) { 4785 fprintf(where, 4786 cpu_title, 4787 format_units(), 4788 local_cpu_method, 4789 remote_cpu_method); 4790 } 4791 4792 fprintf(where, 4793 cpu_fmt_1, /* the format string */ 4794 rsr_size, /* remote recvbuf size */ 4795 lss_size, /* local sendbuf size */ 4796 send_size, /* how large were the sends */ 4797 elapsed_time, /* how long was the test */ 4798 thruput, /* what was the xfer rate */ 4799 local_cpu_utilization, /* local cpu */ 4800 remote_cpu_utilization, /* remote cpu */ 4801 local_service_demand, /* local service demand */ 4802 remote_service_demand, /* remote service demand */ 4803 ((print_headers) || 4804 (result_brand == NULL)) ? "" : result_brand); 4805 break; 4806 } 4807 4808 } 4809 4810 else { 4811 /* The tester did not wish to measure service demand. */ 4812 4813 switch (verbosity) { 4814 4815 case 0: 4816 4817 fprintf(where, 4818 tput_fmt_0, 4819 thruput, 4820 ((print_headers) || 4821 (result_brand == NULL)) ? "" : result_brand); 4822 break; 4823 4824 case 1: 4825 case 2: 4826 4827 if (print_headers) { 4828 fprintf(where,tput_title,format_units()); 4829 } 4830 4831 fprintf(where, 4832 tput_fmt_1, /* the format string */ 4833 rsr_size, /* remote recvbuf size */ 4834 lss_size, /* local sendbuf size */ 4835 send_size, /* how large were the sends */ 4836 elapsed_time, /* how long did it take */ 4837 thruput, /* how fast did it go */ 4838 ((print_headers) || 4839 (result_brand == NULL)) ? "" : result_brand); 4840 break; 4841 } 4842 } 4843 4844 /* it would be a good thing to include information about some of the */ 4845 /* other parameters that may have been set for this test, but at the */ 4846 /* moment, I do not wish to figure-out all the formatting, so I will */ 4847 /* just put this comment here to help remind me that it is something */ 4848 /* that should be done at a later time. */ 4849 4850 if (verbosity > 1) { 4851 4852 /* The user wanted to know it all, so we will give it to him. */ 4853 /* This information will include as much as we can find about */ 4854 /* TCP statistics, the alignments of the sends and receives */ 4855 /* and all that sort of rot... */ 4856 4857 /* this stuff needs to be worked-out in the presence of confidence */ 4858 /* intervals and multiple iterations of the test... raj 11/94 */ 4859 4860 fprintf(where, 4861 ksink_fmt, 4862 "Bytes", 4863 "Bytes", 4864 "Bytes", 4865 local_send_align, 4866 remote_recv_align, 4867 local_send_offset, 4868 remote_recv_offset, 4869 bytes_sent, 4870 bytes_sent / (double)nummessages, 4871 nummessages, 4872 bytes_sent / (double)tcp_stream_result->recv_calls, 4873 tcp_stream_result->recv_calls); 4874 4875 fprintf(where, 4876 ksink_fmt2, 4877 tcp_mss); 4878 4879 fflush(where); 4880 4881 #ifdef WANT_HISTOGRAM 4882 4883 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 4884 fflush(where); 4885 HIST_report(time_hist); 4886 #endif /* WANT_HISTOGRAM */ 4887 } 4888 } 4889 4890 #endif /* HAVE_SENDFILE */ 4891 4892 /* This is the server-side routine for the tcp stream test. It is */ 4893 /* implemented as one routine. I could break things-out somewhat, but */ 4894 /* didn't feel it was necessary. */ 4895 4896 void 4897 recv_tcp_stream() 4898 { 4899 4900 struct sockaddr_storage myaddr_in, peeraddr_in; 4901 SOCKET s_listen,s_data; 4902 netperf_socklen_t addrlen; 4903 int len; 4904 unsigned int receive_calls; 4905 float elapsed_time; 4906 double bytes_received; 4907 4908 struct ring_elt *recv_ring; 4909 4910 struct addrinfo *local_res; 4911 char local_name[BUFSIZ]; 4912 char port_buffer[PORTBUFSIZE]; 4913 4914 #ifdef DO_SELECT 4915 fd_set readfds; 4916 struct timeval timeout; 4917 #endif /* DO_SELECT */ 4918 4919 struct tcp_stream_request_struct *tcp_stream_request; 4920 struct tcp_stream_response_struct *tcp_stream_response; 4921 struct tcp_stream_results_struct *tcp_stream_results; 4922 4923 #ifdef DO_SELECT 4924 FD_ZERO(&readfds); 4925 timeout.tv_sec = 1; 4926 timeout.tv_usec = 0; 4927 #endif /* DO_SELECT */ 4928 4929 tcp_stream_request = 4930 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 4931 tcp_stream_response = 4932 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 4933 tcp_stream_results = 4934 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 4935 4936 if (debug) { 4937 fprintf(where,"netserver: recv_tcp_stream: entered...\n"); 4938 fflush(where); 4939 } 4940 4941 /* We want to set-up the listen socket with all the desired */ 4942 /* parameters and then let the initiator know that all is ready. If */ 4943 /* socket size defaults are to be used, then the initiator will have */ 4944 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 4945 /* send-back what they are. If that information cannot be determined, */ 4946 /* then we send-back -1's for the sizes. If things go wrong for any */ 4947 /* reason, we will drop back ten yards and punt. */ 4948 4949 /* If anything goes wrong, we want the remote to know about it. It */ 4950 /* would be best if the error that the remote reports to the user is */ 4951 /* the actual error we encountered, rather than some bogus unexpected */ 4952 /* response type message. */ 4953 4954 if (debug) { 4955 fprintf(where,"recv_tcp_stream: setting the response type...\n"); 4956 fflush(where); 4957 } 4958 4959 netperf_response.content.response_type = TCP_STREAM_RESPONSE; 4960 4961 if (debug) { 4962 fprintf(where,"recv_tcp_stream: the response type is set...\n"); 4963 fflush(where); 4964 } 4965 4966 /* We now alter the message_ptr variable to be at the desired */ 4967 /* alignment with the desired offset. */ 4968 4969 if (debug) { 4970 fprintf(where,"recv_tcp_stream: requested alignment of %d\n", 4971 tcp_stream_request->recv_alignment); 4972 fflush(where); 4973 } 4974 4975 /* create_data_socket expects to find some things in the global */ 4976 /* variables, so set the globals based on the values in the request. */ 4977 /* once the socket has been created, we will set the response values */ 4978 /* based on the updated value of those globals. raj 7/94 */ 4979 lss_size_req = tcp_stream_request->send_buf_size; 4980 lsr_size_req = tcp_stream_request->recv_buf_size; 4981 loc_nodelay = tcp_stream_request->no_delay; 4982 loc_rcvavoid = tcp_stream_request->so_rcvavoid; 4983 loc_sndavoid = tcp_stream_request->so_sndavoid; 4984 4985 set_hostname_and_port(local_name, 4986 port_buffer, 4987 nf_to_af(tcp_stream_request->ipfamily), 4988 tcp_stream_request->port); 4989 4990 local_res = complete_addrinfo(local_name, 4991 local_name, 4992 port_buffer, 4993 nf_to_af(tcp_stream_request->ipfamily), 4994 SOCK_STREAM, 4995 IPPROTO_TCP, 4996 0); 4997 4998 s_listen = create_data_socket(local_res); 4999 5000 if (s_listen == INVALID_SOCKET) { 5001 netperf_response.content.serv_errno = errno; 5002 send_response(); 5003 exit(1); 5004 } 5005 5006 #ifdef WIN32 5007 /* The test timer can fire during operations on the listening socket, 5008 so to make the start_timer below work we have to move 5009 it to close s_listen while we are blocked on accept. */ 5010 win_kludge_socket2 = s_listen; 5011 #endif 5012 5013 /* what sort of sizes did we end-up with? */ 5014 if (tcp_stream_request->receive_size == 0) { 5015 if (lsr_size > 0) { 5016 recv_size = lsr_size; 5017 } 5018 else { 5019 recv_size = 4096; 5020 } 5021 } 5022 else { 5023 recv_size = tcp_stream_request->receive_size; 5024 } 5025 5026 /* we want to set-up our recv_ring in a manner analagous to what we */ 5027 /* do on the sending side. this is more for the sake of symmetry */ 5028 /* than for the needs of say copy avoidance, but it might also be */ 5029 /* more realistic - this way one could conceivably go with a */ 5030 /* double-buffering scheme when taking the data an putting it into */ 5031 /* the filesystem or something like that. raj 7/94 */ 5032 5033 if (recv_width == 0) { 5034 recv_width = (lsr_size/recv_size) + 1; 5035 if (recv_width == 1) recv_width++; 5036 } 5037 5038 recv_ring = allocate_buffer_ring(recv_width, 5039 recv_size, 5040 tcp_stream_request->recv_alignment, 5041 tcp_stream_request->recv_offset); 5042 5043 if (debug) { 5044 fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n"); 5045 fflush(where); 5046 } 5047 5048 /* Now, let's set-up the socket to listen for connections */ 5049 if (listen(s_listen, 5) == SOCKET_ERROR) { 5050 netperf_response.content.serv_errno = errno; 5051 close(s_listen); 5052 send_response(); 5053 5054 exit(1); 5055 } 5056 5057 5058 /* now get the port number assigned by the system */ 5059 addrlen = sizeof(myaddr_in); 5060 if (getsockname(s_listen, 5061 (struct sockaddr *)&myaddr_in, 5062 &addrlen) == SOCKET_ERROR){ 5063 netperf_response.content.serv_errno = errno; 5064 close(s_listen); 5065 send_response(); 5066 5067 exit(1); 5068 } 5069 5070 /* Now myaddr_in contains the port and the internet address this is */ 5071 /* returned to the sender also implicitly telling the sender that the */ 5072 /* socket buffer sizing has been done. */ 5073 5074 tcp_stream_response->data_port_number = 5075 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 5076 netperf_response.content.serv_errno = 0; 5077 5078 /* But wait, there's more. If the initiator wanted cpu measurements, */ 5079 /* then we must call the calibrate routine, which will return the max */ 5080 /* rate back to the initiator. If the CPU was not to be measured, or */ 5081 /* something went wrong with the calibration, we will return a -1 to */ 5082 /* the initiator. */ 5083 5084 tcp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 5085 if (tcp_stream_request->measure_cpu) { 5086 tcp_stream_response->measure_cpu = 1; 5087 tcp_stream_response->cpu_rate = 5088 calibrate_local_cpu(tcp_stream_request->cpu_rate); 5089 } 5090 else { 5091 tcp_stream_response->measure_cpu = 0; 5092 } 5093 5094 /* before we send the response back to the initiator, pull some of */ 5095 /* the socket parms from the globals */ 5096 tcp_stream_response->send_buf_size = lss_size; 5097 tcp_stream_response->recv_buf_size = lsr_size; 5098 tcp_stream_response->no_delay = loc_nodelay; 5099 tcp_stream_response->so_rcvavoid = loc_rcvavoid; 5100 tcp_stream_response->so_sndavoid = loc_sndavoid; 5101 tcp_stream_response->receive_size = recv_size; 5102 5103 send_response(); 5104 5105 addrlen = sizeof(peeraddr_in); 5106 5107 if ((s_data=accept(s_listen, 5108 (struct sockaddr *)&peeraddr_in, 5109 &addrlen)) == INVALID_SOCKET) { 5110 /* Let's just punt. The remote will be given some information */ 5111 close(s_listen); 5112 exit(1); 5113 } 5114 5115 #ifdef WIN32 5116 /* this is used so the timer thread can close the socket out from */ 5117 /* under us, which to date is the easiest/cleanest/least */ 5118 /* Windows-specific way I can find to force the winsock calls to */ 5119 /* return WSAEINTR with the test is over. anything that will run on */ 5120 /* 95 and NT and is closer to what netperf expects from Unix signals */ 5121 /* and such would be appreciated raj 1/96 */ 5122 win_kludge_socket = s_data; 5123 win_kludge_socket2 = INVALID_SOCKET; 5124 #endif /* WIN32 */ 5125 5126 times_up = 0; 5127 5128 start_timer(tcp_stream_request->test_length + PAD_TIME); 5129 5130 #ifdef KLUDGE_SOCKET_OPTIONS 5131 /* this is for those systems which *INCORRECTLY* fail to pass */ 5132 /* attributes across an accept() call. Including this goes against */ 5133 /* my better judgement :( raj 11/95 */ 5134 5135 kludge_socket_options(s_data); 5136 5137 #endif /* KLUDGE_SOCKET_OPTIONS */ 5138 5139 /* Now it's time to start receiving data on the connection. We will */ 5140 /* first grab the apropriate counters and then start grabbing. */ 5141 5142 cpu_start(tcp_stream_request->measure_cpu); 5143 5144 /* The loop will exit when the sender does a shutdown, which will */ 5145 /* return a length of zero */ 5146 5147 /* there used to be an #ifdef DIRTY call to access_buffer() here, 5148 but we have switched from accessing the buffer before the recv() 5149 call to accessing the buffer after the recv() call. The 5150 accessing before was, IIRC, related to having dirty data when 5151 doing page-flipping copy avoidance. */ 5152 5153 bytes_received = 0; 5154 receive_calls = 0; 5155 5156 while (!times_up && ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0)) { 5157 if (len == SOCKET_ERROR ) { 5158 if (times_up) { 5159 break; 5160 } 5161 netperf_response.content.serv_errno = errno; 5162 send_response(); 5163 exit(1); 5164 } 5165 bytes_received += len; 5166 receive_calls++; 5167 5168 #ifdef DIRTY 5169 /* we access the buffer after the recv() call now, rather than before */ 5170 access_buffer(recv_ring->buffer_ptr, 5171 recv_size, 5172 tcp_stream_request->dirty_count, 5173 tcp_stream_request->clean_count); 5174 #endif /* DIRTY */ 5175 5176 5177 /* move to the next buffer in the recv_ring */ 5178 recv_ring = recv_ring->next; 5179 5180 #ifdef PAUSE 5181 sleep(1); 5182 #endif /* PAUSE */ 5183 5184 #ifdef DO_SELECT 5185 FD_SET(s_data,&readfds); 5186 select(s_data+1,&readfds,NULL,NULL,&timeout); 5187 #endif /* DO_SELECT */ 5188 5189 } 5190 5191 /* perform a shutdown to signal the sender that */ 5192 /* we have received all the data sent. raj 4/93 */ 5193 5194 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR && !times_up) { 5195 netperf_response.content.serv_errno = errno; 5196 send_response(); 5197 exit(1); 5198 } 5199 5200 cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time); 5201 5202 /* send the results to the sender */ 5203 5204 if (debug) { 5205 fprintf(where, 5206 "recv_tcp_stream: got %g bytes\n", 5207 bytes_received); 5208 fprintf(where, 5209 "recv_tcp_stream: got %d recvs\n", 5210 receive_calls); 5211 fflush(where); 5212 } 5213 5214 tcp_stream_results->bytes_received = htond(bytes_received); 5215 tcp_stream_results->elapsed_time = elapsed_time; 5216 tcp_stream_results->recv_calls = receive_calls; 5217 5218 tcp_stream_results->cpu_method = cpu_method; 5219 tcp_stream_results->num_cpus = lib_num_loc_cpus; 5220 5221 if (tcp_stream_request->measure_cpu) { 5222 tcp_stream_results->cpu_util = calc_cpu_util(0.0); 5223 }; 5224 5225 if (debug) { 5226 fprintf(where, 5227 "recv_tcp_stream: test complete, sending results.\n"); 5228 fprintf(where, 5229 " bytes_received %g receive_calls %d\n", 5230 bytes_received, 5231 receive_calls); 5232 fprintf(where, 5233 " len %d\n", 5234 len); 5235 fflush(where); 5236 } 5237 5238 send_response(); 5239 5240 /* we are now done with the sockets */ 5241 close(s_data); 5242 close(s_listen); 5243 5244 } 5245 5246 /* This is the server-side routine for the tcp maerts test. It is 5248 implemented as one routine. I could break things-out somewhat, but 5249 didn't feel it was necessary. */ 5250 5251 void 5252 recv_tcp_maerts() 5253 { 5254 5255 struct sockaddr_storage myaddr_in, peeraddr_in; 5256 struct addrinfo *local_res; 5257 char local_name[BUFSIZ]; 5258 char port_buffer[PORTBUFSIZE]; 5259 5260 SOCKET s_listen,s_data; 5261 netperf_socklen_t addrlen; 5262 int len; 5263 unsigned int send_calls; 5264 float elapsed_time; 5265 double bytes_sent = 0.0 ; 5266 5267 struct ring_elt *send_ring; 5268 5269 struct tcp_maerts_request_struct *tcp_maerts_request; 5270 struct tcp_maerts_response_struct *tcp_maerts_response; 5271 struct tcp_maerts_results_struct *tcp_maerts_results; 5272 5273 tcp_maerts_request = 5274 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data; 5275 tcp_maerts_response = 5276 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data; 5277 tcp_maerts_results = 5278 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data; 5279 5280 if (debug) { 5281 fprintf(where,"netserver: recv_tcp_maerts: entered...\n"); 5282 fflush(where); 5283 } 5284 5285 /* We want to set-up the listen socket with all the desired 5286 parameters and then let the initiator know that all is ready. If 5287 socket size defaults are to be used, then the initiator will have 5288 sent us 0's. If the socket sizes cannot be changed, then we will 5289 send-back what they are. If that information cannot be 5290 determined, then we send-back -1's for the sizes. If things go 5291 wrong for any reason, we will drop back ten yards and punt. */ 5292 5293 /* If anything goes wrong, we want the remote to know about it. It 5294 would be best if the error that the remote reports to the user is 5295 the actual error we encountered, rather than some bogus 5296 unexpected response type message. */ 5297 5298 if (debug) { 5299 fprintf(where,"recv_tcp_maerts: setting the response type...\n"); 5300 fflush(where); 5301 } 5302 5303 netperf_response.content.response_type = TCP_MAERTS_RESPONSE; 5304 5305 if (debug) { 5306 fprintf(where,"recv_tcp_maerts: the response type is set...\n"); 5307 fflush(where); 5308 } 5309 5310 /* We now alter the message_ptr variable to be at the desired */ 5311 /* alignment with the desired offset. */ 5312 5313 if (debug) { 5314 fprintf(where,"recv_tcp_maerts: requested alignment of %d\n", 5315 tcp_maerts_request->send_alignment); 5316 fflush(where); 5317 } 5318 5319 /* Grab a socket to listen on, and then listen on it. */ 5320 5321 if (debug) { 5322 fprintf(where,"recv_tcp_maerts: grabbing a socket...\n"); 5323 fflush(where); 5324 } 5325 5326 /* create_data_socket expects to find some things in the global */ 5327 /* variables, so set the globals based on the values in the request. */ 5328 /* once the socket has been created, we will set the response values */ 5329 /* based on the updated value of those globals. raj 7/94 */ 5330 lss_size_req = tcp_maerts_request->send_buf_size; 5331 lsr_size_req = tcp_maerts_request->recv_buf_size; 5332 loc_nodelay = tcp_maerts_request->no_delay; 5333 loc_rcvavoid = tcp_maerts_request->so_rcvavoid; 5334 loc_sndavoid = tcp_maerts_request->so_sndavoid; 5335 5336 set_hostname_and_port(local_name, 5337 port_buffer, 5338 nf_to_af(tcp_maerts_request->ipfamily), 5339 tcp_maerts_request->port); 5340 5341 local_res = complete_addrinfo(local_name, 5342 local_name, 5343 port_buffer, 5344 nf_to_af(tcp_maerts_request->ipfamily), 5345 SOCK_STREAM, 5346 IPPROTO_TCP, 5347 0); 5348 5349 s_listen = create_data_socket(local_res); 5350 5351 if (s_listen == INVALID_SOCKET) { 5352 netperf_response.content.serv_errno = errno; 5353 send_response(); 5354 exit(1); 5355 } 5356 5357 #ifdef WIN32 5358 /* The test timer can fire during operations on the listening socket, 5359 so to make the start_timer below work we have to move 5360 it to close s_listen while we are blocked on accept. */ 5361 win_kludge_socket2 = s_listen; 5362 #endif 5363 5364 5365 /* what sort of sizes did we end-up with? */ 5366 if (tcp_maerts_request->send_size == 0) { 5367 if (lss_size > 0) { 5368 send_size = lss_size; 5369 } 5370 else { 5371 send_size = 4096; 5372 } 5373 } 5374 else { 5375 send_size = tcp_maerts_request->send_size; 5376 } 5377 5378 /* we want to set-up our recv_ring in a manner analagous to what we */ 5379 /* do on the recving side. this is more for the sake of symmetry */ 5380 /* than for the needs of say copy avoidance, but it might also be */ 5381 /* more realistic - this way one could conceivably go with a */ 5382 /* double-buffering scheme when taking the data an putting it into */ 5383 /* the filesystem or something like that. raj 7/94 */ 5384 5385 if (send_width == 0) { 5386 send_width = (lsr_size/send_size) + 1; 5387 if (send_width == 1) send_width++; 5388 } 5389 5390 send_ring = allocate_buffer_ring(send_width, 5391 send_size, 5392 tcp_maerts_request->send_alignment, 5393 tcp_maerts_request->send_offset); 5394 5395 if (debug) { 5396 fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n"); 5397 fflush(where); 5398 } 5399 5400 /* Now, let's set-up the socket to listen for connections */ 5401 if (listen(s_listen, 5) == SOCKET_ERROR) { 5402 netperf_response.content.serv_errno = errno; 5403 close(s_listen); 5404 send_response(); 5405 5406 exit(1); 5407 } 5408 5409 5410 /* now get the port number assigned by the system */ 5411 addrlen = sizeof(myaddr_in); 5412 if (getsockname(s_listen, 5413 (struct sockaddr *)&myaddr_in, 5414 &addrlen) == SOCKET_ERROR){ 5415 netperf_response.content.serv_errno = errno; 5416 close(s_listen); 5417 send_response(); 5418 5419 exit(1); 5420 } 5421 5422 /* Now myaddr_in contains the port and the internet address this is */ 5423 /* returned to the sender also implicitly telling the sender that the */ 5424 /* socket buffer sizing has been done. */ 5425 5426 tcp_maerts_response->data_port_number = 5427 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 5428 netperf_response.content.serv_errno = 0; 5429 5430 /* But wait, there's more. If the initiator wanted cpu measurements, */ 5431 /* then we must call the calibrate routine, which will return the max */ 5432 /* rate back to the initiator. If the CPU was not to be measured, or */ 5433 /* something went wrong with the calibration, we will return a -1 to */ 5434 /* the initiator. */ 5435 5436 tcp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */ 5437 if (tcp_maerts_request->measure_cpu) { 5438 tcp_maerts_response->measure_cpu = 1; 5439 tcp_maerts_response->cpu_rate = 5440 calibrate_local_cpu(tcp_maerts_request->cpu_rate); 5441 } 5442 else { 5443 tcp_maerts_response->measure_cpu = 0; 5444 } 5445 5446 /* before we send the response back to the initiator, pull some of */ 5447 /* the socket parms from the globals */ 5448 tcp_maerts_response->send_buf_size = lss_size; 5449 tcp_maerts_response->recv_buf_size = lsr_size; 5450 tcp_maerts_response->no_delay = loc_nodelay; 5451 tcp_maerts_response->so_rcvavoid = loc_rcvavoid; 5452 tcp_maerts_response->so_sndavoid = loc_sndavoid; 5453 tcp_maerts_response->send_size = send_size; 5454 5455 send_response(); 5456 5457 addrlen = sizeof(peeraddr_in); 5458 5459 /* we will start the timer before the accept() to be somewhat 5460 analagous to the starting of the timer before the connect() call 5461 in the TCP_STREAM test. raj 2002-06-21 */ 5462 5463 start_timer(tcp_maerts_request->test_length); 5464 5465 /* Now it's time to start receiving data on the connection. We will 5466 first grab the apropriate counters and then start grabbing. */ 5467 5468 cpu_start(tcp_maerts_request->measure_cpu); 5469 5470 5471 if ((s_data=accept(s_listen, 5472 (struct sockaddr *)&peeraddr_in, 5473 &addrlen)) == INVALID_SOCKET) { 5474 /* Let's just punt. The remote will be given some information */ 5475 close(s_listen); 5476 exit(1); 5477 } 5478 5479 #ifdef WIN32 5480 /* this is used so the timer thread can close the socket out from */ 5481 /* under us, which to date is the easiest/cleanest/least */ 5482 /* Windows-specific way I can find to force the winsock calls to */ 5483 /* return WSAEINTR with the test is over. anything that will run on */ 5484 /* 95 and NT and is closer to what netperf expects from Unix signals */ 5485 /* and such would be appreciated raj 1/96 */ 5486 win_kludge_socket = s_data; 5487 win_kludge_socket2 = INVALID_SOCKET; 5488 #endif /* WIN32 */ 5489 5490 #ifdef KLUDGE_SOCKET_OPTIONS 5491 5492 /* this is for those systems which *INCORRECTLY* fail to pass 5493 attributes across an accept() call. Including this goes against 5494 my better judgement :( raj 11/95 */ 5495 5496 kludge_socket_options(s_data); 5497 5498 #endif /* KLUDGE_SOCKET_OPTIONS */ 5499 5500 /* The loop will exit when the sender does a shutdown, which will */ 5501 /* return a length of zero */ 5502 5503 bytes_sent = 0.0; 5504 send_calls = 0; 5505 5506 len = 0; /* nt-lint; len is not initialized (printf far below) if 5507 times_up initially true.*/ 5508 times_up = 0; /* must remember to initialize this little beauty */ 5509 while (!times_up) { 5510 5511 #ifdef DIRTY 5512 /* we want to dirty some number of consecutive integers in the buffer */ 5513 /* we are about to send. we may also want to bring some number of */ 5514 /* them cleanly into the cache. The clean ones will follow any dirty */ 5515 /* ones into the cache. */ 5516 5517 access_buffer(send_ring->buffer_ptr, 5518 send_size, 5519 tcp_maerts_request->dirty_count, 5520 tcp_maerts_request->clean_count); 5521 5522 #endif /* DIRTY */ 5523 5524 if((len=send(s_data, 5525 send_ring->buffer_ptr, 5526 send_size, 5527 0)) != send_size) { 5528 if ((len >=0) || SOCKET_EINTR(len)) { 5529 /* the test was interrupted, must be the end of test */ 5530 break; 5531 } 5532 netperf_response.content.serv_errno = errno; 5533 send_response(); 5534 exit(1); 5535 } 5536 5537 bytes_sent += len; 5538 send_calls++; 5539 5540 /* more to the next buffer in the send_ring */ 5541 send_ring = send_ring->next; 5542 5543 } 5544 5545 /* perform a shutdown to signal the sender that */ 5546 /* we have received all the data sent. raj 4/93 */ 5547 5548 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) { 5549 netperf_response.content.serv_errno = errno; 5550 send_response(); 5551 exit(1); 5552 } 5553 5554 /* hang a recv() off the socket to block until the remote has 5555 brought all the data up into the application. it will do a 5556 shutdown to cause a FIN to be sent our way. We will assume that 5557 any exit from the recv() call is good... raj 4/93 */ 5558 5559 recv(s_data, send_ring->buffer_ptr, send_size, 0); 5560 5561 5562 cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time); 5563 5564 /* send the results to the sender */ 5565 5566 if (debug) { 5567 fprintf(where, 5568 "recv_tcp_maerts: got %g bytes\n", 5569 bytes_sent); 5570 fprintf(where, 5571 "recv_tcp_maerts: got %d sends\n", 5572 send_calls); 5573 fflush(where); 5574 } 5575 5576 tcp_maerts_results->bytes_sent = htond(bytes_sent); 5577 tcp_maerts_results->elapsed_time = elapsed_time; 5578 tcp_maerts_results->send_calls = send_calls; 5579 5580 if (tcp_maerts_request->measure_cpu) { 5581 tcp_maerts_results->cpu_util = calc_cpu_util(0.0); 5582 }; 5583 5584 if (debug) { 5585 fprintf(where, 5586 "recv_tcp_maerts: test complete, sending results.\n"); 5587 fprintf(where, 5588 " bytes_sent %g send_calls %d\n", 5589 bytes_sent, 5590 send_calls); 5591 fprintf(where, 5592 " len %d\n", 5593 len); 5594 fflush(where); 5595 } 5596 5597 tcp_maerts_results->cpu_method = cpu_method; 5598 tcp_maerts_results->num_cpus = lib_num_loc_cpus; 5599 send_response(); 5600 5601 /* we are now done with the sockets */ 5602 close(s_data); 5603 close(s_listen); 5604 5605 } 5606 5607 5609 /* this routine implements the sending (netperf) side of the TCP_RR */ 5610 /* test. */ 5611 #ifndef WANT_MIGRATION 5612 void 5613 send_tcp_rr(char remote_host[]) 5614 { 5615 5616 char *tput_title = "\ 5617 Local /Remote\n\ 5618 Socket Size Request Resp. Elapsed Trans.\n\ 5619 Send Recv Size Size Time Rate \n\ 5620 bytes Bytes bytes bytes secs. per sec \n\n"; 5621 5622 char *tput_title_band = "\ 5623 Local /Remote\n\ 5624 Socket Size Request Resp. Elapsed \n\ 5625 Send Recv Size Size Time Throughput \n\ 5626 bytes Bytes bytes bytes secs. %s/sec \n\n"; 5627 5628 char *tput_fmt_0 = 5629 "%7.2f %s\n"; 5630 5631 char *tput_fmt_1_line_1 = "\ 5632 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 5633 char *tput_fmt_1_line_2 = "\ 5634 %-6d %-6d\n"; 5635 5636 char *cpu_title = "\ 5637 Local /Remote\n\ 5638 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 5639 Send Recv Size Size Time Rate local remote local remote\n\ 5640 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 5641 5642 char *cpu_title_tput = "\ 5643 Local /Remote\n\ 5644 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 5645 Send Recv Size Size Time %-8.8s local remote local remote\n\ 5646 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 5647 5648 char *cpu_title_latency = "\ 5649 Local /Remote\n\ 5650 Socket Size Request Resp. Elapsed Latency CPU CPU S.dem S.dem\n\ 5651 Send Recv Size Size Time usecs local remote local remote\n\ 5652 bytes bytes bytes bytes secs. per tran %% %c %% %c us/Tr us/Tr\n\n"; 5653 5654 char *cpu_fmt_0 = 5655 "%6.3f %c %s\n"; 5656 5657 char *cpu_fmt_1_line_1 = "\ 5658 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 5659 5660 char *cpu_fmt_1_line_2 = "\ 5661 %-6d %-6d\n"; 5662 5663 char *ksink_fmt = "\ 5664 Alignment Offset RoundTrip Trans Throughput\n\ 5665 Local Remote Local Remote Latency Rate %-8.8s/s\n\ 5666 Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\ 5667 %5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n"; 5668 5669 5670 int timed_out = 0; 5671 float elapsed_time; 5672 5673 int len; 5674 char *temp_message_ptr; 5675 int nummessages; 5676 SOCKET send_socket; 5677 int trans_remaining; 5678 double bytes_xferd; 5679 5680 struct ring_elt *send_ring; 5681 struct ring_elt *recv_ring; 5682 5683 int rsp_bytes_left; 5684 int rsp_bytes_recvd; 5685 5686 float local_cpu_utilization; 5687 float local_service_demand; 5688 float remote_cpu_utilization; 5689 float remote_service_demand; 5690 double thruput; 5691 5692 struct addrinfo *local_res; 5693 struct addrinfo *remote_res; 5694 5695 struct tcp_rr_request_struct *tcp_rr_request; 5696 struct tcp_rr_response_struct *tcp_rr_response; 5697 struct tcp_rr_results_struct *tcp_rr_result; 5698 5699 #ifdef WANT_FIRST_BURST 5700 #define REQUEST_CWND_INITIAL 2 5701 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both 5702 Unix and the state of New Jersey - both were simple an unspoiled. 5703 then it was realized that some stacks are quite picky about 5704 initial congestion windows and a non-trivial initial burst of 5705 requests would not be individual segments even with TCP_NODELAY 5706 set. so, we have to start tracking a poor-man's congestion window 5707 up here in window space because we want to try to make something 5708 happen that frankly, we cannot guarantee with the specification 5709 of TCP. ain't that grand?-) raj 2006-01-30 */ 5710 int requests_outstanding = 0; 5711 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having 5712 three requests 5713 outstanding at the 5714 beginning of the test 5715 is ok with TCP stacks 5716 of interest. the first 5717 two will come from our 5718 first_burst loop, and 5719 the third from our 5720 regularly scheduled 5721 send */ 5722 #endif 5723 5724 tcp_rr_request = 5725 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 5726 tcp_rr_response= 5727 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 5728 tcp_rr_result = 5729 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 5730 5731 #ifdef WANT_HISTOGRAM 5732 if (verbosity > 1) { 5733 time_hist = HIST_new(); 5734 } 5735 #endif /* WANT_HISTOGRAM */ 5736 5737 /* since we are now disconnected from the code that established the */ 5738 /* control socket, and since we want to be able to use different */ 5739 /* protocols and such, we are passed the name of the remote host and */ 5740 /* must turn that into the test specific addressing information. */ 5741 5742 complete_addrinfos(&remote_res, 5743 &local_res, 5744 remote_host, 5745 SOCK_STREAM, 5746 IPPROTO_TCP, 5747 0); 5748 5749 if ( print_headers ) { 5750 print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res); 5751 } 5752 5753 /* initialize a few counters */ 5754 5755 send_ring = NULL; 5756 recv_ring = NULL; 5757 confidence_iteration = 1; 5758 init_stat(); 5759 5760 /* we have a great-big while loop which controls the number of times */ 5761 /* we run a particular test. this is for the calculation of a */ 5762 /* confidence interval (I really should have stayed awake during */ 5763 /* probstats :). If the user did not request confidence measurement */ 5764 /* (no confidence is the default) then we will only go though the */ 5765 /* loop once. the confidence stuff originates from the folks at IBM */ 5766 5767 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 5768 (confidence_iteration <= iteration_min)) { 5769 5770 /* initialize a few counters. we have to remember that we might be */ 5771 /* going through the loop more than once. */ 5772 5773 nummessages = 0; 5774 bytes_xferd = 0.0; 5775 times_up = 0; 5776 timed_out = 0; 5777 trans_remaining = 0; 5778 5779 #ifdef WANT_FIRST_BURST 5780 /* we have to remember to reset the number of transactions 5781 outstanding and the "congestion window for each new 5782 iteration. raj 2006-01-31 */ 5783 requests_outstanding = 0; 5784 request_cwnd = REQUEST_CWND_INITIAL; 5785 #endif 5786 5787 5788 /* set-up the data buffers with the requested alignment and offset. */ 5789 /* since this is a request/response test, default the send_width and */ 5790 /* recv_width to 1 and not two raj 7/94 */ 5791 5792 if (send_width == 0) send_width = 1; 5793 if (recv_width == 0) recv_width = 1; 5794 5795 if (send_ring == NULL) { 5796 send_ring = allocate_buffer_ring(send_width, 5797 req_size, 5798 local_send_align, 5799 local_send_offset); 5800 } 5801 5802 if (recv_ring == NULL) { 5803 recv_ring = allocate_buffer_ring(recv_width, 5804 rsp_size, 5805 local_recv_align, 5806 local_recv_offset); 5807 } 5808 5809 /*set up the data socket */ 5810 send_socket = create_data_socket(local_res); 5811 5812 if (send_socket == INVALID_SOCKET){ 5813 perror("netperf: send_tcp_rr: tcp stream data socket"); 5814 exit(1); 5815 } 5816 5817 if (debug) { 5818 fprintf(where,"send_tcp_rr: send_socket obtained...\n"); 5819 } 5820 5821 /* If the user has requested cpu utilization measurements, we must */ 5822 /* calibrate the cpu(s). We will perform this task within the tests */ 5823 /* themselves. If the user has specified the cpu rate, then */ 5824 /* calibrate_local_cpu will return rather quickly as it will have */ 5825 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 5826 /* all the "normal" calibration stuff and return the rate back.*/ 5827 5828 if (local_cpu_usage) { 5829 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 5830 } 5831 5832 if (!no_control) { 5833 /* Tell the remote end to do a listen. The server alters the 5834 socket paramters on the other side at this point, hence the 5835 reason for all the values being passed in the setup 5836 message. If the user did not specify any of the parameters, 5837 they will be passed as 0, which will indicate to the remote 5838 that no changes beyond the system's default should be 5839 used. Alignment is the exception, it will default to 8, which 5840 will be no alignment alterations. */ 5841 5842 netperf_request.content.request_type = DO_TCP_RR; 5843 tcp_rr_request->recv_buf_size = rsr_size_req; 5844 tcp_rr_request->send_buf_size = rss_size_req; 5845 tcp_rr_request->recv_alignment = remote_recv_align; 5846 tcp_rr_request->recv_offset = remote_recv_offset; 5847 tcp_rr_request->send_alignment = remote_send_align; 5848 tcp_rr_request->send_offset = remote_send_offset; 5849 tcp_rr_request->request_size = req_size; 5850 tcp_rr_request->response_size = rsp_size; 5851 tcp_rr_request->no_delay = rem_nodelay; 5852 tcp_rr_request->measure_cpu = remote_cpu_usage; 5853 tcp_rr_request->cpu_rate = remote_cpu_rate; 5854 tcp_rr_request->so_rcvavoid = rem_rcvavoid; 5855 tcp_rr_request->so_sndavoid = rem_sndavoid; 5856 if (test_time) { 5857 tcp_rr_request->test_length = test_time; 5858 } 5859 else { 5860 tcp_rr_request->test_length = test_trans * -1; 5861 } 5862 tcp_rr_request->port = atoi(remote_data_port); 5863 tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 5864 5865 if (debug > 1) { 5866 fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n"); 5867 } 5868 5869 send_request(); 5870 5871 /* The response from the remote will contain all of the relevant 5872 socket parameters for this test type. We will put them back 5873 into the variables here so they can be displayed if desired. 5874 The remote will have calibrated CPU if necessary, and will 5875 have done all the needed set-up we will have calibrated the 5876 cpu locally before sending the request, and will grab the 5877 counter value right after the connect returns. The remote 5878 will grab the counter right after the accept call. This saves 5879 the hassle of extra messages being sent for the TCP 5880 tests. */ 5881 5882 recv_response(); 5883 5884 if (!netperf_response.content.serv_errno) { 5885 if (debug) 5886 fprintf(where,"remote listen done.\n"); 5887 rsr_size = tcp_rr_response->recv_buf_size; 5888 rss_size = tcp_rr_response->send_buf_size; 5889 rem_nodelay = tcp_rr_response->no_delay; 5890 remote_cpu_usage = tcp_rr_response->measure_cpu; 5891 remote_cpu_rate = tcp_rr_response->cpu_rate; 5892 /* make sure that port numbers are in network order */ 5893 set_port_number(remote_res,(short)tcp_rr_response->data_port_number); 5894 } 5895 else { 5896 Set_errno(netperf_response.content.serv_errno); 5897 fprintf(where, 5898 "netperf: remote error %d", 5899 netperf_response.content.serv_errno); 5900 perror(""); 5901 fflush(where); 5902 5903 exit(1); 5904 } 5905 } 5906 5907 #ifdef WANT_DEMO 5908 demo_rr_setup(1000); 5909 #endif 5910 5911 /*Connect up to the remote port on the data socket */ 5912 if (connect(send_socket, 5913 remote_res->ai_addr, 5914 remote_res->ai_addrlen) == INVALID_SOCKET){ 5915 perror("netperf: data socket connect failed"); 5916 5917 exit(1); 5918 } 5919 5920 #ifdef WIN32 5921 /* this is used so the timer thread can close the socket out from */ 5922 /* under us, which to date is the easiest/cleanest/least */ 5923 /* Windows-specific way I can find to force the winsock calls to */ 5924 /* return WSAEINTR with the test is over. anything that will run on */ 5925 /* 95 and NT and is closer to what netperf expects from Unix signals */ 5926 /* and such would be appreciated raj 1/96 */ 5927 win_kludge_socket = send_socket; 5928 #endif /* WIN32 */ 5929 5930 /* Data Socket set-up is finished. If there were problems, either the */ 5931 /* connect would have failed, or the previous response would have */ 5932 /* indicated a problem. I failed to see the value of the extra */ 5933 /* message after the accept on the remote. If it failed, we'll see it */ 5934 /* here. If it didn't, we might as well start pumping data. */ 5935 5936 /* Set-up the test end conditions. For a request/response test, they */ 5937 /* can be either time or transaction based. */ 5938 5939 if (test_time) { 5940 /* The user wanted to end the test after a period of time. */ 5941 times_up = 0; 5942 trans_remaining = 0; 5943 start_timer(test_time); 5944 } 5945 else { 5946 /* The tester wanted to send a number of bytes. */ 5947 trans_remaining = test_bytes; 5948 times_up = 1; 5949 } 5950 5951 /* The cpu_start routine will grab the current time and possibly */ 5952 /* value of the idle counter for later use in measuring cpu */ 5953 /* utilization and/or service demand and thruput. */ 5954 5955 cpu_start(local_cpu_usage); 5956 5957 #ifdef WANT_INTERVALS 5958 INTERVALS_INIT(); 5959 #endif /* WANT_INTERVALS */ 5960 5961 /* We use an "OR" to control test execution. When the test is */ 5962 /* controlled by time, the byte count check will always return false. */ 5963 /* When the test is controlled by byte count, the time test will */ 5964 /* always return false. When the test is finished, the whole */ 5965 /* expression will go false and we will stop sending data. I think I */ 5966 /* just arbitrarily decrement trans_remaining for the timed test, but */ 5967 /* will not do that just yet... One other question is whether or not */ 5968 /* the send buffer and the receive buffer should be the same buffer. */ 5969 5970 #ifdef WANT_DEMO 5971 if (demo_mode) { 5972 demo_first_timestamp(); 5973 } 5974 #endif 5975 5976 while ((!times_up) || (trans_remaining > 0)) { 5977 /* send the request. we assume that if we use a blocking socket, */ 5978 /* the request will be sent at one shot. */ 5979 5980 #ifdef WANT_FIRST_BURST 5981 /* we can inject no more than request_cwnd, which will grow with 5982 time, and no more than first_burst_size. we don't use <= to 5983 account for the "regularly scheduled" send call. of course 5984 that makes it more a "max_outstanding_ than a 5985 "first_burst_size" but for now we won't fix the names. also, 5986 I suspect the extra check against < first_burst_size is 5987 redundant since later I expect to make sure that request_cwnd 5988 can never get larger than first_burst_size, but just at the 5989 moment I'm feeling like a belt and suspenders kind of 5990 programmer. raj 2006-01-30 */ 5991 while ((first_burst_size > 0) && 5992 (requests_outstanding < request_cwnd) && 5993 (requests_outstanding < first_burst_size)) { 5994 if (debug) { 5995 fprintf(where, 5996 "injecting, req_outstndng %d req_cwnd %d burst %d\n", 5997 requests_outstanding, 5998 request_cwnd, 5999 first_burst_size); 6000 } 6001 if ((len = send(send_socket, 6002 send_ring->buffer_ptr, 6003 req_size, 6004 0)) != req_size) { 6005 /* we should never hit the end of the test in the first burst */ 6006 perror("send_tcp_rr: initial burst data send error"); 6007 exit(-1); 6008 } 6009 requests_outstanding += 1; 6010 } 6011 6012 #endif /* WANT_FIRST_BURST */ 6013 6014 #ifdef WANT_HISTOGRAM 6015 if (verbosity > 1) { 6016 /* timestamp just before our call to send, and then again just 6017 after the receive raj 8/94 */ 6018 /* but only if we are actually going to display one. raj 6019 2007-02-07 */ 6020 6021 HIST_timestamp(&time_one); 6022 } 6023 #endif /* WANT_HISTOGRAM */ 6024 6025 if ((len = send(send_socket, 6026 send_ring->buffer_ptr, 6027 req_size, 6028 0)) != req_size) { 6029 if (SOCKET_EINTR(len) || (errno == 0)) { 6030 /* we hit the end of a */ 6031 /* timed test. */ 6032 timed_out = 1; 6033 break; 6034 } 6035 perror("send_tcp_rr: data send error"); 6036 exit(1); 6037 } 6038 send_ring = send_ring->next; 6039 6040 #ifdef WANT_FIRST_BURST 6041 requests_outstanding += 1; 6042 #endif 6043 6044 /* receive the response */ 6045 rsp_bytes_left = rsp_size; 6046 temp_message_ptr = recv_ring->buffer_ptr; 6047 while(rsp_bytes_left > 0) { 6048 if((rsp_bytes_recvd=recv(send_socket, 6049 temp_message_ptr, 6050 rsp_bytes_left, 6051 0)) == SOCKET_ERROR || rsp_bytes_recvd == 0) { 6052 if ( SOCKET_EINTR(rsp_bytes_recvd) ) { 6053 /* We hit the end of a timed test. */ 6054 timed_out = 1; 6055 break; 6056 } 6057 perror("send_tcp_rr: data recv error"); 6058 exit(1); 6059 } 6060 rsp_bytes_left -= rsp_bytes_recvd; 6061 temp_message_ptr += rsp_bytes_recvd; 6062 } 6063 recv_ring = recv_ring->next; 6064 6065 #ifdef WANT_FIRST_BURST 6066 /* so, since we've gotten a response back, update the 6067 bookkeeping accordingly. there is one less request 6068 outstanding and we can put one more out there than before. */ 6069 requests_outstanding -= 1; 6070 if (request_cwnd < first_burst_size) { 6071 request_cwnd += 1; 6072 if (debug) { 6073 fprintf(where, 6074 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n", 6075 request_cwnd, 6076 first_burst_size, 6077 requests_outstanding); 6078 } 6079 } 6080 #endif 6081 if (timed_out) { 6082 /* we may have been in a nested while loop - we need */ 6083 /* another call to break. */ 6084 break; 6085 } 6086 6087 #ifdef WANT_HISTOGRAM 6088 if (verbosity > 1) { 6089 HIST_timestamp(&time_two); 6090 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 6091 } 6092 #endif /* WANT_HISTOGRAM */ 6093 6094 #ifdef WANT_DEMO 6095 demo_rr_interval(1); 6096 #endif 6097 6098 #ifdef WANT_INTERVALS 6099 INTERVALS_WAIT(); 6100 #endif /* WANT_INTERVALS */ 6101 6102 nummessages++; 6103 if (trans_remaining) { 6104 trans_remaining--; 6105 } 6106 6107 if (debug > 3) { 6108 if ((nummessages % 100) == 0) { 6109 fprintf(where, 6110 "Transaction %d completed\n", 6111 nummessages); 6112 fflush(where); 6113 } 6114 } 6115 } 6116 6117 /* At this point we used to call shutdown on the data socket to be 6118 sure all the data was delivered, but this was not germane in a 6119 request/response test, and it was causing the tests to "hang" 6120 when they were being controlled by time. So, I have replaced 6121 this shutdown call with a call to close that can be found later 6122 in the procedure. */ 6123 6124 /* this call will always give us the elapsed time for the test, 6125 and will also store-away the necessaries for cpu utilization */ 6126 6127 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 6128 /* measured? how long */ 6129 /* did we really run? */ 6130 6131 #if defined(WANT_INTERVALS) 6132 #ifdef WIN32 6133 stop_itimer(); 6134 #endif 6135 #endif /* WANT_INTERVALS */ 6136 6137 if (!no_control) { 6138 /* Get the statistics from the remote end. The remote will have 6139 calculated CPU utilization. If it wasn't supposed to care, it 6140 will return obvious values. */ 6141 6142 recv_response(); 6143 if (!netperf_response.content.serv_errno) { 6144 if (debug) 6145 fprintf(where,"remote results obtained\n"); 6146 } 6147 else { 6148 Set_errno(netperf_response.content.serv_errno); 6149 fprintf(where,"netperf: remote error %d", 6150 netperf_response.content.serv_errno); 6151 perror(""); 6152 fflush(where); 6153 exit(1); 6154 } 6155 } 6156 6157 /* We now calculate what our "throughput" was for the test. */ 6158 6159 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 6160 thruput = nummessages/elapsed_time; 6161 6162 if (local_cpu_usage || remote_cpu_usage) { 6163 /* We must now do a little math for service demand and cpu 6164 utilization for the system(s) Of course, some of the 6165 information might be bogus because there was no idle counter in 6166 the kernel(s). We need to make a note of this for the user's 6167 benefit... */ 6168 if (local_cpu_usage) { 6169 local_cpu_utilization = calc_cpu_util(0.0); 6170 /* since calc_service demand is doing ms/Kunit we will 6171 multiply the number of transaction by 1024 to get "good" 6172 numbers */ 6173 local_service_demand = calc_service_demand((double) nummessages*1024, 6174 0.0, 6175 0.0, 6176 0); 6177 } 6178 else { 6179 local_cpu_utilization = (float) -1.0; 6180 local_service_demand = (float) -1.0; 6181 } 6182 6183 if (remote_cpu_usage) { 6184 remote_cpu_utilization = tcp_rr_result->cpu_util; 6185 /* since calc_service demand is doing ms/Kunit we will 6186 multiply the number of transaction by 1024 to get "good" 6187 numbers */ 6188 remote_service_demand = calc_service_demand((double) nummessages*1024, 6189 0.0, 6190 remote_cpu_utilization, 6191 tcp_rr_result->num_cpus); 6192 } 6193 else { 6194 remote_cpu_utilization = (float) -1.0; 6195 remote_service_demand = (float) -1.0; 6196 } 6197 6198 } 6199 else { 6200 /* we were not measuring cpu, for the confidence stuff, we */ 6201 /* should make it -1.0 */ 6202 local_cpu_utilization = (float) -1.0; 6203 local_service_demand = (float) -1.0; 6204 remote_cpu_utilization = (float) -1.0; 6205 remote_service_demand = (float) -1.0; 6206 } 6207 6208 /* at this point, we want to calculate the confidence information. 6209 if debugging is on, calculate_confidence will print-out the 6210 parameters we pass it */ 6211 6212 calculate_confidence(confidence_iteration, 6213 elapsed_time, 6214 thruput, 6215 local_cpu_utilization, 6216 remote_cpu_utilization, 6217 local_service_demand, 6218 remote_service_demand); 6219 6220 6221 confidence_iteration++; 6222 6223 /* we are now done with the socket, so close it */ 6224 close(send_socket); 6225 6226 } 6227 6228 retrieve_confident_values(&elapsed_time, 6229 &thruput, 6230 &local_cpu_utilization, 6231 &remote_cpu_utilization, 6232 &local_service_demand, 6233 &remote_service_demand); 6234 6235 /* We are now ready to print all the information. If the user has 6236 specified zero-level verbosity, we will just print the local 6237 service demand, or the remote service demand. If the user has 6238 requested verbosity level 1, he will get the basic "streamperf" 6239 numbers. If the user has specified a verbosity of greater than 1, 6240 we will display a veritable plethora of background information 6241 from outside of this block as it it not cpu_measurement 6242 specific... */ 6243 6244 if (confidence < 0) { 6245 /* we did not hit confidence, but were we asked to look for it? */ 6246 if (iteration_max > 1) { 6247 display_confidence(); 6248 } 6249 } 6250 6251 if (local_cpu_usage || remote_cpu_usage) { 6252 local_cpu_method = format_cpu_method(cpu_method); 6253 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method); 6254 6255 switch (verbosity) { 6256 case 0: 6257 if (local_cpu_usage) { 6258 fprintf(where, 6259 cpu_fmt_0, 6260 local_service_demand, 6261 local_cpu_method, 6262 ((print_headers) || 6263 (result_brand == NULL)) ? "" : result_brand); 6264 } 6265 else { 6266 fprintf(where, 6267 cpu_fmt_0, 6268 remote_service_demand, 6269 remote_cpu_method, 6270 ((print_headers) || 6271 (result_brand == NULL)) ? "" : result_brand); 6272 } 6273 break; 6274 case 1: 6275 case 2: 6276 if (print_headers) { 6277 if ('x' == libfmt) { 6278 fprintf(where, 6279 cpu_title, 6280 local_cpu_method, 6281 remote_cpu_method); 6282 } 6283 else { 6284 fprintf(where, 6285 cpu_title_tput, 6286 format_units(), 6287 local_cpu_method, 6288 remote_cpu_method); 6289 } 6290 } 6291 6292 fprintf(where, 6293 cpu_fmt_1_line_1, /* the format string */ 6294 lss_size, /* local sendbuf size */ 6295 lsr_size, 6296 req_size, /* how large were the requests */ 6297 rsp_size, /* guess */ 6298 elapsed_time, /* how long was the test */ 6299 ('x' == libfmt) ? thruput : 6300 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 6301 1.0), 6302 local_cpu_utilization, /* local cpu */ 6303 remote_cpu_utilization, /* remote cpu */ 6304 local_service_demand, /* local service demand */ 6305 remote_service_demand, /* remote service demand */ 6306 ((print_headers) || 6307 (result_brand == NULL)) ? "" : result_brand); 6308 fprintf(where, 6309 cpu_fmt_1_line_2, 6310 rss_size, 6311 rsr_size); 6312 break; 6313 } 6314 } 6315 else { 6316 /* The tester did not wish to measure service demand. */ 6317 6318 switch (verbosity) { 6319 case 0: 6320 fprintf(where, 6321 tput_fmt_0, 6322 ('x' == libfmt) ? thruput : 6323 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 6324 1.0), 6325 ((print_headers) || 6326 (result_brand == NULL)) ? "" : result_brand); 6327 break; 6328 case 1: 6329 case 2: 6330 if (print_headers) { 6331 fprintf(where, 6332 ('x' == libfmt) ? tput_title : tput_title_band, 6333 format_units()); 6334 } 6335 6336 fprintf(where, 6337 tput_fmt_1_line_1, /* the format string */ 6338 lss_size, 6339 lsr_size, 6340 req_size, /* how large were the requests */ 6341 rsp_size, /* how large were the responses */ 6342 elapsed_time, /* how long did it take */ 6343 /* are we trans or do we need to convert to bytes then 6344 bits? at this point, thruput is in our "confident" 6345 transactions per second. we can convert to a 6346 bidirectional bitrate by multiplying that by the sum 6347 of the req_size and rsp_size. we pass that to 6348 calc_thruput_interval_omni with an elapsed time of 6349 1.0 s to get it converted to [kmg]bits/s or 6350 [KMG]Bytes/s */ 6351 ('x' == libfmt) ? thruput : 6352 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 6353 1.0), 6354 ((print_headers) || 6355 (result_brand == NULL)) ? "" : result_brand); 6356 fprintf(where, 6357 tput_fmt_1_line_2, 6358 rss_size, /* remote recvbuf size */ 6359 rsr_size); 6360 6361 break; 6362 } 6363 } 6364 6365 /* it would be a good thing to include information about some of the */ 6366 /* other parameters that may have been set for this test, but at the */ 6367 /* moment, I do not wish to figure-out all the formatting, so I will */ 6368 /* just put this comment here to help remind me that it is something */ 6369 /* that should be done at a later time. */ 6370 6371 /* how to handle the verbose information in the presence of */ 6372 /* confidence intervals is yet to be determined... raj 11/94 */ 6373 if (verbosity > 1) { 6374 /* The user wanted to know it all, so we will give it to him. */ 6375 /* This information will include as much as we can find about */ 6376 /* TCP statistics, the alignments of the sends and receives */ 6377 /* and all that sort of rot... */ 6378 6379 /* normally, you might think that if we were messing about with 6380 the value of libfmt we would need to put it back again, but 6381 since this is basically the last thing we are going to do with 6382 it, it does not matter. so there :) raj 2007-06-08 */ 6383 /* if the user was asking for transactions, then we report 6384 megabits per second for the unidirectional throughput, 6385 otherwise we use the desired units. */ 6386 if ('x' == libfmt) { 6387 libfmt = 'm'; 6388 } 6389 6390 fprintf(where, 6391 ksink_fmt, 6392 format_units(), 6393 local_send_align, 6394 remote_recv_offset, 6395 local_send_offset, 6396 remote_recv_offset, 6397 /* if the user has enable burst mode, we have to remember 6398 to account for that in the number of transactions 6399 outstanding at any one time. otherwise we will 6400 underreport the latency of individual 6401 transactions. learned from saf by raj 2007-06-08 */ 6402 (((double)1.0/thruput)*(double)1000000.0) * 6403 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)), 6404 thruput, 6405 calc_thruput_interval_omni(thruput * (double)req_size,1.0), 6406 calc_thruput_interval_omni(thruput * (double)rsp_size,1.0)); 6407 6408 #ifdef WANT_HISTOGRAM 6409 fprintf(where,"\nHistogram of request/response times\n"); 6410 fflush(where); 6411 HIST_report(time_hist); 6412 #endif /* WANT_HISTOGRAM */ 6413 6414 } 6415 6416 } 6417 #endif /* WANT_MIGRATION */ 6418 6419 #if defined(__linux) 6421 /* 6422 * Linux has this odd behavior where if the socket buffers are larger than 6423 * a device's txqueuelen, the kernel will silently drop transmits which would 6424 * not fit into the tx queue, and not pass an ENOBUFS error back to the 6425 * application. As a result, a UDP stream test can report absurd transmit 6426 * bandwidths (like 20Gb/s on a 1GbE NIC). This behavior can be avoided if 6427 * you request extended error reporting on the socket. This is done by 6428 * setting the IP_RECVERR socket option at the IP level. 6429 */ 6430 static void 6431 enable_enobufs(int s) 6432 { 6433 struct protoent *pr; 6434 int on = 1; 6435 6436 if ((pr = getprotobyname("ip")) == NULL) { 6437 fprintf(where, "enable_enobufs failed: getprotobyname\n"); 6438 fflush(where); 6439 return; 6440 } 6441 if (setsockopt(s, pr->p_proto, IP_RECVERR, (char *)&on, sizeof(on)) < 0) { 6442 fprintf(where, "enable_enobufs failed: setsockopt\n"); 6443 fflush(where); 6444 return; 6445 } 6446 } 6447 #endif 6448 6449 #ifndef WANT_MIGRATION 6450 void 6451 send_udp_stream(char remote_host[]) 6452 { 6453 /**********************************************************************/ 6454 /* */ 6455 /* UDP Unidirectional Send Test */ 6456 /* */ 6457 /**********************************************************************/ 6458 6459 #define UDP_LENGTH_MAX 0XFFFF - 28 6460 6461 char *tput_title = "\ 6462 Socket Message Elapsed Messages \n\ 6463 Size Size Time Okay Errors Throughput\n\ 6464 bytes bytes secs # # %s/sec\n\n"; 6465 6466 char *tput_fmt_0 = 6467 "%7.2f\n"; 6468 6469 char *tput_fmt_1 = "\ 6470 %6d %6d %-7.2f %7d %6d %7.2f\n\ 6471 %6d %-7.2f %7d %7.2f\n\n"; 6472 6473 6474 char *cpu_title = "\ 6475 Socket Message Elapsed Messages CPU Service\n\ 6476 Size Size Time Okay Errors Throughput Util Demand\n\ 6477 bytes bytes secs # # %s/sec %% %c%c us/KB\n\n"; 6478 6479 char *cpu_fmt_0 = 6480 "%6.2f %c\n"; 6481 6482 char *cpu_fmt_1 = "\ 6483 %6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\ 6484 %6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n"; 6485 6486 unsigned int messages_recvd; 6487 unsigned int messages_sent; 6488 unsigned int failed_sends; 6489 6490 float elapsed_time, 6491 local_cpu_utilization, 6492 remote_cpu_utilization; 6493 6494 float local_service_demand, remote_service_demand; 6495 double local_thruput, remote_thruput; 6496 double bytes_sent; 6497 double bytes_recvd; 6498 6499 6500 int len; 6501 struct ring_elt *send_ring; 6502 SOCKET data_socket; 6503 6504 unsigned int sum_messages_sent; 6505 unsigned int sum_messages_recvd; 6506 unsigned int sum_failed_sends; 6507 double sum_local_thruput; 6508 6509 struct addrinfo *local_res; 6510 struct addrinfo *remote_res; 6511 6512 struct udp_stream_request_struct *udp_stream_request; 6513 struct udp_stream_response_struct *udp_stream_response; 6514 struct udp_stream_results_struct *udp_stream_results; 6515 6516 udp_stream_request = 6517 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data; 6518 udp_stream_response = 6519 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data; 6520 udp_stream_results = 6521 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data; 6522 6523 #ifdef WANT_HISTOGRAM 6524 if (verbosity > 1) { 6525 time_hist = HIST_new(); 6526 } 6527 #endif /* WANT_HISTOGRAM */ 6528 6529 /* since we are now disconnected from the code that established the */ 6530 /* control socket, and since we want to be able to use different */ 6531 /* protocols and such, we are passed the name of the remote host and */ 6532 /* must turn that into the test specific addressing information. */ 6533 6534 complete_addrinfos(&remote_res, 6535 &local_res, 6536 remote_host, 6537 SOCK_DGRAM, 6538 IPPROTO_UDP, 6539 0); 6540 6541 if ( print_headers ) { 6542 print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res); 6543 } 6544 6545 send_ring = NULL; 6546 confidence_iteration = 1; 6547 init_stat(); 6548 sum_messages_sent = 0; 6549 sum_messages_recvd = 0; 6550 sum_failed_sends = 0; 6551 sum_local_thruput = 0.0; 6552 6553 /* we have a great-big while loop which controls the number of times */ 6554 /* we run a particular test. this is for the calculation of a */ 6555 /* confidence interval (I really should have stayed awake during */ 6556 /* probstats :). If the user did not request confidence measurement */ 6557 /* (no confidence is the default) then we will only go though the */ 6558 /* loop once. the confidence stuff originates from the folks at IBM */ 6559 6560 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 6561 (confidence_iteration <= iteration_min)) { 6562 6563 /* initialize a few counters. we have to remember that we might be */ 6564 /* going through the loop more than once. */ 6565 messages_sent = 0; 6566 messages_recvd = 0; 6567 failed_sends = 0; 6568 times_up = 0; 6569 6570 /*set up the data socket */ 6571 data_socket = create_data_socket(local_res); 6572 6573 if (data_socket == INVALID_SOCKET){ 6574 perror("udp_send: data socket"); 6575 exit(1); 6576 } 6577 6578 /* now, we want to see if we need to set the send_size */ 6579 if (send_size == 0) { 6580 if (lss_size > 0) { 6581 send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX); 6582 } 6583 else { 6584 send_size = 4096; 6585 } 6586 } 6587 6588 6589 /* set-up the data buffer with the requested alignment and offset, */ 6590 /* most of the numbers here are just a hack to pick something nice */ 6591 /* and big in an attempt to never try to send a buffer a second time */ 6592 /* before it leaves the node...unless the user set the width */ 6593 /* explicitly. */ 6594 if (send_width == 0) send_width = 32; 6595 6596 if (send_ring == NULL ) { 6597 send_ring = allocate_buffer_ring(send_width, 6598 send_size, 6599 local_send_align, 6600 local_send_offset); 6601 } 6602 6603 6604 /* if the user supplied a cpu rate, this call will complete rather */ 6605 /* quickly, otherwise, the cpu rate will be retured to us for */ 6606 /* possible display. The Library will keep it's own copy of this data */ 6607 /* for use elsewhere. We will only display it. (Does that make it */ 6608 /* "opaque" to us?) */ 6609 6610 if (local_cpu_usage) 6611 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 6612 6613 if (!no_control) { 6614 /* Tell the remote end to set up the data connection. The server 6615 sends back the port number and alters the socket parameters 6616 there. Of course this is a datagram service so no connection 6617 is actually set up, the server just sets up the socket and 6618 binds it. */ 6619 6620 netperf_request.content.request_type = DO_UDP_STREAM; 6621 udp_stream_request->recv_buf_size = rsr_size_req; 6622 udp_stream_request->message_size = send_size; 6623 udp_stream_request->recv_connected = remote_connected; 6624 udp_stream_request->recv_alignment = remote_recv_align; 6625 udp_stream_request->recv_offset = remote_recv_offset; 6626 udp_stream_request->measure_cpu = remote_cpu_usage; 6627 udp_stream_request->cpu_rate = remote_cpu_rate; 6628 udp_stream_request->test_length = test_time; 6629 udp_stream_request->so_rcvavoid = rem_rcvavoid; 6630 udp_stream_request->so_sndavoid = rem_sndavoid; 6631 udp_stream_request->port = atoi(remote_data_port); 6632 udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 6633 6634 send_request(); 6635 6636 recv_response(); 6637 6638 if (!netperf_response.content.serv_errno) { 6639 if (debug) 6640 fprintf(where,"send_udp_stream: remote data connection done.\n"); 6641 } 6642 else { 6643 Set_errno(netperf_response.content.serv_errno); 6644 perror("send_udp_stream: error on remote"); 6645 exit(1); 6646 } 6647 6648 /* Place the port number returned by the remote into the sockaddr */ 6649 /* structure so our sends can be sent to the correct place. Also get */ 6650 /* some of the returned socket buffer information for user display. */ 6651 6652 /* make sure that port numbers are in the proper order */ 6653 set_port_number(remote_res,(short)udp_stream_response->data_port_number); 6654 6655 rsr_size = udp_stream_response->recv_buf_size; 6656 rss_size = udp_stream_response->send_buf_size; 6657 remote_cpu_rate = udp_stream_response->cpu_rate; 6658 } 6659 6660 #ifdef WANT_DEMO 6661 demo_stream_setup(lss_size,rsr_size); 6662 #endif 6663 6664 /* We "connect" up to the remote post to allow is to use the send */ 6665 /* call instead of the sendto call. Presumeably, this is a little */ 6666 /* simpler, and a little more efficient. I think that it also means */ 6667 /* that we can be informed of certain things, but am not sure */ 6668 /* yet...also, this is the way I would expect a client to behave */ 6669 /* when talking to a server */ 6670 if (local_connected) { 6671 if (connect(data_socket, 6672 remote_res->ai_addr, 6673 remote_res->ai_addrlen) == INVALID_SOCKET){ 6674 perror("send_udp_stream: data socket connect failed"); 6675 exit(1); 6676 } else if (debug) { 6677 fprintf(where,"send_udp_stream: connected data socket.\n"); 6678 fflush(where); 6679 } 6680 } 6681 6682 #if defined (__linux) 6683 enable_enobufs(data_socket); 6684 #endif 6685 6686 #ifdef WIN32 6687 /* this is used so the timer thread can close the socket out from */ 6688 /* under us, which to date is the easiest/cleanest/least */ 6689 /* Windows-specific way I can find to force the winsock calls to */ 6690 /* return WSAEINTR with the test is over. anything that will run on */ 6691 /* 95 and NT and is closer to what netperf expects from Unix signals */ 6692 /* and such would be appreciated raj 1/96 */ 6693 win_kludge_socket = data_socket; 6694 #endif /* WIN32 */ 6695 6696 /* set up the timer to call us after test_time. one of these days, */ 6697 /* it might be nice to figure-out a nice reliable way to have the */ 6698 /* test controlled by a byte count as well, but since UDP is not */ 6699 /* reliable, that could prove difficult. so, in the meantime, we */ 6700 /* only allow a UDP_STREAM test to be a timed test. */ 6701 6702 if (test_time) { 6703 times_up = 0; 6704 start_timer(test_time); 6705 } 6706 else { 6707 fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n"); 6708 fflush(where); 6709 } 6710 6711 /* Get the start count for the idle counter and the start time */ 6712 6713 cpu_start(local_cpu_usage); 6714 6715 #ifdef WANT_INTERVALS 6716 INTERVALS_INIT(); 6717 #endif /* WANT_INTERVALS */ 6718 6719 #ifdef WANT_DEMO 6720 if (demo_mode) { 6721 demo_first_timestamp(); 6722 } 6723 #endif 6724 6725 /* Send datagrams like there was no tomorrow. at somepoint it might */ 6726 /* be nice to set this up so that a quantity of bytes could be sent, */ 6727 /* but we still need some sort of end of test trigger on the receive */ 6728 /* side. that could be a select with a one second timeout, but then */ 6729 /* if there is a test where none of the data arrives for awile and */ 6730 /* then starts again, we would end the test too soon. something to */ 6731 /* think about... */ 6732 while (!times_up) { 6733 6734 #ifdef DIRTY 6735 /* we want to dirty some number of consecutive integers in the buffer */ 6736 /* we are about to send. we may also want to bring some number of */ 6737 /* them cleanly into the cache. The clean ones will follow any dirty */ 6738 /* ones into the cache. */ 6739 6740 access_buffer(send_ring->buffer_ptr, 6741 send_size, 6742 loc_dirty_count, 6743 loc_clean_count); 6744 #endif /* DIRTY */ 6745 6746 #ifdef WANT_HISTOGRAM 6747 if (verbosity > 1) { 6748 HIST_timestamp(&time_one); 6749 } 6750 #endif /* WANT_HISTOGRAM */ 6751 6752 if (local_connected) { 6753 len = send(data_socket, 6754 send_ring->buffer_ptr, 6755 send_size, 6756 0); 6757 } else { 6758 len = sendto(data_socket, 6759 send_ring->buffer_ptr, 6760 send_size, 6761 0, 6762 remote_res->ai_addr, 6763 remote_res->ai_addrlen); 6764 } 6765 6766 if (len != send_size) { 6767 if ((len >= 0) || 6768 SOCKET_EINTR(len)) 6769 break; 6770 if (errno == ENOBUFS) { 6771 failed_sends++; 6772 continue; 6773 } 6774 perror("udp_send: data send error"); 6775 exit(1); 6776 } 6777 messages_sent++; 6778 6779 /* now we want to move our pointer to the next position in the */ 6780 /* data buffer... */ 6781 6782 send_ring = send_ring->next; 6783 6784 6785 #ifdef WANT_HISTOGRAM 6786 if (verbosity > 1) { 6787 /* get the second timestamp */ 6788 HIST_timestamp(&time_two); 6789 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 6790 } 6791 #endif /* WANT_HISTOGRAM */ 6792 6793 #ifdef WANT_DEMO 6794 demo_stream_interval(send_size); 6795 #endif 6796 6797 #ifdef WANT_INTERVALS 6798 INTERVALS_WAIT(); 6799 #endif /* WANT_INTERVALS */ 6800 6801 } 6802 6803 /* This is a timed test, so the remote will be returning to us after */ 6804 /* a time. We should not need to send any "strange" messages to tell */ 6805 /* the remote that the test is completed, unless we decide to add a */ 6806 /* number of messages to the test. */ 6807 6808 /* the test is over, so get stats and stuff */ 6809 cpu_stop(local_cpu_usage, 6810 &elapsed_time); 6811 6812 #if defined(WANT_INTERVALS) 6813 #ifdef WIN32 6814 stop_itimer(); 6815 #endif 6816 #endif /* WANT_INTERVALS */ 6817 6818 if (!no_control) { 6819 /* Get the statistics from the remote end */ 6820 recv_response(); 6821 if (!netperf_response.content.serv_errno) { 6822 if (debug) 6823 fprintf(where,"send_udp_stream: remote results obtained\n"); 6824 } 6825 else { 6826 Set_errno(netperf_response.content.serv_errno); 6827 perror("send_udp_stream: error on remote"); 6828 exit(1); 6829 } 6830 messages_recvd = udp_stream_results->messages_recvd; 6831 bytes_recvd = (double) send_size * (double) messages_recvd; 6832 } 6833 else { 6834 /* since there was no control connection, we've no idea what was 6835 actually received. raj 2007-02-08 */ 6836 messages_recvd = -1; 6837 bytes_recvd = -1.0; 6838 } 6839 6840 bytes_sent = (double) send_size * (double) messages_sent; 6841 local_thruput = calc_thruput(bytes_sent); 6842 6843 6844 /* we asume that the remote ran for as long as we did */ 6845 6846 remote_thruput = calc_thruput(bytes_recvd); 6847 6848 /* print the results for this socket and message size */ 6849 6850 if (local_cpu_usage || remote_cpu_usage) { 6851 /* We must now do a little math for service demand and cpu */ 6852 /* utilization for the system(s) We pass zeros for the local */ 6853 /* cpu utilization and elapsed time to tell the routine to use */ 6854 /* the libraries own values for those. */ 6855 if (local_cpu_usage) { 6856 local_cpu_utilization = calc_cpu_util(0.0); 6857 /* shouldn't this really be based on bytes_recvd, since that is */ 6858 /* the effective throughput of the test? I think that it should, */ 6859 /* so will make the change raj 11/94 */ 6860 local_service_demand = calc_service_demand(bytes_recvd, 6861 0.0, 6862 0.0, 6863 0); 6864 } 6865 else { 6866 local_cpu_utilization = (float) -1.0; 6867 local_service_demand = (float) -1.0; 6868 } 6869 6870 /* The local calculations could use variables being kept by */ 6871 /* the local netlib routines. The remote calcuations need to */ 6872 /* have a few things passed to them. */ 6873 if (remote_cpu_usage) { 6874 remote_cpu_utilization = udp_stream_results->cpu_util; 6875 remote_service_demand = calc_service_demand(bytes_recvd, 6876 0.0, 6877 remote_cpu_utilization, 6878 udp_stream_results->num_cpus); 6879 } 6880 else { 6881 remote_cpu_utilization = (float) -1.0; 6882 remote_service_demand = (float) -1.0; 6883 } 6884 } 6885 else { 6886 /* we were not measuring cpu, for the confidence stuff, we */ 6887 /* should make it -1.0 */ 6888 local_cpu_utilization = (float) -1.0; 6889 local_service_demand = (float) -1.0; 6890 remote_cpu_utilization = (float) -1.0; 6891 remote_service_demand = (float) -1.0; 6892 } 6893 6894 /* at this point, we want to calculate the confidence information. */ 6895 /* if debugging is on, calculate_confidence will print-out the */ 6896 /* parameters we pass it */ 6897 6898 calculate_confidence(confidence_iteration, 6899 elapsed_time, 6900 remote_thruput, 6901 local_cpu_utilization, 6902 remote_cpu_utilization, 6903 local_service_demand, 6904 remote_service_demand); 6905 6906 /* since the routine calculate_confidence is rather generic, and */ 6907 /* we have a few other parms of interest, we will do a little work */ 6908 /* here to caclulate their average. */ 6909 sum_messages_sent += messages_sent; 6910 sum_messages_recvd += messages_recvd; 6911 sum_failed_sends += failed_sends; 6912 sum_local_thruput += local_thruput; 6913 6914 confidence_iteration++; 6915 6916 /* this datapoint is done, so we don't need the socket any longer */ 6917 close(data_socket); 6918 6919 } 6920 6921 /* we should reach this point once the test is finished */ 6922 6923 retrieve_confident_values(&elapsed_time, 6924 &remote_thruput, 6925 &local_cpu_utilization, 6926 &remote_cpu_utilization, 6927 &local_service_demand, 6928 &remote_service_demand); 6929 6930 /* some of the interesting values aren't covered by the generic */ 6931 /* confidence routine */ 6932 messages_sent = sum_messages_sent / (confidence_iteration -1); 6933 messages_recvd = sum_messages_recvd / (confidence_iteration -1); 6934 failed_sends = sum_failed_sends / (confidence_iteration -1); 6935 local_thruput = sum_local_thruput / (confidence_iteration -1); 6936 6937 /* We are now ready to print all the information. If the user */ 6938 /* has specified zero-level verbosity, we will just print the */ 6939 /* local service demand, or the remote service demand. If the */ 6940 /* user has requested verbosity level 1, he will get the basic */ 6941 /* "streamperf" numbers. If the user has specified a verbosity */ 6942 /* of greater than 1, we will display a veritable plethora of */ 6943 /* background information from outside of this block as it it */ 6944 /* not cpu_measurement specific... */ 6945 6946 6947 if (confidence < 0) { 6948 /* we did not hit confidence, but were we asked to look for it? */ 6949 if (iteration_max > 1) { 6950 display_confidence(); 6951 } 6952 } 6953 6954 if (local_cpu_usage || remote_cpu_usage) { 6955 local_cpu_method = format_cpu_method(cpu_method); 6956 remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method); 6957 6958 switch (verbosity) { 6959 case 0: 6960 if (local_cpu_usage) { 6961 fprintf(where, 6962 cpu_fmt_0, 6963 local_service_demand, 6964 local_cpu_method); 6965 } 6966 else { 6967 fprintf(where, 6968 cpu_fmt_0, 6969 remote_service_demand, 6970 local_cpu_method); 6971 } 6972 break; 6973 case 1: 6974 case 2: 6975 if (print_headers) { 6976 fprintf(where, 6977 cpu_title, 6978 format_units(), 6979 local_cpu_method, 6980 remote_cpu_method); 6981 } 6982 6983 fprintf(where, 6984 cpu_fmt_1, /* the format string */ 6985 lss_size, /* local sendbuf size */ 6986 send_size, /* how large were the sends */ 6987 elapsed_time, /* how long was the test */ 6988 messages_sent, 6989 failed_sends, 6990 local_thruput, /* what was the xfer rate */ 6991 local_cpu_utilization, /* local cpu */ 6992 local_service_demand, /* local service demand */ 6993 rsr_size, 6994 elapsed_time, 6995 messages_recvd, 6996 remote_thruput, 6997 remote_cpu_utilization, /* remote cpu */ 6998 remote_service_demand); /* remote service demand */ 6999 break; 7000 } 7001 } 7002 else { 7003 /* The tester did not wish to measure service demand. */ 7004 switch (verbosity) { 7005 case 0: 7006 fprintf(where, 7007 tput_fmt_0, 7008 local_thruput); 7009 break; 7010 case 1: 7011 case 2: 7012 if (print_headers) { 7013 fprintf(where,tput_title,format_units()); 7014 } 7015 fprintf(where, 7016 tput_fmt_1, /* the format string */ 7017 lss_size, /* local sendbuf size */ 7018 send_size, /* how large were the sends */ 7019 elapsed_time, /* how long did it take */ 7020 messages_sent, 7021 failed_sends, 7022 local_thruput, 7023 rsr_size, /* remote recvbuf size */ 7024 elapsed_time, 7025 messages_recvd, 7026 remote_thruput); 7027 break; 7028 } 7029 } 7030 7031 fflush(where); 7032 #ifdef WANT_HISTOGRAM 7033 if (verbosity > 1) { 7034 fprintf(where,"\nHistogram of time spent in send() call\n"); 7035 fflush(where); 7036 HIST_report(time_hist); 7037 } 7038 #endif /* WANT_HISTOGRAM */ 7039 7040 } 7041 #endif /* WANT_MIGRATION */ 7042 7043 7045 /* this routine implements the receive side (netserver) of the */ 7046 /* UDP_STREAM performance test. */ 7047 7048 void 7049 recv_udp_stream() 7050 { 7051 struct ring_elt *recv_ring; 7052 struct addrinfo *local_res; 7053 char local_name[BUFSIZ]; 7054 char port_buffer[PORTBUFSIZE]; 7055 7056 struct sockaddr_storage myaddr_in; 7057 SOCKET s_data; 7058 netperf_socklen_t addrlen; 7059 struct sockaddr_storage remote_addr; 7060 netperf_socklen_t remote_addrlen; 7061 7062 int len = 0; 7063 unsigned int bytes_received = 0; 7064 float elapsed_time; 7065 7066 int message_size; 7067 unsigned int messages_recvd = 0; 7068 7069 struct udp_stream_request_struct *udp_stream_request; 7070 struct udp_stream_response_struct *udp_stream_response; 7071 struct udp_stream_results_struct *udp_stream_results; 7072 7073 udp_stream_request = 7074 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data; 7075 udp_stream_response = 7076 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data; 7077 udp_stream_results = 7078 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data; 7079 7080 if (debug) { 7081 fprintf(where,"netserver: recv_udp_stream: entered...\n"); 7082 fflush(where); 7083 } 7084 7085 /* We want to set-up the listen socket with all the desired */ 7086 /* parameters and then let the initiator know that all is ready. If */ 7087 /* socket size defaults are to be used, then the initiator will have */ 7088 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 7089 /* send-back what they are. If that information cannot be determined, */ 7090 /* then we send-back -1's for the sizes. If things go wrong for any */ 7091 /* reason, we will drop back ten yards and punt. */ 7092 7093 /* If anything goes wrong, we want the remote to know about it. It */ 7094 /* would be best if the error that the remote reports to the user is */ 7095 /* the actual error we encountered, rather than some bogus unexpected */ 7096 /* response type message. */ 7097 7098 if (debug > 1) { 7099 fprintf(where,"recv_udp_stream: setting the response type...\n"); 7100 fflush(where); 7101 } 7102 7103 netperf_response.content.response_type = UDP_STREAM_RESPONSE; 7104 7105 if (debug > 2) { 7106 fprintf(where,"recv_udp_stream: the response type is set...\n"); 7107 fflush(where); 7108 } 7109 7110 /* We now alter the message_ptr variable to be at the desired */ 7111 /* alignment with the desired offset. */ 7112 7113 if (debug > 1) { 7114 fprintf(where,"recv_udp_stream: requested alignment of %d\n", 7115 udp_stream_request->recv_alignment); 7116 fflush(where); 7117 } 7118 7119 if (recv_width == 0) recv_width = 1; 7120 7121 recv_ring = allocate_buffer_ring(recv_width, 7122 udp_stream_request->message_size, 7123 udp_stream_request->recv_alignment, 7124 udp_stream_request->recv_offset); 7125 7126 if (debug > 1) { 7127 fprintf(where,"recv_udp_stream: receive alignment and offset set...\n"); 7128 fflush(where); 7129 } 7130 7131 /* Grab a socket to listen on, and then listen on it. */ 7132 7133 if (debug > 1) { 7134 fprintf(where,"recv_udp_stream: grabbing a socket...\n"); 7135 fflush(where); 7136 } 7137 7138 /* create_data_socket expects to find some things in the global */ 7139 /* variables, so set the globals based on the values in the request. */ 7140 /* once the socket has been created, we will set the response values */ 7141 /* based on the updated value of those globals. raj 7/94 */ 7142 lsr_size_req = udp_stream_request->recv_buf_size; 7143 loc_rcvavoid = udp_stream_request->so_rcvavoid; 7144 loc_sndavoid = udp_stream_request->so_sndavoid; 7145 local_connected = udp_stream_request->recv_connected; 7146 7147 set_hostname_and_port(local_name, 7148 port_buffer, 7149 nf_to_af(udp_stream_request->ipfamily), 7150 udp_stream_request->port); 7151 7152 local_res = complete_addrinfo(local_name, 7153 local_name, 7154 port_buffer, 7155 nf_to_af(udp_stream_request->ipfamily), 7156 SOCK_DGRAM, 7157 IPPROTO_UDP, 7158 0); 7159 7160 s_data = create_data_socket(local_res); 7161 7162 if (s_data == INVALID_SOCKET) { 7163 netperf_response.content.serv_errno = errno; 7164 send_response(); 7165 exit(1); 7166 } 7167 7168 udp_stream_response->test_length = udp_stream_request->test_length; 7169 7170 /* now get the port number assigned by the system */ 7171 addrlen = sizeof(myaddr_in); 7172 if (getsockname(s_data, 7173 (struct sockaddr *)&myaddr_in, 7174 &addrlen) == SOCKET_ERROR){ 7175 netperf_response.content.serv_errno = errno; 7176 close(s_data); 7177 send_response(); 7178 7179 exit(1); 7180 } 7181 7182 /* Now myaddr_in contains the port and the internet address this is */ 7183 /* returned to the sender also implicitly telling the sender that the */ 7184 /* socket buffer sizing has been done. */ 7185 7186 udp_stream_response->data_port_number = 7187 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 7188 netperf_response.content.serv_errno = 0; 7189 7190 /* But wait, there's more. If the initiator wanted cpu measurements, */ 7191 /* then we must call the calibrate routine, which will return the max */ 7192 /* rate back to the initiator. If the CPU was not to be measured, or */ 7193 /* something went wrong with the calibration, we will return a -1 to */ 7194 /* the initiator. */ 7195 7196 udp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 7197 udp_stream_response->measure_cpu = 0; 7198 if (udp_stream_request->measure_cpu) { 7199 /* We will pass the rate into the calibration routine. If the */ 7200 /* user did not specify one, it will be 0.0, and we will do a */ 7201 /* "real" calibration. Otherwise, all it will really do is */ 7202 /* store it away... */ 7203 udp_stream_response->measure_cpu = 1; 7204 udp_stream_response->cpu_rate = 7205 calibrate_local_cpu(udp_stream_request->cpu_rate); 7206 } 7207 7208 message_size = udp_stream_request->message_size; 7209 test_time = udp_stream_request->test_length; 7210 7211 /* before we send the response back to the initiator, pull some of */ 7212 /* the socket parms from the globals */ 7213 udp_stream_response->send_buf_size = lss_size; 7214 udp_stream_response->recv_buf_size = lsr_size; 7215 udp_stream_response->so_rcvavoid = loc_rcvavoid; 7216 udp_stream_response->so_sndavoid = loc_sndavoid; 7217 7218 send_response(); 7219 7220 /* Now it's time to start receiving data on the connection. We will */ 7221 /* first grab the apropriate counters and then start grabbing. */ 7222 7223 cpu_start(udp_stream_request->measure_cpu); 7224 7225 #ifdef WIN32 7226 /* this is used so the timer thread can close the socket out from */ 7227 /* under us, which to date is the easiest/cleanest/least */ 7228 /* Windows-specific way I can find to force the winsock calls to */ 7229 /* return WSAEINTR with the test is over. anything that will run on */ 7230 /* 95 and NT and is closer to what netperf expects from Unix signals */ 7231 /* and such would be appreciated raj 1/96 */ 7232 win_kludge_socket = s_data; 7233 #endif /* WIN32 */ 7234 7235 /* The loop will exit when the timer pops, or if we happen to recv a */ 7236 /* message of less than send_size bytes... */ 7237 7238 times_up = 0; 7239 7240 start_timer(test_time + PAD_TIME); 7241 7242 if (debug) { 7243 fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n"); 7244 fflush(where); 7245 } 7246 7247 /* We "connect" up to the remote post to allow us to use the recv */ 7248 /* call instead of the recvfrom call. Presumeably, this is a little */ 7249 /* simpler, and a little more efficient. */ 7250 7251 if (local_connected) { 7252 7253 /* Receive the first message using recvfrom to find the remote address */ 7254 remote_addrlen = sizeof(remote_addr); 7255 len = recvfrom(s_data, recv_ring->buffer_ptr, 7256 message_size, 0, 7257 (struct sockaddr*)&remote_addr, &remote_addrlen); 7258 if (len != message_size) { 7259 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) { 7260 netperf_response.content.serv_errno = errno; 7261 send_response(); 7262 exit(1); 7263 } 7264 } 7265 messages_recvd++; 7266 recv_ring = recv_ring->next; 7267 7268 7269 /* Now connect with the remote socket address */ 7270 if (connect(s_data, 7271 (struct sockaddr*)&remote_addr, 7272 remote_addrlen )== INVALID_SOCKET) { 7273 netperf_response.content.serv_errno = errno; 7274 close(s_data); 7275 send_response(); 7276 exit(1); 7277 } 7278 7279 if (debug) { 7280 fprintf(where,"recv_udp_stream: connected data socket\n"); 7281 fflush(where); 7282 } 7283 } 7284 7285 while (!times_up) { 7286 if(local_connected) { 7287 len = recv(s_data, 7288 recv_ring->buffer_ptr, 7289 message_size, 7290 0); 7291 } else { 7292 len = recvfrom(s_data, 7293 recv_ring->buffer_ptr, 7294 message_size, 7295 0,0,0); 7296 } 7297 7298 if (len != message_size) { 7299 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) { 7300 netperf_response.content.serv_errno = errno; 7301 send_response(); 7302 exit(1); 7303 } 7304 break; 7305 } 7306 messages_recvd++; 7307 recv_ring = recv_ring->next; 7308 } 7309 7310 if (debug) { 7311 fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd); 7312 fflush(where); 7313 } 7314 7315 7316 /* The loop now exits due timer or < send_size bytes received. in */ 7317 /* reality, we only really support a timed UDP_STREAM test. raj */ 7318 /* 12/95 */ 7319 7320 cpu_stop(udp_stream_request->measure_cpu,&elapsed_time); 7321 7322 if (times_up) { 7323 /* we ended on a timer, subtract the PAD_TIME */ 7324 elapsed_time -= (float)PAD_TIME; 7325 } 7326 else { 7327 stop_timer(); 7328 } 7329 7330 if (debug) { 7331 fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time); 7332 fflush(where); 7333 } 7334 7335 7336 /* We will count the "off" message that got us out of the loop */ 7337 bytes_received = (messages_recvd * message_size) + len; 7338 7339 /* send the results to the sender */ 7340 7341 if (debug) { 7342 fprintf(where, 7343 "recv_udp_stream: got %d bytes\n", 7344 bytes_received); 7345 fflush(where); 7346 } 7347 7348 netperf_response.content.response_type = UDP_STREAM_RESULTS; 7349 udp_stream_results->bytes_received = bytes_received; 7350 udp_stream_results->messages_recvd = messages_recvd; 7351 udp_stream_results->elapsed_time = elapsed_time; 7352 udp_stream_results->cpu_method = cpu_method; 7353 udp_stream_results->num_cpus = lib_num_loc_cpus; 7354 if (udp_stream_request->measure_cpu) { 7355 udp_stream_results->cpu_util = calc_cpu_util(elapsed_time); 7356 } 7357 else { 7358 udp_stream_results->cpu_util = (float) -1.0; 7359 } 7360 7361 if (debug > 1) { 7362 fprintf(where, 7363 "recv_udp_stream: test complete, sending results.\n"); 7364 fflush(where); 7365 } 7366 7367 send_response(); 7368 7369 close(s_data); 7370 7371 } 7372 7373 #ifndef WANT_MIGRATION 7375 void 7376 send_udp_rr(char remote_host[]) 7377 { 7378 7379 char *tput_title = "\ 7380 Local /Remote\n\ 7381 Socket Size Request Resp. Elapsed Trans.\n\ 7382 Send Recv Size Size Time Rate \n\ 7383 bytes Bytes bytes bytes secs. per sec \n\n"; 7384 7385 char *tput_title_band = "\ 7386 Local /Remote\n\ 7387 Socket Size Request Resp. Elapsed \n\ 7388 Send Recv Size Size Time Throughput \n\ 7389 bytes Bytes bytes bytes secs. %s/sec \n\n"; 7390 7391 char *tput_fmt_0 = 7392 "%7.2f %s\n"; 7393 7394 char *tput_fmt_1_line_1 = "\ 7395 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 7396 7397 char *tput_fmt_1_line_2 = "\ 7398 %-6d %-6d\n"; 7399 7400 char *cpu_title = "\ 7401 Local /Remote\n\ 7402 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 7403 Send Recv Size Size Time Rate local remote local remote\n\ 7404 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 7405 7406 char *cpu_title_tput = "\ 7407 Local /Remote\n\ 7408 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 7409 Send Recv Size Size Time %-8.8s local remote local remote\n\ 7410 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 7411 7412 char *cpu_fmt_0 = 7413 "%6.3f %c %s\n"; 7414 7415 char *cpu_fmt_1_line_1 = "\ 7416 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 7417 7418 char *cpu_fmt_1_line_2 = "\ 7419 %-6d %-6d\n"; 7420 7421 float elapsed_time; 7422 7423 struct ring_elt *send_ring; 7424 struct ring_elt *recv_ring; 7425 7426 int len; 7427 int nummessages; 7428 SOCKET send_socket; 7429 int trans_remaining; 7430 int bytes_xferd; 7431 7432 int rsp_bytes_recvd; 7433 7434 float local_cpu_utilization; 7435 float local_service_demand; 7436 float remote_cpu_utilization; 7437 float remote_service_demand; 7438 double thruput; 7439 7440 struct addrinfo *local_res; 7441 struct addrinfo *remote_res; 7442 7443 struct udp_rr_request_struct *udp_rr_request; 7444 struct udp_rr_response_struct *udp_rr_response; 7445 struct udp_rr_results_struct *udp_rr_result; 7446 7447 udp_rr_request = 7448 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data; 7449 udp_rr_response = 7450 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data; 7451 udp_rr_result = 7452 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data; 7453 7454 #ifdef WANT_HISTOGRAM 7455 if (verbosity > 1) { 7456 time_hist = HIST_new(); 7457 } 7458 #endif 7459 7460 /* since we are now disconnected from the code that established the */ 7461 /* control socket, and since we want to be able to use different */ 7462 /* protocols and such, we are passed the name of the remote host and */ 7463 /* must turn that into the test specific addressing information. */ 7464 7465 complete_addrinfos(&remote_res, 7466 &local_res, 7467 remote_host, 7468 SOCK_DGRAM, 7469 IPPROTO_UDP, 7470 0); 7471 7472 if ( print_headers ) { 7473 print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res); 7474 } 7475 7476 /* initialize a few counters */ 7477 7478 send_ring = NULL; 7479 recv_ring = NULL; 7480 nummessages = 0; 7481 bytes_xferd = 0; 7482 times_up = 0; 7483 confidence_iteration = 1; 7484 init_stat(); 7485 7486 /* we have a great-big while loop which controls the number of times */ 7487 /* we run a particular test. this is for the calculation of a */ 7488 /* confidence interval (I really should have stayed awake during */ 7489 /* probstats :). If the user did not request confidence measurement */ 7490 /* (no confidence is the default) then we will only go though the */ 7491 /* loop once. the confidence stuff originates from the folks at IBM */ 7492 7493 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 7494 (confidence_iteration <= iteration_min)) { 7495 7496 nummessages = 0; 7497 bytes_xferd = 0; 7498 times_up = 0; 7499 trans_remaining = 0; 7500 7501 /* set-up the data buffers with the requested alignment and offset */ 7502 7503 if (send_width == 0) send_width = 1; 7504 if (recv_width == 0) recv_width = 1; 7505 7506 if (send_ring == NULL) { 7507 send_ring = allocate_buffer_ring(send_width, 7508 req_size, 7509 local_send_align, 7510 local_send_offset); 7511 } 7512 7513 if (recv_ring == NULL) { 7514 recv_ring = allocate_buffer_ring(recv_width, 7515 rsp_size, 7516 local_recv_align, 7517 local_recv_offset); 7518 } 7519 7520 /*set up the data socket */ 7521 send_socket = create_data_socket(local_res); 7522 7523 if (send_socket == INVALID_SOCKET){ 7524 perror("netperf: send_udp_rr: udp rr data socket"); 7525 exit(1); 7526 } 7527 7528 if (debug) { 7529 fprintf(where,"send_udp_rr: send_socket obtained...\n"); 7530 } 7531 7532 /* If the user has requested cpu utilization measurements, we must */ 7533 /* calibrate the cpu(s). We will perform this task within the tests */ 7534 /* themselves. If the user has specified the cpu rate, then */ 7535 /* calibrate_local_cpu will return rather quickly as it will have */ 7536 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 7537 /* all the "normal" calibration stuff and return the rate back. If */ 7538 /* there is no idle counter in the kernel idle loop, the */ 7539 /* local_cpu_rate will be set to -1. */ 7540 7541 if (local_cpu_usage) { 7542 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 7543 } 7544 7545 if (!no_control) { 7546 /* Tell the remote end to do a listen. The server alters the 7547 socket paramters on the other side at this point, hence the 7548 reason for all the values being passed in the setup 7549 message. If the user did not specify any of the parameters, 7550 they will be passed as 0, which will indicate to the remote 7551 that no changes beyond the system's default should be 7552 used. Alignment is the exception, it will default to 8, which 7553 will be no alignment alterations. */ 7554 7555 netperf_request.content.request_type = DO_UDP_RR; 7556 udp_rr_request->recv_buf_size = rsr_size_req; 7557 udp_rr_request->send_buf_size = rss_size_req; 7558 udp_rr_request->recv_alignment = remote_recv_align; 7559 udp_rr_request->recv_offset = remote_recv_offset; 7560 udp_rr_request->send_alignment = remote_send_align; 7561 udp_rr_request->send_offset = remote_send_offset; 7562 udp_rr_request->request_size = req_size; 7563 udp_rr_request->response_size = rsp_size; 7564 udp_rr_request->measure_cpu = remote_cpu_usage; 7565 udp_rr_request->cpu_rate = remote_cpu_rate; 7566 udp_rr_request->so_rcvavoid = rem_rcvavoid; 7567 udp_rr_request->so_sndavoid = rem_sndavoid; 7568 if (test_time) { 7569 udp_rr_request->test_length = test_time; 7570 } 7571 else { 7572 udp_rr_request->test_length = test_trans * -1; 7573 } 7574 udp_rr_request->port = atoi(remote_data_port); 7575 udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 7576 7577 if (debug > 1) { 7578 fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n"); 7579 } 7580 7581 send_request(); 7582 7583 /* The response from the remote will contain all of the relevant 7584 socket parameters for this test type. We will put them back 7585 into the variables here so they can be displayed if desired. 7586 The remote will have calibrated CPU if necessary, and will 7587 have done all the needed set-up we will have calibrated the 7588 cpu locally before sending the request, and will grab the 7589 counter value right after the connect returns. The remote 7590 will grab the counter right after the accept call. This saves 7591 the hassle of extra messages being sent for the UDP 7592 tests. */ 7593 7594 recv_response(); 7595 7596 if (!netperf_response.content.serv_errno) { 7597 if (debug) 7598 fprintf(where,"remote listen done.\n"); 7599 rsr_size = udp_rr_response->recv_buf_size; 7600 rss_size = udp_rr_response->send_buf_size; 7601 remote_cpu_usage = udp_rr_response->measure_cpu; 7602 remote_cpu_rate = udp_rr_response->cpu_rate; 7603 /* port numbers in proper order */ 7604 set_port_number(remote_res,(short)udp_rr_response->data_port_number); 7605 } 7606 else { 7607 Set_errno(netperf_response.content.serv_errno); 7608 fprintf(where, 7609 "netperf: remote error %d", 7610 netperf_response.content.serv_errno); 7611 perror(""); 7612 fflush(where); 7613 exit(1); 7614 } 7615 } 7616 7617 #ifdef WANT_DEMO 7618 demo_rr_setup(100); 7619 #endif 7620 7621 /* Connect up to the remote port on the data socket. This will set */ 7622 /* the default destination address on this socket. With UDP, this */ 7623 /* does make a performance difference as we may not have to do as */ 7624 /* many routing lookups, however, I expect that a client would */ 7625 /* behave this way. raj 1/94 */ 7626 7627 if ( connect(send_socket, 7628 remote_res->ai_addr, 7629 remote_res->ai_addrlen) == INVALID_SOCKET ) { 7630 perror("netperf: data socket connect failed"); 7631 exit(1); 7632 } 7633 7634 #ifdef WIN32 7635 /* this is used so the timer thread can close the socket out from */ 7636 /* under us, which to date is the easiest/cleanest/least */ 7637 /* Windows-specific way I can find to force the winsock calls to */ 7638 /* return WSAEINTR with the test is over. anything that will run on */ 7639 /* 95 and NT and is closer to what netperf expects from Unix signals */ 7640 /* and such would be appreciated raj 1/96 */ 7641 win_kludge_socket = send_socket; 7642 #endif /* WIN32 */ 7643 7644 /* Data Socket set-up is finished. If there were problems, either the */ 7645 /* connect would have failed, or the previous response would have */ 7646 /* indicated a problem. I failed to see the value of the extra */ 7647 /* message after the accept on the remote. If it failed, we'll see it */ 7648 /* here. If it didn't, we might as well start pumping data. */ 7649 7650 /* Set-up the test end conditions. For a request/response test, they */ 7651 /* can be either time or transaction based. */ 7652 7653 if (test_time) { 7654 /* The user wanted to end the test after a period of time. */ 7655 times_up = 0; 7656 trans_remaining = 0; 7657 start_timer(test_time); 7658 } 7659 else { 7660 /* The tester wanted to send a number of bytes. */ 7661 trans_remaining = test_bytes; 7662 times_up = 1; 7663 } 7664 7665 /* The cpu_start routine will grab the current time and possibly */ 7666 /* value of the idle counter for later use in measuring cpu */ 7667 /* utilization and/or service demand and thruput. */ 7668 7669 cpu_start(local_cpu_usage); 7670 7671 #ifdef WANT_DEMO 7672 if (demo_mode) { 7673 demo_first_timestamp(); 7674 } 7675 #endif 7676 7677 #ifdef WANT_INTERVALS 7678 INTERVALS_INIT(); 7679 #endif /* WANT_INTERVALS */ 7680 7681 /* We use an "OR" to control test execution. When the test is */ 7682 /* controlled by time, the byte count check will always return */ 7683 /* false. When the test is controlled by byte count, the time test */ 7684 /* will always return false. When the test is finished, the whole */ 7685 /* expression will go false and we will stop sending data. I think */ 7686 /* I just arbitrarily decrement trans_remaining for the timed */ 7687 /* test, but will not do that just yet... One other question is */ 7688 /* whether or not the send buffer and the receive buffer should be */ 7689 /* the same buffer. */ 7690 7691 #ifdef WANT_FIRST_BURST 7692 { 7693 int i; 7694 for (i = 0; i < first_burst_size; i++) { 7695 if((len=send(send_socket, 7696 send_ring->buffer_ptr, 7697 req_size, 7698 0)) != req_size) { 7699 /* we should never hit the end of the test in the first burst */ 7700 perror("send_udp_rr: initial burst data send error"); 7701 exit(-1); 7702 } 7703 } 7704 } 7705 #endif /* WANT_FIRST_BURST */ 7706 7707 while ((!times_up) || (trans_remaining > 0)) { 7708 /* send the request */ 7709 #ifdef WANT_HISTOGRAM 7710 if (verbosity > 1) { 7711 HIST_timestamp(&time_one); 7712 } 7713 #endif 7714 if((len=send(send_socket, 7715 send_ring->buffer_ptr, 7716 req_size, 7717 0)) != req_size) { 7718 if (SOCKET_EINTR(len)) { 7719 /* We likely hit */ 7720 /* test-end time. */ 7721 break; 7722 } 7723 perror("send_udp_rr: data send error"); 7724 exit(1); 7725 } 7726 send_ring = send_ring->next; 7727 7728 /* receive the response. with UDP we will get it all, or nothing */ 7729 7730 if((rsp_bytes_recvd=recv(send_socket, 7731 recv_ring->buffer_ptr, 7732 rsp_size, 7733 0)) != rsp_size) { 7734 if (SOCKET_EINTR(rsp_bytes_recvd)) 7735 { 7736 /* Again, we have likely hit test-end time */ 7737 break; 7738 } 7739 perror("send_udp_rr: data recv error"); 7740 exit(1); 7741 } 7742 recv_ring = recv_ring->next; 7743 7744 #ifdef WANT_HISTOGRAM 7745 if (verbosity > 1) { 7746 HIST_timestamp(&time_two); 7747 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 7748 } 7749 7750 #endif 7751 7752 /* at this point, we may wish to sleep for some period of */ 7753 /* time, so we see how long that last transaction just took, */ 7754 /* and sleep for the difference of that and the interval. We */ 7755 /* will not sleep if the time would be less than a */ 7756 /* millisecond. */ 7757 7758 #ifdef WANT_DEMO 7759 demo_rr_interval(1); 7760 #endif 7761 7762 #ifdef WANT_INTERVALS 7763 INTERVALS_WAIT(); 7764 #endif /* WANT_INTERVALS */ 7765 7766 nummessages++; 7767 if (trans_remaining) { 7768 trans_remaining--; 7769 } 7770 7771 if (debug > 3) { 7772 if ((nummessages % 100) == 0) { 7773 fprintf(where,"Transaction %d completed\n",nummessages); 7774 fflush(where); 7775 } 7776 } 7777 7778 } 7779 7780 /* for some strange reason, I used to call shutdown on the UDP */ 7781 /* data socket here. I'm not sure why, because it would not have */ 7782 /* any effect... raj 11/94 */ 7783 7784 /* this call will always give us the elapsed time for the test, and */ 7785 /* will also store-away the necessaries for cpu utilization */ 7786 7787 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 7788 /* measured? how long */ 7789 /* did we really run? */ 7790 7791 #if defined(WANT_INTERVALS) 7792 #ifdef WIN32 7793 stop_itimer(); 7794 #endif 7795 #endif /* WANT_INTERVALS */ 7796 7797 if (!no_control) { 7798 /* Get the statistics from the remote end. The remote will have 7799 calculated service demand and all those interesting 7800 things. If it wasn't supposed to care, it will return obvious 7801 values. */ 7802 7803 recv_response(); 7804 if (!netperf_response.content.serv_errno) { 7805 if (debug) 7806 fprintf(where,"remote results obtained\n"); 7807 } 7808 else { 7809 Set_errno(netperf_response.content.serv_errno); 7810 fprintf(where, 7811 "netperf: remote error %d", 7812 netperf_response.content.serv_errno); 7813 perror(""); 7814 fflush(where); 7815 exit(1); 7816 } 7817 } 7818 7819 /* We now calculate what our thruput was for the test. In the */ 7820 /* future, we may want to include a calculation of the thruput */ 7821 /* measured by the remote, but it should be the case that for a */ 7822 /* UDP rr test, that the two numbers should be *very* close... */ 7823 /* We calculate bytes_sent regardless of the way the test length */ 7824 /* was controlled. */ 7825 7826 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 7827 thruput = nummessages / elapsed_time; 7828 7829 if (local_cpu_usage || remote_cpu_usage) { 7830 7831 /* We must now do a little math for service demand and cpu */ 7832 /* utilization for the system(s) Of course, some of the */ 7833 /* information might be bogus because there was no idle counter */ 7834 /* in the kernel(s). We need to make a note of this for the */ 7835 /* user's benefit by placing a code for the metod used in the */ 7836 /* test banner */ 7837 7838 if (local_cpu_usage) { 7839 local_cpu_utilization = calc_cpu_util(0.0); 7840 7841 /* since calc_service demand is doing ms/Kunit we will */ 7842 /* multiply the number of transaction by 1024 to get */ 7843 /* "good" numbers */ 7844 7845 local_service_demand = calc_service_demand((double) nummessages*1024, 7846 0.0, 7847 0.0, 7848 0); 7849 } 7850 else { 7851 local_cpu_utilization = (float) -1.0; 7852 local_service_demand = (float) -1.0; 7853 } 7854 7855 if (remote_cpu_usage) { 7856 remote_cpu_utilization = udp_rr_result->cpu_util; 7857 7858 /* since calc_service demand is doing ms/Kunit we will */ 7859 /* multiply the number of transaction by 1024 to get */ 7860 /* "good" numbers */ 7861 7862 remote_service_demand = calc_service_demand((double) nummessages*1024, 7863 0.0, 7864 remote_cpu_utilization, 7865 udp_rr_result->num_cpus); 7866 } 7867 else { 7868 remote_cpu_utilization = (float) -1.0; 7869 remote_service_demand = (float) -1.0; 7870 } 7871 } 7872 else { 7873 /* we were not measuring cpu, for the confidence stuff, we */ 7874 /* should make it -1.0 */ 7875 local_cpu_utilization = (float) -1.0; 7876 local_service_demand = (float) -1.0; 7877 remote_cpu_utilization = (float) -1.0; 7878 remote_service_demand = (float) -1.0; 7879 } 7880 7881 /* at this point, we want to calculate the confidence information. */ 7882 /* if debugging is on, calculate_confidence will print-out the */ 7883 /* parameters we pass it */ 7884 7885 calculate_confidence(confidence_iteration, 7886 elapsed_time, 7887 thruput, 7888 local_cpu_utilization, 7889 remote_cpu_utilization, 7890 local_service_demand, 7891 remote_service_demand); 7892 7893 7894 confidence_iteration++; 7895 7896 /* we are done with the socket */ 7897 close(send_socket); 7898 } 7899 7900 /* at this point, we have made all the iterations we are going to */ 7901 /* make. */ 7902 retrieve_confident_values(&elapsed_time, 7903 &thruput, 7904 &local_cpu_utilization, 7905 &remote_cpu_utilization, 7906 &local_service_demand, 7907 &remote_service_demand); 7908 7909 /* We are now ready to print all the information. If the user */ 7910 /* has specified zero-level verbosity, we will just print the */ 7911 /* local service demand, or the remote service demand. If the */ 7912 /* user has requested verbosity level 1, he will get the basic */ 7913 /* "streamperf" numbers. If the user has specified a verbosity */ 7914 /* of greater than 1, we will display a veritable plethora of */ 7915 /* background information from outside of this block as it it */ 7916 /* not cpu_measurement specific... */ 7917 7918 if (confidence < 0) { 7919 /* we did not hit confidence, but were we asked to look for it? */ 7920 if (iteration_max > 1) { 7921 display_confidence(); 7922 } 7923 } 7924 7925 if (local_cpu_usage || remote_cpu_usage) { 7926 local_cpu_method = format_cpu_method(cpu_method); 7927 remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method); 7928 7929 switch (verbosity) { 7930 case 0: 7931 if (local_cpu_usage) { 7932 fprintf(where, 7933 cpu_fmt_0, 7934 local_service_demand, 7935 local_cpu_method, 7936 ((print_headers) || 7937 (result_brand == NULL)) ? "" : result_brand); 7938 7939 } 7940 else { 7941 fprintf(where, 7942 cpu_fmt_0, 7943 remote_service_demand, 7944 remote_cpu_method, 7945 ((print_headers) || 7946 (result_brand == NULL)) ? "" : result_brand); 7947 7948 } 7949 break; 7950 case 1: 7951 case 2: 7952 if (print_headers) { 7953 if ('x' == libfmt) { 7954 fprintf(where, 7955 cpu_title, 7956 local_cpu_method, 7957 remote_cpu_method); 7958 } 7959 else { 7960 fprintf(where, 7961 cpu_title_tput, 7962 format_units(), 7963 local_cpu_method, 7964 remote_cpu_method); 7965 } 7966 } 7967 7968 fprintf(where, 7969 cpu_fmt_1_line_1, /* the format string */ 7970 lss_size, /* local sendbuf size */ 7971 lsr_size, 7972 req_size, /* how large were the requests */ 7973 rsp_size, /* guess */ 7974 elapsed_time, /* how long was the test */ 7975 ('x' == libfmt) ? thruput : 7976 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 7977 1.0), 7978 local_cpu_utilization, /* local cpu */ 7979 remote_cpu_utilization, /* remote cpu */ 7980 local_service_demand, /* local service demand */ 7981 remote_service_demand, /* remote service demand */ 7982 ((print_headers) || 7983 (result_brand == NULL)) ? "" : result_brand); 7984 fprintf(where, 7985 cpu_fmt_1_line_2, 7986 rss_size, 7987 rsr_size); 7988 break; 7989 } 7990 } 7991 else { 7992 /* The tester did not wish to measure service demand. */ 7993 switch (verbosity) { 7994 case 0: 7995 fprintf(where, 7996 tput_fmt_0, 7997 ('x' == libfmt) ? thruput : 7998 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 7999 1.0), 8000 ((print_headers) || 8001 (result_brand == NULL)) ? "" : result_brand); 8002 break; 8003 case 1: 8004 case 2: 8005 if (print_headers) { 8006 fprintf(where, 8007 ('x' == libfmt) ? tput_title : tput_title_band, 8008 format_units()); 8009 } 8010 8011 fprintf(where, 8012 tput_fmt_1_line_1, /* the format string */ 8013 lss_size, 8014 lsr_size, 8015 req_size, /* how large were the requests */ 8016 rsp_size, /* how large were the responses */ 8017 elapsed_time, /* how long did it take */ 8018 ('x' == libfmt) ? thruput : 8019 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 8020 1.0), 8021 ((print_headers) || 8022 (result_brand == NULL)) ? "" : result_brand); 8023 fprintf(where, 8024 tput_fmt_1_line_2, 8025 rss_size, /* remote recvbuf size */ 8026 rsr_size); 8027 8028 break; 8029 } 8030 } 8031 fflush(where); 8032 8033 /* it would be a good thing to include information about some of the */ 8034 /* other parameters that may have been set for this test, but at the */ 8035 /* moment, I do not wish to figure-out all the formatting, so I will */ 8036 /* just put this comment here to help remind me that it is something */ 8037 /* that should be done at a later time. */ 8038 8039 /* how to handle the verbose information in the presence of */ 8040 /* confidence intervals is yet to be determined... raj 11/94 */ 8041 8042 if (verbosity > 1) { 8043 /* The user wanted to know it all, so we will give it to him. */ 8044 /* This information will include as much as we can find about */ 8045 /* UDP statistics, the alignments of the sends and receives */ 8046 /* and all that sort of rot... */ 8047 8048 #ifdef WANT_HISTOGRAM 8049 fprintf(where,"\nHistogram of request/reponse times.\n"); 8050 fflush(where); 8051 HIST_report(time_hist); 8052 #endif /* WANT_HISTOGRAM */ 8053 } 8054 } 8055 #endif /* WANT_MIGRATION */ 8056 8057 /* this routine implements the receive side (netserver) of a UDP_RR */ 8059 /* test. */ 8060 void 8061 recv_udp_rr() 8062 { 8063 8064 struct ring_elt *recv_ring; 8065 struct ring_elt *send_ring; 8066 8067 struct addrinfo *local_res; 8068 char local_name[BUFSIZ]; 8069 char port_buffer[PORTBUFSIZE]; 8070 8071 struct sockaddr_storage myaddr_in; 8072 struct sockaddr_storage peeraddr; 8073 SOCKET s_data; 8074 netperf_socklen_t addrlen; 8075 int trans_received; 8076 int trans_remaining; 8077 int request_bytes_recvd; 8078 int response_bytes_sent; 8079 float elapsed_time; 8080 8081 struct udp_rr_request_struct *udp_rr_request; 8082 struct udp_rr_response_struct *udp_rr_response; 8083 struct udp_rr_results_struct *udp_rr_results; 8084 8085 udp_rr_request = 8086 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data; 8087 udp_rr_response = 8088 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data; 8089 udp_rr_results = 8090 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data; 8091 8092 if (debug) { 8093 fprintf(where,"netserver: recv_udp_rr: entered...\n"); 8094 fflush(where); 8095 } 8096 8097 /* We want to set-up the listen socket with all the desired */ 8098 /* parameters and then let the initiator know that all is ready. If */ 8099 /* socket size defaults are to be used, then the initiator will have */ 8100 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 8101 /* send-back what they are. If that information cannot be determined, */ 8102 /* then we send-back -1's for the sizes. If things go wrong for any */ 8103 /* reason, we will drop back ten yards and punt. */ 8104 8105 /* If anything goes wrong, we want the remote to know about it. It */ 8106 /* would be best if the error that the remote reports to the user is */ 8107 /* the actual error we encountered, rather than some bogus unexpected */ 8108 /* response type message. */ 8109 8110 if (debug) { 8111 fprintf(where,"recv_udp_rr: setting the response type...\n"); 8112 fflush(where); 8113 } 8114 8115 netperf_response.content.response_type = UDP_RR_RESPONSE; 8116 8117 if (debug) { 8118 fprintf(where,"recv_udp_rr: the response type is set...\n"); 8119 fflush(where); 8120 } 8121 8122 /* We now alter the message_ptr variables to be at the desired */ 8123 /* alignments with the desired offsets. */ 8124 8125 if (debug) { 8126 fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n", 8127 udp_rr_request->recv_alignment, 8128 udp_rr_request->recv_offset); 8129 fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n", 8130 udp_rr_request->send_alignment, 8131 udp_rr_request->send_offset); 8132 fflush(where); 8133 } 8134 8135 if (send_width == 0) send_width = 1; 8136 if (recv_width == 0) recv_width = 1; 8137 8138 recv_ring = allocate_buffer_ring(recv_width, 8139 udp_rr_request->request_size, 8140 udp_rr_request->recv_alignment, 8141 udp_rr_request->recv_offset); 8142 8143 send_ring = allocate_buffer_ring(send_width, 8144 udp_rr_request->response_size, 8145 udp_rr_request->send_alignment, 8146 udp_rr_request->send_offset); 8147 8148 if (debug) { 8149 fprintf(where,"recv_udp_rr: receive alignment and offset set...\n"); 8150 fflush(where); 8151 } 8152 8153 /* Grab a socket to listen on, and then listen on it. */ 8154 8155 if (debug) { 8156 fprintf(where,"recv_udp_rr: grabbing a socket...\n"); 8157 fflush(where); 8158 } 8159 8160 8161 /* create_data_socket expects to find some things in the global */ 8162 /* variables, so set the globals based on the values in the request. */ 8163 /* once the socket has been created, we will set the response values */ 8164 /* based on the updated value of those globals. raj 7/94 */ 8165 lss_size_req = udp_rr_request->send_buf_size; 8166 lsr_size_req = udp_rr_request->recv_buf_size; 8167 loc_rcvavoid = udp_rr_request->so_rcvavoid; 8168 loc_sndavoid = udp_rr_request->so_sndavoid; 8169 8170 set_hostname_and_port(local_name, 8171 port_buffer, 8172 nf_to_af(udp_rr_request->ipfamily), 8173 udp_rr_request->port); 8174 8175 local_res = complete_addrinfo(local_name, 8176 local_name, 8177 port_buffer, 8178 nf_to_af(udp_rr_request->ipfamily), 8179 SOCK_DGRAM, 8180 IPPROTO_UDP, 8181 0); 8182 8183 s_data = create_data_socket(local_res); 8184 8185 if (s_data == INVALID_SOCKET) { 8186 netperf_response.content.serv_errno = errno; 8187 send_response(); 8188 8189 exit(1); 8190 } 8191 8192 /* now get the port number assigned by the system */ 8193 addrlen = sizeof(myaddr_in); 8194 if (getsockname(s_data, 8195 (struct sockaddr *)&myaddr_in, 8196 &addrlen) == SOCKET_ERROR){ 8197 netperf_response.content.serv_errno = errno; 8198 close(s_data); 8199 send_response(); 8200 8201 exit(1); 8202 } 8203 8204 /* Now myaddr_in contains the port and the internet address this is */ 8205 /* returned to the sender also implicitly telling the sender that the */ 8206 /* socket buffer sizing has been done. */ 8207 8208 udp_rr_response->data_port_number = 8209 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 8210 netperf_response.content.serv_errno = 0; 8211 8212 if (debug) { 8213 fprintf(where, 8214 "recv port number %d\n", 8215 ((struct sockaddr_in *)&myaddr_in)->sin_port); 8216 fflush(where); 8217 } 8218 8219 /* But wait, there's more. If the initiator wanted cpu measurements, */ 8220 /* then we must call the calibrate routine, which will return the max */ 8221 /* rate back to the initiator. If the CPU was not to be measured, or */ 8222 /* something went wrong with the calibration, we will return a 0.0 to */ 8223 /* the initiator. */ 8224 8225 udp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 8226 udp_rr_response->measure_cpu = 0; 8227 if (udp_rr_request->measure_cpu) { 8228 udp_rr_response->measure_cpu = 1; 8229 udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate); 8230 } 8231 8232 /* before we send the response back to the initiator, pull some of */ 8233 /* the socket parms from the globals */ 8234 udp_rr_response->send_buf_size = lss_size; 8235 udp_rr_response->recv_buf_size = lsr_size; 8236 udp_rr_response->so_rcvavoid = loc_rcvavoid; 8237 udp_rr_response->so_sndavoid = loc_sndavoid; 8238 8239 send_response(); 8240 8241 8242 /* Now it's time to start receiving data on the connection. We will */ 8243 /* first grab the apropriate counters and then start grabbing. */ 8244 8245 cpu_start(udp_rr_request->measure_cpu); 8246 8247 #ifdef WIN32 8248 /* this is used so the timer thread can close the socket out from */ 8249 /* under us, which to date is the easiest/cleanest/least */ 8250 /* Windows-specific way I can find to force the winsock calls to */ 8251 /* return WSAEINTR with the test is over. anything that will run on */ 8252 /* 95 and NT and is closer to what netperf expects from Unix signals */ 8253 /* and such would be appreciated raj 1/96 */ 8254 win_kludge_socket = s_data; 8255 #endif /* WIN32 */ 8256 8257 if (udp_rr_request->test_length > 0) { 8258 times_up = 0; 8259 trans_remaining = 0; 8260 start_timer(udp_rr_request->test_length + PAD_TIME); 8261 } 8262 else { 8263 times_up = 1; 8264 trans_remaining = udp_rr_request->test_length * -1; 8265 } 8266 8267 addrlen = sizeof(peeraddr); 8268 bzero((char *)&peeraddr, addrlen); 8269 8270 trans_received = 0; 8271 8272 while ((!times_up) || (trans_remaining > 0)) { 8273 8274 /* receive the request from the other side */ 8275 if ((request_bytes_recvd = recvfrom(s_data, 8276 recv_ring->buffer_ptr, 8277 udp_rr_request->request_size, 8278 0, 8279 (struct sockaddr *)&peeraddr, 8280 &addrlen)) != udp_rr_request->request_size) { 8281 if ( SOCKET_EINTR(request_bytes_recvd) ) 8282 { 8283 /* we must have hit the end of test time. */ 8284 break; 8285 } 8286 netperf_response.content.serv_errno = errno; 8287 send_response(); 8288 exit(1); 8289 } 8290 recv_ring = recv_ring->next; 8291 8292 /* Now, send the response to the remote */ 8293 if ((response_bytes_sent = sendto(s_data, 8294 send_ring->buffer_ptr, 8295 udp_rr_request->response_size, 8296 0, 8297 (struct sockaddr *)&peeraddr, 8298 addrlen)) != 8299 udp_rr_request->response_size) { 8300 if ( SOCKET_EINTR(response_bytes_sent) ) 8301 { 8302 /* we have hit end of test time. */ 8303 break; 8304 } 8305 netperf_response.content.serv_errno = errno; 8306 send_response(); 8307 exit(1); 8308 } 8309 send_ring = send_ring->next; 8310 8311 trans_received++; 8312 if (trans_remaining) { 8313 trans_remaining--; 8314 } 8315 8316 if (debug) { 8317 fprintf(where, 8318 "recv_udp_rr: Transaction %d complete.\n", 8319 trans_received); 8320 fflush(where); 8321 } 8322 8323 } 8324 8325 8326 /* The loop now exits due to timeout or transaction count being */ 8327 /* reached */ 8328 8329 cpu_stop(udp_rr_request->measure_cpu,&elapsed_time); 8330 8331 if (times_up) { 8332 /* we ended the test by time, which was at least 2 seconds */ 8333 /* longer than we wanted to run. so, we want to subtract */ 8334 /* PAD_TIME from the elapsed_time. */ 8335 elapsed_time -= PAD_TIME; 8336 } 8337 /* send the results to the sender */ 8338 8339 if (debug) { 8340 fprintf(where, 8341 "recv_udp_rr: got %d transactions\n", 8342 trans_received); 8343 fflush(where); 8344 } 8345 8346 udp_rr_results->bytes_received = (trans_received * 8347 (udp_rr_request->request_size + 8348 udp_rr_request->response_size)); 8349 udp_rr_results->trans_received = trans_received; 8350 udp_rr_results->elapsed_time = elapsed_time; 8351 udp_rr_results->cpu_method = cpu_method; 8352 udp_rr_results->num_cpus = lib_num_loc_cpus; 8353 if (udp_rr_request->measure_cpu) { 8354 udp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 8355 } 8356 8357 if (debug) { 8358 fprintf(where, 8359 "recv_udp_rr: test complete, sending results.\n"); 8360 fflush(where); 8361 } 8362 8363 send_response(); 8364 8365 /* we are done with the socket now */ 8366 close(s_data); 8367 8368 } 8369 8370 8371 /* this routine implements the receive (netserver) side of a TCP_RR */ 8373 /* test */ 8374 void 8375 recv_tcp_rr() 8376 { 8377 8378 struct ring_elt *send_ring; 8379 struct ring_elt *recv_ring; 8380 8381 struct addrinfo *local_res; 8382 char local_name[BUFSIZ]; 8383 char port_buffer[PORTBUFSIZE]; 8384 8385 struct sockaddr_storage myaddr_in, 8386 peeraddr_in; 8387 SOCKET s_listen,s_data; 8388 netperf_socklen_t addrlen; 8389 char *temp_message_ptr; 8390 int trans_received; 8391 int trans_remaining; 8392 int bytes_sent; 8393 int request_bytes_recvd; 8394 int request_bytes_remaining; 8395 int timed_out = 0; 8396 int sock_closed = 0; 8397 float elapsed_time; 8398 8399 struct tcp_rr_request_struct *tcp_rr_request; 8400 struct tcp_rr_response_struct *tcp_rr_response; 8401 struct tcp_rr_results_struct *tcp_rr_results; 8402 8403 tcp_rr_request = 8404 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 8405 tcp_rr_response = 8406 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 8407 tcp_rr_results = 8408 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 8409 8410 if (debug) { 8411 fprintf(where,"netserver: recv_tcp_rr: entered...\n"); 8412 fflush(where); 8413 } 8414 8415 /* We want to set-up the listen socket with all the desired */ 8416 /* parameters and then let the initiator know that all is ready. If */ 8417 /* socket size defaults are to be used, then the initiator will have */ 8418 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 8419 /* send-back what they are. If that information cannot be determined, */ 8420 /* then we send-back -1's for the sizes. If things go wrong for any */ 8421 /* reason, we will drop back ten yards and punt. */ 8422 8423 /* If anything goes wrong, we want the remote to know about it. It */ 8424 /* would be best if the error that the remote reports to the user is */ 8425 /* the actual error we encountered, rather than some bogus unexpected */ 8426 /* response type message. */ 8427 8428 if (debug) { 8429 fprintf(where,"recv_tcp_rr: setting the response type...\n"); 8430 fflush(where); 8431 } 8432 8433 netperf_response.content.response_type = TCP_RR_RESPONSE; 8434 8435 if (debug) { 8436 fprintf(where,"recv_tcp_rr: the response type is set...\n"); 8437 fflush(where); 8438 } 8439 8440 /* allocate the recv and send rings with the requested alignments */ 8441 /* and offsets. raj 7/94 */ 8442 if (debug) { 8443 fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n", 8444 tcp_rr_request->recv_alignment, 8445 tcp_rr_request->recv_offset); 8446 fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n", 8447 tcp_rr_request->send_alignment, 8448 tcp_rr_request->send_offset); 8449 fflush(where); 8450 } 8451 8452 /* at some point, these need to come to us from the remote system */ 8453 if (send_width == 0) send_width = 1; 8454 if (recv_width == 0) recv_width = 1; 8455 8456 send_ring = allocate_buffer_ring(send_width, 8457 tcp_rr_request->response_size, 8458 tcp_rr_request->send_alignment, 8459 tcp_rr_request->send_offset); 8460 8461 recv_ring = allocate_buffer_ring(recv_width, 8462 tcp_rr_request->request_size, 8463 tcp_rr_request->recv_alignment, 8464 tcp_rr_request->recv_offset); 8465 8466 8467 /* Grab a socket to listen on, and then listen on it. */ 8468 8469 if (debug) { 8470 fprintf(where,"recv_tcp_rr: grabbing a socket...\n"); 8471 fflush(where); 8472 } 8473 8474 /* create_data_socket expects to find some things in the global */ 8475 /* variables, so set the globals based on the values in the request. */ 8476 /* once the socket has been created, we will set the response values */ 8477 /* based on the updated value of those globals. raj 7/94 */ 8478 lss_size_req = tcp_rr_request->send_buf_size; 8479 lsr_size_req = tcp_rr_request->recv_buf_size; 8480 loc_nodelay = tcp_rr_request->no_delay; 8481 loc_rcvavoid = tcp_rr_request->so_rcvavoid; 8482 loc_sndavoid = tcp_rr_request->so_sndavoid; 8483 8484 set_hostname_and_port(local_name, 8485 port_buffer, 8486 nf_to_af(tcp_rr_request->ipfamily), 8487 tcp_rr_request->port); 8488 8489 local_res = complete_addrinfo(local_name, 8490 local_name, 8491 port_buffer, 8492 nf_to_af(tcp_rr_request->ipfamily), 8493 SOCK_STREAM, 8494 IPPROTO_TCP, 8495 0); 8496 8497 s_listen = create_data_socket(local_res); 8498 8499 if (s_listen == INVALID_SOCKET) { 8500 netperf_response.content.serv_errno = errno; 8501 send_response(); 8502 8503 exit(1); 8504 } 8505 8506 8507 #ifdef WIN32 8508 /* The test timer can fire during operations on the listening socket, 8509 so to make the start_timer below work we have to move 8510 it to close s_listen while we are blocked on accept. */ 8511 win_kludge_socket2 = s_listen; 8512 #endif 8513 8514 8515 /* Now, let's set-up the socket to listen for connections */ 8516 if (listen(s_listen, 5) == SOCKET_ERROR) { 8517 netperf_response.content.serv_errno = errno; 8518 close(s_listen); 8519 send_response(); 8520 8521 exit(1); 8522 } 8523 8524 8525 /* now get the port number assigned by the system */ 8526 addrlen = sizeof(myaddr_in); 8527 if (getsockname(s_listen, 8528 (struct sockaddr *)&myaddr_in, 8529 &addrlen) == SOCKET_ERROR) { 8530 netperf_response.content.serv_errno = errno; 8531 close(s_listen); 8532 send_response(); 8533 8534 exit(1); 8535 } 8536 8537 /* Now myaddr_in contains the port and the internet address this is */ 8538 /* returned to the sender also implicitly telling the sender that the */ 8539 /* socket buffer sizing has been done. */ 8540 8541 tcp_rr_response->data_port_number = 8542 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 8543 netperf_response.content.serv_errno = 0; 8544 8545 /* But wait, there's more. If the initiator wanted cpu measurements, */ 8546 /* then we must call the calibrate routine, which will return the max */ 8547 /* rate back to the initiator. If the CPU was not to be measured, or */ 8548 /* something went wrong with the calibration, we will return a 0.0 to */ 8549 /* the initiator. */ 8550 8551 tcp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 8552 tcp_rr_response->measure_cpu = 0; 8553 8554 if (tcp_rr_request->measure_cpu) { 8555 tcp_rr_response->measure_cpu = 1; 8556 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate); 8557 } 8558 8559 8560 /* before we send the response back to the initiator, pull some of */ 8561 /* the socket parms from the globals */ 8562 tcp_rr_response->send_buf_size = lss_size; 8563 tcp_rr_response->recv_buf_size = lsr_size; 8564 tcp_rr_response->no_delay = loc_nodelay; 8565 tcp_rr_response->so_rcvavoid = loc_rcvavoid; 8566 tcp_rr_response->so_sndavoid = loc_sndavoid; 8567 tcp_rr_response->test_length = tcp_rr_request->test_length; 8568 send_response(); 8569 8570 addrlen = sizeof(peeraddr_in); 8571 8572 if ((s_data = accept(s_listen, 8573 (struct sockaddr *)&peeraddr_in, 8574 &addrlen)) == INVALID_SOCKET) { 8575 /* Let's just punt. The remote will be given some information */ 8576 close(s_listen); 8577 8578 exit(1); 8579 } 8580 8581 #ifdef KLUDGE_SOCKET_OPTIONS 8582 /* this is for those systems which *INCORRECTLY* fail to pass */ 8583 /* attributes across an accept() call. Including this goes against */ 8584 /* my better judgement :( raj 11/95 */ 8585 8586 kludge_socket_options(s_data); 8587 8588 #endif /* KLUDGE_SOCKET_OPTIONS */ 8589 8590 #ifdef WIN32 8591 /* this is used so the timer thread can close the socket out from */ 8592 /* under us, which to date is the easiest/cleanest/least */ 8593 /* Windows-specific way I can find to force the winsock calls to */ 8594 /* return WSAEINTR with the test is over. anything that will run on */ 8595 /* 95 and NT and is closer to what netperf expects from Unix signals */ 8596 /* and such would be appreciated raj 1/96 */ 8597 win_kludge_socket = s_data; 8598 win_kludge_socket2 = INVALID_SOCKET; 8599 #endif /* WIN32 */ 8600 8601 if (debug) { 8602 fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n"); 8603 fflush(where); 8604 } 8605 8606 /* Now it's time to start receiving data on the connection. We will */ 8607 /* first grab the apropriate counters and then start grabbing. */ 8608 8609 cpu_start(tcp_rr_request->measure_cpu); 8610 8611 /* The loop will exit when we hit the end of the test time, or when */ 8612 /* we have exchanged the requested number of transactions. */ 8613 8614 if (tcp_rr_request->test_length > 0) { 8615 times_up = 0; 8616 trans_remaining = 0; 8617 start_timer(tcp_rr_request->test_length + PAD_TIME); 8618 } 8619 else { 8620 times_up = 1; 8621 trans_remaining = tcp_rr_request->test_length * -1; 8622 } 8623 8624 trans_received = 0; 8625 8626 while ((!times_up) || (trans_remaining > 0)) { 8627 temp_message_ptr = recv_ring->buffer_ptr; 8628 request_bytes_remaining = tcp_rr_request->request_size; 8629 while(request_bytes_remaining > 0) { 8630 if((request_bytes_recvd=recv(s_data, 8631 temp_message_ptr, 8632 request_bytes_remaining, 8633 0)) == SOCKET_ERROR) { 8634 if (SOCKET_EINTR(request_bytes_recvd)) 8635 { 8636 timed_out = 1; 8637 break; 8638 } 8639 8640 netperf_response.content.serv_errno = errno; 8641 send_response(); 8642 exit(1); 8643 } 8644 else if( request_bytes_recvd == 0 ) { 8645 if (debug) { 8646 fprintf(where,"zero is my hero\n"); 8647 fflush(where); 8648 } 8649 sock_closed = 1; 8650 break; 8651 } 8652 else { 8653 request_bytes_remaining -= request_bytes_recvd; 8654 temp_message_ptr += request_bytes_recvd; 8655 } 8656 } 8657 8658 recv_ring = recv_ring->next; 8659 8660 if ((timed_out) || (sock_closed)) { 8661 /* we hit the end of the test based on time - or the socket 8662 closed on us along the way. bail out of here now... */ 8663 if (debug) { 8664 fprintf(where,"yo5\n"); 8665 fflush(where); 8666 } 8667 break; 8668 } 8669 8670 /* Now, send the response to the remote */ 8671 if((bytes_sent=send(s_data, 8672 send_ring->buffer_ptr, 8673 tcp_rr_request->response_size, 8674 0)) == SOCKET_ERROR) { 8675 if (SOCKET_EINTR(bytes_sent)) { 8676 /* the test timer has popped */ 8677 timed_out = 1; 8678 fprintf(where,"yo6\n"); 8679 fflush(where); 8680 break; 8681 } 8682 netperf_response.content.serv_errno = 992; 8683 send_response(); 8684 exit(1); 8685 } 8686 8687 send_ring = send_ring->next; 8688 8689 trans_received++; 8690 if (trans_remaining) { 8691 trans_remaining--; 8692 } 8693 } 8694 8695 8696 /* The loop now exits due to timeout or transaction count being */ 8697 /* reached */ 8698 8699 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time); 8700 8701 stop_timer(); 8702 8703 if (timed_out) { 8704 /* we ended the test by time, which was at least 2 seconds */ 8705 /* longer than we wanted to run. so, we want to subtract */ 8706 /* PAD_TIME from the elapsed_time. */ 8707 elapsed_time -= PAD_TIME; 8708 } 8709 8710 /* send the results to the sender */ 8711 8712 if (debug) { 8713 fprintf(where, 8714 "recv_tcp_rr: got %d transactions\n", 8715 trans_received); 8716 fflush(where); 8717 } 8718 8719 tcp_rr_results->bytes_received = (trans_received * 8720 (tcp_rr_request->request_size + 8721 tcp_rr_request->response_size)); 8722 tcp_rr_results->trans_received = trans_received; 8723 tcp_rr_results->elapsed_time = elapsed_time; 8724 tcp_rr_results->cpu_method = cpu_method; 8725 tcp_rr_results->num_cpus = lib_num_loc_cpus; 8726 if (tcp_rr_request->measure_cpu) { 8727 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 8728 } 8729 8730 if (debug) { 8731 fprintf(where, 8732 "recv_tcp_rr: test complete, sending results.\n"); 8733 fflush(where); 8734 } 8735 8736 /* we are now done with the sockets */ 8737 close(s_data); 8738 close(s_listen); 8739 8740 send_response(); 8741 8742 } 8743 8744 8745 void 8747 loc_cpu_rate() 8748 { 8749 #if defined(USE_LOOPER) 8750 float dummy; 8751 #endif 8752 8753 /* a rather simple little test - it merely calibrates the local cpu */ 8754 /* and prints the results. There are no headers to allow someone to */ 8755 /* find a rate and use it in other tests automagically by setting a */ 8756 /* variable equal to the output of this test. We ignore any rates */ 8757 /* that may have been specified. In fact, we ignore all of the */ 8758 /* command line args! */ 8759 8760 fprintf(where, 8761 "%g", 8762 calibrate_local_cpu(0.0)); 8763 8764 if (verbosity > 1) 8765 fprintf(where, 8766 "\nThere %s %d local %s\n", 8767 (lib_num_loc_cpus > 1) ? "are" : "is", 8768 lib_num_loc_cpus, 8769 (lib_num_loc_cpus > 1) ? "cpus" : "cpu"); 8770 8771 /* we need the cpu_start, cpu_stop in the looper case to kill the */ 8772 /* child proceses raj 4/95 */ 8773 8774 #ifdef USE_LOOPER 8775 cpu_start(1); 8776 cpu_stop(1,&dummy); 8777 #endif /* USE_LOOPER */ 8778 8779 } 8780 8781 void 8782 rem_cpu_rate() 8783 { 8784 /* this test is much like the local variant, except that it works for */ 8785 /* the remote system, so in this case, we do pay attention to the */ 8786 /* value of the '-H' command line argument. */ 8787 8788 fprintf(where, 8789 "%g", 8790 calibrate_remote_cpu()); 8791 8792 if (verbosity > 1) 8793 fprintf(where, 8794 "\nThere %s %d remote %s\n", 8795 (lib_num_rem_cpus > 1) ? "are" : "is", 8796 lib_num_rem_cpus, 8797 (lib_num_rem_cpus > 1) ? "cpus" : "cpu"); 8798 8799 } 8800 8801 8802 #ifndef WANT_MIGRATION 8804 /* this test is intended to test the performance of establishing a 8805 connection, exchanging a request/response pair, and repeating. it 8806 is expected that this would be a good starting-point for 8807 comparision of T/TCP with classic TCP for transactional workloads. 8808 it will also look (can look) much like the communication pattern 8809 of http for www access. */ 8810 8811 void 8812 send_tcp_conn_rr(char remote_host[]) 8813 { 8814 8815 char *tput_title = "\ 8816 Local /Remote\n\ 8817 Socket Size Request Resp. Elapsed Trans.\n\ 8818 Send Recv Size Size Time Rate \n\ 8819 bytes Bytes bytes bytes secs. per sec \n\n"; 8820 8821 char *tput_fmt_0 = 8822 "%7.2f\n"; 8823 8824 char *tput_fmt_1_line_1 = "\ 8825 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 8826 char *tput_fmt_1_line_2 = "\ 8827 %-6d %-6d\n"; 8828 8829 char *cpu_title = "\ 8830 Local /Remote\n\ 8831 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 8832 Send Recv Size Size Time Rate local remote local remote\n\ 8833 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 8834 8835 char *cpu_fmt_0 = 8836 "%6.3f\n"; 8837 8838 char *cpu_fmt_1_line_1 = "\ 8839 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 8840 8841 char *cpu_fmt_1_line_2 = "\ 8842 %-6d %-6d\n"; 8843 8844 char *ksink_fmt = "\n\ 8845 Alignment Offset\n\ 8846 Local Remote Local Remote\n\ 8847 Send Recv Send Recv\n\ 8848 %5d %5d %5d %5d\n"; 8849 8850 8851 int timed_out = 0; 8852 float elapsed_time; 8853 8854 int len; 8855 struct ring_elt *send_ring; 8856 struct ring_elt *recv_ring; 8857 char *temp_message_ptr; 8858 int nummessages; 8859 SOCKET send_socket; 8860 int trans_remaining; 8861 double bytes_xferd; 8862 int rsp_bytes_left; 8863 int rsp_bytes_recvd; 8864 8865 float local_cpu_utilization; 8866 float local_service_demand; 8867 float remote_cpu_utilization; 8868 float remote_service_demand; 8869 double thruput; 8870 8871 struct addrinfo *local_res; 8872 struct addrinfo *remote_res; 8873 8874 int myport; 8875 int ret; 8876 8877 struct tcp_conn_rr_request_struct *tcp_conn_rr_request; 8878 struct tcp_conn_rr_response_struct *tcp_conn_rr_response; 8879 struct tcp_conn_rr_results_struct *tcp_conn_rr_result; 8880 8881 tcp_conn_rr_request = 8882 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data; 8883 tcp_conn_rr_response = 8884 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data; 8885 tcp_conn_rr_result = 8886 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data; 8887 8888 8889 #ifdef WANT_HISTOGRAM 8890 if (verbosity > 1) { 8891 time_hist = HIST_new(); 8892 } 8893 #endif /* WANT_HISTOGRAM */ 8894 8895 /* since we are now disconnected from the code that established the */ 8896 /* control socket, and since we want to be able to use different */ 8897 /* protocols and such, we are passed the name of the remote host and */ 8898 /* must turn that into the test specific addressing information. */ 8899 8900 complete_addrinfos(&remote_res, 8901 &local_res, 8902 remote_host, 8903 SOCK_STREAM, 8904 IPPROTO_TCP, 8905 0); 8906 8907 if ( print_headers ) { 8908 print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res); 8909 } 8910 8911 /* initialize a few counters */ 8912 8913 nummessages = 0; 8914 bytes_xferd = 0.0; 8915 times_up = 0; 8916 8917 /* set-up the data buffers with the requested alignment and offset */ 8918 if (send_width == 0) send_width = 1; 8919 if (recv_width == 0) recv_width = 1; 8920 8921 send_ring = allocate_buffer_ring(send_width, 8922 req_size, 8923 local_send_align, 8924 local_send_offset); 8925 8926 recv_ring = allocate_buffer_ring(recv_width, 8927 rsp_size, 8928 local_recv_align, 8929 local_recv_offset); 8930 8931 8932 if (debug) { 8933 fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n"); 8934 } 8935 8936 /* If the user has requested cpu utilization measurements, we must */ 8937 /* calibrate the cpu(s). We will perform this task within the tests */ 8938 /* themselves. If the user has specified the cpu rate, then */ 8939 /* calibrate_local_cpu will return rather quickly as it will have */ 8940 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 8941 /* all the "normal" calibration stuff and return the rate back.*/ 8942 8943 if (local_cpu_usage) { 8944 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 8945 } 8946 8947 if (!no_control) { 8948 8949 /* Tell the remote end to do a listen. The server alters the 8950 socket paramters on the other side at this point, hence the 8951 reason for all the values being passed in the setup message. If 8952 the user did not specify any of the parameters, they will be 8953 passed as 0, which will indicate to the remote that no changes 8954 beyond the system's default should be used. Alignment is the 8955 exception, it will default to 8, which will be no alignment 8956 alterations. */ 8957 8958 netperf_request.content.request_type = DO_TCP_CRR; 8959 tcp_conn_rr_request->recv_buf_size = rsr_size_req; 8960 tcp_conn_rr_request->send_buf_size = rss_size_req; 8961 tcp_conn_rr_request->recv_alignment = remote_recv_align; 8962 tcp_conn_rr_request->recv_offset = remote_recv_offset; 8963 tcp_conn_rr_request->send_alignment = remote_send_align; 8964 tcp_conn_rr_request->send_offset = remote_send_offset; 8965 tcp_conn_rr_request->request_size = req_size; 8966 tcp_conn_rr_request->response_size = rsp_size; 8967 tcp_conn_rr_request->no_delay = rem_nodelay; 8968 tcp_conn_rr_request->measure_cpu = remote_cpu_usage; 8969 tcp_conn_rr_request->cpu_rate = remote_cpu_rate; 8970 tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid; 8971 tcp_conn_rr_request->so_sndavoid = rem_sndavoid; 8972 if (test_time) { 8973 tcp_conn_rr_request->test_length = test_time; 8974 } 8975 else { 8976 tcp_conn_rr_request->test_length = test_trans * -1; 8977 } 8978 tcp_conn_rr_request->port = atoi(remote_data_port); 8979 tcp_conn_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 8980 8981 if (debug > 1) { 8982 fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n"); 8983 } 8984 8985 send_request(); 8986 8987 /* The response from the remote will contain all of the relevant 8988 socket parameters for this test type. We will put them back 8989 into the variables here so they can be displayed if desired. 8990 The remote will have calibrated CPU if necessary, and will have 8991 done all the needed set-up we will have calibrated the cpu 8992 locally before sending the request, and will grab the counter 8993 value right after the connect returns. The remote will grab the 8994 counter right after the accept call. This saves the hassle of 8995 extra messages being sent for the TCP tests. */ 8996 8997 recv_response(); 8998 8999 if (!netperf_response.content.serv_errno) { 9000 rsr_size = tcp_conn_rr_response->recv_buf_size; 9001 rss_size = tcp_conn_rr_response->send_buf_size; 9002 rem_nodelay = tcp_conn_rr_response->no_delay; 9003 remote_cpu_usage = tcp_conn_rr_response->measure_cpu; 9004 remote_cpu_rate = tcp_conn_rr_response->cpu_rate; 9005 /* make sure that port numbers are in network order */ 9006 set_port_number(remote_res, 9007 (unsigned short)tcp_conn_rr_response->data_port_number); 9008 9009 if (debug) { 9010 fprintf(where,"remote listen done.\n"); 9011 fprintf(where,"remote port is %u\n",get_port_number(remote_res)); 9012 fflush(where); 9013 } 9014 } 9015 else { 9016 Set_errno(netperf_response.content.serv_errno); 9017 fprintf(where, 9018 "netperf: remote error %d", 9019 netperf_response.content.serv_errno); 9020 perror(""); 9021 fflush(where); 9022 exit(1); 9023 } 9024 } 9025 #ifdef WANT_DEMO 9026 demo_rr_setup(100); 9027 #endif 9028 9029 /* pick a nice random spot between client_port_min and */ 9030 /* client_port_max for our initial port number */ 9031 srand(getpid()); 9032 if (client_port_max - client_port_min) { 9033 myport = client_port_min + 9034 (rand() % (client_port_max - client_port_min)); 9035 } 9036 else { 9037 myport = client_port_min; 9038 } 9039 /* there will be a ++ before the first call to bind, so subtract one */ 9040 myport--; 9041 /* Set-up the test end conditions. For a request/response test, they */ 9042 /* can be either time or transaction based. */ 9043 9044 if (test_time) { 9045 /* The user wanted to end the test after a period of time. */ 9046 times_up = 0; 9047 trans_remaining = 0; 9048 start_timer(test_time); 9049 } 9050 else { 9051 /* The tester wanted to send a number of bytes. */ 9052 trans_remaining = test_bytes; 9053 times_up = 1; 9054 } 9055 9056 /* The cpu_start routine will grab the current time and possibly */ 9057 /* value of the idle counter for later use in measuring cpu */ 9058 /* utilization and/or service demand and thruput. */ 9059 9060 9061 cpu_start(local_cpu_usage); 9062 9063 #ifdef WANT_DEMO 9064 if (demo_mode) { 9065 demo_first_timestamp(); 9066 } 9067 #endif 9068 9069 /* We use an "OR" to control test execution. When the test is */ 9070 /* controlled by time, the byte count check will always return false. */ 9071 /* When the test is controlled by byte count, the time test will */ 9072 /* always return false. When the test is finished, the whole */ 9073 /* expression will go false and we will stop sending data. I think I */ 9074 /* just arbitrarily decrement trans_remaining for the timed test, but */ 9075 /* will not do that just yet... One other question is whether or not */ 9076 /* the send buffer and the receive buffer should be the same buffer. */ 9077 9078 while ((!times_up) || (trans_remaining > 0)) { 9079 9080 #ifdef WANT_HISTOGRAM 9081 if (verbosity > 1) { 9082 /* timestamp just before our call to create the socket, and then */ 9083 /* again just after the receive raj 3/95 */ 9084 HIST_timestamp(&time_one); 9085 } 9086 #endif /* WANT_HISTOGRAM */ 9087 9088 newport: 9089 /* pick a new port number */ 9090 myport++; 9091 9092 /* wrap the port number when we get to client_port_max. NOTE, some */ 9093 /* broken TCP's might treat the port number as a signed 16 bit */ 9094 /* quantity. we aren't interested in testing such broken */ 9095 /* implementations :) so we won't make sure that it is below 32767 */ 9096 /* raj 8/94 */ 9097 if (myport >= client_port_max) { 9098 myport = client_port_min; 9099 } 9100 9101 /* we do not want to use the port number that the server is */ 9102 /* sitting at - this would cause us to fail in a loopback test. we */ 9103 /* could just rely on the failure of the bind to get us past this, */ 9104 /* but I'm guessing that in this one case at least, it is much */ 9105 /* faster, given that we *know* that port number is already in use */ 9106 /* (or rather would be in a loopback test) */ 9107 9108 if (myport == get_port_number(remote_res)) myport++; 9109 9110 if (debug) { 9111 if ((nummessages % 100) == 0) { 9112 printf("port %d\n",myport); 9113 } 9114 } 9115 9116 /* set up the data socket */ 9117 set_port_number(local_res, (unsigned short)myport); 9118 send_socket = create_data_socket(local_res); 9119 9120 if (send_socket == INVALID_SOCKET) { 9121 perror("netperf: send_tcp_conn_rr: tcp stream data socket"); 9122 exit(1); 9123 } 9124 9125 9126 /* we used to call bind here, but that is now taken-care-of by the 9127 create_data_socket routine. */ 9128 9129 /* Connect up to the remote port on the data socket */ 9130 if ((ret = connect(send_socket, 9131 remote_res->ai_addr, 9132 remote_res->ai_addrlen)) == INVALID_SOCKET){ 9133 if (SOCKET_EINTR(ret)) 9134 { 9135 /* we hit the end of a */ 9136 /* timed test. */ 9137 timed_out = 1; 9138 break; 9139 } 9140 if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) { 9141 /* likely something our explicit bind() would have caught in 9142 the past, so go get another port, via create_data_socket. 9143 yes, this is a bit more overhead than before, but the 9144 condition should be rather rare. raj 2005-02-08 */ 9145 close(send_socket); 9146 goto newport; 9147 } 9148 perror("netperf: data socket connect failed"); 9149 printf("\tattempted to connect on socket %d to port %d", 9150 send_socket, 9151 get_port_number(remote_res)); 9152 printf(" from port %d \n",get_port_number(local_res)); 9153 exit(1); 9154 } 9155 9156 9157 /* send the request */ 9158 if((len=send(send_socket, 9159 send_ring->buffer_ptr, 9160 req_size, 9161 0)) != req_size) { 9162 if (SOCKET_EINTR(len)) 9163 { 9164 /* we hit the end of a */ 9165 /* timed test. */ 9166 timed_out = 1; 9167 break; 9168 } 9169 perror("send_tcp_conn_rr: data send error"); 9170 exit(1); 9171 } 9172 send_ring = send_ring->next; 9173 9174 /* receive the response */ 9175 rsp_bytes_left = rsp_size; 9176 temp_message_ptr = recv_ring->buffer_ptr; 9177 9178 9179 do { 9180 rsp_bytes_recvd = recv(send_socket, 9181 temp_message_ptr, 9182 rsp_bytes_left, 9183 0); 9184 if (rsp_bytes_recvd > 0) { 9185 rsp_bytes_left -= rsp_bytes_recvd; 9186 temp_message_ptr += rsp_bytes_recvd; 9187 } 9188 else { 9189 break; 9190 } 9191 } while (rsp_bytes_left); 9192 9193 9194 /* OK, we are out of the loop - now what? */ 9195 if (rsp_bytes_recvd < 0) { 9196 /* did the timer hit, or was there an error? */ 9197 if (SOCKET_EINTR(rsp_bytes_recvd)) 9198 { 9199 /* We hit the end of a timed test. */ 9200 timed_out = 1; 9201 break; 9202 } 9203 perror("send_tcp_conn_rr: data recv error"); 9204 exit(1); 9205 } 9206 9207 /* if this is a no_control test, we initiate connection close, 9208 otherwise the remote netserver does it to remain just like 9209 previous behaviour. raj 2007-27-08 */ 9210 if (!no_control) { 9211 shutdown(send_socket,SHUT_WR); 9212 } 9213 9214 /* we are expecting to get either a return of zero indicating 9215 connection close, or an error. */ 9216 rsp_bytes_recvd = recv(send_socket, 9217 temp_message_ptr, 9218 1, 9219 0); 9220 9221 /* our exit from the while loop should generally be when */ 9222 /* tmp_bytes_recvd is equal to zero, which implies the connection */ 9223 /* has been closed by the server side. By waiting until we get the */ 9224 /* zero return we can avoid race conditions that stick us with the */ 9225 /* TIME_WAIT connection and not the server. raj 8/96 */ 9226 9227 #ifdef VMWARE_UW 9228 /* why this should be for VMware I'm not sure, but it was given as 9229 part of the patches, so we include it here, but put it under an 9230 ifdef VMWARE_UW. raj 2008-07-25 */ 9231 if (sp_bytes_recvd < 0 && errno == ECONNRESET) { 9232 rsp_bytes_recvd = 0; 9233 } 9234 #endif /* VMWARE_UW */ 9235 9236 if (rsp_bytes_recvd == 0) { 9237 /* connection close, call close. we assume that the requisite */ 9238 /* number of bytes have been received */ 9239 recv_ring = recv_ring->next; 9240 9241 #ifdef WANT_HISTOGRAM 9242 if (verbosity > 1) { 9243 HIST_timestamp(&time_two); 9244 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 9245 } 9246 #endif /* WANT_HISTOGRAM */ 9247 9248 #ifdef WANT_DEMO 9249 demo_rr_interval(1); 9250 #endif 9251 9252 nummessages++; 9253 if (trans_remaining) { 9254 trans_remaining--; 9255 } 9256 9257 if (debug > 3) { 9258 fprintf(where, 9259 "Transaction %d completed on local port %d\n", 9260 nummessages, 9261 get_port_number(local_res)); 9262 fflush(where); 9263 } 9264 9265 close(send_socket); 9266 9267 } 9268 else { 9269 /* it was less than zero - an error occured */ 9270 if (SOCKET_EINTR(rsp_bytes_recvd)) 9271 { 9272 /* We hit the end of a timed test. */ 9273 timed_out = 1; 9274 break; 9275 } 9276 perror("send_tcp_conn_rr: data recv error"); 9277 exit(1); 9278 } 9279 9280 } 9281 9282 9283 /* this call will always give us the elapsed time for the test, and */ 9284 /* will also store-away the necessaries for cpu utilization */ 9285 9286 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 9287 /* how long did we really run? */ 9288 9289 if (!no_control) { 9290 /* Get the statistics from the remote end. The remote will have 9291 calculated service demand and all those interesting things. If 9292 it wasn't supposed to care, it will return obvious values. */ 9293 9294 recv_response(); 9295 if (!netperf_response.content.serv_errno) { 9296 if (debug) 9297 fprintf(where,"remote results obtained\n"); 9298 } 9299 else { 9300 Set_errno(netperf_response.content.serv_errno); 9301 fprintf(where, 9302 "netperf: remote error %d", 9303 netperf_response.content.serv_errno); 9304 perror(""); 9305 fflush(where); 9306 9307 exit(1); 9308 } 9309 } 9310 9311 /* We now calculate what our thruput was for the test. In the future, */ 9312 /* we may want to include a calculation of the thruput measured by */ 9313 /* the remote, but it should be the case that for a TCP stream test, */ 9314 /* that the two numbers should be *very* close... We calculate */ 9315 /* bytes_sent regardless of the way the test length was controlled. */ 9316 /* If it was time, we needed to, and if it was by bytes, the user may */ 9317 /* have specified a number of bytes that wasn't a multiple of the */ 9318 /* send_size, so we really didn't send what he asked for ;-) We use */ 9319 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 9320 /* 1024. A future enhancement *might* be to choose from a couple of */ 9321 /* unit selections. */ 9322 9323 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 9324 thruput = calc_thruput(bytes_xferd); 9325 9326 if (local_cpu_usage || remote_cpu_usage) { 9327 /* We must now do a little math for service demand and cpu */ 9328 /* utilization for the system(s) */ 9329 /* Of course, some of the information might be bogus because */ 9330 /* there was no idle counter in the kernel(s). We need to make */ 9331 /* a note of this for the user's benefit...*/ 9332 if (local_cpu_usage) { 9333 if (local_cpu_rate == 0.0) { 9334 fprintf(where, 9335 "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 9336 fprintf(where, 9337 "Local CPU usage numbers based on process information only!\n"); 9338 fflush(where); 9339 } 9340 local_cpu_utilization = calc_cpu_util(0.0); 9341 /* since calc_service demand is doing ms/Kunit we will */ 9342 /* multiply the number of transaction by 1024 to get */ 9343 /* "good" numbers */ 9344 local_service_demand = calc_service_demand((double) nummessages*1024, 9345 0.0, 9346 0.0, 9347 0); 9348 } 9349 else { 9350 local_cpu_utilization = (float) -1.0; 9351 local_service_demand = (float) -1.0; 9352 } 9353 9354 if (remote_cpu_usage) { 9355 if (remote_cpu_rate == 0.0) { 9356 fprintf(where, 9357 "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 9358 fprintf(where, 9359 "Remote CPU usage numbers based on process information only!\n"); 9360 fflush(where); 9361 } 9362 remote_cpu_utilization = tcp_conn_rr_result->cpu_util; 9363 /* since calc_service demand is doing ms/Kunit we will */ 9364 /* multiply the number of transaction by 1024 to get */ 9365 /* "good" numbers */ 9366 remote_service_demand = calc_service_demand((double) nummessages*1024, 9367 0.0, 9368 remote_cpu_utilization, 9369 tcp_conn_rr_result->num_cpus); 9370 } 9371 else { 9372 remote_cpu_utilization = (float) -1.0; 9373 remote_service_demand = (float) -1.0; 9374 } 9375 9376 /* We are now ready to print all the information. If the user */ 9377 /* has specified zero-level verbosity, we will just print the */ 9378 /* local service demand, or the remote service demand. If the */ 9379 /* user has requested verbosity level 1, he will get the basic */ 9380 /* "streamperf" numbers. If the user has specified a verbosity */ 9381 /* of greater than 1, we will display a veritable plethora of */ 9382 /* background information from outside of this block as it it */ 9383 /* not cpu_measurement specific... */ 9384 9385 switch (verbosity) { 9386 case 0: 9387 if (local_cpu_usage) { 9388 fprintf(where, 9389 cpu_fmt_0, 9390 local_service_demand); 9391 } 9392 else { 9393 fprintf(where, 9394 cpu_fmt_0, 9395 remote_service_demand); 9396 } 9397 break; 9398 case 1: 9399 case 2: 9400 9401 if (print_headers) { 9402 fprintf(where, 9403 cpu_title, 9404 local_cpu_method, 9405 remote_cpu_method); 9406 } 9407 9408 fprintf(where, 9409 cpu_fmt_1_line_1, /* the format string */ 9410 lss_size, /* local sendbuf size */ 9411 lsr_size, 9412 req_size, /* how large were the requests */ 9413 rsp_size, /* guess */ 9414 elapsed_time, /* how long was the test */ 9415 nummessages/elapsed_time, 9416 local_cpu_utilization, /* local cpu */ 9417 remote_cpu_utilization, /* remote cpu */ 9418 local_service_demand, /* local service demand */ 9419 remote_service_demand); /* remote service demand */ 9420 fprintf(where, 9421 cpu_fmt_1_line_2, 9422 rss_size, 9423 rsr_size); 9424 break; 9425 } 9426 } 9427 else { 9428 /* The tester did not wish to measure service demand. */ 9429 switch (verbosity) { 9430 case 0: 9431 fprintf(where, 9432 tput_fmt_0, 9433 nummessages/elapsed_time); 9434 break; 9435 case 1: 9436 case 2: 9437 if (print_headers) { 9438 fprintf(where,tput_title,format_units()); 9439 } 9440 9441 fprintf(where, 9442 tput_fmt_1_line_1, /* the format string */ 9443 lss_size, 9444 lsr_size, 9445 req_size, /* how large were the requests */ 9446 rsp_size, /* how large were the responses */ 9447 elapsed_time, /* how long did it take */ 9448 nummessages/elapsed_time); 9449 fprintf(where, 9450 tput_fmt_1_line_2, 9451 rss_size, /* remote recvbuf size */ 9452 rsr_size); 9453 9454 break; 9455 } 9456 } 9457 9458 /* it would be a good thing to include information about some of the */ 9459 /* other parameters that may have been set for this test, but at the */ 9460 /* moment, I do not wish to figure-out all the formatting, so I will */ 9461 /* just put this comment here to help remind me that it is something */ 9462 /* that should be done at a later time. */ 9463 9464 if (verbosity > 1) { 9465 /* The user wanted to know it all, so we will give it to him. */ 9466 /* This information will include as much as we can find about */ 9467 /* TCP statistics, the alignments of the sends and receives */ 9468 /* and all that sort of rot... */ 9469 9470 fprintf(where, 9471 ksink_fmt, 9472 local_send_align, 9473 remote_recv_offset, 9474 local_send_offset, 9475 remote_recv_offset); 9476 9477 #ifdef WANT_HISTOGRAM 9478 fprintf(where,"\nHistogram of request/response times\n"); 9479 fflush(where); 9480 HIST_report(time_hist); 9481 #endif /* WANT_HISTOGRAM */ 9482 9483 } 9484 9485 } 9486 #endif /* WANT_MIGRATION */ 9487 9488 void 9490 recv_tcp_conn_rr() 9491 { 9492 9493 char *message; 9494 struct addrinfo *local_res; 9495 char local_name[BUFSIZ]; 9496 char port_buffer[PORTBUFSIZE]; 9497 9498 struct sockaddr_storage myaddr_in, peeraddr_in; 9499 SOCKET s_listen,s_data; 9500 netperf_socklen_t addrlen; 9501 char *recv_message_ptr; 9502 char *send_message_ptr; 9503 char *temp_message_ptr; 9504 int trans_received; 9505 int trans_remaining; 9506 int bytes_sent; 9507 int request_bytes_recvd; 9508 int request_bytes_remaining; 9509 int timed_out = 0; 9510 float elapsed_time; 9511 9512 struct tcp_conn_rr_request_struct *tcp_conn_rr_request; 9513 struct tcp_conn_rr_response_struct *tcp_conn_rr_response; 9514 struct tcp_conn_rr_results_struct *tcp_conn_rr_results; 9515 9516 tcp_conn_rr_request = 9517 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data; 9518 tcp_conn_rr_response = 9519 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data; 9520 tcp_conn_rr_results = 9521 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data; 9522 9523 if (debug) { 9524 fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n"); 9525 fflush(where); 9526 } 9527 9528 /* We want to set-up the listen socket with all the desired */ 9529 /* parameters and then let the initiator know that all is ready. If */ 9530 /* socket size defaults are to be used, then the initiator will have */ 9531 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 9532 /* send-back what they are. If that information cannot be determined, */ 9533 /* then we send-back -1's for the sizes. If things go wrong for any */ 9534 /* reason, we will drop back ten yards and punt. */ 9535 9536 /* If anything goes wrong, we want the remote to know about it. It */ 9537 /* would be best if the error that the remote reports to the user is */ 9538 /* the actual error we encountered, rather than some bogus unexpected */ 9539 /* response type message. */ 9540 9541 if (debug) { 9542 fprintf(where,"recv_tcp_conn_rr: setting the response type...\n"); 9543 fflush(where); 9544 } 9545 9546 netperf_response.content.response_type = TCP_CRR_RESPONSE; 9547 9548 if (debug) { 9549 fprintf(where,"recv_tcp_conn_rr: the response type is set...\n"); 9550 fflush(where); 9551 } 9552 9553 /* set-up the data buffer with the requested alignment and offset */ 9554 message = (char *)malloc(DATABUFFERLEN); 9555 if (message == NULL) { 9556 printf("malloc(%d) failed!\n", DATABUFFERLEN); 9557 exit(1); 9558 } 9559 9560 /* We now alter the message_ptr variables to be at the desired */ 9561 /* alignments with the desired offsets. */ 9562 9563 if (debug) { 9564 fprintf(where, 9565 "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n", 9566 tcp_conn_rr_request->recv_alignment, 9567 tcp_conn_rr_request->recv_offset); 9568 fprintf(where, 9569 "recv_tcp_conn_rr: requested send alignment of %d offset %d\n", 9570 tcp_conn_rr_request->send_alignment, 9571 tcp_conn_rr_request->send_offset); 9572 fflush(where); 9573 } 9574 9575 recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset); 9576 9577 send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset); 9578 9579 if (debug) { 9580 fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n"); 9581 fflush(where); 9582 } 9583 9584 /* Grab a socket to listen on, and then listen on it. */ 9585 9586 if (debug) { 9587 fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n"); 9588 fflush(where); 9589 } 9590 9591 /* create_data_socket expects to find some things in the global */ 9592 /* variables, so set the globals based on the values in the request. */ 9593 /* once the socket has been created, we will set the response values */ 9594 /* based on the updated value of those globals. raj 7/94 */ 9595 lss_size_req = tcp_conn_rr_request->send_buf_size; 9596 lsr_size_req = tcp_conn_rr_request->recv_buf_size; 9597 loc_nodelay = tcp_conn_rr_request->no_delay; 9598 loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid; 9599 loc_sndavoid = tcp_conn_rr_request->so_sndavoid; 9600 9601 set_hostname_and_port(local_name, 9602 port_buffer, 9603 nf_to_af(tcp_conn_rr_request->ipfamily), 9604 tcp_conn_rr_request->port); 9605 9606 local_res = complete_addrinfo(local_name, 9607 local_name, 9608 port_buffer, 9609 nf_to_af(tcp_conn_rr_request->ipfamily), 9610 SOCK_STREAM, 9611 IPPROTO_TCP, 9612 0); 9613 9614 s_listen = create_data_socket(local_res); 9615 9616 if (s_listen == INVALID_SOCKET) { 9617 netperf_response.content.serv_errno = errno; 9618 send_response(); 9619 if (debug) { 9620 fprintf(where,"could not create data socket\n"); 9621 fflush(where); 9622 } 9623 exit(1); 9624 } 9625 9626 #ifdef WIN32 9627 /* The test timer can fire during operations on the listening socket, 9628 so to make the start_timer below work we have to move 9629 it to close s_listen while we are blocked on accept. */ 9630 win_kludge_socket2 = s_listen; 9631 #endif 9632 9633 9634 /* Now, let's set-up the socket to listen for connections */ 9635 if (listen(s_listen, 128) == SOCKET_ERROR) { 9636 netperf_response.content.serv_errno = errno; 9637 close(s_listen); 9638 send_response(); 9639 if (debug) { 9640 fprintf(where,"could not listen\n"); 9641 fflush(where); 9642 } 9643 exit(1); 9644 } 9645 9646 /* now get the port number assigned by the system */ 9647 addrlen = sizeof(myaddr_in); 9648 if (getsockname(s_listen, 9649 (struct sockaddr *)&myaddr_in, 9650 &addrlen) == SOCKET_ERROR){ 9651 netperf_response.content.serv_errno = errno; 9652 close(s_listen); 9653 send_response(); 9654 if (debug) { 9655 fprintf(where,"could not getsockname\n"); 9656 fflush(where); 9657 } 9658 exit(1); 9659 } 9660 9661 /* Now myaddr_in contains the port and the internet address this is */ 9662 /* returned to the sender also implicitly telling the sender that the */ 9663 /* socket buffer sizing has been done. */ 9664 9665 tcp_conn_rr_response->data_port_number = 9666 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 9667 if (debug) { 9668 fprintf(where,"telling the remote to call me at %d\n", 9669 tcp_conn_rr_response->data_port_number); 9670 fflush(where); 9671 } 9672 netperf_response.content.serv_errno = 0; 9673 9674 /* But wait, there's more. If the initiator wanted cpu measurements, */ 9675 /* then we must call the calibrate routine, which will return the max */ 9676 /* rate back to the initiator. If the CPU was not to be measured, or */ 9677 /* something went wrong with the calibration, we will return a 0.0 to */ 9678 /* the initiator. */ 9679 9680 tcp_conn_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 9681 if (tcp_conn_rr_request->measure_cpu) { 9682 tcp_conn_rr_response->measure_cpu = 1; 9683 tcp_conn_rr_response->cpu_rate = 9684 calibrate_local_cpu(tcp_conn_rr_request->cpu_rate); 9685 } 9686 9687 9688 9689 /* before we send the response back to the initiator, pull some of */ 9690 /* the socket parms from the globals */ 9691 tcp_conn_rr_response->send_buf_size = lss_size; 9692 tcp_conn_rr_response->recv_buf_size = lsr_size; 9693 tcp_conn_rr_response->no_delay = loc_nodelay; 9694 tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid; 9695 tcp_conn_rr_response->so_sndavoid = loc_sndavoid; 9696 9697 send_response(); 9698 9699 addrlen = sizeof(peeraddr_in); 9700 9701 /* Now it's time to start receiving data on the connection. We will */ 9702 /* first grab the apropriate counters and then start grabbing. */ 9703 9704 cpu_start(tcp_conn_rr_request->measure_cpu); 9705 9706 /* The loop will exit when the sender does a shutdown, which will */ 9707 /* return a length of zero */ 9708 9709 if (tcp_conn_rr_request->test_length > 0) { 9710 times_up = 0; 9711 trans_remaining = 0; 9712 start_timer(tcp_conn_rr_request->test_length + PAD_TIME); 9713 } 9714 else { 9715 times_up = 1; 9716 trans_remaining = tcp_conn_rr_request->test_length * -1; 9717 } 9718 9719 trans_received = 0; 9720 9721 while ((!times_up) || (trans_remaining > 0)) { 9722 9723 /* accept a connection from the remote */ 9724 #ifdef WIN32 9725 /* The test timer will probably fire during this accept, 9726 so to make the start_timer above work we have to move 9727 it to close s_listen while we are blocked on accept. */ 9728 win_kludge_socket = s_listen; 9729 #endif 9730 if ((s_data=accept(s_listen, 9731 (struct sockaddr *)&peeraddr_in, 9732 &addrlen)) == INVALID_SOCKET) { 9733 if (errno == EINTR) { 9734 /* the timer popped */ 9735 timed_out = 1; 9736 break; 9737 } 9738 fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno); 9739 fflush(where); 9740 close(s_listen); 9741 9742 exit(1); 9743 } 9744 9745 if (debug) { 9746 fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n"); 9747 fflush(where); 9748 } 9749 9750 #ifdef WIN32 9751 /* this is used so the timer thread can close the socket out from */ 9752 /* under us, which to date is the easiest/cleanest/least */ 9753 /* Windows-specific way I can find to force the winsock calls to */ 9754 /* return WSAEINTR with the test is over. anything that will run on */ 9755 /* 95 and NT and is closer to what netperf expects from Unix signals */ 9756 /* and such would be appreciated raj 1/96 */ 9757 win_kludge_socket = s_data; 9758 #endif /* WIN32 */ 9759 9760 #ifdef KLUDGE_SOCKET_OPTIONS 9761 /* this is for those systems which *INCORRECTLY* fail to pass */ 9762 /* attributes across an accept() call. Including this goes against */ 9763 /* my better judgement :( raj 11/95 */ 9764 9765 kludge_socket_options(s_data); 9766 9767 #endif /* KLUDGE_SOCKET_OPTIONS */ 9768 9769 temp_message_ptr = recv_message_ptr; 9770 request_bytes_remaining = tcp_conn_rr_request->request_size; 9771 9772 /* receive the request from the other side */ 9773 while (!times_up && (request_bytes_remaining > 0)) { 9774 if((request_bytes_recvd=recv(s_data, 9775 temp_message_ptr, 9776 request_bytes_remaining, 9777 0)) == SOCKET_ERROR) { 9778 if (SOCKET_EINTR(request_bytes_recvd)) 9779 { 9780 /* the timer popped */ 9781 timed_out = 1; 9782 break; 9783 } 9784 netperf_response.content.serv_errno = errno; 9785 send_response(); 9786 exit(1); 9787 } 9788 else if (request_bytes_recvd > 0) { 9789 request_bytes_remaining -= request_bytes_recvd; 9790 temp_message_ptr += request_bytes_recvd; 9791 } 9792 else { 9793 /* for some reason the remote closed the connection on 9794 * us and that is unexpected so we should just close the 9795 * socket and move-on. for that we will use an evil goto 9796 * neener neener raj 20090622 */ 9797 goto bail; 9798 } 9799 } 9800 9801 if (timed_out) { 9802 /* we hit the end of the test based on time - lets */ 9803 /* bail out of here now... */ 9804 fprintf(where,"yo5\n"); 9805 fflush(where); 9806 break; 9807 } 9808 9809 /* Now, send the response to the remote */ 9810 if((bytes_sent=send(s_data, 9811 send_message_ptr, 9812 tcp_conn_rr_request->response_size, 9813 0)) == SOCKET_ERROR) { 9814 if (errno == EINTR) { 9815 /* the test timer has popped */ 9816 timed_out = 1; 9817 fprintf(where,"yo6\n"); 9818 fflush(where); 9819 break; 9820 } 9821 netperf_response.content.serv_errno = 99; 9822 send_response(); 9823 exit(1); 9824 } 9825 9826 trans_received++; 9827 if (trans_remaining) { 9828 trans_remaining--; 9829 } 9830 9831 if (debug) { 9832 fprintf(where, 9833 "recv_tcp_conn_rr: Transaction %d complete\n", 9834 trans_received); 9835 fflush(where); 9836 } 9837 9838 /* close the connection. the server will likely do a graceful */ 9839 /* close of the connection, insuring that all data has arrived at */ 9840 /* the client. for this it will call shutdown(), and then recv() and */ 9841 /* then close(). I'm reasonably confident that this is the */ 9842 /* appropriate sequence of calls - I would like to hear of */ 9843 /* examples in web servers to the contrary. raj 10/95*/ 9844 #ifdef TCP_CRR_SHUTDOWN 9845 shutdown(s_data,SHUT_WR); 9846 recv(s_data, 9847 recv_message_ptr, 9848 1, 9849 0); 9850 bail: 9851 close(s_data); 9852 #else 9853 bail: 9854 close(s_data); 9855 #endif /* TCP_CRR_SHUTDOWN */ 9856 9857 } 9858 9859 9860 /* The loop now exits due to timeout or transaction count being */ 9861 /* reached */ 9862 9863 cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time); 9864 9865 if (timed_out) { 9866 /* we ended the test by time, which was at least 2 seconds */ 9867 /* longer than we wanted to run. so, we want to subtract */ 9868 /* PAD_TIME from the elapsed_time. */ 9869 elapsed_time -= PAD_TIME; 9870 } 9871 /* send the results to the sender */ 9872 9873 if (debug) { 9874 fprintf(where, 9875 "recv_tcp_conn_rr: got %d transactions\n", 9876 trans_received); 9877 fflush(where); 9878 } 9879 9880 tcp_conn_rr_results->bytes_received = (trans_received * 9881 (tcp_conn_rr_request->request_size + 9882 tcp_conn_rr_request->response_size)); 9883 tcp_conn_rr_results->trans_received = trans_received; 9884 tcp_conn_rr_results->elapsed_time = elapsed_time; 9885 if (tcp_conn_rr_request->measure_cpu) { 9886 tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time); 9887 } 9888 9889 if (debug) { 9890 fprintf(where, 9891 "recv_tcp_conn_rr: test complete, sending results.\n"); 9892 fflush(where); 9893 } 9894 9895 send_response(); 9896 9897 } 9898 9899 9901 #ifdef DO_1644 9902 9903 /* this test is intended to test the performance of establishing a */ 9904 /* connection, exchanging a request/response pair, and repeating. it */ 9905 /* is expected that this would be a good starting-point for */ 9906 /* comparision of T/TCP with classic TCP for transactional workloads. */ 9907 /* it will also look (can look) much like the communication pattern */ 9908 /* of http for www access. */ 9909 9910 int 9911 send_tcp_tran_rr(char remote_host[]) 9912 { 9913 9914 char *tput_title = "\ 9915 Local /Remote\n\ 9916 Socket Size Request Resp. Elapsed Trans.\n\ 9917 Send Recv Size Size Time Rate \n\ 9918 bytes Bytes bytes bytes secs. per sec \n\n"; 9919 9920 char *tput_fmt_0 = 9921 "%7.2f\n"; 9922 9923 char *tput_fmt_1_line_1 = "\ 9924 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 9925 char *tput_fmt_1_line_2 = "\ 9926 %-6d %-6d\n"; 9927 9928 char *cpu_title = "\ 9929 Local /Remote\n\ 9930 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 9931 Send Recv Size Size Time Rate local remote local remote\n\ 9932 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 9933 9934 char *cpu_fmt_0 = 9935 "%6.3f\n"; 9936 9937 char *cpu_fmt_1_line_1 = "\ 9938 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 9939 9940 char *cpu_fmt_1_line_2 = "\ 9941 %-6d %-6d\n"; 9942 9943 char *ksink_fmt = "\n\ 9944 Alignment Offset\n\ 9945 Local Remote Local Remote\n\ 9946 Send Recv Send Recv\n\ 9947 %5d %5d %5d %5d\n"; 9948 9949 9950 int one = 1; 9951 int timed_out = 0; 9952 float elapsed_time; 9953 9954 int len; 9955 struct ring_elt *send_ring; 9956 struct ring_elt *recv_ring; 9957 char *temp_message_ptr; 9958 int nummessages; 9959 SOCKET send_socket; 9960 int trans_remaining; 9961 double bytes_xferd; 9962 int sock_opt_len = sizeof(int); 9963 int rsp_bytes_left; 9964 int rsp_bytes_recvd; 9965 9966 float local_cpu_utilization; 9967 float local_service_demand; 9968 float remote_cpu_utilization; 9969 float remote_service_demand; 9970 double thruput; 9971 9972 struct hostent *hp; 9973 struct sockaddr_in server; 9974 struct sockaddr_in *myaddr; 9975 unsigned int addr; 9976 int myport; 9977 9978 struct tcp_tran_rr_request_struct *tcp_tran_rr_request; 9979 struct tcp_tran_rr_response_struct *tcp_tran_rr_response; 9980 struct tcp_tran_rr_results_struct *tcp_tran_rr_result; 9981 9982 tcp_tran_rr_request = 9983 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data; 9984 tcp_tran_rr_response = 9985 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data; 9986 tcp_tran_rr_result = 9987 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data; 9988 9989 9990 #ifdef WANT_HISTOGRAM 9991 if (verbosity > 1) { 9992 time_hist = HIST_new(); 9993 } 9994 #endif /* WANT_HISTOGRAM */ 9995 9996 /* since we are now disconnected from the code that established the */ 9997 /* control socket, and since we want to be able to use different */ 9998 /* protocols and such, we are passed the name of the remote host and */ 9999 /* must turn that into the test specific addressing information. */ 10000 10001 myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage)); 10002 if (myaddr == NULL) { 10003 printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage)); 10004 exit(1); 10005 } 10006 10007 bzero((char *)&server, 10008 sizeof(server)); 10009 bzero((char *)myaddr, 10010 sizeof(struct sockaddr_storage)); 10011 myaddr->sin_family = AF_INET; 10012 10013 complete_addrinfos(&remote_res, 10014 &local_res, 10015 remote_host, 10016 SOCK_STREAM, 10017 IPPROTO_TCP, 10018 0); 10019 10020 if ( print_headers ) { 10021 print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res); 10022 } 10023 10024 /* initialize a few counters */ 10025 10026 nummessages = 0; 10027 bytes_xferd = 0.0; 10028 times_up = 0; 10029 10030 /* set-up the data buffers with the requested alignment and offset */ 10031 if (send_width == 0) send_width = 1; 10032 if (recv_width == 0) recv_width = 1; 10033 10034 send_ring = allocate_buffer_ring(send_width, 10035 req_size, 10036 local_send_align, 10037 local_send_offset); 10038 10039 recv_ring = allocate_buffer_ring(recv_width, 10040 rsp_size, 10041 local_recv_align, 10042 local_recv_offset); 10043 10044 10045 if (debug) { 10046 fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n"); 10047 } 10048 10049 /* If the user has requested cpu utilization measurements, we must */ 10050 /* calibrate the cpu(s). We will perform this task within the tests */ 10051 /* themselves. If the user has specified the cpu rate, then */ 10052 /* calibrate_local_cpu will return rather quickly as it will have */ 10053 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 10054 /* all the "normal" calibration stuff and return the rate back.*/ 10055 10056 if (local_cpu_usage) { 10057 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 10058 } 10059 10060 /* Tell the remote end to do a listen. The server alters the socket */ 10061 /* paramters on the other side at this point, hence the reason for */ 10062 /* all the values being passed in the setup message. If the user did */ 10063 /* not specify any of the parameters, they will be passed as 0, which */ 10064 /* will indicate to the remote that no changes beyond the system's */ 10065 /* default should be used. Alignment is the exception, it will */ 10066 /* default to 8, which will be no alignment alterations. */ 10067 10068 netperf_request.content.request_type = DO_TCP_TRR; 10069 tcp_tran_rr_request->recv_buf_size = rsr_size_req; 10070 tcp_tran_rr_request->send_buf_size = rss_size_req; 10071 tcp_tran_rr_request->recv_alignment = remote_recv_align; 10072 tcp_tran_rr_request->recv_offset = remote_recv_offset; 10073 tcp_tran_rr_request->send_alignment = remote_send_align; 10074 tcp_tran_rr_request->send_offset = remote_send_offset; 10075 tcp_tran_rr_request->request_size = req_size; 10076 tcp_tran_rr_request->response_size = rsp_size; 10077 tcp_tran_rr_request->no_delay = rem_nodelay; 10078 tcp_tran_rr_request->measure_cpu = remote_cpu_usage; 10079 tcp_tran_rr_request->cpu_rate = remote_cpu_rate; 10080 tcp_tran_rr_request->so_rcvavoid = rem_rcvavoid; 10081 tcp_tran_rr_request->so_sndavoid = rem_sndavoid; 10082 if (test_time) { 10083 tcp_tran_rr_request->test_length = test_time; 10084 } 10085 else { 10086 tcp_tran_rr_request->test_length = test_trans * -1; 10087 } 10088 tcp_tran_rr_request->port = atoi(remote_data_port); 10089 tcp_tran_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 10090 10091 if (debug > 1) { 10092 fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n"); 10093 } 10094 10095 send_request(); 10096 10097 /* The response from the remote will contain all of the relevant */ 10098 /* socket parameters for this test type. We will put them back into */ 10099 /* the variables here so they can be displayed if desired. The */ 10100 /* remote will have calibrated CPU if necessary, and will have done */ 10101 /* all the needed set-up we will have calibrated the cpu locally */ 10102 /* before sending the request, and will grab the counter value right */ 10103 /* after the connect returns. The remote will grab the counter right */ 10104 /* after the accept call. This saves the hassle of extra messages */ 10105 /* being sent for the TCP tests. */ 10106 10107 recv_response(); 10108 10109 if (!netperf_response.content.serv_errno) { 10110 rsr_size = tcp_tran_rr_response->recv_buf_size; 10111 rss_size = tcp_tran_rr_response->send_buf_size; 10112 rem_nodelay = tcp_tran_rr_response->no_delay; 10113 remote_cpu_usage= tcp_tran_rr_response->measure_cpu; 10114 remote_cpu_rate = tcp_tran_rr_response->cpu_rate; 10115 /* make sure that port numbers are in network order */ 10116 server.sin_port = tcp_tran_rr_response->data_port_number; 10117 server.sin_port = htons(server.sin_port); 10118 if (debug) { 10119 fprintf(where,"remote listen done.\n"); 10120 fprintf(where,"remote port is %d\n",ntohs(server.sin_port)); 10121 fflush(where); 10122 } 10123 } 10124 else { 10125 Set_errno(netperf_response.content.serv_errno); 10126 fprintf(where, 10127 "netperf: remote error %d", 10128 netperf_response.content.serv_errno); 10129 perror(""); 10130 fflush(where); 10131 exit(1); 10132 } 10133 10134 /* pick a nice random spot between client_port_min and */ 10135 /* client_port_max for our initial port number. if they are the */ 10136 /* same, then just set to _min */ 10137 if (client_port_max - client_port_min) { 10138 srand(getpid()); 10139 myport = client_port_min + 10140 (rand() % (client_port_max - client_port_min)); 10141 } 10142 else { 10143 myport = client_port_min; 10144 } 10145 10146 /* there will be a ++ before the first call to bind, so subtract one */ 10147 myport--; 10148 myaddr->sin_port = htons((unsigned short)myport); 10149 10150 /* Set-up the test end conditions. For a request/response test, they */ 10151 /* can be either time or transaction based. */ 10152 10153 if (test_time) { 10154 /* The user wanted to end the test after a period of time. */ 10155 times_up = 0; 10156 trans_remaining = 0; 10157 start_timer(test_time); 10158 } 10159 else { 10160 /* The tester wanted to send a number of bytes. */ 10161 trans_remaining = test_bytes; 10162 times_up = 1; 10163 } 10164 10165 /* The cpu_start routine will grab the current time and possibly */ 10166 /* value of the idle counter for later use in measuring cpu */ 10167 /* utilization and/or service demand and thruput. */ 10168 10169 cpu_start(local_cpu_usage); 10170 10171 /* We use an "OR" to control test execution. When the test is */ 10172 /* controlled by time, the byte count check will always return false. */ 10173 /* When the test is controlled by byte count, the time test will */ 10174 /* always return false. When the test is finished, the whole */ 10175 /* expression will go false and we will stop sending data. I think I */ 10176 /* just arbitrarily decrement trans_remaining for the timed test, but */ 10177 /* will not do that just yet... One other question is whether or not */ 10178 /* the send buffer and the receive buffer should be the same buffer. */ 10179 10180 while ((!times_up) || (trans_remaining > 0)) { 10181 10182 #ifdef WANT_HISTOGRAM 10183 if (verbosity > 1) { 10184 /* timestamp just before our call to create the socket, and then */ 10185 /* again just after the receive raj 3/95 */ 10186 HIST_timestamp(&time_one); 10187 } 10188 #endif /* WANT_HISTOGRAM */ 10189 10190 /* set up the data socket - is this really necessary or can I just */ 10191 /* re-use the same socket and move this cal out of the while loop. */ 10192 /* it does introcudea *boatload* of system calls. I guess that it */ 10193 /* all depends on "reality of programming." keeping it this way is */ 10194 /* a bit more conservative I imagine - raj 3/95 */ 10195 send_socket = create_data_socket(local_res); 10196 10197 if (send_socket == INVALID_SOCKET) { 10198 perror("netperf: send_tcp_tran_rr: tcp stream data socket"); 10199 exit(1); 10200 } 10201 10202 /* we set SO_REUSEADDR on the premis that no unreserved port */ 10203 /* number on the local system is going to be already connected to */ 10204 /* the remote netserver's port number. One thing that I might */ 10205 /* try later is to have the remote actually allocate a couple of */ 10206 /* port numbers and cycle through those as well. depends on if we */ 10207 /* can get through all the unreserved port numbers in less than */ 10208 /* the length of the TIME_WAIT state raj 8/94 */ 10209 one = 1; 10210 if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR, 10211 (char *)&one, sock_opt_len) == SOCKET_ERROR) { 10212 perror("netperf: send_tcp_tran_rr: so_reuseaddr"); 10213 exit(1); 10214 } 10215 10216 newport: 10217 /* pick a new port number */ 10218 myport = ntohs(myaddr->sin_port); 10219 myport++; 10220 10221 /* we do not want to use the port number that the server is */ 10222 /* sitting at - this would cause us to fail in a loopback test. we */ 10223 /* could just rely on the failure of the bind to get us past this, */ 10224 /* but I'm guessing that in this one case at least, it is much */ 10225 /* faster, given that we *know* that port number is already in use */ 10226 /* (or rather would be in a loopback test) */ 10227 10228 if (myport == ntohs(server.sin_port)) myport++; 10229 10230 /* wrap the port number when we get to 65535. NOTE, some broken */ 10231 /* TCP's might treat the port number as a signed 16 bit quantity. */ 10232 /* we aren't interested in testing such broken implementations :) */ 10233 /* raj 8/94 */ 10234 if (myport >= client_port_max) { 10235 myport = client_port_min; 10236 } 10237 myaddr->sin_port = htons((unsigned short)myport); 10238 10239 if (debug) { 10240 if ((nummessages % 100) == 0) { 10241 printf("port %d\n",myport); 10242 } 10243 } 10244 10245 /* we want to bind our socket to a particular port number. */ 10246 if (bind(send_socket, 10247 (struct sockaddr *)myaddr, 10248 sizeof(struct sockaddr_storage)) == SOCKET_ERROR) { 10249 /* if the bind failed, someone else must have that port number */ 10250 /* - perhaps in the listen state. since we can't use it, skip to */ 10251 /* the next port number. we may have to do this again later, but */ 10252 /* that's just too bad :) */ 10253 if (debug > 1) { 10254 fprintf(where, 10255 "send_tcp_tran_rr: tried to bind to port %d errno %d\n", 10256 ntohs(myaddr->sin_port), 10257 errno); 10258 fflush(where); 10259 } 10260 /* yes, goto's are supposed to be evil, but they do have their */ 10261 /* uses from time to time. the real world doesn't always have */ 10262 /* to code to ge tthe A in CS 101 :) raj 3/95 */ 10263 goto newport; 10264 } 10265 10266 /* Connect up to the remote port on the data socket. Since this is */ 10267 /* a test for RFC_1644-style transactional TCP, we can use the */ 10268 /* sendto() call instead of calling connect and then send() */ 10269 10270 /* send the request */ 10271 if((len=sendto(send_socket, 10272 send_ring->buffer_ptr, 10273 req_size, 10274 MSG_EOF, 10275 (struct sockaddr *)&server, 10276 sizeof(server))) != req_size) { 10277 if (SOCKET_EINTR(len)) 10278 { 10279 /* we hit the end of a */ 10280 /* timed test. */ 10281 timed_out = 1; 10282 break; 10283 } 10284 perror("send_tcp_tran_rr: data send error"); 10285 exit(1); 10286 } 10287 send_ring = send_ring->next; 10288 10289 /* receive the response */ 10290 rsp_bytes_left = rsp_size; 10291 temp_message_ptr = recv_ring->buffer_ptr; 10292 while(rsp_bytes_left > 0) { 10293 if((rsp_bytes_recvd=recv(send_socket, 10294 temp_message_ptr, 10295 rsp_bytes_left, 10296 0)) == SOCKET_ERROR) { 10297 if (SOCKET_EINTR(rsp_bytes_recvd)) 10298 { 10299 /* We hit the end of a timed test. */ 10300 timed_out = 1; 10301 break; 10302 } 10303 perror("send_tcp_tran_rr: data recv error"); 10304 exit(1); 10305 } 10306 rsp_bytes_left -= rsp_bytes_recvd; 10307 temp_message_ptr += rsp_bytes_recvd; 10308 } 10309 recv_ring = recv_ring->next; 10310 10311 if (timed_out) { 10312 /* we may have been in a nested while loop - we need */ 10313 /* another call to break. */ 10314 break; 10315 } 10316 10317 close(send_socket); 10318 10319 #ifdef WANT_HISTOGRAM 10320 if (verbosity > 1) { 10321 HIST_timestamp(&time_two); 10322 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 10323 } 10324 #endif /* WANT_HISTOGRAM */ 10325 10326 nummessages++; 10327 if (trans_remaining) { 10328 trans_remaining--; 10329 } 10330 10331 if (debug > 3) { 10332 fprintf(where, 10333 "Transaction %d completed on local port %d\n", 10334 nummessages, 10335 ntohs(myaddr->sin_port)); 10336 fflush(where); 10337 } 10338 10339 10340 } 10341 10342 /* this call will always give us the elapsed time for the test, and */ 10343 /* will also store-away the necessaries for cpu utilization */ 10344 10345 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 10346 /* how long did we really run? */ 10347 10348 /* Get the statistics from the remote end. The remote will have */ 10349 /* calculated service demand and all those interesting things. If it */ 10350 /* wasn't supposed to care, it will return obvious values. */ 10351 10352 recv_response(); 10353 if (!netperf_response.content.serv_errno) { 10354 if (debug) 10355 fprintf(where,"remote results obtained\n"); 10356 } 10357 else { 10358 Set_errno(netperf_response.content.serv_errno); 10359 fprintf(where, 10360 "netperf: remote error %d", 10361 netperf_response.content.serv_errno); 10362 perror(""); 10363 fflush(where); 10364 exit(1); 10365 } 10366 10367 /* We now calculate what our thruput was for the test. In the future, */ 10368 /* we may want to include a calculation of the thruput measured by */ 10369 /* the remote, but it should be the case that for a TCP stream test, */ 10370 /* that the two numbers should be *very* close... We calculate */ 10371 /* bytes_sent regardless of the way the test length was controlled. */ 10372 /* If it was time, we needed to, and if it was by bytes, the user may */ 10373 /* have specified a number of bytes that wasn't a multiple of the */ 10374 /* send_size, so we really didn't send what he asked for ;-) We use */ 10375 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 10376 /* 1024. A future enhancement *might* be to choose from a couple of */ 10377 /* unit selections. */ 10378 10379 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 10380 thruput = calc_thruput(bytes_xferd); 10381 10382 if (local_cpu_usage || remote_cpu_usage) { 10383 /* We must now do a little math for service demand and cpu */ 10384 /* utilization for the system(s) */ 10385 /* Of course, some of the information might be bogus because */ 10386 /* there was no idle counter in the kernel(s). We need to make */ 10387 /* a note of this for the user's benefit...*/ 10388 if (local_cpu_usage) { 10389 if (local_cpu_rate == 0.0) { 10390 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 10391 fprintf(where,"Local CPU usage numbers based on process information only!\n"); 10392 fflush(where); 10393 } 10394 local_cpu_utilization = calc_cpu_util(0.0); 10395 /* since calc_service demand is doing ms/Kunit we will */ 10396 /* multiply the number of transaction by 1024 to get */ 10397 /* "good" numbers */ 10398 local_service_demand = calc_service_demand((double) nummessages*1024, 10399 0.0, 10400 0.0, 10401 0); 10402 } 10403 else { 10404 local_cpu_utilization = (float) -1.0; 10405 local_service_demand = (float) -1.0; 10406 } 10407 10408 if (remote_cpu_usage) { 10409 if (remote_cpu_rate == 0.0) { 10410 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 10411 fprintf(where,"Remote CPU usage numbers based on process information only!\n"); 10412 fflush(where); 10413 } 10414 remote_cpu_utilization = tcp_tran_rr_result->cpu_util; 10415 /* since calc_service demand is doing ms/Kunit we will */ 10416 /* multiply the number of transaction by 1024 to get */ 10417 /* "good" numbers */ 10418 remote_service_demand = calc_service_demand((double) nummessages*1024, 10419 0.0, 10420 remote_cpu_utilization, 10421 tcp_tran_rr_result->num_cpus); 10422 } 10423 else { 10424 remote_cpu_utilization = (float) -1.0; 10425 remote_service_demand = (float) -1.0; 10426 } 10427 10428 /* We are now ready to print all the information. If the user */ 10429 /* has specified zero-level verbosity, we will just print the */ 10430 /* local service demand, or the remote service demand. If the */ 10431 /* user has requested verbosity level 1, he will get the basic */ 10432 /* "streamperf" numbers. If the user has specified a verbosity */ 10433 /* of greater than 1, we will display a veritable plethora of */ 10434 /* background information from outside of this block as it it */ 10435 /* not cpu_measurement specific... */ 10436 10437 switch (verbosity) { 10438 case 0: 10439 if (local_cpu_usage) { 10440 fprintf(where, 10441 cpu_fmt_0, 10442 local_service_demand); 10443 } 10444 else { 10445 fprintf(where, 10446 cpu_fmt_0, 10447 remote_service_demand); 10448 } 10449 break; 10450 case 1: 10451 case 2: 10452 10453 if (print_headers) { 10454 fprintf(where, 10455 cpu_title, 10456 local_cpu_method, 10457 remote_cpu_method); 10458 } 10459 10460 fprintf(where, 10461 cpu_fmt_1_line_1, /* the format string */ 10462 lss_size, /* local sendbuf size */ 10463 lsr_size, 10464 req_size, /* how large were the requests */ 10465 rsp_size, /* guess */ 10466 elapsed_time, /* how long was the test */ 10467 nummessages/elapsed_time, 10468 local_cpu_utilization, /* local cpu */ 10469 remote_cpu_utilization, /* remote cpu */ 10470 local_service_demand, /* local service demand */ 10471 remote_service_demand); /* remote service demand */ 10472 fprintf(where, 10473 cpu_fmt_1_line_2, 10474 rss_size, 10475 rsr_size); 10476 break; 10477 } 10478 } 10479 else { 10480 /* The tester did not wish to measure service demand. */ 10481 switch (verbosity) { 10482 case 0: 10483 fprintf(where, 10484 tput_fmt_0, 10485 nummessages/elapsed_time); 10486 break; 10487 case 1: 10488 case 2: 10489 if (print_headers) { 10490 fprintf(where,tput_title,format_units()); 10491 } 10492 10493 fprintf(where, 10494 tput_fmt_1_line_1, /* the format string */ 10495 lss_size, 10496 lsr_size, 10497 req_size, /* how large were the requests */ 10498 rsp_size, /* how large were the responses */ 10499 elapsed_time, /* how long did it take */ 10500 nummessages/elapsed_time); 10501 fprintf(where, 10502 tput_fmt_1_line_2, 10503 rss_size, /* remote recvbuf size */ 10504 rsr_size); 10505 10506 break; 10507 } 10508 } 10509 10510 /* it would be a good thing to include information about some of the */ 10511 /* other parameters that may have been set for this test, but at the */ 10512 /* moment, I do not wish to figure-out all the formatting, so I will */ 10513 /* just put this comment here to help remind me that it is something */ 10514 /* that should be done at a later time. */ 10515 10516 if (verbosity > 1) { 10517 /* The user wanted to know it all, so we will give it to him. */ 10518 /* This information will include as much as we can find about */ 10519 /* TCP statistics, the alignments of the sends and receives */ 10520 /* and all that sort of rot... */ 10521 10522 fprintf(where, 10523 ksink_fmt, 10524 local_send_align, 10525 remote_recv_offset, 10526 local_send_offset, 10527 remote_recv_offset); 10528 10529 #ifdef WANT_HISTOGRAM 10530 fprintf(where,"\nHistogram of request/response times\n"); 10531 fflush(where); 10532 HIST_report(time_hist); 10533 #endif /* WANT_HISTOGRAM */ 10534 10535 } 10536 10537 } 10538 10539 10540 int 10542 recv_tcp_tran_rr() 10543 { 10544 10545 char *message; 10546 struct sockaddr_in myaddr_in, 10547 peeraddr_in; 10548 SOCKET s_listen,s_data; 10549 netperf_socklen_t addrlen; 10550 int NoPush = 1; 10551 10552 char *recv_message_ptr; 10553 char *send_message_ptr; 10554 char *temp_message_ptr; 10555 int trans_received; 10556 int trans_remaining; 10557 int bytes_sent; 10558 int request_bytes_recvd; 10559 int request_bytes_remaining; 10560 int timed_out = 0; 10561 float elapsed_time; 10562 10563 struct tcp_tran_rr_request_struct *tcp_tran_rr_request; 10564 struct tcp_tran_rr_response_struct *tcp_tran_rr_response; 10565 struct tcp_tran_rr_results_struct *tcp_tran_rr_results; 10566 10567 tcp_tran_rr_request = 10568 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data; 10569 tcp_tran_rr_response = 10570 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data; 10571 tcp_tran_rr_results = 10572 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data; 10573 10574 if (debug) { 10575 fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n"); 10576 fflush(where); 10577 } 10578 10579 /* We want to set-up the listen socket with all the desired */ 10580 /* parameters and then let the initiator know that all is ready. If */ 10581 /* socket size defaults are to be used, then the initiator will have */ 10582 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 10583 /* send-back what they are. If that information cannot be determined, */ 10584 /* then we send-back -1's for the sizes. If things go wrong for any */ 10585 /* reason, we will drop back ten yards and punt. */ 10586 10587 /* If anything goes wrong, we want the remote to know about it. It */ 10588 /* would be best if the error that the remote reports to the user is */ 10589 /* the actual error we encountered, rather than some bogus unexpected */ 10590 /* response type message. */ 10591 10592 if (debug) { 10593 fprintf(where,"recv_tcp_tran_rr: setting the response type...\n"); 10594 fflush(where); 10595 } 10596 10597 netperf_response.content.response_type = TCP_TRR_RESPONSE; 10598 10599 if (debug) { 10600 fprintf(where,"recv_tcp_tran_rr: the response type is set...\n"); 10601 fflush(where); 10602 } 10603 10604 /* set-up the data buffer with the requested alignment and offset */ 10605 message = (char *)malloc(DATABUFFERLEN); 10606 if (message == NULL) { 10607 printf("malloc(%d) failed!\n", DATABUFFERLEN); 10608 exit(1); 10609 } 10610 10611 /* We now alter the message_ptr variables to be at the desired */ 10612 /* alignments with the desired offsets. */ 10613 10614 if (debug) { 10615 fprintf(where, 10616 "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n", 10617 tcp_tran_rr_request->recv_alignment, 10618 tcp_tran_rr_request->recv_offset); 10619 fprintf(where, 10620 "recv_tcp_tran_rr: requested send alignment of %d offset %d\n", 10621 tcp_tran_rr_request->send_alignment, 10622 tcp_tran_rr_request->send_offset); 10623 fflush(where); 10624 } 10625 10626 recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset); 10627 10628 send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset); 10629 10630 if (debug) { 10631 fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n"); 10632 fflush(where); 10633 } 10634 10635 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */ 10636 /* can put in OUR values !-) At some point, we may want to nail this */ 10637 /* socket to a particular network-level address, but for now, */ 10638 /* INADDR_ANY should be just fine. */ 10639 10640 bzero((char *)&myaddr_in, 10641 sizeof(myaddr_in)); 10642 myaddr_in.sin_family = AF_INET; 10643 myaddr_in.sin_addr.s_addr = INADDR_ANY; 10644 myaddr_in.sin_port = htons((unsigned short)tcp_tran_rr_request->port); 10645 10646 /* Grab a socket to listen on, and then listen on it. */ 10647 10648 if (debug) { 10649 fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n"); 10650 fflush(where); 10651 } 10652 10653 /* create_data_socket expects to find some things in the global */ 10654 /* variables, so set the globals based on the values in the request. */ 10655 /* once the socket has been created, we will set the response values */ 10656 /* based on the updated value of those globals. raj 7/94 */ 10657 lss_size_req = tcp_tran_rr_request->send_buf_size; 10658 lsr_size_req = tcp_tran_rr_request->recv_buf_size; 10659 loc_nodelay = tcp_tran_rr_request->no_delay; 10660 loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid; 10661 loc_sndavoid = tcp_tran_rr_request->so_sndavoid; 10662 10663 set_hostname_and_port(local_name, 10664 port_buffer, 10665 nf_to_af(tcp_tran_rr_request->ipfamily), 10666 tcp_tran_rr_request->port); 10667 10668 local_res = complete_addrinfo(local_name, 10669 local_name, 10670 port_buffer, 10671 nf_to_af(tcp_tran_rr_request->ipfamily), 10672 SOCK_STREAM, 10673 IPPROTO_TCP, 10674 0); 10675 10676 s_listen = create_data_socket(local_res); 10677 10678 if (s_listen == INVALID_SOCKET) { 10679 netperf_response.content.serv_errno = errno; 10680 send_response(); 10681 if (debug) { 10682 fprintf(where,"could not create data socket\n"); 10683 fflush(where); 10684 } 10685 exit(1); 10686 } 10687 10688 #ifdef WIN32 10689 /* The test timer can fire during operations on the listening socket, 10690 so to make the start_timer below work we have to move 10691 it to close s_listen while we are blocked on accept. */ 10692 win_kludge_socket2 = s_listen; 10693 #endif 10694 10695 10696 /* Let's get an address assigned to this socket so we can tell the */ 10697 /* initiator how to reach the data socket. There may be a desire to */ 10698 /* nail this socket to a specific IP address in a multi-homed, */ 10699 /* multi-connection situation, but for now, we'll ignore the issue */ 10700 /* and concentrate on single connection testing. */ 10701 10702 if (bind(s_listen, 10703 (struct sockaddr *)&myaddr_in, 10704 sizeof(myaddr_in)) == SOCKET_ERROR) { 10705 netperf_response.content.serv_errno = errno; 10706 close(s_listen); 10707 send_response(); 10708 if (debug) { 10709 fprintf(where,"could not bind\n"); 10710 fflush(where); 10711 } 10712 exit(1); 10713 } 10714 10715 /* we want to disable the implicit PUSH on all sends. at some point, */ 10716 /* this might want to be a parm to the test raj 3/95 */ 10717 if (setsockopt(s_listen, 10718 IPPROTO_TCP, 10719 TCP_NOPUSH, 10720 (const char *)&NoPush, 10721 sizeof(int)) == SOCKET_ERROR) { 10722 fprintf(where, 10723 "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n", 10724 errno); 10725 fflush(where); 10726 netperf_response.content.serv_errno = errno; 10727 close(s_listen); 10728 send_response(); 10729 } 10730 10731 /* Now, let's set-up the socket to listen for connections */ 10732 if (listen(s_listen, 5) == SOCKET_ERROR) { 10733 netperf_response.content.serv_errno = errno; 10734 close(s_listen); 10735 send_response(); 10736 if (debug) { 10737 fprintf(where,"could not listen\n"); 10738 fflush(where); 10739 } 10740 exit(1); 10741 } 10742 10743 /* now get the port number assigned by the system */ 10744 addrlen = sizeof(myaddr_in); 10745 if (getsockname(s_listen, 10746 (struct sockaddr *)&myaddr_in, 10747 &addrlen) == SOCKET_ERROR){ 10748 netperf_response.content.serv_errno = errno; 10749 close(s_listen); 10750 send_response(); 10751 if (debug) { 10752 fprintf(where,"could not geetsockname\n"); 10753 fflush(where); 10754 } 10755 exit(1); 10756 } 10757 10758 /* Now myaddr_in contains the port and the internet address this is */ 10759 /* returned to the sender also implicitly telling the sender that the */ 10760 /* socket buffer sizing has been done. */ 10761 10762 tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 10763 if (debug) { 10764 fprintf(where,"telling the remote to call me at %d\n", 10765 tcp_tran_rr_response->data_port_number); 10766 fflush(where); 10767 } 10768 netperf_response.content.serv_errno = 0; 10769 10770 /* But wait, there's more. If the initiator wanted cpu measurements, */ 10771 /* then we must call the calibrate routine, which will return the max */ 10772 /* rate back to the initiator. If the CPU was not to be measured, or */ 10773 /* something went wrong with the calibration, we will return a 0.0 to */ 10774 /* the initiator. */ 10775 10776 tcp_tran_rr_response->cpu_rate = 0.0; /* assume no cpu */ 10777 if (tcp_tran_rr_request->measure_cpu) { 10778 tcp_tran_rr_response->measure_cpu = 1; 10779 tcp_tran_rr_response->cpu_rate = 10780 calibrate_local_cpu(tcp_tran_rr_request->cpu_rate); 10781 } 10782 10783 10784 10785 /* before we send the response back to the initiator, pull some of */ 10786 /* the socket parms from the globals */ 10787 tcp_tran_rr_response->send_buf_size = lss_size; 10788 tcp_tran_rr_response->recv_buf_size = lsr_size; 10789 tcp_tran_rr_response->no_delay = loc_nodelay; 10790 tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid; 10791 tcp_tran_rr_response->so_sndavoid = loc_sndavoid; 10792 10793 send_response(); 10794 10795 addrlen = sizeof(peeraddr_in); 10796 10797 /* Now it's time to start receiving data on the connection. We will */ 10798 /* first grab the apropriate counters and then start grabbing. */ 10799 10800 cpu_start(tcp_tran_rr_request->measure_cpu); 10801 10802 /* The loop will exit when the sender does a shutdown, which will */ 10803 /* return a length of zero */ 10804 10805 if (tcp_tran_rr_request->test_length > 0) { 10806 times_up = 0; 10807 trans_remaining = 0; 10808 start_timer(tcp_tran_rr_request->test_length + PAD_TIME); 10809 } 10810 else { 10811 times_up = 1; 10812 trans_remaining = tcp_tran_rr_request->test_length * -1; 10813 } 10814 10815 trans_received = 0; 10816 10817 while ((!times_up) || (trans_remaining > 0)) { 10818 10819 /* accept a connection from the remote */ 10820 if ((s_data=accept(s_listen, 10821 (struct sockaddr *)&peeraddr_in, 10822 &addrlen)) == INVALID_SOCKET) { 10823 if (errno == EINTR) { 10824 /* the timer popped */ 10825 timed_out = 1; 10826 break; 10827 } 10828 fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno); 10829 fflush(where); 10830 close(s_listen); 10831 10832 exit(1); 10833 } 10834 10835 if (debug) { 10836 fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n"); 10837 fflush(where); 10838 } 10839 10840 #ifdef WIN32 10841 /* this is used so the timer thread can close the socket out from */ 10842 /* under us, which to date is the easiest/cleanest/least */ 10843 /* Windows-specific way I can find to force the winsock calls to */ 10844 /* return WSAEINTR with the test is over. anything that will run on */ 10845 /* 95 and NT and is closer to what netperf expects from Unix signals */ 10846 /* and such would be appreciated raj 1/96 */ 10847 win_kludge_socket = s_data; 10848 #endif /* WIN32 */ 10849 10850 #ifdef KLUDGE_SOCKET_OPTIONS 10851 /* this is for those systems which *INCORRECTLY* fail to pass */ 10852 /* attributes across an accept() call. Including this goes against */ 10853 /* my better judgement :( raj 11/95 */ 10854 10855 kludge_socket_options(s_data); 10856 10857 #endif /* KLUDGE_SOCKET_OPTIONS */ 10858 10859 temp_message_ptr = recv_message_ptr; 10860 request_bytes_remaining = tcp_tran_rr_request->request_size; 10861 10862 /* receive the request from the other side. we can just receive */ 10863 /* until we get zero bytes, but that would be a slight structure */ 10864 /* change in the code, with minimal perfomance effects. If */ 10865 /* however, I has variable-length messages, I would want to do */ 10866 /* this to avoid needing "double reads" - one for the message */ 10867 /* length, and one for the rest of the message raj 3/95 */ 10868 while(request_bytes_remaining > 0) { 10869 if((request_bytes_recvd=recv(s_data, 10870 temp_message_ptr, 10871 request_bytes_remaining, 10872 0)) == SOCKET_ERROR) { 10873 if ( SOCKET_EINTR(request_bytes_recvd) ) 10874 { 10875 /* the timer popped */ 10876 timed_out = 1; 10877 break; 10878 } 10879 netperf_response.content.serv_errno = errno; 10880 send_response(); 10881 exit(1); 10882 } 10883 else { 10884 request_bytes_remaining -= request_bytes_recvd; 10885 temp_message_ptr += request_bytes_recvd; 10886 } 10887 } 10888 10889 if (timed_out) { 10890 /* we hit the end of the test based on time - lets */ 10891 /* bail out of here now... */ 10892 fprintf(where,"yo5\n"); 10893 fflush(where); 10894 break; 10895 } 10896 10897 /* Now, send the response to the remote we can use sendto here to */ 10898 /* help remind people that this is an rfc 1644 style of test */ 10899 if((bytes_sent=sendto(s_data, 10900 send_message_ptr, 10901 tcp_tran_rr_request->response_size, 10902 MSG_EOF, 10903 (struct sockaddr *)&peeraddr_in, 10904 sizeof(struct sockaddr_storage))) == SOCKET_ERROR) { 10905 if (SOCKET_EINTR(bytes_sent)) { 10906 /* the test timer has popped */ 10907 timed_out = 1; 10908 fprintf(where,"yo6\n"); 10909 fflush(where); 10910 break; 10911 } 10912 netperf_response.content.serv_errno = 99; 10913 send_response(); 10914 exit(1); 10915 } 10916 10917 trans_received++; 10918 if (trans_remaining) { 10919 trans_remaining--; 10920 } 10921 10922 if (debug) { 10923 fprintf(where, 10924 "recv_tcp_tran_rr: Transaction %d complete\n", 10925 trans_received); 10926 fflush(where); 10927 } 10928 10929 /* close the connection. since we have disable PUSH on sends, the */ 10930 /* FIN should be tacked-onto our last send instead of being */ 10931 /* standalone */ 10932 close(s_data); 10933 10934 } 10935 10936 10937 /* The loop now exits due to timeout or transaction count being */ 10938 /* reached */ 10939 10940 cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time); 10941 10942 if (timed_out) { 10943 /* we ended the test by time, which was at least 2 seconds */ 10944 /* longer than we wanted to run. so, we want to subtract */ 10945 /* PAD_TIME from the elapsed_time. */ 10946 elapsed_time -= PAD_TIME; 10947 } 10948 /* send the results to the sender */ 10949 10950 if (debug) { 10951 fprintf(where, 10952 "recv_tcp_tran_rr: got %d transactions\n", 10953 trans_received); 10954 fflush(where); 10955 } 10956 10957 tcp_tran_rr_results->bytes_received = (trans_received * 10958 (tcp_tran_rr_request->request_size + 10959 tcp_tran_rr_request->response_size)); 10960 tcp_tran_rr_results->trans_received = trans_received; 10961 tcp_tran_rr_results->elapsed_time = elapsed_time; 10962 if (tcp_tran_rr_request->measure_cpu) { 10963 tcp_tran_rr_results->cpu_util = calc_cpu_util(elapsed_time); 10964 } 10965 10966 if (debug) { 10967 fprintf(where, 10968 "recv_tcp_tran_rr: test complete, sending results.\n"); 10969 fflush(where); 10970 } 10971 10972 send_response(); 10973 10974 } 10975 #endif /* DO_1644 */ 10976 10977 #ifdef DO_NBRR 10979 /* this routine implements the sending (netperf) side of the TCP_RR */ 10980 /* test using POSIX-style non-blocking sockets. */ 10981 10982 void 10983 send_tcp_nbrr(char remote_host[]) 10984 { 10985 10986 char *tput_title = "\ 10987 Local /Remote\n\ 10988 Socket Size Request Resp. Elapsed Trans.\n\ 10989 Send Recv Size Size Time Rate \n\ 10990 bytes Bytes bytes bytes secs. per sec \n\n"; 10991 10992 char *tput_fmt_0 = 10993 "%7.2f\n"; 10994 10995 char *tput_fmt_1_line_1 = "\ 10996 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 10997 char *tput_fmt_1_line_2 = "\ 10998 %-6d %-6d\n"; 10999 11000 char *cpu_title = "\ 11001 Local /Remote\n\ 11002 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 11003 Send Recv Size Size Time Rate local remote local remote\n\ 11004 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 11005 11006 char *cpu_fmt_0 = 11007 "%6.3f %c\n"; 11008 11009 char *cpu_fmt_1_line_1 = "\ 11010 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 11011 11012 char *cpu_fmt_1_line_2 = "\ 11013 %-6d %-6d\n"; 11014 11015 char *ksink_fmt = "\ 11016 Alignment Offset\n\ 11017 Local Remote Local Remote\n\ 11018 Send Recv Send Recv\n\ 11019 %5d %5d %5d %5d\n"; 11020 11021 11022 int timed_out = 0; 11023 float elapsed_time; 11024 11025 int len; 11026 char *temp_message_ptr; 11027 int nummessages; 11028 SOCKET send_socket; 11029 int trans_remaining; 11030 double bytes_xferd; 11031 11032 struct ring_elt *send_ring; 11033 struct ring_elt *recv_ring; 11034 11035 int rsp_bytes_left; 11036 int rsp_bytes_recvd; 11037 11038 float local_cpu_utilization; 11039 float local_service_demand; 11040 float remote_cpu_utilization; 11041 float remote_service_demand; 11042 double thruput; 11043 11044 struct hostent *hp; 11045 struct sockaddr_storage server; 11046 unsigned int addr; 11047 11048 struct tcp_rr_request_struct *tcp_rr_request; 11049 struct tcp_rr_response_struct *tcp_rr_response; 11050 struct tcp_rr_results_struct *tcp_rr_result; 11051 11052 struct addrinfo *remote_res; 11053 struct addrinfo *local_res; 11054 11055 tcp_rr_request = 11056 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 11057 tcp_rr_response= 11058 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 11059 tcp_rr_result = 11060 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 11061 11062 #ifdef WANT_HISTOGRAM 11063 if (verbosity > 1) { 11064 time_hist = HIST_new(); 11065 } 11066 #endif /* WANT_HISTOGRAM */ 11067 11068 /* since we are now disconnected from the code that established the */ 11069 /* control socket, and since we want to be able to use different */ 11070 /* protocols and such, we are passed the name of the remote host and */ 11071 /* must turn that into the test specific addressing information. */ 11072 11073 bzero((char *)&server, 11074 sizeof(server)); 11075 11076 complete_addrinfos(&remote_res, 11077 &local_res, 11078 remote_host, 11079 SOCK_STREAM, 11080 IPPROTO_TCP, 11081 0); 11082 11083 if ( print_headers ) { 11084 print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res); 11085 } 11086 11087 /* initialize a few counters */ 11088 11089 send_ring = NULL; 11090 recv_ring = NULL; 11091 confidence_iteration = 1; 11092 init_stat(); 11093 11094 /* we have a great-big while loop which controls the number of times */ 11095 /* we run a particular test. this is for the calculation of a */ 11096 /* confidence interval (I really should have stayed awake during */ 11097 /* probstats :). If the user did not request confidence measurement */ 11098 /* (no confidence is the default) then we will only go though the */ 11099 /* loop once. the confidence stuff originates from the folks at IBM */ 11100 11101 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 11102 (confidence_iteration <= iteration_min)) { 11103 11104 /* initialize a few counters. we have to remember that we might be */ 11105 /* going through the loop more than once. */ 11106 11107 nummessages = 0; 11108 bytes_xferd = 0.0; 11109 times_up = 0; 11110 timed_out = 0; 11111 trans_remaining = 0; 11112 11113 /* set-up the data buffers with the requested alignment and offset. */ 11114 /* since this is a request/response test, default the send_width and */ 11115 /* recv_width to 1 and not two raj 7/94 */ 11116 11117 if (send_width == 0) send_width = 1; 11118 if (recv_width == 0) recv_width = 1; 11119 11120 if (send_ring == NULL) { 11121 send_ring = allocate_buffer_ring(send_width, 11122 req_size, 11123 local_send_align, 11124 local_send_offset); 11125 } 11126 11127 if (recv_ring == NULL) { 11128 recv_ring = allocate_buffer_ring(recv_width, 11129 rsp_size, 11130 local_recv_align, 11131 local_recv_offset); 11132 } 11133 11134 /*set up the data socket */ 11135 send_socket = create_data_socket(local_res); 11136 11137 if (send_socket == INVALID_SOCKET){ 11138 perror("netperf: send_tcp_nbrr: tcp stream data socket"); 11139 exit(1); 11140 } 11141 11142 if (debug) { 11143 fprintf(where,"send_tcp_nbrr: send_socket obtained...\n"); 11144 } 11145 11146 /* If the user has requested cpu utilization measurements, we must */ 11147 /* calibrate the cpu(s). We will perform this task within the tests */ 11148 /* themselves. If the user has specified the cpu rate, then */ 11149 /* calibrate_local_cpu will return rather quickly as it will have */ 11150 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 11151 /* all the "normal" calibration stuff and return the rate back.*/ 11152 11153 if (local_cpu_usage) { 11154 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 11155 } 11156 11157 /* Tell the remote end to do a listen. The server alters the socket */ 11158 /* paramters on the other side at this point, hence the reason for */ 11159 /* all the values being passed in the setup message. If the user did */ 11160 /* not specify any of the parameters, they will be passed as 0, which */ 11161 /* will indicate to the remote that no changes beyond the system's */ 11162 /* default should be used. Alignment is the exception, it will */ 11163 /* default to 8, which will be no alignment alterations. */ 11164 11165 netperf_request.content.request_type = DO_TCP_NBRR; 11166 tcp_rr_request->recv_buf_size = rsr_size_req; 11167 tcp_rr_request->send_buf_size = rss_size_req; 11168 tcp_rr_request->recv_alignment = remote_recv_align; 11169 tcp_rr_request->recv_offset = remote_recv_offset; 11170 tcp_rr_request->send_alignment = remote_send_align; 11171 tcp_rr_request->send_offset = remote_send_offset; 11172 tcp_rr_request->request_size = req_size; 11173 tcp_rr_request->response_size = rsp_size; 11174 tcp_rr_request->no_delay = rem_nodelay; 11175 tcp_rr_request->measure_cpu = remote_cpu_usage; 11176 tcp_rr_request->cpu_rate = remote_cpu_rate; 11177 tcp_rr_request->so_rcvavoid = rem_rcvavoid; 11178 tcp_rr_request->so_sndavoid = rem_sndavoid; 11179 if (test_time) { 11180 tcp_rr_request->test_length = test_time; 11181 } 11182 else { 11183 tcp_rr_request->test_length = test_trans * -1; 11184 } 11185 11186 if (debug > 1) { 11187 fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n"); 11188 } 11189 11190 send_request(); 11191 11192 /* The response from the remote will contain all of the relevant */ 11193 /* socket parameters for this test type. We will put them back into */ 11194 /* the variables here so they can be displayed if desired. The */ 11195 /* remote will have calibrated CPU if necessary, and will have done */ 11196 /* all the needed set-up we will have calibrated the cpu locally */ 11197 /* before sending the request, and will grab the counter value right*/ 11198 /* after the connect returns. The remote will grab the counter right*/ 11199 /* after the accept call. This saves the hassle of extra messages */ 11200 /* being sent for the TCP tests. */ 11201 11202 recv_response(); 11203 11204 if (!netperf_response.content.serv_errno) { 11205 if (debug) 11206 fprintf(where,"remote listen done.\n"); 11207 rsr_size = tcp_rr_response->recv_buf_size; 11208 rss_size = tcp_rr_response->send_buf_size; 11209 rem_nodelay = tcp_rr_response->no_delay; 11210 remote_cpu_usage = tcp_rr_response->measure_cpu; 11211 remote_cpu_rate = tcp_rr_response->cpu_rate; 11212 /* make sure that port numbers are in network order */ 11213 server.sin_port = (unsigned short)tcp_rr_response->data_port_number; 11214 server.sin_port = htons(server.sin_port); 11215 } 11216 else { 11217 Set_errno(netperf_response.content.serv_errno); 11218 fprintf(where, 11219 "netperf: remote error %d", 11220 netperf_response.content.serv_errno); 11221 perror(""); 11222 fflush(where); 11223 exit(1); 11224 } 11225 11226 /*Connect up to the remote port on the data socket */ 11227 if (connect(send_socket, 11228 remote_res->ai_addr, 11229 remote_res->ai_addrlen) == INVALID_SOCKET){ 11230 perror("netperf: data socket connect failed"); 11231 11232 exit(1); 11233 } 11234 11235 /* now that we are connected, mark the socket as non-blocking */ 11236 if (!set_nonblock(send_socket)) { 11237 perror("netperf: set_nonblock"); 11238 exit(1); 11239 } 11240 11241 #ifdef WIN32 11242 /* this is used so the timer thread can close the socket out from */ 11243 /* under us, which to date is the easiest/cleanest/least */ 11244 /* Windows-specific way I can find to force the winsock calls to */ 11245 /* return WSAEINTR with the test is over. anything that will run on */ 11246 /* 95 and NT and is closer to what netperf expects from Unix signals */ 11247 /* and such would be appreciated raj 1/96 */ 11248 win_kludge_socket = send_socket; 11249 #endif /* WIN32 */ 11250 11251 /* Data Socket set-up is finished. If there were problems, either the */ 11252 /* connect would have failed, or the previous response would have */ 11253 /* indicated a problem. I failed to see the value of the extra */ 11254 /* message after the accept on the remote. If it failed, we'll see it */ 11255 /* here. If it didn't, we might as well start pumping data. */ 11256 11257 /* Set-up the test end conditions. For a request/response test, they */ 11258 /* can be either time or transaction based. */ 11259 11260 if (test_time) { 11261 /* The user wanted to end the test after a period of time. */ 11262 times_up = 0; 11263 trans_remaining = 0; 11264 start_timer(test_time); 11265 } 11266 else { 11267 /* The tester wanted to send a number of bytes. */ 11268 trans_remaining = test_bytes; 11269 times_up = 1; 11270 } 11271 11272 /* The cpu_start routine will grab the current time and possibly */ 11273 /* value of the idle counter for later use in measuring cpu */ 11274 /* utilization and/or service demand and thruput. */ 11275 11276 cpu_start(local_cpu_usage); 11277 11278 #ifdef WANT_INTERVALS 11279 INTERVALS_INIT(); 11280 #endif /* WANT_INTERVALS */ 11281 11282 /* We use an "OR" to control test execution. When the test is */ 11283 /* controlled by time, the byte count check will always return false. */ 11284 /* When the test is controlled by byte count, the time test will */ 11285 /* always return false. When the test is finished, the whole */ 11286 /* expression will go false and we will stop sending data. I think I */ 11287 /* just arbitrarily decrement trans_remaining for the timed test, but */ 11288 /* will not do that just yet... One other question is whether or not */ 11289 /* the send buffer and the receive buffer should be the same buffer. */ 11290 11291 while ((!times_up) || (trans_remaining > 0)) { 11292 /* send the request. we assume that if we use a blocking socket, */ 11293 /* the request will be sent at one shot. */ 11294 11295 #ifdef WANT_HISTOGRAM 11296 if (verbosity > 1) { 11297 /* timestamp just before our call to send, and then again just */ 11298 /* after the receive raj 8/94 */ 11299 HIST_timestamp(&time_one); 11300 } 11301 #endif /* WANT_HISTOGRAM */ 11302 11303 /* even though this is a non-blocking socket, we will assume for */ 11304 /* the time being that we will be able to send an entire request */ 11305 /* without getting an EAGAIN */ 11306 if((len=send(send_socket, 11307 send_ring->buffer_ptr, 11308 req_size, 11309 0)) != req_size) { 11310 if (SOCKET_EINTR(len)) { 11311 /* we hit the end of a */ 11312 /* timed test. */ 11313 timed_out = 1; 11314 break; 11315 } 11316 perror("send_tcp_nbrr: data send error"); 11317 exit(1); 11318 } 11319 send_ring = send_ring->next; 11320 11321 /* receive the response. since we are using non-blocking I/O, we */ 11322 /* will "spin" on the recvs */ 11323 rsp_bytes_left = rsp_size; 11324 temp_message_ptr = recv_ring->buffer_ptr; 11325 while(rsp_bytes_left > 0) { 11326 if((rsp_bytes_recvd=recv(send_socket, 11327 temp_message_ptr, 11328 rsp_bytes_left, 11329 0)) == SOCKET_ERROR) { 11330 if (SOCKET_EINTR(rsp_bytes_recvd)) 11331 { 11332 /* We hit the end of a timed test. */ 11333 timed_out = 1; 11334 break; 11335 } 11336 #ifndef WIN32 // But what does WinNT indicate in this situation... 11337 else if (errno == EAGAIN) { 11338 Set_errno(0); 11339 continue; 11340 } 11341 #endif 11342 else { 11343 perror("send_tcp_nbrr: data recv error"); 11344 exit(1); 11345 } 11346 } 11347 rsp_bytes_left -= rsp_bytes_recvd; 11348 temp_message_ptr += rsp_bytes_recvd; 11349 } 11350 recv_ring = recv_ring->next; 11351 11352 if (timed_out) { 11353 /* we may have been in a nested while loop - we need */ 11354 /* another call to break. */ 11355 break; 11356 } 11357 11358 #ifdef WANT_HISTOGRAM 11359 if (verbosity > 1) { 11360 HIST_timestamp(&time_two); 11361 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 11362 } 11363 #endif /* WANT_HISTOGRAM */ 11364 #ifdef WANT_INTERVALS 11365 INTERVALS_WAIT(); 11366 #endif /* WANT_INTERVALS */ 11367 11368 nummessages++; 11369 if (trans_remaining) { 11370 trans_remaining--; 11371 } 11372 11373 if (debug > 3) { 11374 if ((nummessages % 100) == 0) { 11375 fprintf(where, 11376 "Transaction %d completed\n", 11377 nummessages); 11378 fflush(where); 11379 } 11380 } 11381 } 11382 11383 /* At this point we used to call shutdown on the data socket to be */ 11384 /* sure all the data was delivered, but this was not germane in a */ 11385 /* request/response test, and it was causing the tests to "hang" when */ 11386 /* they were being controlled by time. So, I have replaced this */ 11387 /* shutdown call with a call to close that can be found later in the */ 11388 /* procedure. */ 11389 11390 /* this call will always give us the elapsed time for the test, and */ 11391 /* will also store-away the necessaries for cpu utilization */ 11392 11393 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 11394 /* measured? how long */ 11395 /* did we really run? */ 11396 11397 /* Get the statistics from the remote end. The remote will have */ 11398 /* calculated service demand and all those interesting things. If it */ 11399 /* wasn't supposed to care, it will return obvious values. */ 11400 11401 #if defined(WANT_INTERVALS) 11402 #ifdef WIN32 11403 stop_itimer(); 11404 #endif 11405 #endif /* WANT_INTERVALS */ 11406 11407 recv_response(); 11408 if (!netperf_response.content.serv_errno) { 11409 if (debug) 11410 fprintf(where,"remote results obtained\n"); 11411 } 11412 else { 11413 Set_errno(netperf_response.content.serv_errno); 11414 fprintf(where, 11415 "netperf: remote error %d", 11416 netperf_response.content.serv_errno); 11417 perror(""); 11418 fflush(where); 11419 11420 exit(1); 11421 } 11422 11423 /* We now calculate what our thruput was for the test. */ 11424 11425 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 11426 thruput = nummessages/elapsed_time; 11427 11428 if (local_cpu_usage || remote_cpu_usage) { 11429 /* We must now do a little math for service demand and cpu */ 11430 /* utilization for the system(s) */ 11431 /* Of course, some of the information might be bogus because */ 11432 /* there was no idle counter in the kernel(s). We need to make */ 11433 /* a note of this for the user's benefit...*/ 11434 if (local_cpu_usage) { 11435 local_cpu_utilization = calc_cpu_util(0.0); 11436 /* since calc_service demand is doing ms/Kunit we will */ 11437 /* multiply the number of transaction by 1024 to get */ 11438 /* "good" numbers */ 11439 local_service_demand = calc_service_demand((double) nummessages*1024, 11440 0.0, 11441 0.0, 11442 0); 11443 } 11444 else { 11445 local_cpu_utilization = (float) -1.0; 11446 local_service_demand = (float) -1.0; 11447 } 11448 11449 if (remote_cpu_usage) { 11450 remote_cpu_utilization = tcp_rr_result->cpu_util; 11451 /* since calc_service demand is doing ms/Kunit we will */ 11452 /* multiply the number of transaction by 1024 to get */ 11453 /* "good" numbers */ 11454 remote_service_demand = calc_service_demand((double) nummessages*1024, 11455 0.0, 11456 remote_cpu_utilization, 11457 tcp_rr_result->num_cpus); 11458 } 11459 else { 11460 remote_cpu_utilization = (float) -1.0; 11461 remote_service_demand = (float) -1.0; 11462 } 11463 11464 } 11465 else { 11466 /* we were not measuring cpu, for the confidence stuff, we */ 11467 /* should make it -1.0 */ 11468 local_cpu_utilization = (float) -1.0; 11469 local_service_demand = (float) -1.0; 11470 remote_cpu_utilization = (float) -1.0; 11471 remote_service_demand = (float) -1.0; 11472 } 11473 11474 /* at this point, we want to calculate the confidence information. */ 11475 /* if debugging is on, calculate_confidence will print-out the */ 11476 /* parameters we pass it */ 11477 11478 calculate_confidence(confidence_iteration, 11479 elapsed_time, 11480 thruput, 11481 local_cpu_utilization, 11482 remote_cpu_utilization, 11483 local_service_demand, 11484 remote_service_demand); 11485 11486 11487 confidence_iteration++; 11488 11489 /* we are now done with the socket, so close it */ 11490 close(send_socket); 11491 11492 } 11493 11494 retrieve_confident_values(&elapsed_time, 11495 &thruput, 11496 &local_cpu_utilization, 11497 &remote_cpu_utilization, 11498 &local_service_demand, 11499 &remote_service_demand); 11500 11501 /* We are now ready to print all the information. If the user */ 11502 /* has specified zero-level verbosity, we will just print the */ 11503 /* local service demand, or the remote service demand. If the */ 11504 /* user has requested verbosity level 1, he will get the basic */ 11505 /* "streamperf" numbers. If the user has specified a verbosity */ 11506 /* of greater than 1, we will display a veritable plethora of */ 11507 /* background information from outside of this block as it it */ 11508 /* not cpu_measurement specific... */ 11509 11510 if (confidence < 0) { 11511 /* we did not hit confidence, but were we asked to look for it? */ 11512 if (iteration_max > 1) { 11513 display_confidence(); 11514 } 11515 } 11516 11517 if (local_cpu_usage || remote_cpu_usage) { 11518 local_cpu_method = format_cpu_method(cpu_method); 11519 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method); 11520 11521 switch (verbosity) { 11522 case 0: 11523 if (local_cpu_usage) { 11524 fprintf(where, 11525 cpu_fmt_0, 11526 local_service_demand, 11527 local_cpu_method); 11528 } 11529 else { 11530 fprintf(where, 11531 cpu_fmt_0, 11532 remote_service_demand, 11533 remote_cpu_method); 11534 } 11535 break; 11536 case 1: 11537 case 2: 11538 if (print_headers) { 11539 fprintf(where, 11540 cpu_title, 11541 local_cpu_method, 11542 remote_cpu_method); 11543 } 11544 11545 fprintf(where, 11546 cpu_fmt_1_line_1, /* the format string */ 11547 lss_size, /* local sendbuf size */ 11548 lsr_size, 11549 req_size, /* how large were the requests */ 11550 rsp_size, /* guess */ 11551 elapsed_time, /* how long was the test */ 11552 thruput, 11553 local_cpu_utilization, /* local cpu */ 11554 remote_cpu_utilization, /* remote cpu */ 11555 local_service_demand, /* local service demand */ 11556 remote_service_demand); /* remote service demand */ 11557 fprintf(where, 11558 cpu_fmt_1_line_2, 11559 rss_size, 11560 rsr_size); 11561 break; 11562 } 11563 } 11564 else { 11565 /* The tester did not wish to measure service demand. */ 11566 11567 switch (verbosity) { 11568 case 0: 11569 fprintf(where, 11570 tput_fmt_0, 11571 thruput); 11572 break; 11573 case 1: 11574 case 2: 11575 if (print_headers) { 11576 fprintf(where,tput_title,format_units()); 11577 } 11578 11579 fprintf(where, 11580 tput_fmt_1_line_1, /* the format string */ 11581 lss_size, 11582 lsr_size, 11583 req_size, /* how large were the requests */ 11584 rsp_size, /* how large were the responses */ 11585 elapsed_time, /* how long did it take */ 11586 thruput); 11587 fprintf(where, 11588 tput_fmt_1_line_2, 11589 rss_size, /* remote recvbuf size */ 11590 rsr_size); 11591 11592 break; 11593 } 11594 } 11595 11596 /* it would be a good thing to include information about some of the */ 11597 /* other parameters that may have been set for this test, but at the */ 11598 /* moment, I do not wish to figure-out all the formatting, so I will */ 11599 /* just put this comment here to help remind me that it is something */ 11600 /* that should be done at a later time. */ 11601 11602 /* how to handle the verbose information in the presence of */ 11603 /* confidence intervals is yet to be determined... raj 11/94 */ 11604 if (verbosity > 1) { 11605 /* The user wanted to know it all, so we will give it to him. */ 11606 /* This information will include as much as we can find about */ 11607 /* TCP statistics, the alignments of the sends and receives */ 11608 /* and all that sort of rot... */ 11609 11610 fprintf(where, 11611 ksink_fmt, 11612 local_send_align, 11613 remote_recv_offset, 11614 local_send_offset, 11615 remote_recv_offset); 11616 11617 #ifdef WANT_HISTOGRAM 11618 fprintf(where,"\nHistogram of request/response times\n"); 11619 fflush(where); 11620 HIST_report(time_hist); 11621 #endif /* WANT_HISTOGRAM */ 11622 11623 } 11624 11625 } 11626 11627 /* this routine implements the receive (netserver) side of a TCP_RR */ 11629 /* test */ 11630 void 11631 recv_tcp_nbrr() 11632 { 11633 11634 struct ring_elt *send_ring; 11635 struct ring_elt *recv_ring; 11636 11637 struct sockaddr_in myaddr_in, 11638 peeraddr_in; 11639 SOCKET s_listen,s_data; 11640 netperf_socklen_t addrlen; 11641 char *temp_message_ptr; 11642 int trans_received; 11643 int trans_remaining; 11644 int bytes_sent; 11645 int request_bytes_recvd; 11646 int request_bytes_remaining; 11647 int timed_out = 0; 11648 float elapsed_time; 11649 11650 struct addrinfo *local_res; 11651 char local_name[BUFSIZ]; 11652 char port_buffer[PORTBUFSIZE]; 11653 11654 struct tcp_rr_request_struct *tcp_rr_request; 11655 struct tcp_rr_response_struct *tcp_rr_response; 11656 struct tcp_rr_results_struct *tcp_rr_results; 11657 11658 tcp_rr_request = 11659 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 11660 tcp_rr_response = 11661 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 11662 tcp_rr_results = 11663 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 11664 11665 if (debug) { 11666 fprintf(where,"netserver: recv_tcp_nbrr: entered...\n"); 11667 fflush(where); 11668 } 11669 11670 /* We want to set-up the listen socket with all the desired */ 11671 /* parameters and then let the initiator know that all is ready. If */ 11672 /* socket size defaults are to be used, then the initiator will have */ 11673 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 11674 /* send-back what they are. If that information cannot be determined, */ 11675 /* then we send-back -1's for the sizes. If things go wrong for any */ 11676 /* reason, we will drop back ten yards and punt. */ 11677 11678 /* If anything goes wrong, we want the remote to know about it. It */ 11679 /* would be best if the error that the remote reports to the user is */ 11680 /* the actual error we encountered, rather than some bogus unexpected */ 11681 /* response type message. */ 11682 11683 if (debug) { 11684 fprintf(where,"recv_tcp_nbrr: setting the response type...\n"); 11685 fflush(where); 11686 } 11687 11688 netperf_response.content.response_type = TCP_RR_RESPONSE; 11689 11690 if (debug) { 11691 fprintf(where,"recv_tcp_nbrr: the response type is set...\n"); 11692 fflush(where); 11693 } 11694 11695 /* allocate the recv and send rings with the requested alignments */ 11696 /* and offsets. raj 7/94 */ 11697 if (debug) { 11698 fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n", 11699 tcp_rr_request->recv_alignment, 11700 tcp_rr_request->recv_offset); 11701 fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n", 11702 tcp_rr_request->send_alignment, 11703 tcp_rr_request->send_offset); 11704 fflush(where); 11705 } 11706 11707 /* at some point, these need to come to us from the remote system */ 11708 if (send_width == 0) send_width = 1; 11709 if (recv_width == 0) recv_width = 1; 11710 11711 send_ring = allocate_buffer_ring(send_width, 11712 tcp_rr_request->response_size, 11713 tcp_rr_request->send_alignment, 11714 tcp_rr_request->send_offset); 11715 11716 recv_ring = allocate_buffer_ring(recv_width, 11717 tcp_rr_request->request_size, 11718 tcp_rr_request->recv_alignment, 11719 tcp_rr_request->recv_offset); 11720 11721 11722 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */ 11723 /* can put in OUR values !-) At some point, we may want to nail this */ 11724 /* socket to a particular network-level address, but for now, */ 11725 /* INADDR_ANY should be just fine. */ 11726 11727 bzero((char *)&myaddr_in, 11728 sizeof(myaddr_in)); 11729 myaddr_in.sin_family = AF_INET; 11730 myaddr_in.sin_addr.s_addr = INADDR_ANY; 11731 myaddr_in.sin_port = htons((unsigned short)tcp_rr_request->port); 11732 11733 /* Grab a socket to listen on, and then listen on it. */ 11734 11735 if (debug) { 11736 fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n"); 11737 fflush(where); 11738 } 11739 11740 /* create_data_socket expects to find some things in the global */ 11741 /* variables, so set the globals based on the values in the request. */ 11742 /* once the socket has been created, we will set the response values */ 11743 /* based on the updated value of those globals. raj 7/94 */ 11744 lss_size_req = tcp_rr_request->send_buf_size; 11745 lsr_size_req = tcp_rr_request->recv_buf_size; 11746 loc_nodelay = tcp_rr_request->no_delay; 11747 loc_rcvavoid = tcp_rr_request->so_rcvavoid; 11748 loc_sndavoid = tcp_rr_request->so_sndavoid; 11749 11750 set_hostname_and_port(local_name, 11751 port_buffer, 11752 nf_to_af(tcp_rr_request->ipfamily), 11753 tcp_rr_request->port); 11754 11755 local_res = complete_addrinfo(local_name, 11756 local_name, 11757 port_buffer, 11758 nf_to_af(tcp_rr_request->ipfamily), 11759 SOCK_STREAM, 11760 IPPROTO_TCP, 11761 0); 11762 11763 s_listen = create_data_socket(local_res); 11764 11765 if (s_listen == INVALID_SOCKET) { 11766 netperf_response.content.serv_errno = errno; 11767 send_response(); 11768 11769 exit(1); 11770 } 11771 11772 /* Let's get an address assigned to this socket so we can tell the */ 11773 /* initiator how to reach the data socket. There may be a desire to */ 11774 /* nail this socket to a specific IP address in a multi-homed, */ 11775 /* multi-connection situation, but for now, we'll ignore the issue */ 11776 /* and concentrate on single connection testing. */ 11777 11778 if (bind(s_listen, 11779 (struct sockaddr *)&myaddr_in, 11780 sizeof(myaddr_in)) == SOCKET_ERROR) { 11781 netperf_response.content.serv_errno = errno; 11782 close(s_listen); 11783 send_response(); 11784 11785 exit(1); 11786 } 11787 11788 /* Now, let's set-up the socket to listen for connections */ 11789 if (listen(s_listen, 5) == SOCKET_ERROR) { 11790 netperf_response.content.serv_errno = errno; 11791 close(s_listen); 11792 send_response(); 11793 11794 exit(1); 11795 } 11796 11797 11798 /* now get the port number assigned by the system */ 11799 addrlen = sizeof(myaddr_in); 11800 if (getsockname(s_listen, 11801 (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){ 11802 netperf_response.content.serv_errno = errno; 11803 close(s_listen); 11804 send_response(); 11805 11806 exit(1); 11807 } 11808 11809 /* Now myaddr_in contains the port and the internet address this is */ 11810 /* returned to the sender also implicitly telling the sender that the */ 11811 /* socket buffer sizing has been done. */ 11812 11813 tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 11814 netperf_response.content.serv_errno = 0; 11815 11816 /* But wait, there's more. If the initiator wanted cpu measurements, */ 11817 /* then we must call the calibrate routine, which will return the max */ 11818 /* rate back to the initiator. If the CPU was not to be measured, or */ 11819 /* something went wrong with the calibration, we will return a 0.0 to */ 11820 /* the initiator. */ 11821 11822 tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */ 11823 tcp_rr_response->measure_cpu = 0; 11824 11825 if (tcp_rr_request->measure_cpu) { 11826 tcp_rr_response->measure_cpu = 1; 11827 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate); 11828 } 11829 11830 11831 /* before we send the response back to the initiator, pull some of */ 11832 /* the socket parms from the globals */ 11833 tcp_rr_response->send_buf_size = lss_size; 11834 tcp_rr_response->recv_buf_size = lsr_size; 11835 tcp_rr_response->no_delay = loc_nodelay; 11836 tcp_rr_response->so_rcvavoid = loc_rcvavoid; 11837 tcp_rr_response->so_sndavoid = loc_sndavoid; 11838 tcp_rr_response->test_length = tcp_rr_request->test_length; 11839 send_response(); 11840 11841 addrlen = sizeof(peeraddr_in); 11842 11843 if ((s_data = accept(s_listen, 11844 (struct sockaddr *)&peeraddr_in, 11845 &addrlen)) == INVALID_SOCKET) { 11846 /* Let's just punt. The remote will be given some information */ 11847 close(s_listen); 11848 exit(1); 11849 } 11850 11851 if (debug) { 11852 fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n"); 11853 fflush(where); 11854 } 11855 11856 #ifdef KLUDGE_SOCKET_OPTIONS 11857 /* this is for those systems which *INCORRECTLY* fail to pass */ 11858 /* attributes across an accept() call. Including this goes against */ 11859 /* my better judgement :( raj 11/95 */ 11860 11861 kludge_socket_options(s_data); 11862 11863 #endif /* KLUDGE_SOCKET_OPTIONS */ 11864 11865 /* now that we are connected, mark the socket as non-blocking */ 11866 if (!set_nonblock(s_data)) { 11867 close(s_data); 11868 exit(1); 11869 } 11870 11871 11872 /* Now it's time to start receiving data on the connection. We will */ 11873 /* first grab the apropriate counters and then start grabbing. */ 11874 11875 cpu_start(tcp_rr_request->measure_cpu); 11876 11877 #ifdef WIN32 11878 /* this is used so the timer thread can close the socket out from */ 11879 /* under us, which to date is the easiest/cleanest/least */ 11880 /* Windows-specific way I can find to force the winsock calls to */ 11881 /* return WSAEINTR with the test is over. anything that will run on */ 11882 /* 95 and NT and is closer to what netperf expects from Unix signals */ 11883 /* and such would be appreciated raj 1/96 */ 11884 win_kludge_socket = s_data; 11885 #endif /* WIN32 */ 11886 11887 /* The loop will exit when the sender does a shutdown, which will */ 11888 /* return a length of zero */ 11889 11890 if (tcp_rr_request->test_length > 0) { 11891 times_up = 0; 11892 trans_remaining = 0; 11893 start_timer(tcp_rr_request->test_length + PAD_TIME); 11894 } 11895 else { 11896 times_up = 1; 11897 trans_remaining = tcp_rr_request->test_length * -1; 11898 } 11899 11900 trans_received = 0; 11901 11902 while ((!times_up) || (trans_remaining > 0)) { 11903 temp_message_ptr = recv_ring->buffer_ptr; 11904 request_bytes_remaining = tcp_rr_request->request_size; 11905 while(request_bytes_remaining > 0) { 11906 if((request_bytes_recvd=recv(s_data, 11907 temp_message_ptr, 11908 request_bytes_remaining, 11909 0)) == SOCKET_ERROR) { 11910 if ( SOCKET_EINTR(request_bytes_recvd)) 11911 { 11912 /* the timer popped */ 11913 timed_out = 1; 11914 break; 11915 } 11916 #ifndef WIN32 // But what does WinNT indicate in this situation... 11917 else if (errno == EAGAIN) { 11918 Set_errno(0); 11919 if (times_up) { 11920 timed_out = 1; 11921 break; 11922 } 11923 continue; 11924 } 11925 #endif 11926 else { 11927 netperf_response.content.serv_errno = errno; 11928 send_response(); 11929 exit(1); 11930 } 11931 } 11932 else { 11933 request_bytes_remaining -= request_bytes_recvd; 11934 temp_message_ptr += request_bytes_recvd; 11935 } 11936 } 11937 11938 recv_ring = recv_ring->next; 11939 11940 if (timed_out) { 11941 /* we hit the end of the test based on time - lets */ 11942 /* bail out of here now... */ 11943 fprintf(where,"yo5\n"); 11944 fflush(where); 11945 break; 11946 } 11947 11948 /* Now, send the response to the remote */ 11949 if((bytes_sent=send(s_data, 11950 send_ring->buffer_ptr, 11951 tcp_rr_request->response_size, 11952 0)) == SOCKET_ERROR) { 11953 if (SOCKET_EINTR(bytes_sent)) { 11954 /* the test timer has popped */ 11955 timed_out = 1; 11956 fprintf(where,"yo6\n"); 11957 fflush(where); 11958 break; 11959 } 11960 netperf_response.content.serv_errno = 992; 11961 send_response(); 11962 exit(1); 11963 } 11964 11965 send_ring = send_ring->next; 11966 11967 trans_received++; 11968 if (trans_remaining) { 11969 trans_remaining--; 11970 } 11971 } 11972 11973 11974 /* The loop now exits due to timeout or transaction count being */ 11975 /* reached */ 11976 11977 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time); 11978 11979 stop_timer(); 11980 11981 if (timed_out) { 11982 /* we ended the test by time, which was at least 2 seconds */ 11983 /* longer than we wanted to run. so, we want to subtract */ 11984 /* PAD_TIME from the elapsed_time. */ 11985 elapsed_time -= PAD_TIME; 11986 } 11987 11988 /* send the results to the sender */ 11989 11990 if (debug) { 11991 fprintf(where, 11992 "recv_tcp_nbrr: got %d transactions\n", 11993 trans_received); 11994 fflush(where); 11995 } 11996 11997 tcp_rr_results->bytes_received = (trans_received * 11998 (tcp_rr_request->request_size + 11999 tcp_rr_request->response_size)); 12000 tcp_rr_results->trans_received = trans_received; 12001 tcp_rr_results->elapsed_time = elapsed_time; 12002 tcp_rr_results->cpu_method = cpu_method; 12003 tcp_rr_results->num_cpus = lib_num_loc_cpus; 12004 if (tcp_rr_request->measure_cpu) { 12005 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 12006 } 12007 12008 if (debug) { 12009 fprintf(where, 12010 "recv_tcp_nbrr: test complete, sending results.\n"); 12011 fflush(where); 12012 } 12013 12014 /* we are done with the socket, free it */ 12015 close(s_data); 12016 12017 send_response(); 12018 12019 } 12020 12021 #endif /* DO_NBRR */ 12022 12023 12025 /* this test is intended to test the performance of establishing a */ 12026 /* connection, and then closing it again. this test is of somewhat */ 12027 /* arcane interest since no packets are exchanged between the */ 12028 /* user-space processes, but it will show the raw overhead of */ 12029 /* establishing a TCP connection. that service demand could then be */ 12030 /* compared with the sum of the service demands of a TCP_CRR and */ 12031 /* TCP_RR test - presumeably, they would all relate */ 12032 12033 void 12034 send_tcp_cc(char remote_host[]) 12035 { 12036 12037 char *tput_title = "\ 12038 Local /Remote\n\ 12039 Socket Size Request Resp. Elapsed Trans.\n\ 12040 Send Recv Size Size Time Rate \n\ 12041 bytes Bytes bytes bytes secs. per sec \n\n"; 12042 12043 char *tput_fmt_0 = 12044 "%7.2f\n"; 12045 12046 char *tput_fmt_1_line_1 = "\ 12047 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 12048 char *tput_fmt_1_line_2 = "\ 12049 %-6d %-6d\n"; 12050 12051 char *cpu_title = "\ 12052 Local /Remote\n\ 12053 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 12054 Send Recv Size Size Time Rate local remote local remote\n\ 12055 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 12056 12057 char *cpu_fmt_0 = 12058 "%6.3f\n"; 12059 12060 char *cpu_fmt_1_line_1 = "\ 12061 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 12062 12063 char *cpu_fmt_1_line_2 = "\ 12064 %-6d %-6d\n"; 12065 12066 char *ksink_fmt = "\n\ 12067 Alignment Offset\n\ 12068 Local Remote Local Remote\n\ 12069 Send Recv Send Recv\n\ 12070 %5d %5d %5d %5d\n"; 12071 12072 12073 int timed_out = 0; 12074 float elapsed_time; 12075 12076 char temp_message_ptr[1]; 12077 int nummessages; 12078 SOCKET send_socket; 12079 int trans_remaining; 12080 double bytes_xferd; 12081 int rsp_bytes_left = 1; 12082 int rsp_bytes_recvd; 12083 12084 float local_cpu_utilization; 12085 float local_service_demand; 12086 float remote_cpu_utilization; 12087 float remote_service_demand; 12088 double thruput; 12089 12090 struct addrinfo *local_res; 12091 struct addrinfo *remote_res; 12092 12093 int myport; 12094 int ret; 12095 12096 struct tcp_cc_request_struct *tcp_cc_request; 12097 struct tcp_cc_response_struct *tcp_cc_response; 12098 struct tcp_cc_results_struct *tcp_cc_result; 12099 12100 tcp_cc_request = 12101 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data; 12102 tcp_cc_response = 12103 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data; 12104 tcp_cc_result = 12105 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data; 12106 12107 12108 #ifdef WANT_HISTOGRAM 12109 if (verbosity > 1) { 12110 time_hist = HIST_new(); 12111 } 12112 #endif /* WANT_HISTOGRAM */ 12113 12114 /* since we are now disconnected from the code that established the */ 12115 /* control socket, and since we want to be able to use different */ 12116 /* protocols and such, we are passed the name of the remote host and */ 12117 /* must turn that into the test specific addressing information. */ 12118 12119 complete_addrinfos(&remote_res, 12120 &local_res, 12121 remote_host, 12122 SOCK_STREAM, 12123 IPPROTO_TCP, 12124 0); 12125 12126 if ( print_headers ) { 12127 print_top_test_header("TCP Connect/Close TEST",local_res,remote_res); 12128 } 12129 12130 /* initialize a few counters */ 12131 12132 nummessages = 0; 12133 bytes_xferd = 0.0; 12134 times_up = 0; 12135 12136 /* since there are no data buffers in this test, we need no send or */ 12137 /* recv rings */ 12138 12139 if (debug) { 12140 fprintf(where,"send_tcp_cc: send_socket obtained...\n"); 12141 } 12142 12143 /* If the user has requested cpu utilization measurements, we must */ 12144 /* calibrate the cpu(s). We will perform this task within the tests */ 12145 /* themselves. If the user has specified the cpu rate, then */ 12146 /* calibrate_local_cpu will return rather quickly as it will have */ 12147 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 12148 /* all the "normal" calibration stuff and return the rate back.*/ 12149 12150 if (local_cpu_usage) { 12151 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 12152 } 12153 12154 /* Tell the remote end to do a listen. The server alters the socket */ 12155 /* paramters on the other side at this point, hence the reason for */ 12156 /* all the values being passed in the setup message. If the user did */ 12157 /* not specify any of the parameters, they will be passed as 0, which */ 12158 /* will indicate to the remote that no changes beyond the system's */ 12159 /* default should be used. Alignment is the exception, it will */ 12160 /* default to 8, which will be no alignment alterations. */ 12161 12162 netperf_request.content.request_type = DO_TCP_CC; 12163 tcp_cc_request->recv_buf_size = rsr_size_req; 12164 tcp_cc_request->send_buf_size = rss_size_req; 12165 tcp_cc_request->recv_alignment = remote_recv_align; 12166 tcp_cc_request->recv_offset = remote_recv_offset; 12167 tcp_cc_request->send_alignment = remote_send_align; 12168 tcp_cc_request->send_offset = remote_send_offset; 12169 tcp_cc_request->request_size = req_size; 12170 tcp_cc_request->response_size = rsp_size; 12171 tcp_cc_request->no_delay = rem_nodelay; 12172 tcp_cc_request->measure_cpu = remote_cpu_usage; 12173 tcp_cc_request->cpu_rate = remote_cpu_rate; 12174 tcp_cc_request->so_rcvavoid = rem_rcvavoid; 12175 tcp_cc_request->so_sndavoid = rem_sndavoid; 12176 if (test_time) { 12177 tcp_cc_request->test_length = test_time; 12178 } 12179 else { 12180 tcp_cc_request->test_length = test_trans * -1; 12181 } 12182 tcp_cc_request->port = atoi(remote_data_port); 12183 tcp_cc_request->ipfamily = af_to_nf(remote_res->ai_family); 12184 12185 if (debug > 1) { 12186 fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n"); 12187 } 12188 12189 send_request(); 12190 12191 /* The response from the remote will contain all of the relevant */ 12192 /* socket parameters for this test type. We will put them back into */ 12193 /* the variables here so they can be displayed if desired. The */ 12194 /* remote will have calibrated CPU if necessary, and will have done */ 12195 /* all the needed set-up we will have calibrated the cpu locally */ 12196 /* before sending the request, and will grab the counter value right */ 12197 /* after the connect returns. The remote will grab the counter right */ 12198 /* after the accept call. This saves the hassle of extra messages */ 12199 /* being sent for the TCP tests. */ 12200 12201 recv_response(); 12202 12203 if (!netperf_response.content.serv_errno) { 12204 rsr_size = tcp_cc_response->recv_buf_size; 12205 rss_size = tcp_cc_response->send_buf_size; 12206 rem_nodelay = tcp_cc_response->no_delay; 12207 remote_cpu_usage= tcp_cc_response->measure_cpu; 12208 remote_cpu_rate = tcp_cc_response->cpu_rate; 12209 /* make sure that port numbers are in network order */ 12210 set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number); 12211 12212 if (debug) { 12213 fprintf(where,"remote listen done.\n"); 12214 fprintf(where,"remote port is %d\n",get_port_number(remote_res)); 12215 fflush(where); 12216 } 12217 } 12218 else { 12219 Set_errno(netperf_response.content.serv_errno); 12220 fprintf(where, 12221 "netperf: remote error %d", 12222 netperf_response.content.serv_errno); 12223 perror(""); 12224 fflush(where); 12225 exit(1); 12226 } 12227 12228 #ifdef WANT_DEMO 12229 demo_rr_setup(100); 12230 #endif 12231 12232 /* pick a nice random spot between client_port_min and */ 12233 /* client_port_max for our initial port number */ 12234 srand(getpid()); 12235 if (client_port_max - client_port_min) { 12236 myport = client_port_min + 12237 (rand() % (client_port_max - client_port_min)); 12238 } 12239 else { 12240 myport = client_port_min; 12241 } 12242 /* there will be a ++ before the first call to bind, so subtract one */ 12243 myport--; 12244 12245 /* Set-up the test end conditions. For a request/response test, they */ 12246 /* can be either time or transaction based. */ 12247 12248 if (test_time) { 12249 /* The user wanted to end the test after a period of time. */ 12250 times_up = 0; 12251 trans_remaining = 0; 12252 start_timer(test_time); 12253 } 12254 else { 12255 /* The tester wanted to send a number of bytes. */ 12256 trans_remaining = test_bytes; 12257 times_up = 1; 12258 } 12259 12260 /* The cpu_start routine will grab the current time and possibly */ 12261 /* value of the idle counter for later use in measuring cpu */ 12262 /* utilization and/or service demand and thruput. */ 12263 12264 cpu_start(local_cpu_usage); 12265 12266 #ifdef WANT_DEMO 12267 if (demo_mode) { 12268 demo_first_timestamp(); 12269 } 12270 #endif 12271 12272 /* We use an "OR" to control test execution. When the test is */ 12273 /* controlled by time, the byte count check will always return false. */ 12274 /* When the test is controlled by byte count, the time test will */ 12275 /* always return false. When the test is finished, the whole */ 12276 /* expression will go false and we will stop sending data. I think I */ 12277 /* just arbitrarily decrement trans_remaining for the timed test, but */ 12278 /* will not do that just yet... One other question is whether or not */ 12279 /* the send buffer and the receive buffer should be the same buffer. */ 12280 12281 while ((!times_up) || (trans_remaining > 0)) { 12282 12283 #ifdef WANT_HISTOGRAM 12284 if (verbosity > 1) { 12285 /* timestamp just before our call to create the socket, and then */ 12286 /* again just after the receive raj 3/95 */ 12287 HIST_timestamp(&time_one); 12288 } 12289 #endif /* WANT_HISTOGRAM */ 12290 12291 /* set up the data socket */ 12292 /* newport: is this label really required any longer? */ 12293 /* pick a new port number */ 12294 myport++; 12295 12296 /* wrap the port number when we get to client_port_max. NOTE, some */ 12297 /* broken TCP's might treat the port number as a signed 16 bit */ 12298 /* quantity. we aren't interested in testing such broken */ 12299 /* implementations :) so we won't make sure that it is below 32767 */ 12300 /* raj 8/94 */ 12301 if (myport >= client_port_max) { 12302 myport = client_port_min; 12303 } 12304 12305 /* we do not want to use the port number that the server is */ 12306 /* sitting at - this would cause us to fail in a loopback test. we */ 12307 /* could just rely on the failure of the bind to get us past this, */ 12308 /* but I'm guessing that in this one case at least, it is much */ 12309 /* faster, given that we *know* that port number is already in use */ 12310 /* (or rather would be in a loopback test) */ 12311 12312 if (myport == get_port_number(remote_res)) myport++; 12313 12314 if (debug) { 12315 if ((nummessages % 100) == 0) { 12316 printf("port %d\n",myport); 12317 } 12318 } 12319 set_port_number(local_res, (unsigned short)myport); 12320 send_socket = create_data_socket(local_res); 12321 12322 if (send_socket == INVALID_SOCKET) { 12323 perror("netperf: send_tcp_cc: tcp stream data socket"); 12324 exit(1); 12325 } 12326 12327 #ifdef WIN32 12328 /* this is used so the timer thread can close the socket out from */ 12329 /* under us, which to date is the easiest/cleanest/least */ 12330 /* Windows-specific way I can find to force the winsock calls to */ 12331 /* return WSAEINTR with the test is over. anything that will run on */ 12332 /* 95 and NT and is closer to what netperf expects from Unix signals */ 12333 /* and such would be appreciated raj 1/96 */ 12334 win_kludge_socket = send_socket; 12335 #endif /* WIN32 */ 12336 12337 /* we used to have a call to bind() here, but that is being 12338 taken care of by create_data_socket(). raj 2005-02-08 */ 12339 12340 /* Connect up to the remote port on the data socket */ 12341 if ((ret = connect(send_socket, 12342 remote_res->ai_addr, 12343 remote_res->ai_addrlen)) == INVALID_SOCKET){ 12344 if (SOCKET_EINTR(ret)) 12345 { 12346 /* we hit the end of a */ 12347 /* timed test. */ 12348 timed_out = 1; 12349 break; 12350 } 12351 perror("netperf: data socket connect failed"); 12352 printf("\tattempted to connect on socket %d to port %d", 12353 send_socket, 12354 get_port_number(remote_res)); 12355 printf(" from port %u \n",get_port_number(local_res)); 12356 exit(1); 12357 } 12358 12359 /* we hang in a recv() to get the remote's close indication */ 12360 12361 rsp_bytes_recvd=recv(send_socket, 12362 temp_message_ptr, 12363 rsp_bytes_left, 12364 0); 12365 12366 12367 if (rsp_bytes_recvd == 0) { 12368 /* connection close, call close. we assume that the requisite */ 12369 /* number of bytes have been received */ 12370 12371 #ifdef WANT_HISTOGRAM 12372 if (verbosity > 1) { 12373 HIST_timestamp(&time_two); 12374 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 12375 } 12376 #endif /* WANT_HISTOGRAM */ 12377 12378 #ifdef WANT_DEMO 12379 demo_rr_interval(1); 12380 #endif 12381 12382 nummessages++; 12383 if (trans_remaining) { 12384 trans_remaining--; 12385 } 12386 12387 if (debug > 3) { 12388 fprintf(where, 12389 "Transaction %d completed on local port %u\n", 12390 nummessages, 12391 get_port_number(local_res)); 12392 fflush(where); 12393 } 12394 12395 close(send_socket); 12396 12397 } 12398 else { 12399 /* it was less than zero - an error occured */ 12400 if (SOCKET_EINTR(rsp_bytes_recvd)) 12401 { 12402 /* We hit the end of a timed test. */ 12403 timed_out = 1; 12404 break; 12405 } 12406 perror("send_tcp_cc: data recv error"); 12407 exit(1); 12408 } 12409 12410 } 12411 12412 12413 /* this call will always give us the elapsed time for the test, and */ 12414 /* will also store-away the necessaries for cpu utilization */ 12415 12416 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 12417 /* how long did we really run? */ 12418 12419 /* Get the statistics from the remote end. The remote will have */ 12420 /* calculated service demand and all those interesting things. If it */ 12421 /* wasn't supposed to care, it will return obvious values. */ 12422 12423 recv_response(); 12424 if (!netperf_response.content.serv_errno) { 12425 if (debug) 12426 fprintf(where,"remote results obtained\n"); 12427 } 12428 else { 12429 Set_errno(netperf_response.content.serv_errno); 12430 fprintf(where, 12431 "netperf: remote error %d", 12432 netperf_response.content.serv_errno); 12433 perror(""); 12434 fflush(where); 12435 12436 exit(1); 12437 } 12438 12439 /* We now calculate what our thruput was for the test. In the future, */ 12440 /* we may want to include a calculation of the thruput measured by */ 12441 /* the remote, but it should be the case that for a TCP stream test, */ 12442 /* that the two numbers should be *very* close... We calculate */ 12443 /* bytes_sent regardless of the way the test length was controlled. */ 12444 /* If it was time, we needed to, and if it was by bytes, the user may */ 12445 /* have specified a number of bytes that wasn't a multiple of the */ 12446 /* send_size, so we really didn't send what he asked for ;-) We use */ 12447 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 12448 /* 1024. A future enhancement *might* be to choose from a couple of */ 12449 /* unit selections. */ 12450 12451 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 12452 thruput = calc_thruput(bytes_xferd); 12453 12454 if (local_cpu_usage || remote_cpu_usage) { 12455 /* We must now do a little math for service demand and cpu */ 12456 /* utilization for the system(s) */ 12457 /* Of course, some of the information might be bogus because */ 12458 /* there was no idle counter in the kernel(s). We need to make */ 12459 /* a note of this for the user's benefit...*/ 12460 if (local_cpu_usage) { 12461 if (local_cpu_rate == 0.0) { 12462 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 12463 fprintf(where,"Local CPU usage numbers based on process information only!\n"); 12464 fflush(where); 12465 } 12466 local_cpu_utilization = calc_cpu_util(0.0); 12467 /* since calc_service demand is doing ms/Kunit we will */ 12468 /* multiply the number of transaction by 1024 to get */ 12469 /* "good" numbers */ 12470 local_service_demand = calc_service_demand((double) nummessages*1024, 12471 0.0, 12472 0.0, 12473 0); 12474 } 12475 else { 12476 local_cpu_utilization = (float) -1.0; 12477 local_service_demand = (float) -1.0; 12478 } 12479 12480 if (remote_cpu_usage) { 12481 if (remote_cpu_rate == 0.0) { 12482 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 12483 fprintf(where,"Remote CPU usage numbers based on process information only!\n"); 12484 fflush(where); 12485 } 12486 remote_cpu_utilization = tcp_cc_result->cpu_util; 12487 /* since calc_service demand is doing ms/Kunit we will */ 12488 /* multiply the number of transaction by 1024 to get */ 12489 /* "good" numbers */ 12490 remote_service_demand = calc_service_demand((double) nummessages*1024, 12491 0.0, 12492 remote_cpu_utilization, 12493 tcp_cc_result->num_cpus); 12494 } 12495 else { 12496 remote_cpu_utilization = (float) -1.0; 12497 remote_service_demand = (float) -1.0; 12498 } 12499 12500 /* We are now ready to print all the information. If the user */ 12501 /* has specified zero-level verbosity, we will just print the */ 12502 /* local service demand, or the remote service demand. If the */ 12503 /* user has requested verbosity level 1, he will get the basic */ 12504 /* "streamperf" numbers. If the user has specified a verbosity */ 12505 /* of greater than 1, we will display a veritable plethora of */ 12506 /* background information from outside of this block as it it */ 12507 /* not cpu_measurement specific... */ 12508 12509 switch (verbosity) { 12510 case 0: 12511 if (local_cpu_usage) { 12512 fprintf(where, 12513 cpu_fmt_0, 12514 local_service_demand); 12515 } 12516 else { 12517 fprintf(where, 12518 cpu_fmt_0, 12519 remote_service_demand); 12520 } 12521 break; 12522 case 1: 12523 case 2: 12524 12525 if (print_headers) { 12526 fprintf(where, 12527 cpu_title, 12528 local_cpu_method, 12529 remote_cpu_method); 12530 } 12531 12532 fprintf(where, 12533 cpu_fmt_1_line_1, /* the format string */ 12534 lss_size, /* local sendbuf size */ 12535 lsr_size, 12536 req_size, /* how large were the requests */ 12537 rsp_size, /* guess */ 12538 elapsed_time, /* how long was the test */ 12539 nummessages/elapsed_time, 12540 local_cpu_utilization, /* local cpu */ 12541 remote_cpu_utilization, /* remote cpu */ 12542 local_service_demand, /* local service demand */ 12543 remote_service_demand); /* remote service demand */ 12544 fprintf(where, 12545 cpu_fmt_1_line_2, 12546 rss_size, 12547 rsr_size); 12548 break; 12549 } 12550 } 12551 else { 12552 /* The tester did not wish to measure service demand. */ 12553 switch (verbosity) { 12554 case 0: 12555 fprintf(where, 12556 tput_fmt_0, 12557 nummessages/elapsed_time); 12558 break; 12559 case 1: 12560 case 2: 12561 if (print_headers) { 12562 fprintf(where,tput_title,format_units()); 12563 } 12564 12565 fprintf(where, 12566 tput_fmt_1_line_1, /* the format string */ 12567 lss_size, 12568 lsr_size, 12569 req_size, /* how large were the requests */ 12570 rsp_size, /* how large were the responses */ 12571 elapsed_time, /* how long did it take */ 12572 nummessages/elapsed_time); 12573 fprintf(where, 12574 tput_fmt_1_line_2, 12575 rss_size, /* remote recvbuf size */ 12576 rsr_size); 12577 12578 break; 12579 } 12580 } 12581 12582 /* it would be a good thing to include information about some of the */ 12583 /* other parameters that may have been set for this test, but at the */ 12584 /* moment, I do not wish to figure-out all the formatting, so I will */ 12585 /* just put this comment here to help remind me that it is something */ 12586 /* that should be done at a later time. */ 12587 12588 if (verbosity > 1) { 12589 /* The user wanted to know it all, so we will give it to him. */ 12590 /* This information will include as much as we can find about */ 12591 /* TCP statistics, the alignments of the sends and receives */ 12592 /* and all that sort of rot... */ 12593 12594 fprintf(where, 12595 ksink_fmt, 12596 local_send_align, 12597 remote_recv_offset, 12598 local_send_offset, 12599 remote_recv_offset); 12600 12601 #ifdef WANT_HISTOGRAM 12602 fprintf(where,"\nHistogram of request/response times\n"); 12603 fflush(where); 12604 HIST_report(time_hist); 12605 #endif /* WANT_HISTOGRAM */ 12606 12607 } 12608 12609 } 12610 12611 12612 void 12614 recv_tcp_cc() 12615 { 12616 12617 char *message; 12618 12619 struct addrinfo *local_res; 12620 char local_name[BUFSIZ]; 12621 char port_buffer[PORTBUFSIZE]; 12622 12623 struct sockaddr_storage myaddr_in, peeraddr_in; 12624 SOCKET s_listen,s_data; 12625 netperf_socklen_t addrlen; 12626 char *recv_message_ptr; 12627 char *send_message_ptr; 12628 int trans_received; 12629 int trans_remaining; 12630 int timed_out = 0; 12631 float elapsed_time; 12632 12633 struct tcp_cc_request_struct *tcp_cc_request; 12634 struct tcp_cc_response_struct *tcp_cc_response; 12635 struct tcp_cc_results_struct *tcp_cc_results; 12636 12637 tcp_cc_request = 12638 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data; 12639 tcp_cc_response = 12640 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data; 12641 tcp_cc_results = 12642 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data; 12643 12644 if (debug) { 12645 fprintf(where,"netserver: recv_tcp_cc: entered...\n"); 12646 fflush(where); 12647 } 12648 12649 /* We want to set-up the listen socket with all the desired */ 12650 /* parameters and then let the initiator know that all is ready. If */ 12651 /* socket size defaults are to be used, then the initiator will have */ 12652 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 12653 /* send-back what they are. If that information cannot be determined, */ 12654 /* then we send-back -1's for the sizes. If things go wrong for any */ 12655 /* reason, we will drop back ten yards and punt. */ 12656 12657 /* If anything goes wrong, we want the remote to know about it. It */ 12658 /* would be best if the error that the remote reports to the user is */ 12659 /* the actual error we encountered, rather than some bogus unexpected */ 12660 /* response type message. */ 12661 12662 if (debug) { 12663 fprintf(where,"recv_tcp_cc: setting the response type...\n"); 12664 fflush(where); 12665 } 12666 12667 netperf_response.content.response_type = TCP_CC_RESPONSE; 12668 12669 if (debug) { 12670 fprintf(where,"recv_tcp_cc: the response type is set...\n"); 12671 fflush(where); 12672 } 12673 12674 /* set-up the data buffer with the requested alignment and offset */ 12675 message = (char *)malloc(DATABUFFERLEN); 12676 if (message == NULL) { 12677 printf("malloc(%d) failed!\n", DATABUFFERLEN); 12678 exit(1); 12679 } 12680 12681 /* We now alter the message_ptr variables to be at the desired */ 12682 /* alignments with the desired offsets. */ 12683 12684 if (debug) { 12685 fprintf(where, 12686 "recv_tcp_cc: requested recv alignment of %d offset %d\n", 12687 tcp_cc_request->recv_alignment, 12688 tcp_cc_request->recv_offset); 12689 fprintf(where, 12690 "recv_tcp_cc: requested send alignment of %d offset %d\n", 12691 tcp_cc_request->send_alignment, 12692 tcp_cc_request->send_offset); 12693 fflush(where); 12694 } 12695 12696 recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset); 12697 12698 send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset); 12699 12700 if (debug) { 12701 fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n"); 12702 fflush(where); 12703 } 12704 12705 /* Grab a socket to listen on, and then listen on it. */ 12706 12707 if (debug) { 12708 fprintf(where,"recv_tcp_cc: grabbing a socket...\n"); 12709 fflush(where); 12710 } 12711 12712 /* create_data_socket expects to find some things in the global */ 12713 /* variables, so set the globals based on the values in the request. */ 12714 /* once the socket has been created, we will set the response values */ 12715 /* based on the updated value of those globals. raj 7/94 */ 12716 lss_size_req = tcp_cc_request->send_buf_size; 12717 lsr_size_req = tcp_cc_request->recv_buf_size; 12718 loc_nodelay = tcp_cc_request->no_delay; 12719 loc_rcvavoid = tcp_cc_request->so_rcvavoid; 12720 loc_sndavoid = tcp_cc_request->so_sndavoid; 12721 12722 set_hostname_and_port(local_name, 12723 port_buffer, 12724 nf_to_af(tcp_cc_request->ipfamily), 12725 tcp_cc_request->port); 12726 12727 local_res = complete_addrinfo(local_name, 12728 local_name, 12729 port_buffer, 12730 nf_to_af(tcp_cc_request->ipfamily), 12731 SOCK_STREAM, 12732 IPPROTO_TCP, 12733 0); 12734 12735 s_listen = create_data_socket(local_res); 12736 12737 if (s_listen == INVALID_SOCKET) { 12738 netperf_response.content.serv_errno = errno; 12739 send_response(); 12740 if (debug) { 12741 fprintf(where,"could not create data socket\n"); 12742 fflush(where); 12743 } 12744 exit(1); 12745 } 12746 12747 #ifdef WIN32 12748 /* The test timer can fire during operations on the listening socket, 12749 so to make the start_timer below work we have to move 12750 it to close s_listen while we are blocked on accept. */ 12751 win_kludge_socket2 = s_listen; 12752 #endif 12753 12754 12755 /* Now, let's set-up the socket to listen for connections */ 12756 if (listen(s_listen, 5) == SOCKET_ERROR) { 12757 netperf_response.content.serv_errno = errno; 12758 close(s_listen); 12759 send_response(); 12760 if (debug) { 12761 fprintf(where,"could not listen\n"); 12762 fflush(where); 12763 } 12764 exit(1); 12765 } 12766 12767 /* now get the port number assigned by the system */ 12768 addrlen = sizeof(myaddr_in); 12769 if (getsockname(s_listen, 12770 (struct sockaddr *)&myaddr_in, 12771 &addrlen) == SOCKET_ERROR){ 12772 netperf_response.content.serv_errno = errno; 12773 close(s_listen); 12774 send_response(); 12775 if (debug) { 12776 fprintf(where,"could not geetsockname\n"); 12777 fflush(where); 12778 } 12779 exit(1); 12780 } 12781 12782 /* Now myaddr_in contains the port and the internet address this is */ 12783 /* returned to the sender also implicitly telling the sender that the */ 12784 /* socket buffer sizing has been done. */ 12785 12786 tcp_cc_response->data_port_number = 12787 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 12788 if (debug) { 12789 fprintf(where,"telling the remote to call me at %d\n", 12790 tcp_cc_response->data_port_number); 12791 fflush(where); 12792 } 12793 netperf_response.content.serv_errno = 0; 12794 12795 /* But wait, there's more. If the initiator wanted cpu measurements, */ 12796 /* then we must call the calibrate routine, which will return the max */ 12797 /* rate back to the initiator. If the CPU was not to be measured, or */ 12798 /* something went wrong with the calibration, we will return a 0.0 to */ 12799 /* the initiator. */ 12800 12801 tcp_cc_response->cpu_rate = (float)0.0; /* assume no cpu */ 12802 if (tcp_cc_request->measure_cpu) { 12803 tcp_cc_response->measure_cpu = 1; 12804 tcp_cc_response->cpu_rate = 12805 calibrate_local_cpu(tcp_cc_request->cpu_rate); 12806 } 12807 12808 12809 12810 /* before we send the response back to the initiator, pull some of */ 12811 /* the socket parms from the globals */ 12812 tcp_cc_response->send_buf_size = lss_size; 12813 tcp_cc_response->recv_buf_size = lsr_size; 12814 tcp_cc_response->no_delay = loc_nodelay; 12815 tcp_cc_response->so_rcvavoid = loc_rcvavoid; 12816 tcp_cc_response->so_sndavoid = loc_sndavoid; 12817 12818 send_response(); 12819 12820 addrlen = sizeof(peeraddr_in); 12821 12822 /* Now it's time to start receiving data on the connection. We will */ 12823 /* first grab the apropriate counters and then start grabbing. */ 12824 12825 cpu_start(tcp_cc_request->measure_cpu); 12826 12827 /* The loop will exit when the sender does a shutdown, which will */ 12828 /* return a length of zero */ 12829 12830 if (tcp_cc_request->test_length > 0) { 12831 times_up = 0; 12832 trans_remaining = 0; 12833 start_timer(tcp_cc_request->test_length + PAD_TIME); 12834 } 12835 else { 12836 times_up = 1; 12837 trans_remaining = tcp_cc_request->test_length * -1; 12838 } 12839 12840 trans_received = 0; 12841 12842 while ((!times_up) || (trans_remaining > 0)) { 12843 #ifdef WIN32 12844 /* The test timer will probably fire during this accept, 12845 so to make the start_timer above work we have to move 12846 it to close s_listen while we are blocked on accept. */ 12847 win_kludge_socket = s_listen; 12848 #endif 12849 /* accept a connection from the remote */ 12850 if ((s_data=accept(s_listen, 12851 (struct sockaddr *)&peeraddr_in, 12852 &addrlen)) == INVALID_SOCKET) { 12853 if (errno == EINTR) { 12854 /* the timer popped */ 12855 timed_out = 1; 12856 break; 12857 } 12858 fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno); 12859 fflush(where); 12860 close(s_listen); 12861 12862 exit(1); 12863 } 12864 12865 #ifdef KLUDGE_SOCKET_OPTIONS 12866 /* this is for those systems which *INCORRECTLY* fail to pass */ 12867 /* attributes across an accept() call. Including this goes against */ 12868 /* my better judgement :( raj 11/95 */ 12869 12870 kludge_socket_options(s_data); 12871 12872 #endif /* KLUDGE_SOCKET_OPTIONS */ 12873 12874 #ifdef WIN32 12875 /* this is used so the timer thread can close the socket out from */ 12876 /* under us, which to date is the easiest/cleanest/least */ 12877 /* Windows-specific way I can find to force the winsock calls to */ 12878 /* return WSAEINTR with the test is over. anything that will run on */ 12879 /* 95 and NT and is closer to what netperf expects from Unix signals */ 12880 /* and such would be appreciated raj 1/96 */ 12881 win_kludge_socket = s_data; 12882 #endif /* WIN32 */ 12883 12884 if (debug) { 12885 fprintf(where,"recv_tcp_cc: accepted data connection.\n"); 12886 fflush(where); 12887 } 12888 12889 12890 /* close the connection. the server will likely do a graceful */ 12891 /* close of the connection, insuring that all data has arrived at */ 12892 /* the client. for this it will call shutdown(), and then recv() and */ 12893 /* then close(). I'm reasonably confident that this is the */ 12894 /* appropriate sequence of calls - I would like to hear of */ 12895 /* examples in web servers to the contrary. raj 10/95*/ 12896 close(s_data); 12897 12898 trans_received++; 12899 if (trans_remaining) { 12900 trans_remaining--; 12901 } 12902 12903 if (debug) { 12904 fprintf(where, 12905 "recv_tcp_cc: Transaction %d complete\n", 12906 trans_received); 12907 fflush(where); 12908 } 12909 12910 } 12911 12912 12913 /* The loop now exits due to timeout or transaction count being */ 12914 /* reached */ 12915 12916 cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time); 12917 12918 if (timed_out) { 12919 /* we ended the test by time, which was at least 2 seconds */ 12920 /* longer than we wanted to run. so, we want to subtract */ 12921 /* PAD_TIME from the elapsed_time. */ 12922 elapsed_time -= PAD_TIME; 12923 } 12924 /* send the results to the sender */ 12925 12926 if (debug) { 12927 fprintf(where, 12928 "recv_tcp_cc: got %d transactions\n", 12929 trans_received); 12930 fflush(where); 12931 } 12932 12933 tcp_cc_results->bytes_received = (trans_received * 12934 (tcp_cc_request->request_size + 12935 tcp_cc_request->response_size)); 12936 tcp_cc_results->trans_received = trans_received; 12937 tcp_cc_results->elapsed_time = elapsed_time; 12938 tcp_cc_results->num_cpus = lib_num_loc_cpus; 12939 if (tcp_cc_request->measure_cpu) { 12940 tcp_cc_results->cpu_util = calc_cpu_util(elapsed_time); 12941 } 12942 12943 if (debug) { 12944 fprintf(where, 12945 "recv_tcp_cc: test complete, sending results.\n"); 12946 fflush(where); 12947 } 12948 12949 send_response(); 12950 12951 } 12952 12953 void 12955 print_sockets_usage() 12956 { 12957 12958 fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout); 12959 exit(1); 12960 12961 } 12962 12963 void 12964 scan_sockets_args(int argc, char *argv[]) 12965 12966 { 12967 12968 #define SOCKETS_ARGS "b:CDnNhH:L:m:M:p:P:r:R:s:S:T:Vw:W:z46" 12969 12970 extern char *optarg; /* pointer to option string */ 12971 12972 int c; 12973 12974 char 12975 arg1[BUFSIZ], /* argument holders */ 12976 arg2[BUFSIZ]; 12977 12978 if (debug) { 12979 int i; 12980 printf("%s called with the following argument vector\n", 12981 #if _MSC_VER <= 1200 12982 "scan_sockets_args"); 12983 #else 12984 __func__); 12985 #endif 12986 for (i = 0; i< argc; i++) { 12987 printf("%s ",argv[i]); 12988 } 12989 printf("\n"); 12990 } 12991 12992 strncpy(local_data_port,"0",sizeof(local_data_port)); 12993 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 12994 12995 /* by default, only a UDP_STREAM test disallows routing, to cover 12996 the backsides of incompetent testers who have bogus setups */ 12997 if (strcasecmp(test_name,"UDP_STREAM") == 0) { 12998 routing_allowed = 0; 12999 } 13000 13001 /* Go through all the command line arguments and break them */ 13002 /* out. For those options that take two parms, specifying only */ 13003 /* the first will set both to that value. Specifying only the */ 13004 /* second will leave the first untouched. To change only the */ 13005 /* first, use the form "first," (see the routine break_args.. */ 13006 13007 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) { 13008 switch (c) { 13009 case '?': 13010 case '4': 13011 remote_data_family = AF_INET; 13012 local_data_family = AF_INET; 13013 break; 13014 case '6': 13015 #if defined(AF_INET6) 13016 remote_data_family = AF_INET6; 13017 local_data_family = AF_INET6; 13018 #else 13019 fprintf(stderr, 13020 "This netperf was not compiled on an IPv6 capable host!\n"); 13021 fflush(stderr); 13022 exit(-1); 13023 #endif 13024 break; 13025 case 'h': 13026 print_sockets_usage(); 13027 exit(1); 13028 case 'b': 13029 #ifdef WANT_FIRST_BURST 13030 first_burst_size = atoi(optarg); 13031 #else /* WANT_FIRST_BURST */ 13032 printf("Initial request burst functionality not compiled-in!\n"); 13033 #endif /* WANT_FIRST_BURST */ 13034 break; 13035 case 'C': 13036 #ifdef TCP_CORK 13037 /* set TCP_CORK */ 13038 loc_tcpcork = 1; 13039 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */ 13040 #else 13041 printf("WARNING: TCP_CORK not available on this platform!\n"); 13042 #endif /* TCP_CORK */ 13043 break; 13044 case 'D': 13045 /* set the TCP nodelay flag */ 13046 loc_nodelay = 1; 13047 rem_nodelay = 1; 13048 break; 13049 case 'H': 13050 break_args_explicit(optarg,arg1,arg2); 13051 if (arg1[0]) { 13052 /* make sure we leave room for the NULL termination boys and 13053 girls. raj 2005-02-82 */ 13054 remote_data_address = malloc(strlen(arg1)+1); 13055 strncpy(remote_data_address,arg1,strlen(arg1)); 13056 } 13057 if (arg2[0]) 13058 remote_data_family = parse_address_family(arg2); 13059 break; 13060 case 'L': 13061 break_args_explicit(optarg,arg1,arg2); 13062 if (arg1[0]) { 13063 /* make sure we leave room for the NULL termination boys and 13064 girls. raj 2005-02-82 */ 13065 local_data_address = malloc(strlen(arg1)+1); 13066 strncpy(local_data_address,arg1,strlen(arg1)); 13067 } 13068 if (arg2[0]) 13069 local_data_family = parse_address_family(arg2); 13070 break; 13071 case 's': 13072 /* set local socket sizes */ 13073 break_args(optarg,arg1,arg2); 13074 if (arg1[0]) 13075 lss_size_req = convert(arg1); 13076 if (arg2[0]) 13077 lsr_size_req = convert(arg2); 13078 break; 13079 case 'S': 13080 /* set remote socket sizes */ 13081 break_args(optarg,arg1,arg2); 13082 if (arg1[0]) 13083 rss_size_req = convert(arg1); 13084 if (arg2[0]) 13085 rsr_size_req = convert(arg2); 13086 break; 13087 case 'r': 13088 /* set the request/response sizes */ 13089 break_args(optarg,arg1,arg2); 13090 if (arg1[0]) 13091 req_size = convert(arg1); 13092 if (arg2[0]) 13093 rsp_size = convert(arg2); 13094 break; 13095 case 'R': 13096 /* enable/disable routing on the data connection*/ 13097 routing_allowed = atoi(optarg); 13098 break; 13099 case 'm': 13100 /* set the send size */ 13101 send_size = convert(optarg); 13102 break; 13103 case 'M': 13104 /* set the recv size */ 13105 recv_size = convert(optarg); 13106 break; 13107 case 'n': 13108 /* set the local socket type*/ 13109 local_connected = 1; 13110 break; 13111 case 'N': 13112 /* set the remote socket type*/ 13113 remote_connected = 1; 13114 break; 13115 case 'p': 13116 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */ 13117 /* tests. */ 13118 break_args(optarg,arg1,arg2); 13119 if (arg1[0]) 13120 client_port_min = atoi(arg1); 13121 if (arg2[0]) 13122 client_port_max = atoi(arg2); 13123 break; 13124 case 'P': 13125 /* set the local and remote data port numbers for the tests to 13126 allow them to run through those blankety blank end-to-end 13127 breaking firewalls. raj 2004-06-15 */ 13128 break_args(optarg,arg1,arg2); 13129 if (arg1[0]) 13130 strncpy(local_data_port,arg1,sizeof(local_data_port)); 13131 if (arg2[0]) 13132 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 13133 break; 13134 case 't': 13135 /* set the test name */ 13136 strcpy(test_name,optarg); 13137 break; 13138 case 'W': 13139 /* set the "width" of the user space data */ 13140 /* buffer. This will be the number of */ 13141 /* send_size buffers malloc'd in the */ 13142 /* *_STREAM test. It may be enhanced to set */ 13143 /* both send and receive "widths" but for now */ 13144 /* it is just the sending *_STREAM. */ 13145 send_width = convert(optarg); 13146 break; 13147 case 'V' : 13148 /* we want to do copy avoidance and will set */ 13149 /* it for everything, everywhere, if we really */ 13150 /* can. of course, we don't know anything */ 13151 /* about the remote... */ 13152 #ifdef SO_SND_COPYAVOID 13153 loc_sndavoid = 1; 13154 #else 13155 loc_sndavoid = 0; 13156 printf("Local send copy avoidance not available.\n"); 13157 #endif 13158 #ifdef SO_RCV_COPYAVOID 13159 loc_rcvavoid = 1; 13160 #else 13161 loc_rcvavoid = 0; 13162 printf("Local recv copy avoidance not available.\n"); 13163 #endif 13164 rem_sndavoid = 1; 13165 rem_rcvavoid = 1; 13166 break; 13167 }; 13168 } 13169 13170 #if defined(WANT_FIRST_BURST) 13171 #if defined(WANT_HISTOGRAM) 13172 /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user 13173 indeed wants a non-zero first burst size, and we would emit a 13174 histogram, then we should emit a warning that the two are not 13175 compatible. raj 2006-01-31 */ 13176 if ((first_burst_size > 0) && (verbosity >= 2)) { 13177 fprintf(stderr, 13178 "WARNING! Histograms and first bursts are incompatible!\n"); 13179 fflush(stderr); 13180 } 13181 #endif 13182 #endif 13183 13184 /* we do not want to make remote_data_address non-NULL because if 13185 the user has not specified a remote adata address, we want to 13186 take it from the hostname in the -H global option. raj 13187 2005-02-08 */ 13188 13189 /* so, if there is to be no control connection, we want to have some 13190 different settings for a few things */ 13191 13192 if (no_control) { 13193 13194 if (strcmp(remote_data_port,"0") == 0) { 13195 /* we need to select either the discard port, echo port or 13196 chargen port dedepending on the test name. raj 2007-02-08 */ 13197 if (strstr(test_name,"STREAM") || 13198 strstr(test_name,"SENDFILE")) { 13199 strncpy(remote_data_port,"discard",sizeof(remote_data_port)); 13200 } 13201 else if (strstr(test_name,"RR")) { 13202 strncpy(remote_data_port,"echo",sizeof(remote_data_port)); 13203 } 13204 else if (strstr(test_name,"MAERTS")) { 13205 strncpy(remote_data_port,"chargen",sizeof(remote_data_port)); 13206 } 13207 else { 13208 printf("No default port known for the %s test, please set one yourself\n",test_name); 13209 exit(-1); 13210 } 13211 } 13212 remote_data_port[sizeof(remote_data_port) - 1] = '\0'; 13213 13214 /* I go back and forth on whether these should become -1 or if 13215 they should become 0 for a no_control test. what do you think? 13216 raj 2006-02-08 */ 13217 13218 rem_rcvavoid = -1; 13219 rem_sndavoid = -1; 13220 rss_size_req = -1; 13221 rsr_size_req = -1; 13222 rem_nodelay = -1; 13223 13224 if (strstr(test_name,"STREAM") || 13225 strstr(test_name,"SENDFILE")) { 13226 recv_size = -1; 13227 } 13228 else if (strstr(test_name,"MAERTS")) { 13229 send_size = -1; 13230 } 13231 } 13232 } 13233