1 #ifndef lint 2 char nettest_id[]="\ 3 @(#)nettest_bsd.c (c) Copyright 1993-2004 Hewlett-Packard Co. Version 2.4.3"; 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_udp_stream() perform a udp stream test */ 30 /* recv_udp_stream() */ 31 /* send_udp_rr() perform a udp request/response */ 32 /* recv_udp_rr() */ 33 /* loc_cpu_rate() determine the local cpu maxrate */ 34 /* rem_cpu_rate() find the remote cpu maxrate */ 35 /* */ 36 /****************************************************************/ 37 38 #ifdef HAVE_CONFIG_H 39 #include <config.h> 40 #endif 41 42 #include <stdio.h> 43 #if HAVE_SYS_TYPES_H 44 # include <sys/types.h> 45 #endif 46 #if HAVE_SYS_STAT_H 47 # include <sys/stat.h> 48 #endif 49 #if STDC_HEADERS 50 # include <stdlib.h> 51 # include <stddef.h> 52 #else 53 # if HAVE_STDLIB_H 54 # include <stdlib.h> 55 # endif 56 #endif 57 #if HAVE_STRING_H 58 # if !STDC_HEADERS && HAVE_MEMORY_H 59 # include <memory.h> 60 # endif 61 # include <string.h> 62 #endif 63 #if HAVE_STRINGS_H 64 # include <strings.h> 65 #endif 66 #if HAVE_INTTYPES_H 67 # include <inttypes.h> 68 #else 69 # if HAVE_STDINT_H 70 # include <stdint.h> 71 # endif 72 #endif 73 #if HAVE_UNISTD_H 74 # include <unistd.h> 75 #endif 76 77 #include <fcntl.h> 78 #ifndef WIN32 79 #include <errno.h> 80 #include <signal.h> 81 #endif 82 83 #if TIME_WITH_SYS_TIME 84 # include <sys/time.h> 85 # include <time.h> 86 #else 87 # if HAVE_SYS_TIME_H 88 # include <sys/time.h> 89 # else 90 # include <time.h> 91 # endif 92 #endif 93 94 #ifdef NOSTDLIBH 95 #include <malloc.h> 96 #endif /* NOSTDLIBH */ 97 98 #ifndef WIN32 99 #if !defined(__VMS) 100 #include <sys/ipc.h> 101 #endif /* !defined(__VMS) */ 102 #include <sys/socket.h> 103 #include <netinet/in.h> 104 #include <netinet/tcp.h> 105 #include <arpa/inet.h> 106 #include <netdb.h> 107 #else /* WIN32 */ 108 #include <process.h> 109 #define netperf_socklen_t socklen_t 110 #include <winsock2.h> 111 112 /* while it is unlikely that anyone running Windows 2000 or NT 4 is 113 going to be trying to compile this, if they are they will want to 114 define DONT_IPV6 in the sources file */ 115 #ifndef DONT_IPV6 116 #include <ws2tcpip.h> 117 #endif 118 #include <windows.h> 119 120 #define sleep(x) Sleep((x)*1000) 121 122 #define __func__ __FUNCTION__ 123 #endif /* WIN32 */ 124 125 /* We don't want to use bare constants in the shutdown() call. In the 126 extremely unlikely event that SHUT_WR isn't defined, we will define 127 it to the value we used to be passing to shutdown() anyway. raj 128 2007-02-08 */ 129 #if !defined(SHUT_WR) 130 #define SHUT_WR 1 131 #endif 132 133 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) 134 # include "missing/getaddrinfo.h" 135 #endif 136 137 #include "netlib.h" 138 #include "netsh.h" 139 #include "nettest_bsd.h" 140 141 #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO) 142 #include "hist.h" 143 #endif /* WANT_HISTOGRAM */ 144 145 /* make first_burst_size unconditional so we can use it easily enough 146 when calculating transaction latency for the TCP_RR test. raj 147 2007-06-08 */ 148 int first_burst_size=0; 149 150 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun__)) 151 #include <sys/sendfile.h> 152 #endif /* HAVE_SENDFILE && (__linux || __sun__) */ 153 154 155 157 /* these variables are specific to the BSD sockets tests, but can 158 * be used elsewhere if needed. They are externed through nettest_bsd.h 159 */ 160 161 int 162 rss_size_req = -1, /* requested remote socket send buffer size */ 163 rsr_size_req = -1, /* requested remote socket recv buffer size */ 164 rss_size, /* remote socket send buffer size */ 165 rsr_size, /* remote socket recv buffer size */ 166 lss_size_req = -1, /* requested local socket send buffer size */ 167 lsr_size_req = -1, /* requested local socket recv buffer size */ 168 lss_size, /* local socket send buffer size */ 169 lsr_size, /* local socket recv buffer size */ 170 req_size = 1, /* request size */ 171 rsp_size = 1, /* response size */ 172 send_size, /* how big are individual sends */ 173 recv_size; /* how big are individual receives */ 174 175 static int confidence_iteration; 176 static char local_cpu_method; 177 static char remote_cpu_method; 178 179 /* these will control the width of port numbers we try to use in the */ 180 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */ 181 static int client_port_min = 5000; 182 static int client_port_max = 65535; 183 184 /* different options for the sockets */ 185 186 int 187 loc_nodelay, /* don't/do use NODELAY locally */ 188 rem_nodelay, /* don't/do use NODELAY remotely */ 189 #ifdef TCP_CORK 190 loc_tcpcork=0, /* don't/do use TCP_CORK locally */ 191 rem_tcpcork=0, /* don't/do use TCP_CORK remotely */ 192 #endif /* TCP_CORK */ 193 loc_sndavoid, /* avoid send copies locally */ 194 loc_rcvavoid, /* avoid recv copies locally */ 195 rem_sndavoid, /* avoid send copies remotely */ 196 rem_rcvavoid, /* avoid recv_copies remotely */ 197 local_connected = 0, /* local socket type, connected/non-connected */ 198 remote_connected = 0; /* remote socket type, connected/non-connected */ 199 200 #ifdef WANT_HISTOGRAM 201 #ifdef HAVE_GETHRTIME 202 static hrtime_t time_one; 203 static hrtime_t time_two; 204 #elif HAVE_GET_HRT 205 #include "hrt.h" 206 static hrt_t time_one; 207 static hrt_t time_two; 208 #elif defined(WIN32) 209 static LARGE_INTEGER time_one; 210 static LARGE_INTEGER time_two; 211 #else 212 static struct timeval time_one; 213 static struct timeval time_two; 214 #endif /* HAVE_GETHRTIME */ 215 static HIST time_hist; 216 #endif /* WANT_HISTOGRAM */ 217 218 #ifdef WANT_INTERVALS 219 int interval_count; 220 #ifndef WANT_SPIN 221 sigset_t signal_set; 222 #define INTERVALS_INIT() \ 223 if (interval_burst) { \ 224 /* zero means that we never pause, so we never should need the \ 225 interval timer. we used to use it for demo mode, but we deal \ 226 with that with a variant on watching the clock rather than \ 227 waiting for a timer. raj 2006-02-06 */ \ 228 start_itimer(interval_wate); \ 229 } \ 230 interval_count = interval_burst; \ 231 /* get the signal set for the call to sigsuspend */ \ 232 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \ 233 fprintf(where, \ 234 "%s: unable to get sigmask errno %d\n", \ 235 __func__, \ 236 errno); \ 237 fflush(where); \ 238 exit(1); \ 239 } 240 241 #define INTERVALS_WAIT() \ 242 /* in this case, the interval count is the count-down couter \ 243 to decide to sleep for a little bit */ \ 244 if ((interval_burst) && (--interval_count == 0)) { \ 245 /* call sigsuspend and wait for the interval timer to get us \ 246 out */ \ 247 if (debug > 1) { \ 248 fprintf(where,"about to suspend\n"); \ 249 fflush(where); \ 250 } \ 251 if (sigsuspend(&signal_set) == EFAULT) { \ 252 fprintf(where, \ 253 "%s: fault with sigsuspend.\n", \ 254 __func__); \ 255 fflush(where); \ 256 exit(1); \ 257 } \ 258 interval_count = interval_burst; \ 259 } 260 #else 261 /* first out timestamp */ 262 #ifdef HAVE_GETHRTIME 263 static hrtime_t intvl_one; 264 static hrtime_t intvl_two; 265 static hrtime_t *intvl_one_ptr = &intvl_one; 266 static hrtime_t *intvl_two_ptr = &intvl_two; 267 static hrtime_t *temp_intvl_ptr = &intvl_one; 268 #elif defined(WIN32) 269 static LARGE_INTEGER intvl_one; 270 static LARGE_INTEGER intvl_two; 271 static LARGE_INTEGER *intvl_one_ptr = &intvl_one; 272 static LARGE_INTEGER *intvl_two_ptr = &intvl_two; 273 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one; 274 #else 275 static struct timeval intvl_one; 276 static struct timeval intvl_two; 277 static struct timeval *intvl_one_ptr = &intvl_one; 278 static struct timeval *intvl_two_ptr = &intvl_two; 279 static struct timeval *temp_intvl_ptr = &intvl_one; 280 #endif 281 282 #define INTERVALS_INIT() \ 283 if (interval_burst) { \ 284 HIST_timestamp(intvl_one_ptr); \ 285 } \ 286 interval_count = interval_burst; \ 287 288 #define INTERVALS_WAIT() \ 289 /* in this case, the interval count is the count-down couter \ 290 to decide to sleep for a little bit */ \ 291 if ((interval_burst) && (--interval_count == 0)) { \ 292 /* call sigsuspend and wait for the interval timer to get us \ 293 out */ \ 294 if (debug > 1) { \ 295 fprintf(where,"about to spin suspend\n"); \ 296 fflush(where); \ 297 } \ 298 HIST_timestamp(intvl_two_ptr); \ 299 while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \ 300 HIST_timestamp(intvl_two_ptr); \ 301 } \ 302 temp_intvl_ptr = intvl_one_ptr; \ 303 intvl_one_ptr = intvl_two_ptr; \ 304 intvl_two_ptr = temp_intvl_ptr; \ 305 interval_count = interval_burst; \ 306 } 307 #endif 308 #endif 309 310 #ifdef WANT_DEMO 311 #ifdef HAVE_GETHRTIME 312 static hrtime_t demo_one; 313 static hrtime_t demo_two; 314 static hrtime_t *demo_one_ptr = &demo_one; 315 static hrtime_t *demo_two_ptr = &demo_two; 316 static hrtime_t *temp_demo_ptr = &demo_one; 317 #elif defined(WIN32) 318 static LARGE_INTEGER demo_one; 319 static LARGE_INTEGER demo_two; 320 static LARGE_INTEGER *demo_one_ptr = &demo_one; 321 static LARGE_INTEGER *demo_two_ptr = &demo_two; 322 static LARGE_INTEGER *temp_demo_ptr = &demo_one; 323 #else 324 static struct timeval demo_one; 325 static struct timeval demo_two; 326 static struct timeval *demo_one_ptr = &demo_one; 327 static struct timeval *demo_two_ptr = &demo_two; 328 static struct timeval *temp_demo_ptr = &demo_one; 329 #endif 330 331 /* for a _STREAM test, "a" should be lss_size and "b" should be 332 rsr_size. for a _MAERTS test, "a" should be lsr_size and "b" should 333 be rss_size. raj 2005-04-06 */ 334 #define DEMO_STREAM_SETUP(a,b) \ 335 if ((demo_mode) && (demo_units == 0)) { \ 336 /* take our default value of demo_units to be the larger of \ 337 twice the remote's SO_RCVBUF or twice our SO_SNDBUF */ \ 338 if (a > b) { \ 339 demo_units = 2*a; \ 340 } \ 341 else { \ 342 demo_units = 2*b; \ 343 } \ 344 } 345 346 #define DEMO_STREAM_INTERVAL(units) \ 347 if (demo_mode) { \ 348 double actual_interval; \ 349 units_this_tick += units; \ 350 if (units_this_tick >= demo_units) { \ 351 /* time to possibly update demo_units and maybe output an \ 352 interim result */ \ 353 HIST_timestamp(demo_two_ptr); \ 354 actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \ 355 /* we always want to fine-tune demo_units here whether we \ 356 emit an interim result or not. if we are short, this \ 357 will lengthen demo_units. if we are long, this will \ 358 shorten it */ \ 359 demo_units = demo_units * (demo_interval / actual_interval); \ 360 if (actual_interval >= demo_interval) { \ 361 /* time to emit an interim result */ \ 362 fprintf(where, \ 363 "Interim result: %7.2f %s/s over %.2f seconds\n", \ 364 calc_thruput_interval(units_this_tick, \ 365 actual_interval/1000000.0), \ 366 format_units(), \ 367 actual_interval/1000000.0); \ 368 fflush(where); \ 369 units_this_tick = 0.0; \ 370 /* now get a new starting timestamp. we could be clever \ 371 and swap pointers - the math we do probably does not \ 372 take all that long, but for now this will suffice */ \ 373 temp_demo_ptr = demo_one_ptr; \ 374 demo_one_ptr = demo_two_ptr; \ 375 demo_two_ptr = temp_demo_ptr; \ 376 } \ 377 } \ 378 } 379 380 #define DEMO_RR_SETUP(a) \ 381 if ((demo_mode) && (demo_units == 0)) { \ 382 /* take whatever we are given */ \ 383 demo_units = a; \ 384 } 385 386 #define DEMO_RR_INTERVAL(units) \ 387 if (demo_mode) { \ 388 double actual_interval; \ 389 units_this_tick += units; \ 390 if (units_this_tick >= demo_units) { \ 391 /* time to possibly update demo_units and maybe output an \ 392 interim result */ \ 393 HIST_timestamp(demo_two_ptr); \ 394 actual_interval = delta_micro(demo_one_ptr,demo_two_ptr); \ 395 /* we always want to fine-tune demo_units here whether we \ 396 emit an interim result or not. if we are short, this \ 397 will lengthen demo_units. if we are long, this will \ 398 shorten it */ \ 399 demo_units = demo_units * (demo_interval / actual_interval); \ 400 if (actual_interval >= demo_interval) { \ 401 /* time to emit an interim result */ \ 402 fprintf(where, \ 403 "Interim result: %.2f %s/s over %.2f seconds\n", \ 404 units_this_tick / (actual_interval/1000000.0), \ 405 "Trans", \ 406 actual_interval/1000000.0); \ 407 units_this_tick = 0.0; \ 408 /* now get a new starting timestamp. we could be clever \ 409 and swap pointers - the math we do probably does not \ 410 take all that long, but for now this will suffice */ \ 411 temp_demo_ptr = demo_one_ptr; \ 412 demo_one_ptr = demo_two_ptr; \ 413 demo_two_ptr = temp_demo_ptr; \ 414 } \ 415 } \ 416 } 417 #endif 418 419 char sockets_usage[] = "\n\ 420 Usage: netperf [global options] -- [test options] \n\ 421 \n\ 422 TCP/UDP BSD Sockets Test Options:\n\ 423 -b number Send number requests at start of _RR tests\n\ 424 -C Set TCP_CORK when available\n\ 425 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\ 426 -h Display this text\n\ 427 -H name,fam Use name (or IP) and family as target of data connection\n\ 428 -L name,fam Use name (or IP) and family as source of data connection\n\ 429 -m bytes Set the send size (TCP_STREAM, UDP_STREAM)\n\ 430 -M bytes Set the recv size (TCP_STREAM, UDP_STREAM)\n\ 431 -n Use the connected socket for UDP locally\n\ 432 -N Use the connected socket for UDP remotely\n\ 433 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\ 434 -P local[,remote] Set the local/remote port for the data socket\n\ 435 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\ 436 -s send[,recv] Set local socket send/recv buffer sizes\n\ 437 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 438 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 439 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 440 \n\ 441 For those options taking two parms, at least one must be specified;\n\ 442 specifying one value without a comma will set both parms to that\n\ 443 value, specifying a value with a leading comma will set just the second\n\ 444 parm, a value with a trailing comma will set just the first. To set\n\ 445 each parm to unique values, specify both and separate them with a\n\ 446 comma.\n"; 447 448 449 451 /* these routines convert between the AF address space and the NF 452 address space since the numeric values of AF_mumble are not the 453 same across the platforms. raj 2005-02-08 */ 454 455 int 456 nf_to_af(int nf) { 457 switch(nf) { 458 case NF_INET: 459 return AF_INET; 460 break; 461 case NF_UNSPEC: 462 return AF_UNSPEC; 463 break; 464 case NF_INET6: 465 #if defined(AF_INET6) 466 return AF_INET6; 467 #else 468 return AF_UNSPEC; 469 #endif 470 break; 471 default: 472 return AF_UNSPEC; 473 break; 474 } 475 } 476 477 int 478 af_to_nf(int af) { 479 480 switch(af) { 481 case AF_INET: 482 return NF_INET; 483 break; 484 case AF_UNSPEC: 485 return NF_UNSPEC; 486 break; 487 #if defined(AF_INET6) 488 case AF_INET6: 489 return NF_INET6; 490 break; 491 #endif 492 default: 493 return NF_UNSPEC; 494 break; 495 } 496 } 497 498 499 /* This routine is intended to retrieve interesting aspects of tcp */ 501 /* for the data connection. at first, it attempts to retrieve the */ 502 /* maximum segment size. later, it might be modified to retrieve */ 503 /* other information, but it must be information that can be */ 504 /* retrieved quickly as it is called during the timing of the test. */ 505 /* for that reason, a second routine may be created that can be */ 506 /* called outside of the timing loop */ 507 static 508 void 509 get_tcp_info(SOCKET socket, int *mss) 510 { 511 512 #ifdef TCP_MAXSEG 513 netperf_socklen_t sock_opt_len; 514 515 sock_opt_len = sizeof(netperf_socklen_t); 516 if (getsockopt(socket, 517 getprotobyname("tcp")->p_proto, 518 TCP_MAXSEG, 519 (char *)mss, 520 &sock_opt_len) == SOCKET_ERROR) { 521 fprintf(where, 522 "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n", 523 errno); 524 fflush(where); 525 *mss = -1; 526 } 527 #else 528 *mss = -1; 529 #endif /* TCP_MAXSEG */ 530 } 531 532 534 /* return a pointer to a completed addrinfo chain - prefer 535 data_address to controlhost and utilize the specified address 536 family */ 537 538 struct addrinfo * 539 complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags) 540 { 541 struct addrinfo hints; 542 struct addrinfo *res; 543 struct addrinfo *temp_res; 544 545 #define CHANGED_SOCK_TYPE 0x1 546 #define CHANGED_PROTOCOL 0x2 547 #define CHANGED_SCTP 0x4 548 int change_info = 0; 549 static int change_warning_displayed = 0; 550 551 int count = 0; 552 int error = 0; 553 554 char *hostname; 555 556 /* take data-address over controlhost */ 557 if (data_address) 558 hostname = data_address; 559 else 560 hostname = controlhost; 561 562 if (debug) { 563 fprintf(where, 564 "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n", 565 hostname, 566 port, 567 inet_ftos(family), 568 inet_ttos(type), 569 inet_ptos(protocol), 570 flags); 571 fflush(where); 572 } 573 574 memset(&hints, 0, sizeof(hints)); 575 hints.ai_family = family; 576 hints.ai_socktype = type; 577 hints.ai_protocol = protocol; 578 hints.ai_flags = flags|AI_CANONNAME; 579 580 count = 0; 581 do { 582 error = getaddrinfo((char *)hostname, 583 (char *)port, 584 &hints, 585 &res); 586 count += 1; 587 if (error == EAI_AGAIN) { 588 if (debug) { 589 fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n"); 590 fflush(where); 591 } 592 sleep(1); 593 } 594 /* while you see this kludge first, it is actually the second, the 595 first being the one for Solaris below. The need for this kludge 596 came after implementing the Solaris broken getaddrinfo kludge - 597 now we see a kludge in Linux getaddrinfo where if it is given 598 SOCK_STREAM and IPPROTO_SCTP it barfs with a -7 599 EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if 600 we were asking for IPPROTO_SCTP and if so, kludge, again... raj 601 2008-10-13 */ 602 #ifdef WANT_SCTP 603 if (EAI_SOCKTYPE == error 604 #ifdef EAI_BADHINTS 605 || EAI_BADHINTS == error 606 #endif 607 ) { 608 /* we ass-u-me this is the Linux getaddrinfo bug, clear the 609 hints.ai_protocol field, and set some state "remembering" 610 that we did this so the code for the Solaris kludge can do 611 the fix-up for us. also flip error over to EAI_AGAIN and 612 make sure we don't "count" this time around the loop. */ 613 hints.ai_protocol = 0; 614 error = EAI_AGAIN; 615 count -= 1; 616 change_info |= CHANGED_SCTP; 617 } 618 #endif 619 } while ((error == EAI_AGAIN) && (count <= 5)); 620 621 if (error) { 622 fprintf(where, 623 "complete_addrinfo: could not resolve '%s' port '%s' af %d", 624 hostname, 625 port, 626 family); 627 fprintf(where, 628 "\n\tgetaddrinfo returned %d %s\n", 629 error, 630 gai_strerror(error)); 631 fflush(where); 632 exit(-1); 633 } 634 635 /* there exists at least one platform - Solaris 10 - that does not 636 seem to completely honor the ai_protocol and/or ai_socktype one 637 sets in the hints parm to the getaddrinfo call. so, we need to 638 walk the list of entries returned and if either of those do not 639 match what we asked for, we need to go ahead and set them 640 "correctly" this is based in part on some earlier SCTP-only code 641 from previous revisions. raj 2006-10-09 */ 642 643 temp_res = res; 644 645 while (temp_res) { 646 647 if ((type) && 648 (temp_res->ai_socktype != type)) { 649 change_info |= CHANGED_SOCK_TYPE; 650 if (debug) { 651 fprintf(where, 652 "WARNING! Changed bogus getaddrinfo socket type %d to %d\n", 653 temp_res->ai_socktype, 654 type); 655 fflush(where); 656 } 657 temp_res->ai_socktype = type; 658 } 659 660 if ((protocol) && 661 (temp_res->ai_protocol != protocol)) { 662 change_info |= CHANGED_PROTOCOL; 663 if (debug) { 664 fprintf(where, 665 "WARNING! Changed bogus getaddrinfo protocol %d to %d\n", 666 temp_res->ai_protocol, 667 protocol); 668 fflush(where); 669 } 670 temp_res->ai_protocol = protocol; 671 } 672 temp_res = temp_res->ai_next; 673 } 674 675 if ((change_info & CHANGED_SOCK_TYPE) && 676 !(change_warning_displayed & CHANGED_SOCK_TYPE)) { 677 change_warning_displayed |= CHANGED_SOCK_TYPE; 678 fprintf(where, 679 "WARNING! getaddrinfo returned a socket type which did not\n"); 680 fprintf(where, 681 "match the requested type. Please contact your vendor for\n"); 682 fprintf(where, 683 "a fix to this bug in getaddrinfo()\n"); 684 fflush(where); 685 } 686 687 /* if we dropped the protocol hint, it would be for a protocol that 688 getaddrinfo() wasn't supporting yet, not for the bug that it took 689 our hint and still returned zero. raj 2006-10-16 */ 690 if ((change_info & CHANGED_PROTOCOL) && 691 !(change_warning_displayed & CHANGED_PROTOCOL) && 692 (hints.ai_protocol != 0)) { 693 change_warning_displayed |= CHANGED_PROTOCOL; 694 fprintf(where, 695 "WARNING! getaddrinfo returned a protocol other than the\n"); 696 fprintf(where, 697 "requested protocol. Please contact your vendor for\n"); 698 fprintf(where, 699 "a fix to this bug in getaddrinfo()\n"); 700 fflush(where); 701 } 702 703 if ((change_info & CHANGED_SCTP) && 704 !(change_warning_displayed & CHANGED_SCTP)) { 705 change_warning_displayed |= CHANGED_SCTP; 706 fprintf(where, 707 "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n"); 708 fprintf(where, 709 "Please contact your vendor for a fix to this bug in getaddrinfo().\n"); 710 fflush(where); 711 } 712 713 714 if (debug) { 715 dump_addrinfo(where, res, hostname, port, family); 716 } 717 718 return(res); 719 } 720 721 void 722 complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) { 723 724 *remote = complete_addrinfo(remote_host, 725 remote_data_address, 726 remote_data_port, 727 remote_data_family, 728 type, 729 protocol, 730 flags); 731 732 /* OK, if the user has not specified a local data endpoint address 733 (test-specific -L), pick the local data endpoint address based on 734 the remote data family info (test-specific -H or -4 or -6 735 option). if the user has not specified remote data addressing 736 info (test-specific -H, -4 -6) pick something based on the local 737 control connection address (ie the global -L option). */ 738 739 if (NULL == local_data_address) { 740 local_data_address = malloc(HOSTNAMESIZE); 741 if (NULL == remote_data_address) { 742 if (debug) { 743 fprintf(where, 744 "local_data_address not set, using local_host_name of '%s'\n", 745 local_host_name); 746 fflush(where); 747 } 748 strcpy(local_data_address,local_host_name); 749 } 750 else { 751 if (debug) { 752 fprintf(where, 753 "local_data_address not set, using address family info\n"); 754 fflush(where); 755 } 756 /* by default, use 0.0.0.0 - assume IPv4 */ 757 strcpy(local_data_address,"0.0.0.0"); 758 #if defined(AF_INET6) 759 if ((AF_INET6 == local_data_family) || 760 ((AF_UNSPEC == local_data_family) && 761 (AF_INET6 == remote_data_family)) || 762 ((AF_UNSPEC == local_data_family) && 763 (AF_INET6 == (*remote)->ai_family))) { 764 strcpy(local_data_address,"::0"); 765 } 766 #endif 767 } 768 } 769 770 *local = complete_addrinfo("what to put here?", 771 local_data_address, 772 local_data_port, 773 local_data_family, 774 type, 775 protocol, 776 flags|AI_PASSIVE); 777 778 } 779 780 void 781 set_hostname_and_port(char *hostname, char *portstr, int family, int port) 782 { 783 strcpy(hostname,"0.0.0.0"); 784 #if defined AF_INET6 785 if (AF_INET6 == family) { 786 strcpy(hostname,"::0"); 787 } 788 #endif 789 790 sprintf(portstr, "%u", port); 791 792 } 793 794 static unsigned short 795 get_port_number(struct addrinfo *res) 796 { 797 switch(res->ai_family) { 798 case AF_INET: { 799 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 800 return(ntohs(foo->sin_port)); 801 break; 802 } 803 #if defined(AF_INET6) 804 case AF_INET6: { 805 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 806 return(ntohs(foo->sin6_port)); 807 break; 808 } 809 #endif 810 default: 811 fprintf(where, 812 "Unexpected Address Family of %u\n",res->ai_family); 813 fflush(where); 814 exit(-1); 815 } 816 } 817 818 /* this routine will set the port number of the sockaddr in the 819 addrinfo to the specified value, based on the address family */ 820 void 821 set_port_number(struct addrinfo *res, unsigned short port) 822 { 823 switch(res->ai_family) { 824 case AF_INET: { 825 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr; 826 foo->sin_port = htons(port); 827 break; 828 } 829 #if defined(AF_INET6) 830 case AF_INET6: { 831 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr; 832 foo->sin6_port = htons(port); 833 break; 834 } 835 #endif 836 default: 837 fprintf(where, 838 "Unexpected Address Family of %u\n",res->ai_family); 839 fflush(where); 840 exit(-1); 841 } 842 } 843 844 845 847 /* This routine will create a data (listen) socket with the 848 apropriate options set and return it to the caller. this replaces 849 all the duplicate code in each of the test routines and should help 850 make things a little easier to understand. since this routine can be 851 called by either the netperf or netserver programs, all output 852 should be directed towards "where." family is generally AF_INET and 853 type will be either SOCK_STREAM or SOCK_DGRAM. This routine will 854 also be used by the "SCTP" tests, hence the slightly strange-looking 855 SCTP stuff in the classic bsd sockets test file... vlad/raj 856 2005-03-15 */ 857 858 SOCKET 859 create_data_socket(struct addrinfo *res) 860 { 861 862 SOCKET temp_socket; 863 int one; 864 int on = 1; 865 866 867 /*set up the data socket */ 868 temp_socket = socket(res->ai_family, 869 res->ai_socktype, 870 res->ai_protocol); 871 872 if (temp_socket == INVALID_SOCKET){ 873 fprintf(where, 874 "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n", 875 errno, 876 inet_ftos(res->ai_family), 877 inet_ttos(res->ai_socktype), 878 inet_ptos(res->ai_protocol), 879 strerror(errno)); 880 fflush(where); 881 exit(1); 882 } 883 884 if (debug) { 885 fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket); 886 fflush(where); 887 } 888 889 /* Modify the local socket size. The reason we alter the send buffer 890 size here rather than when the connection is made is to take care 891 of decreases in buffer size. Decreasing the window size after 892 connection establishment is a TCP no-no. Also, by setting the 893 buffer (window) size before the connection is established, we can 894 control the TCP MSS (segment size). The MSS is never (well, should 895 never be) more that 1/2 the minimum receive buffer size at each 896 half of the connection. This is why we are altering the receive 897 buffer size on the sending size of a unidirectional transfer. If 898 the user has not requested that the socket buffers be altered, we 899 will try to find-out what their values are. If we cannot touch the 900 socket buffer in any way, we will set the values to -1 to indicate 901 that. */ 902 903 /* all the oogy nitty gritty stuff moved from here into the routine 904 being called below, per patches from davidm to workaround the bug 905 in Linux getsockopt(). raj 2004-06-15 */ 906 set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size); 907 set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size); 908 909 /* now, we may wish to enable the copy avoidance features on the */ 910 /* local system. of course, this may not be possible... */ 911 912 #ifdef SO_RCV_COPYAVOID 913 if (loc_rcvavoid) { 914 if (setsockopt(temp_socket, 915 SOL_SOCKET, 916 SO_RCV_COPYAVOID, 917 (const char *)&loc_rcvavoid, 918 sizeof(int)) == SOCKET_ERROR) { 919 fprintf(where, 920 "netperf: create_data_socket: Could not enable receive copy avoidance"); 921 fflush(where); 922 loc_rcvavoid = 0; 923 } 924 } 925 #else 926 /* it wasn't compiled in... */ 927 loc_rcvavoid = 0; 928 #endif /* SO_RCV_COPYAVOID */ 929 930 #ifdef SO_SND_COPYAVOID 931 if (loc_sndavoid) { 932 if (setsockopt(temp_socket, 933 SOL_SOCKET, 934 SO_SND_COPYAVOID, 935 (const char *)&loc_sndavoid, 936 sizeof(int)) == SOCKET_ERROR) { 937 fprintf(where, 938 "netperf: create_data_socket: Could not enable send copy avoidance"); 939 fflush(where); 940 loc_sndavoid = 0; 941 } 942 } 943 #else 944 /* it was not compiled in... */ 945 loc_sndavoid = 0; 946 #endif 947 948 /* Now, we will see about setting the TCP_NODELAY flag on the local */ 949 /* socket. We will only do this for those systems that actually */ 950 /* support the option. If it fails, note the fact, but keep going. */ 951 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */ 952 /* will cause an error to be displayed */ 953 954 /* well..... long ago and far away that would have happened, in 955 particular because we would always use IPPROTO_TCP here. 956 however, now we are using res->ai_protocol, which will be 957 IPPROT_UDP, and while HP-UX, and I suspect no-one else on the 958 planet has a UDP_mumble option that overlaps with TCP_NODELAY, 959 sure as knuth made little green programs, linux has a UDP_CORK 960 option that is defined as a value of 1, which is the same a 961 TCP_NODELAY under Linux. So, when asking for -D and 962 "TCP_NODELAY" under Linux, we are actually setting UDP_CORK 963 instead of getting an error like every other OS on the 964 planet. joy and rupture. this stops a UDP_RR test cold sooo we 965 have to make sure that res->ai_protocol actually makes sense for 966 a _NODELAY setsockopt() or a UDP_RR test on Linux where someone 967 mistakenly sets -D will hang. raj 2005-04-21 */ 968 969 #if defined(TCP_NODELAY) || defined(SCTP_NODELAY) 970 if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) { 971 972 /* strictly speaking, since the if defined above is an OR, we 973 should probably check against TCP_NODELAY being defined here. 974 however, the likelihood of SCTP_NODELAY being defined and 975 TCP_NODELAY _NOT_ being defined is, probably :), epsilon. raj 976 2005-03-15 */ 977 978 int option = TCP_NODELAY; 979 980 /* I suspect that WANT_SCTP would suffice here since that is the 981 only time we would have called getaddrinfo with a hints asking 982 for SCTP, but just in case there is an SCTP implementation out 983 there _without_ SCTP_NODELAY... raj 2005-03-15 */ 984 985 #if defined(WANT_SCTP) && defined(SCTP_NODELAY) 986 if (IPPROTO_SCTP == res->ai_protocol) { 987 option = SCTP_NODELAY; 988 } 989 #endif 990 991 one = 1; 992 if(setsockopt(temp_socket, 993 res->ai_protocol, 994 option, 995 (char *)&one, 996 sizeof(one)) == SOCKET_ERROR) { 997 fprintf(where, 998 "netperf: create_data_socket: nodelay: errno %d\n", 999 errno); 1000 fflush(where); 1001 } 1002 1003 if (debug > 1) { 1004 fprintf(where, 1005 "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n"); 1006 fflush(where); 1007 } 1008 } 1009 #else /* TCP_NODELAY */ 1010 1011 loc_nodelay = 0; 1012 1013 #endif /* TCP_NODELAY */ 1014 1015 #if defined(TCP_CORK) 1016 1017 if (loc_tcpcork != 0) { 1018 /* the user wishes for us to set TCP_CORK on the socket */ 1019 int one = 1; 1020 if (setsockopt(temp_socket, 1021 getprotobyname("tcp")->p_proto, 1022 TCP_CORK, 1023 (char *)&one, 1024 sizeof(one)) == SOCKET_ERROR) { 1025 perror("netperf: sendfile_tcp_stream: tcp_cork"); 1026 exit(1); 1027 } 1028 if (debug) { 1029 fprintf(where,"sendfile_tcp_stream: tcp_cork...\n"); 1030 } 1031 } 1032 1033 #endif /* TCP_CORK */ 1034 1035 /* since some of the UDP tests do not do anything to cause an 1036 implicit bind() call, we need to be rather explicit about our 1037 bind() call here. even if the address and/or the port are zero 1038 (INADDR_ANY etc). raj 2004-07-20 */ 1039 1040 if (setsockopt(temp_socket, 1041 SOL_SOCKET, 1042 SO_REUSEADDR, 1043 (const char *)&on, 1044 sizeof(on)) < 0) { 1045 fprintf(where, 1046 "netperf: create_data_socket: SO_REUSEADDR failed %d\n", 1047 errno); 1048 fflush(where); 1049 } 1050 1051 if (bind(temp_socket, 1052 res->ai_addr, 1053 res->ai_addrlen) < 0) { 1054 if (debug) { 1055 fprintf(where, 1056 "netperf: create_data_socket: data socket bind failed errno %d\n", 1057 errno); 1058 fprintf(where," port: %d\n",get_port_number(res)); 1059 fflush(where); 1060 } 1061 } 1062 1063 1064 return(temp_socket); 1065 1066 } 1067 1068 #ifdef KLUDGE_SOCKET_OPTIONS 1069 1070 1071 /* This routine is for those BROKEN systems which do not correctly */ 1073 /* pass socket attributes through calls such as accept(). It should */ 1074 /* only be called for those broken systems. I *really* don't want to */ 1075 /* have this, but even broken systems must be measured. raj 11/95 */ 1076 void 1077 kludge_socket_options(int temp_socket) 1078 { 1079 1080 set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size); 1081 set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size); 1082 1083 /* now, we may wish to enable the copy avoidance features on the */ 1084 /* local system. of course, this may not be possible... */ 1085 /* those calls were only valid for HP-UX, and I know that HP-UX is */ 1086 /* written correctly, and so we do not need to include those calls */ 1087 /* in this kludgy routine. raj 11/95 */ 1088 1089 1090 /* Now, we will see about setting the TCP_NODELAY flag on the local */ 1091 /* socket. We will only do this for those systems that actually */ 1092 /* support the option. If it fails, note the fact, but keep going. */ 1093 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */ 1094 /* will cause an error to be displayed */ 1095 1096 #ifdef TCP_NODELAY 1097 if (loc_nodelay) { 1098 one = 1; 1099 if(setsockopt(temp_socket, 1100 getprotobyname("tcp")->p_proto, 1101 TCP_NODELAY, 1102 (char *)&one, 1103 sizeof(one)) == SOCKET_ERROR) { 1104 fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n", 1105 errno); 1106 fflush(where); 1107 } 1108 1109 if (debug > 1) { 1110 fprintf(where, 1111 "netperf: kludge_socket_options: TCP_NODELAY requested...\n"); 1112 fflush(where); 1113 } 1114 } 1115 #else /* TCP_NODELAY */ 1116 1117 loc_nodelay = 0; 1118 1119 #endif /* TCP_NODELAY */ 1120 1121 } 1122 1123 #endif /* KLUDGE_SOCKET_OPTIONS */ 1124 1125 1127 static void * 1128 get_address_address(struct addrinfo *info) 1129 { 1130 struct sockaddr_in *sin; 1131 #if defined(AF_INET6) 1132 struct sockaddr_in6 *sin6; 1133 #endif 1134 1135 switch(info->ai_family) { 1136 case AF_INET: 1137 sin = (struct sockaddr_in *)info->ai_addr; 1138 return(&(sin->sin_addr)); 1139 break; 1140 #if defined(AF_INET6) 1141 case AF_INET6: 1142 sin6 = (struct sockaddr_in6 *)info->ai_addr; 1143 return(&(sin6->sin6_addr)); 1144 break; 1145 #endif 1146 default: 1147 fprintf(stderr,"we never expected to get here in get_address_address\n"); 1148 fflush(stderr); 1149 exit(-1); 1150 } 1151 } 1152 1153 #if defined(WIN32) 1154 /* +*+ Why isn't this in the winsock headers yet? */ 1155 const char * 1156 inet_ntop(int af, const void *src, char *dst, size_t size); 1157 #endif 1158 1159 /* This routine is a generic test header printer for the topmost header */ 1160 void 1161 print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination) 1162 { 1163 1164 #if defined(AF_INET6) 1165 char address_buf[INET6_ADDRSTRLEN]; 1166 #else 1167 char address_buf[16]; /* magic constant */ 1168 #endif 1169 1170 /* we want to have some additional, interesting information in */ 1171 /* the headers. we know some of it here, but not all, so we will */ 1172 /* only print the test title here and will print the results */ 1173 /* titles after the test is finished */ 1174 fprintf(where,test_name); 1175 address_buf[0] = '\0'; 1176 inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf)); 1177 fprintf(where, 1178 " from %s (%s) port %u %s", 1179 source->ai_canonname, 1180 address_buf, 1181 get_port_number(source), 1182 inet_ftos(source->ai_family)); 1183 address_buf[0] = '\0'; 1184 inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf)); 1185 fprintf(where, 1186 " to %s (%s) port %u %s", 1187 destination->ai_canonname, 1188 address_buf, 1189 get_port_number(destination), 1190 inet_ftos(destination->ai_family)); 1191 1192 if (iteration_max > 1) { 1193 fprintf(where, 1194 " : +/-%3.1f%% @ %2d%% conf. %s", 1195 interval/0.02, 1196 confidence_level, 1197 result_confidence_only ? " on result only" : ""); 1198 } 1199 if ((loc_nodelay > 0) || (rem_nodelay > 0)) { 1200 fprintf(where," : nodelay"); 1201 } 1202 if ((loc_sndavoid > 0) || 1203 (loc_rcvavoid > 0) || 1204 (rem_sndavoid > 0) || 1205 (rem_rcvavoid > 0)) { 1206 fprintf(where," : copy avoidance"); 1207 } 1208 1209 if (no_control) { 1210 fprintf(where," : no control"); 1211 } 1212 1213 #ifdef WANT_HISTOGRAM 1214 fprintf(where," : histogram"); 1215 #endif /* WANT_HISTOGRAM */ 1216 1217 #ifdef WANT_INTERVALS 1218 #ifndef WANT_SPIN 1219 fprintf(where," : interval"); 1220 #else 1221 fprintf(where," : spin interval"); 1222 #endif 1223 #endif /* WANT_INTERVALS */ 1224 1225 #ifdef DIRTY 1226 fprintf(where," : dirty data"); 1227 #endif /* DIRTY */ 1228 #ifdef WANT_DEMO 1229 fprintf(where," : demo"); 1230 #endif 1231 #ifdef WANT_FIRST_BURST 1232 /* a little hokey perhaps, but we really only want this to be 1233 emitted for tests where it actually is used, which means a 1234 "REQUEST/RESPONSE" test. raj 2005-11-10 */ 1235 if (strstr(test_name,"REQUEST/RESPONSE")) { 1236 fprintf(where," : first burst %d",first_burst_size); 1237 } 1238 #endif 1239 if (cpu_binding_requested) { 1240 fprintf(where," : cpu bind"); 1241 } 1242 fprintf(where,"\n"); 1243 1244 } 1245 1246 1247 /* This routine implements the TCP unidirectional data transfer test */ 1248 /* (a.k.a. stream) for the sockets interface. It receives its */ 1249 /* parameters via global variables from the shell and writes its */ 1250 /* output to the standard output. */ 1251 1252 1253 void 1254 send_tcp_stream(char remote_host[]) 1255 { 1256 1257 char *tput_title = "\ 1258 Recv Send Send \n\ 1259 Socket Socket Message Elapsed \n\ 1260 Size Size Size Time Throughput \n\ 1261 bytes bytes bytes secs. %s/sec \n\n"; 1262 1263 char *tput_fmt_0 = 1264 "%7.2f %s\n"; 1265 1266 char *tput_fmt_1 = 1267 "%6d %6d %6d %-6.2f %7.2f %s\n"; 1268 1269 char *cpu_title = "\ 1270 Recv Send Send Utilization Service Demand\n\ 1271 Socket Socket Message Elapsed Send Recv Send Recv\n\ 1272 Size Size Size Time Throughput local remote local remote\n\ 1273 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 1274 1275 char *cpu_fmt_0 = 1276 "%6.3f %c %s\n"; 1277 1278 char *cpu_fmt_1 = 1279 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 1280 1281 char *ksink_fmt = "\n\ 1282 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 1283 Local Remote Local Remote Xfered Per Per\n\ 1284 Send Recv Send Recv Send (avg) Recv (avg)\n\ 1285 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 1286 1287 char *ksink_fmt2 = "\n\ 1288 Maximum\n\ 1289 Segment\n\ 1290 Size (bytes)\n\ 1291 %6d\n"; 1292 1293 1294 float elapsed_time; 1295 1296 /* what we want is to have a buffer space that is at least one */ 1297 /* send-size greater than our send window. this will insure that we */ 1298 /* are never trying to re-use a buffer that may still be in the hands */ 1299 /* of the transport. This buffer will be malloc'd after we have found */ 1300 /* the size of the local senc socket buffer. We will want to deal */ 1301 /* with alignment and offset concerns as well. */ 1302 1303 struct ring_elt *send_ring; 1304 1305 int len; 1306 unsigned int nummessages = 0; 1307 SOCKET send_socket; 1308 int bytes_remaining; 1309 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 1310 1311 /* with links like fddi, one can send > 32 bits worth of bytes */ 1312 /* during a test... ;-) at some point, this should probably become a */ 1313 /* 64bit integral type, but those are not entirely common yet */ 1314 1315 unsigned long long local_bytes_sent = 0; 1316 double bytes_sent = 0.0; 1317 1318 float local_cpu_utilization; 1319 float local_service_demand; 1320 float remote_cpu_utilization; 1321 float remote_service_demand; 1322 1323 double thruput; 1324 1325 struct addrinfo *remote_res; 1326 struct addrinfo *local_res; 1327 1328 struct tcp_stream_request_struct *tcp_stream_request; 1329 struct tcp_stream_response_struct *tcp_stream_response; 1330 struct tcp_stream_results_struct *tcp_stream_result; 1331 1332 tcp_stream_request = 1333 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 1334 tcp_stream_response = 1335 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 1336 tcp_stream_result = 1337 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 1338 1339 #ifdef WANT_HISTOGRAM 1340 if (verbosity > 1) { 1341 time_hist = HIST_new(); 1342 } 1343 #endif /* WANT_HISTOGRAM */ 1344 /* since we are now disconnected from the code that established the */ 1345 /* control socket, and since we want to be able to use different */ 1346 /* protocols and such, we are passed the name of the remote host and */ 1347 /* must turn that into the test specific addressing information. */ 1348 1349 /* complete_addrinfos will either succede or exit the process */ 1350 complete_addrinfos(&remote_res, 1351 &local_res, 1352 remote_host, 1353 SOCK_STREAM, 1354 IPPROTO_TCP, 1355 0); 1356 1357 if ( print_headers ) { 1358 print_top_test_header("TCP STREAM TEST",local_res,remote_res); 1359 } 1360 1361 send_ring = NULL; 1362 confidence_iteration = 1; 1363 init_stat(); 1364 1365 /* we have a great-big while loop which controls the number of times */ 1366 /* we run a particular test. this is for the calculation of a */ 1367 /* confidence interval (I really should have stayed awake during */ 1368 /* probstats :). If the user did not request confidence measurement */ 1369 /* (no confidence is the default) then we will only go though the */ 1370 /* loop once. the confidence stuff originates from the folks at IBM */ 1371 1372 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 1373 (confidence_iteration <= iteration_min)) { 1374 1375 /* initialize a few counters. we have to remember that we might be */ 1376 /* going through the loop more than once. */ 1377 1378 nummessages = 0; 1379 bytes_sent = 0.0; 1380 times_up = 0; 1381 1382 /*set up the data socket */ 1383 send_socket = create_data_socket(local_res); 1384 1385 if (send_socket == INVALID_SOCKET){ 1386 perror("netperf: send_tcp_stream: tcp stream data socket"); 1387 exit(1); 1388 } 1389 1390 if (debug) { 1391 fprintf(where,"send_tcp_stream: send_socket obtained...\n"); 1392 } 1393 1394 /* at this point, we have either retrieved the socket buffer sizes, */ 1395 /* or have tried to set them, so now, we may want to set the send */ 1396 /* size based on that (because the user either did not use a -m */ 1397 /* option, or used one with an argument of 0). If the socket buffer */ 1398 /* size is not available, we will set the send size to 4KB - no */ 1399 /* particular reason, just arbitrary... */ 1400 if (send_size == 0) { 1401 if (lss_size > 0) { 1402 send_size = lss_size; 1403 } 1404 else { 1405 send_size = 4096; 1406 } 1407 } 1408 1409 /* set-up the data buffer ring with the requested alignment and offset. */ 1410 /* note also that we have allocated a quantity */ 1411 /* of memory that is at least one send-size greater than our socket */ 1412 /* buffer size. We want to be sure that there are at least two */ 1413 /* buffers allocated - this can be a bit of a problem when the */ 1414 /* send_size is bigger than the socket size, so we must check... the */ 1415 /* user may have wanted to explicitly set the "width" of our send */ 1416 /* buffers, we should respect that wish... */ 1417 if (send_width == 0) { 1418 send_width = (lss_size/send_size) + 1; 1419 if (send_width == 1) send_width++; 1420 } 1421 1422 if (send_ring == NULL) { 1423 /* only allocate the send ring once. this is a networking test, */ 1424 /* not a memory allocation test. this way, we do not need a */ 1425 /* deallocate_buffer_ring() routine, and I don't feel like */ 1426 /* writing one anyway :) raj 11/94 */ 1427 send_ring = allocate_buffer_ring(send_width, 1428 send_size, 1429 local_send_align, 1430 local_send_offset); 1431 } 1432 1433 /* If the user has requested cpu utilization measurements, we must */ 1434 /* calibrate the cpu(s). We will perform this task within the tests */ 1435 /* themselves. If the user has specified the cpu rate, then */ 1436 /* calibrate_local_cpu will return rather quickly as it will have */ 1437 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 1438 /* all the "normal" calibration stuff and return the rate back. */ 1439 1440 if (local_cpu_usage) { 1441 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 1442 } 1443 1444 if (!no_control) { 1445 /* Tell the remote end to do a listen. The server alters the 1446 socket paramters on the other side at this point, hence the 1447 reason for all the values being passed in the setup 1448 message. If the user did not specify any of the parameters, 1449 they will be passed as 0, which will indicate to the remote 1450 that no changes beyond the system's default should be 1451 used. Alignment is the exception, it will default to 1, which 1452 will be no alignment alterations. */ 1453 1454 netperf_request.content.request_type = DO_TCP_STREAM; 1455 tcp_stream_request->send_buf_size = rss_size_req; 1456 tcp_stream_request->recv_buf_size = rsr_size_req; 1457 tcp_stream_request->receive_size = recv_size; 1458 tcp_stream_request->no_delay = rem_nodelay; 1459 tcp_stream_request->recv_alignment = remote_recv_align; 1460 tcp_stream_request->recv_offset = remote_recv_offset; 1461 tcp_stream_request->measure_cpu = remote_cpu_usage; 1462 tcp_stream_request->cpu_rate = remote_cpu_rate; 1463 if (test_time) { 1464 tcp_stream_request->test_length = test_time; 1465 } 1466 else { 1467 tcp_stream_request->test_length = test_bytes; 1468 } 1469 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 1470 tcp_stream_request->so_sndavoid = rem_sndavoid; 1471 #ifdef DIRTY 1472 tcp_stream_request->dirty_count = rem_dirty_count; 1473 tcp_stream_request->clean_count = rem_clean_count; 1474 #endif /* DIRTY */ 1475 tcp_stream_request->port = atoi(remote_data_port); 1476 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 1477 if (debug > 1) { 1478 fprintf(where, 1479 "netperf: send_tcp_stream: requesting TCP stream test\n"); 1480 } 1481 1482 send_request(); 1483 1484 /* The response from the remote will contain all of the relevant 1485 socket parameters for this test type. We will put them back 1486 into the variables here so they can be displayed if desired. 1487 The remote will have calibrated CPU if necessary, and will 1488 have done all the needed set-up we will have calibrated the 1489 cpu locally before sending the request, and will grab the 1490 counter value right after the connect returns. The remote 1491 will grab the counter right after the accept call. This saves 1492 the hassle of extra messages being sent for the TCP 1493 tests. */ 1494 1495 recv_response(); 1496 1497 if (!netperf_response.content.serv_errno) { 1498 if (debug) 1499 fprintf(where,"remote listen done.\n"); 1500 rsr_size = tcp_stream_response->recv_buf_size; 1501 rss_size = tcp_stream_response->send_buf_size; 1502 rem_nodelay = tcp_stream_response->no_delay; 1503 remote_cpu_usage= tcp_stream_response->measure_cpu; 1504 remote_cpu_rate = tcp_stream_response->cpu_rate; 1505 1506 /* we have to make sure that the server port number is in 1507 network order */ 1508 set_port_number(remote_res, 1509 (short)tcp_stream_response->data_port_number); 1510 1511 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 1512 rem_sndavoid = tcp_stream_response->so_sndavoid; 1513 } 1514 else { 1515 Set_errno(netperf_response.content.serv_errno); 1516 fprintf(where, 1517 "netperf: remote error %d", 1518 netperf_response.content.serv_errno); 1519 perror(""); 1520 fflush(where); 1521 1522 exit(1); 1523 } 1524 } 1525 1526 #ifdef WANT_DEMO 1527 DEMO_STREAM_SETUP(lss_size,rsr_size) 1528 #endif 1529 1530 /*Connect up to the remote port on the data socket */ 1531 if (connect(send_socket, 1532 remote_res->ai_addr, 1533 remote_res->ai_addrlen) == INVALID_SOCKET){ 1534 perror("netperf: send_tcp_stream: data socket connect failed"); 1535 exit(1); 1536 } 1537 1538 /* Data Socket set-up is finished. If there were problems, either */ 1539 /* the connect would have failed, or the previous response would */ 1540 /* have indicated a problem. I failed to see the value of the */ 1541 /* extra message after the accept on the remote. If it failed, */ 1542 /* we'll see it here. If it didn't, we might as well start pumping */ 1543 /* data. */ 1544 1545 /* Set-up the test end conditions. For a stream test, they can be */ 1546 /* either time or byte-count based. */ 1547 1548 if (test_time) { 1549 /* The user wanted to end the test after a period of time. */ 1550 times_up = 0; 1551 bytes_remaining = 0; 1552 /* in previous revisions, we had the same code repeated throught */ 1553 /* all the test suites. this was unnecessary, and meant more */ 1554 /* work for me when I wanted to switch to POSIX signals, so I */ 1555 /* have abstracted this out into a routine in netlib.c. if you */ 1556 /* are experiencing signal problems, you might want to look */ 1557 /* there. raj 11/94 */ 1558 start_timer(test_time); 1559 } 1560 else { 1561 /* The tester wanted to send a number of bytes. */ 1562 bytes_remaining = test_bytes; 1563 times_up = 1; 1564 } 1565 1566 /* The cpu_start routine will grab the current time and possibly */ 1567 /* value of the idle counter for later use in measuring cpu */ 1568 /* utilization and/or service demand and thruput. */ 1569 1570 cpu_start(local_cpu_usage); 1571 1572 /* we only start the interval timer if we are using the 1573 timer-timed intervals rather than the sit and spin ones. raj 1574 2006-02-06 */ 1575 #if defined(WANT_INTERVALS) 1576 INTERVALS_INIT(); 1577 #endif /* WANT_INTERVALS */ 1578 1579 /* before we start, initialize a few variables */ 1580 1581 #ifdef WANT_DEMO 1582 if (demo_mode) { 1583 HIST_timestamp(demo_one_ptr); 1584 } 1585 #endif 1586 1587 1588 /* We use an "OR" to control test execution. When the test is */ 1589 /* controlled by time, the byte count check will always return false. */ 1590 /* When the test is controlled by byte count, the time test will */ 1591 /* always return false. When the test is finished, the whole */ 1592 /* expression will go false and we will stop sending data. */ 1593 1594 while ((!times_up) || (bytes_remaining > 0)) { 1595 1596 #ifdef DIRTY 1597 access_buffer(send_ring->buffer_ptr, 1598 send_size, 1599 loc_dirty_count, 1600 loc_clean_count); 1601 #endif /* DIRTY */ 1602 1603 #ifdef WANT_HISTOGRAM 1604 if (verbosity > 1) { 1605 /* timestamp just before we go into send and then again just 1606 after we come out raj 8/94 */ 1607 /* but lets only do this if there is going to be a histogram 1608 displayed */ 1609 HIST_timestamp(&time_one); 1610 } 1611 #endif /* WANT_HISTOGRAM */ 1612 1613 if((len=send(send_socket, 1614 send_ring->buffer_ptr, 1615 send_size, 1616 0)) != send_size) { 1617 if ((len >=0) || SOCKET_EINTR(len)) { 1618 /* the test was interrupted, must be the end of test */ 1619 break; 1620 } 1621 perror("netperf: data send error"); 1622 printf("len was %d\n",len); 1623 exit(1); 1624 } 1625 1626 local_bytes_sent += send_size; 1627 1628 #ifdef WANT_HISTOGRAM 1629 if (verbosity > 1) { 1630 /* timestamp the exit from the send call and update the histogram */ 1631 HIST_timestamp(&time_two); 1632 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 1633 } 1634 #endif /* WANT_HISTOGRAM */ 1635 1636 #ifdef WANT_DEMO 1637 DEMO_STREAM_INTERVAL(send_size) 1638 #endif 1639 1640 #if defined(WANT_INTERVALS) 1641 INTERVALS_WAIT(); 1642 #endif /* WANT_INTERVALS */ 1643 1644 /* now we want to move our pointer to the next position in the */ 1645 /* data buffer...we may also want to wrap back to the "beginning" */ 1646 /* of the bufferspace, so we will mod the number of messages sent */ 1647 /* by the send width, and use that to calculate the offset to add */ 1648 /* to the base pointer. */ 1649 nummessages++; 1650 send_ring = send_ring->next; 1651 if (bytes_remaining) { 1652 bytes_remaining -= send_size; 1653 } 1654 } 1655 1656 /* The test is over. Flush the buffers to the remote end. We do a */ 1657 /* graceful release to insure that all data has been taken by the */ 1658 /* remote. */ 1659 1660 /* but first, if the verbosity is greater than 1, find-out what */ 1661 /* the TCP maximum segment_size was (if possible) */ 1662 if (verbosity > 1) { 1663 tcp_mss = -1; 1664 get_tcp_info(send_socket,&tcp_mss); 1665 } 1666 1667 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 1668 perror("netperf: cannot shutdown tcp stream socket"); 1669 exit(1); 1670 } 1671 1672 /* hang a recv() off the socket to block until the remote has */ 1673 /* brought all the data up into the application. it will do a */ 1674 /* shutdown to cause a FIN to be sent our way. We will assume that */ 1675 /* any exit from the recv() call is good... raj 4/93 */ 1676 1677 recv(send_socket, send_ring->buffer_ptr, send_size, 0); 1678 1679 /* this call will always give us the elapsed time for the test, and */ 1680 /* will also store-away the necessaries for cpu utilization */ 1681 1682 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 1683 /* measured and how */ 1684 /* long did we really */ 1685 /* run? */ 1686 1687 /* we are finished with the socket, so close it to prevent hitting */ 1688 /* the limit on maximum open files. */ 1689 1690 close(send_socket); 1691 1692 if (!no_control) { 1693 /* Get the statistics from the remote end. The remote will have 1694 calculated service demand and all those interesting 1695 things. If it wasn't supposed to care, it will return obvious 1696 values. */ 1697 1698 recv_response(); 1699 if (!netperf_response.content.serv_errno) { 1700 if (debug) 1701 fprintf(where,"remote results obtained\n"); 1702 } 1703 else { 1704 Set_errno(netperf_response.content.serv_errno); 1705 fprintf(where, 1706 "netperf: remote error %d", 1707 netperf_response.content.serv_errno); 1708 perror(""); 1709 fflush(where); 1710 1711 exit(1); 1712 } 1713 1714 /* We now calculate what our thruput was for the test. In the 1715 future, we may want to include a calculation of the thruput 1716 measured by the remote, but it should be the case that for a 1717 TCP stream test, that the two numbers should be *very* 1718 close... We calculate bytes_sent regardless of the way the 1719 test length was controlled. If it was time, we needed to, 1720 and if it was by bytes, the user may have specified a number 1721 of bytes that wasn't a multiple of the send_size, so we 1722 really didn't send what he asked for ;-) */ 1723 1724 bytes_sent = ntohd(tcp_stream_result->bytes_received); 1725 } 1726 else { 1727 bytes_sent = (double)local_bytes_sent; 1728 } 1729 1730 thruput = calc_thruput(bytes_sent); 1731 1732 if (local_cpu_usage || remote_cpu_usage) { 1733 /* We must now do a little math for service demand and cpu */ 1734 /* utilization for the system(s) */ 1735 /* Of course, some of the information might be bogus because */ 1736 /* there was no idle counter in the kernel(s). We need to make */ 1737 /* a note of this for the user's benefit...*/ 1738 if (local_cpu_usage) { 1739 1740 local_cpu_utilization = calc_cpu_util(0.0); 1741 local_service_demand = calc_service_demand(bytes_sent, 1742 0.0, 1743 0.0, 1744 0); 1745 } 1746 else { 1747 local_cpu_utilization = (float) -1.0; 1748 local_service_demand = (float) -1.0; 1749 } 1750 1751 if (remote_cpu_usage) { 1752 1753 remote_cpu_utilization = tcp_stream_result->cpu_util; 1754 remote_service_demand = calc_service_demand(bytes_sent, 1755 0.0, 1756 remote_cpu_utilization, 1757 tcp_stream_result->num_cpus); 1758 } 1759 else { 1760 remote_cpu_utilization = (float) -1.0; 1761 remote_service_demand = (float) -1.0; 1762 } 1763 } 1764 else { 1765 /* we were not measuring cpu, for the confidence stuff, we */ 1766 /* should make it -1.0 */ 1767 local_cpu_utilization = (float) -1.0; 1768 local_service_demand = (float) -1.0; 1769 remote_cpu_utilization = (float) -1.0; 1770 remote_service_demand = (float) -1.0; 1771 } 1772 1773 /* at this point, we want to calculate the confidence information. */ 1774 /* if debugging is on, calculate_confidence will print-out the */ 1775 /* parameters we pass it */ 1776 1777 calculate_confidence(confidence_iteration, 1778 elapsed_time, 1779 thruput, 1780 local_cpu_utilization, 1781 remote_cpu_utilization, 1782 local_service_demand, 1783 remote_service_demand); 1784 1785 1786 confidence_iteration++; 1787 } 1788 1789 /* at this point, we have finished making all the runs that we */ 1790 /* will be making. so, we should extract what the calcuated values */ 1791 /* are for all the confidence stuff. we could make the values */ 1792 /* global, but that seemed a little messy, and it did not seem worth */ 1793 /* all the mucking with header files. so, we create a routine much */ 1794 /* like calcualte_confidence, which just returns the mean values. */ 1795 /* raj 11/94 */ 1796 1797 retrieve_confident_values(&elapsed_time, 1798 &thruput, 1799 &local_cpu_utilization, 1800 &remote_cpu_utilization, 1801 &local_service_demand, 1802 &remote_service_demand); 1803 1804 /* We are now ready to print all the information. If the user */ 1805 /* has specified zero-level verbosity, we will just print the */ 1806 /* local service demand, or the remote service demand. If the */ 1807 /* user has requested verbosity level 1, he will get the basic */ 1808 /* "streamperf" numbers. If the user has specified a verbosity */ 1809 /* of greater than 1, we will display a veritable plethora of */ 1810 /* background information from outside of this block as it it */ 1811 /* not cpu_measurement specific... */ 1812 1813 if (confidence < 0) { 1814 /* we did not hit confidence, but were we asked to look for it? */ 1815 if (iteration_max > 1) { 1816 display_confidence(); 1817 } 1818 } 1819 1820 if (local_cpu_usage || remote_cpu_usage) { 1821 local_cpu_method = format_cpu_method(cpu_method); 1822 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 1823 1824 switch (verbosity) { 1825 case 0: 1826 if (local_cpu_usage) { 1827 fprintf(where, 1828 cpu_fmt_0, 1829 local_service_demand, 1830 local_cpu_method, 1831 ((print_headers) || 1832 (result_brand == NULL)) ? "" : result_brand); 1833 } 1834 else { 1835 fprintf(where, 1836 cpu_fmt_0, 1837 remote_service_demand, 1838 remote_cpu_method, 1839 ((print_headers) || 1840 (result_brand == NULL)) ? "" : result_brand); 1841 } 1842 break; 1843 case 1: 1844 case 2: 1845 if (print_headers) { 1846 fprintf(where, 1847 cpu_title, 1848 format_units(), 1849 local_cpu_method, 1850 remote_cpu_method); 1851 } 1852 1853 fprintf(where, 1854 cpu_fmt_1, /* the format string */ 1855 rsr_size, /* remote recvbuf size */ 1856 lss_size, /* local sendbuf size */ 1857 send_size, /* how large were the sends */ 1858 elapsed_time, /* how long was the test */ 1859 thruput, /* what was the xfer rate */ 1860 local_cpu_utilization, /* local cpu */ 1861 remote_cpu_utilization, /* remote cpu */ 1862 local_service_demand, /* local service demand */ 1863 remote_service_demand, /* remote service demand */ 1864 ((print_headers) || 1865 (result_brand == NULL)) ? "" : result_brand); 1866 break; 1867 } 1868 } 1869 else { 1870 /* The tester did not wish to measure service demand. */ 1871 1872 switch (verbosity) { 1873 case 0: 1874 fprintf(where, 1875 tput_fmt_0, 1876 thruput, 1877 ((print_headers) || 1878 (result_brand == NULL)) ? "" : result_brand); 1879 break; 1880 case 1: 1881 case 2: 1882 if (print_headers) { 1883 fprintf(where,tput_title,format_units()); 1884 } 1885 fprintf(where, 1886 tput_fmt_1, /* the format string */ 1887 rsr_size, /* remote recvbuf size */ 1888 lss_size, /* local sendbuf size */ 1889 send_size, /* how large were the sends */ 1890 elapsed_time, /* how long did it take */ 1891 thruput, /* how fast did it go */ 1892 ((print_headers) || 1893 (result_brand == NULL)) ? "" : result_brand); 1894 break; 1895 } 1896 } 1897 1898 /* it would be a good thing to include information about some of the */ 1899 /* other parameters that may have been set for this test, but at the */ 1900 /* moment, I do not wish to figure-out all the formatting, so I will */ 1901 /* just put this comment here to help remind me that it is something */ 1902 /* that should be done at a later time. */ 1903 1904 if (verbosity > 1) { 1905 /* The user wanted to know it all, so we will give it to him. */ 1906 /* This information will include as much as we can find about */ 1907 /* TCP statistics, the alignments of the sends and receives */ 1908 /* and all that sort of rot... */ 1909 1910 /* this stuff needs to be worked-out in the presence of confidence */ 1911 /* intervals and multiple iterations of the test... raj 11/94 */ 1912 1913 fprintf(where, 1914 ksink_fmt, 1915 "Bytes", 1916 "Bytes", 1917 "Bytes", 1918 local_send_align, 1919 remote_recv_align, 1920 local_send_offset, 1921 remote_recv_offset, 1922 bytes_sent, 1923 bytes_sent / (double)nummessages, 1924 nummessages, 1925 bytes_sent / (double)tcp_stream_result->recv_calls, 1926 tcp_stream_result->recv_calls); 1927 fprintf(where, 1928 ksink_fmt2, 1929 tcp_mss); 1930 fflush(where); 1931 #ifdef WANT_HISTOGRAM 1932 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 1933 fflush(where); 1934 HIST_report(time_hist); 1935 #endif /* WANT_HISTOGRAM */ 1936 } 1937 1938 } 1939 1940 1941 1943 /* This routine implements the netperf-side TCP unidirectional data 1944 transfer test (a.k.a. stream) for the sockets interface where the 1945 data flow is from the netserver to the netperf. It receives its 1946 parameters via global variables from the shell and writes its 1947 output to the standard output. */ 1948 1949 1950 void 1951 send_tcp_maerts(char remote_host[]) 1952 { 1953 1954 char *tput_title = "\ 1955 Recv Send Send \n\ 1956 Socket Socket Message Elapsed \n\ 1957 Size Size Size Time Throughput \n\ 1958 bytes bytes bytes secs. %s/sec \n\n"; 1959 1960 char *tput_fmt_0 = 1961 "%7.2f %s\n"; 1962 1963 char *tput_fmt_1 = 1964 "%6d %6d %6d %-6.2f %7.2f %s \n"; 1965 1966 char *cpu_title = "\ 1967 Recv Send Send Utilization Service Demand\n\ 1968 Socket Socket Message Elapsed Send Recv Send Recv\n\ 1969 Size Size Size Time Throughput local remote local remote\n\ 1970 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 1971 1972 char *cpu_fmt_0 = 1973 "%6.3f %c %s\n"; 1974 1975 char *cpu_fmt_1 = 1976 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 1977 1978 char *ksink_fmt = "\n\ 1979 Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\ 1980 Local Remote Local Remote Xfered Per Per\n\ 1981 Recv Send Recv Send Recv (avg) Send (avg)\n\ 1982 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 1983 1984 char *ksink_fmt2 = "\n\ 1985 Maximum\n\ 1986 Segment\n\ 1987 Size (bytes)\n\ 1988 %6d\n"; 1989 1990 1991 float elapsed_time; 1992 1993 /* what we want is to have a buffer space that is at least one */ 1994 /* recv-size greater than our recv window. this will insure that we */ 1995 /* are never trying to re-use a buffer that may still be in the hands */ 1996 /* of the transport. This buffer will be malloc'd after we have found */ 1997 /* the size of the local senc socket buffer. We will want to deal */ 1998 /* with alignment and offset concerns as well. */ 1999 2000 struct ring_elt *recv_ring; 2001 2002 int len; 2003 unsigned int nummessages = 0; 2004 SOCKET recv_socket; 2005 int bytes_remaining; 2006 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 2007 2008 /* with links like fddi, one can recv > 32 bits worth of bytes */ 2009 /* during a test... ;-) at some point, this should probably become a */ 2010 /* 64bit integral type, but those are not entirely common yet */ 2011 double bytes_sent = 0.0; 2012 unsigned long long local_bytes_recvd = 0; 2013 2014 float local_cpu_utilization; 2015 float local_service_demand; 2016 float remote_cpu_utilization; 2017 float remote_service_demand; 2018 2019 double thruput; 2020 2021 struct addrinfo *remote_res; 2022 struct addrinfo *local_res; 2023 2024 struct tcp_maerts_request_struct *tcp_maerts_request; 2025 struct tcp_maerts_response_struct *tcp_maerts_response; 2026 struct tcp_maerts_results_struct *tcp_maerts_result; 2027 2028 tcp_maerts_request = 2029 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data; 2030 tcp_maerts_response = 2031 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data; 2032 tcp_maerts_result = 2033 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data; 2034 2035 #ifdef WANT_HISTOGRAM 2036 if (verbosity > 1) { 2037 time_hist = HIST_new(); 2038 } 2039 #endif /* WANT_HISTOGRAM */ 2040 /* since we are now disconnected from the code that established the */ 2041 /* control socket, and since we want to be able to use different */ 2042 /* protocols and such, we are passed the name of the remote host and */ 2043 /* must turn that into the test specific addressing information. */ 2044 2045 complete_addrinfos(&remote_res, 2046 &local_res, 2047 remote_host, 2048 SOCK_STREAM, 2049 IPPROTO_TCP, 2050 0); 2051 2052 if ( print_headers ) { 2053 print_top_test_header("TCP MAERTS TEST",local_res,remote_res); 2054 } 2055 2056 recv_ring = NULL; 2057 confidence_iteration = 1; 2058 init_stat(); 2059 2060 /* we have a great-big while loop which controls the number of times */ 2061 /* we run a particular test. this is for the calculation of a */ 2062 /* confidence interval (I really should have stayed awake during */ 2063 /* probstats :). If the user did not request confidence measurement */ 2064 /* (no confidence is the default) then we will only go though the */ 2065 /* loop once. the confidence stuff originates from the folks at IBM */ 2066 2067 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 2068 (confidence_iteration <= iteration_min)) { 2069 2070 /* initialize a few counters. we have to remember that we might be */ 2071 /* going through the loop more than once. */ 2072 2073 nummessages = 0; 2074 bytes_sent = 0.0; 2075 times_up = 0; 2076 2077 /*set up the data socket */ 2078 recv_socket = create_data_socket(local_res); 2079 2080 if (recv_socket == INVALID_SOCKET){ 2081 perror("netperf: send_tcp_maerts: tcp stream data socket"); 2082 exit(1); 2083 } 2084 2085 if (debug) { 2086 fprintf(where,"send_tcp_maerts: recv_socket obtained...\n"); 2087 } 2088 2089 /* at this point, we have either retrieved the socket buffer sizes, */ 2090 /* or have tried to set them, so now, we may want to set the recv */ 2091 /* size based on that (because the user either did not use a -m */ 2092 /* option, or used one with an argument of 0). If the socket buffer */ 2093 /* size is not available, we will set the recv size to 4KB - no */ 2094 /* particular reason, just arbitrary... */ 2095 if (recv_size == 0) { 2096 if (lsr_size > 0) { 2097 recv_size = lsr_size; 2098 } 2099 else { 2100 recv_size = 4096; 2101 } 2102 } 2103 2104 /* set-up the data buffer ring with the requested alignment and offset. */ 2105 /* note also that we have allocated a quantity */ 2106 /* of memory that is at least one recv-size greater than our socket */ 2107 /* buffer size. We want to be sure that there are at least two */ 2108 /* buffers allocated - this can be a bit of a problem when the */ 2109 /* recv_size is bigger than the socket size, so we must check... the */ 2110 /* user may have wanted to explicitly set the "width" of our recv */ 2111 /* buffers, we should respect that wish... */ 2112 if (recv_width == 0) { 2113 recv_width = (lsr_size/recv_size) + 1; 2114 if (recv_width == 1) recv_width++; 2115 } 2116 2117 if (recv_ring == NULL) { 2118 /* only allocate the recv ring once. this is a networking test, */ 2119 /* not a memory allocation test. this way, we do not need a */ 2120 /* deallocate_buffer_ring() routine, and I don't feel like */ 2121 /* writing one anyway :) raj 11/94 */ 2122 recv_ring = allocate_buffer_ring(recv_width, 2123 recv_size, 2124 local_recv_align, 2125 local_recv_offset); 2126 } 2127 2128 /* If the user has requested cpu utilization measurements, we must */ 2129 /* calibrate the cpu(s). We will perform this task within the tests */ 2130 /* themselves. If the user has specified the cpu rate, then */ 2131 /* calibrate_local_cpu will return rather quickly as it will have */ 2132 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 2133 /* all the "normal" calibration stuff and return the rate back. */ 2134 2135 if (local_cpu_usage) { 2136 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 2137 } 2138 2139 if (!no_control) { 2140 /* Tell the remote end to do a listen. The server alters the 2141 socket paramters on the other side at this point, hence the 2142 reason for all the values being passed in the setup 2143 message. If the user did not specify any of the parameters, 2144 they will be passed as 0, which will indicate to the remote 2145 that no changes beyond the system's default should be 2146 used. Alignment is the exception, it will default to 1, which 2147 will be no alignment alterations. */ 2148 2149 netperf_request.content.request_type = DO_TCP_MAERTS; 2150 tcp_maerts_request->send_buf_size = rss_size_req; 2151 tcp_maerts_request->recv_buf_size = rsr_size_req; 2152 tcp_maerts_request->send_size = send_size; 2153 tcp_maerts_request->no_delay = rem_nodelay; 2154 tcp_maerts_request->send_alignment = remote_send_align; 2155 tcp_maerts_request->send_offset = remote_send_offset; 2156 tcp_maerts_request->measure_cpu = remote_cpu_usage; 2157 tcp_maerts_request->cpu_rate = remote_cpu_rate; 2158 if (test_time) { 2159 tcp_maerts_request->test_length = test_time; 2160 } 2161 else { 2162 tcp_maerts_request->test_length = test_bytes; 2163 } 2164 tcp_maerts_request->so_rcvavoid = rem_rcvavoid; 2165 tcp_maerts_request->so_sndavoid = rem_sndavoid; 2166 #ifdef DIRTY 2167 tcp_maerts_request->dirty_count = rem_dirty_count; 2168 tcp_maerts_request->clean_count = rem_clean_count; 2169 #endif /* DIRTY */ 2170 tcp_maerts_request->port = atoi(remote_data_port); 2171 tcp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family); 2172 if (debug > 1) { 2173 fprintf(where, 2174 "netperf: send_tcp_maerts: requesting TCP maerts test\n"); 2175 } 2176 2177 send_request(); 2178 2179 /* The response from the remote will contain all of the relevant 2180 socket parameters for this test type. We will put them back 2181 into the variables here so they can be displayed if desired. 2182 The remote will have calibrated CPU if necessary, and will 2183 have done all the needed set-up we will have calibrated the 2184 cpu locally before sending the request, and will grab the 2185 counter value right after the connect returns. The remote 2186 will grab the counter right after the accept call. This saves 2187 the hassle of extra messages being sent for the TCP 2188 tests. */ 2189 2190 recv_response(); 2191 2192 if (!netperf_response.content.serv_errno) { 2193 if (debug) 2194 fprintf(where,"remote listen done.\n"); 2195 rsr_size = tcp_maerts_response->recv_buf_size; 2196 rss_size = tcp_maerts_response->send_buf_size; 2197 rem_nodelay = tcp_maerts_response->no_delay; 2198 remote_cpu_usage= tcp_maerts_response->measure_cpu; 2199 remote_cpu_rate = tcp_maerts_response->cpu_rate; 2200 send_size = tcp_maerts_response->send_size; 2201 2202 /* we have to make sure that the server port number is in 2203 network order */ 2204 set_port_number(remote_res, 2205 (short)tcp_maerts_response->data_port_number); 2206 rem_rcvavoid = tcp_maerts_response->so_rcvavoid; 2207 rem_sndavoid = tcp_maerts_response->so_sndavoid; 2208 } 2209 else { 2210 Set_errno(netperf_response.content.serv_errno); 2211 fprintf(where, 2212 "netperf: remote error %d", 2213 netperf_response.content.serv_errno); 2214 perror(""); 2215 fflush(where); 2216 2217 exit(1); 2218 } 2219 } 2220 2221 #ifdef WANT_DEMO 2222 DEMO_STREAM_SETUP(lsr_size,rss_size) 2223 #endif 2224 2225 /*Connect up to the remote port on the data socket */ 2226 if (connect(recv_socket, 2227 remote_res->ai_addr, 2228 remote_res->ai_addrlen) == INVALID_SOCKET){ 2229 perror("netperf: send_tcp_maerts: data socket connect failed"); 2230 exit(1); 2231 } 2232 2233 /* Data Socket set-up is finished. If there were problems, either */ 2234 /* the connect would have failed, or the previous response would */ 2235 /* have indicated a problem. I failed to see the value of the */ 2236 /* extra message after the accept on the remote. If it failed, */ 2237 /* we'll see it here. If it didn't, we might as well start pumping */ 2238 /* data. */ 2239 2240 /* Set-up the test end conditions. For a maerts test, they can be */ 2241 /* either time or byte-count based. */ 2242 2243 if (test_time) { 2244 /* The user wanted to end the test after a period of time. */ 2245 times_up = 0; 2246 bytes_remaining = 0; 2247 /* in previous revisions, we had the same code repeated throught */ 2248 /* all the test suites. this was unnecessary, and meant more */ 2249 /* work for me when I wanted to switch to POSIX signals, so I */ 2250 /* have abstracted this out into a routine in netlib.c. if you */ 2251 /* are experiencing signal problems, you might want to look */ 2252 /* there. raj 11/94 */ 2253 if (!no_control) { 2254 /* this is a netperf to netserver test, netserver will close 2255 to tell us the test is over, so use PAD_TIME to avoid 2256 causing the netserver fits. */ 2257 start_timer(test_time + PAD_TIME); 2258 } 2259 else { 2260 /* this is a netperf to data source test, no PAD_TIME */ 2261 start_timer(test_time); 2262 } 2263 } 2264 else { 2265 /* The tester wanted to recv a number of bytes. we don't do that 2266 in a TCP_MAERTS test. sorry. raj 2002-06-21 */ 2267 printf("netperf: send_tcp_maerts: test must be timed\n"); 2268 exit(1); 2269 } 2270 2271 /* The cpu_start routine will grab the current time and possibly */ 2272 /* value of the idle counter for later use in measuring cpu */ 2273 /* utilization and/or service demand and thruput. */ 2274 2275 cpu_start(local_cpu_usage); 2276 2277 #ifdef WANT_INTERVALS 2278 INTERVALS_INIT(); 2279 #endif /* WANT_INTERVALS */ 2280 2281 /* before we start, initialize a few variables */ 2282 2283 #ifdef WANT_DEMO 2284 if (demo_mode) { 2285 HIST_timestamp(demo_one_ptr); 2286 } 2287 #endif 2288 2289 /* the test will continue until we either get a zero-byte recv() 2290 on the socket or our failsafe timer expires. most of the time 2291 we trust that we get a zero-byte recieve from the socket. raj 2292 2002-06-21 */ 2293 2294 #ifdef WANT_HISTOGRAM 2295 if (verbosity > 1) { 2296 /* timestamp just before we go into recv and then again just 2297 after we come out raj 8/94 */ 2298 /* but only if we are actually going to display a histogram. raj 2299 2006-02-07 */ 2300 HIST_timestamp(&time_one); 2301 } 2302 #endif /* WANT_HISTOGRAM */ 2303 2304 while ((!times_up) && (len=recv(recv_socket, 2305 recv_ring->buffer_ptr, 2306 recv_size, 2307 0)) > 0 ) { 2308 2309 #ifdef WANT_HISTOGRAM 2310 if (verbosity > 1) { 2311 /* timestamp the exit from the recv call and update the histogram */ 2312 HIST_timestamp(&time_two); 2313 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 2314 } 2315 #endif /* WANT_HISTOGRAM */ 2316 2317 #ifdef DIRTY 2318 access_buffer(recv_ring->buffer_ptr, 2319 recv_size, 2320 loc_dirty_count, 2321 loc_clean_count); 2322 #endif /* DIRTY */ 2323 2324 #ifdef WANT_DEMO 2325 DEMO_STREAM_INTERVAL(len); 2326 #endif 2327 2328 #ifdef WANT_INTERVALS 2329 INTERVALS_WAIT(); 2330 #endif /* WANT_INTERVALS */ 2331 2332 /* now we want to move our pointer to the next position in the */ 2333 /* data buffer...we may also want to wrap back to the "beginning" */ 2334 /* of the bufferspace, so we will mod the number of messages sent */ 2335 /* by the recv width, and use that to calculate the offset to add */ 2336 /* to the base pointer. */ 2337 nummessages++; 2338 recv_ring = recv_ring->next; 2339 if (bytes_remaining) { 2340 bytes_remaining -= len; 2341 } 2342 2343 local_bytes_recvd += len; 2344 2345 #ifdef WANT_HISTOGRAM 2346 if (verbosity > 1) { 2347 /* make sure we timestamp just before we go into recv */ 2348 /* raj 2004-06-15 */ 2349 HIST_timestamp(&time_one); 2350 } 2351 #endif /* WANT_HISTOGRAM */ 2352 2353 } 2354 2355 /* an EINTR is to be expected when this is a no_control test */ 2356 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) { 2357 perror("send_tcp_maerts: data recv error"); 2358 printf("len was %d\n",len); 2359 exit(1); 2360 } 2361 2362 /* if we get here, it must mean we had a recv return of 0 before 2363 the watchdog timer expired, or the watchdog timer expired and 2364 this was a no_control test */ 2365 2366 /* The test is over. Flush the buffers to the remote end. We do a 2367 graceful release to tell the remote we have all the data. */ 2368 2369 /* but first, if the verbosity is greater than 1, find-out what */ 2370 /* the TCP maximum segment_size was (if possible) */ 2371 if (verbosity > 1) { 2372 tcp_mss = -1; 2373 get_tcp_info(recv_socket,&tcp_mss); 2374 } 2375 2376 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) { 2377 perror("netperf: cannot shutdown tcp maerts socket"); 2378 exit(1); 2379 } 2380 2381 stop_timer(); 2382 2383 /* this call will always give us the local elapsed time for the 2384 test, and will also store-away the necessaries for cpu 2385 utilization */ 2386 2387 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 2388 /* measured and how */ 2389 /* long did we really */ 2390 /* run? */ 2391 2392 /* we are finished with the socket, so close it to prevent hitting */ 2393 /* the limit on maximum open files. */ 2394 2395 close(recv_socket); 2396 2397 if (!no_control) { 2398 /* Get the statistics from the remote end. The remote will have 2399 calculated service demand and all those interesting 2400 things. If it wasn't supposed to care, it will return obvious 2401 values. */ 2402 2403 recv_response(); 2404 if (!netperf_response.content.serv_errno) { 2405 if (debug) 2406 fprintf(where,"remote results obtained\n"); 2407 } 2408 else { 2409 Set_errno(netperf_response.content.serv_errno); 2410 fprintf(where, 2411 "netperf: remote error %d", 2412 netperf_response.content.serv_errno); 2413 perror(""); 2414 fflush(where); 2415 2416 exit(1); 2417 } 2418 2419 /* We now calculate what our thruput was for the test. In the 2420 future, we may want to include a calculation of the thruput 2421 measured by the remote, but it should be the case that for a 2422 TCP maerts test, that the two numbers should be *very* 2423 close... We calculate bytes_sent regardless of the way the 2424 test length was controlled. If it was time, we needed to, 2425 and if it was by bytes, the user may have specified a number 2426 of bytes that wasn't a multiple of the recv_size, so we 2427 really didn't recv what he asked for ;-) */ 2428 2429 bytes_sent = ntohd(tcp_maerts_result->bytes_sent); 2430 } 2431 else { 2432 bytes_sent = (double)local_bytes_recvd; 2433 } 2434 2435 2436 thruput = calc_thruput(bytes_sent); 2437 2438 if (local_cpu_usage || remote_cpu_usage) { 2439 /* We must now do a little math for service demand and cpu */ 2440 /* utilization for the system(s) */ 2441 /* Of course, some of the information might be bogus because */ 2442 /* there was no idle counter in the kernel(s). We need to make */ 2443 /* a note of this for the user's benefit...*/ 2444 if (local_cpu_usage) { 2445 2446 local_cpu_utilization = calc_cpu_util(0.0); 2447 local_service_demand = calc_service_demand(bytes_sent, 2448 0.0, 2449 0.0, 2450 0); 2451 } 2452 else { 2453 local_cpu_utilization = (float) -1.0; 2454 local_service_demand = (float) -1.0; 2455 } 2456 2457 if (remote_cpu_usage) { 2458 2459 remote_cpu_utilization = tcp_maerts_result->cpu_util; 2460 remote_service_demand = calc_service_demand(bytes_sent, 2461 0.0, 2462 remote_cpu_utilization, 2463 tcp_maerts_result->num_cpus); 2464 } 2465 else { 2466 remote_cpu_utilization = (float) -1.0; 2467 remote_service_demand = (float) -1.0; 2468 } 2469 } 2470 else { 2471 /* we were not measuring cpu, for the confidence stuff, we */ 2472 /* should make it -1.0 */ 2473 local_cpu_utilization = (float) -1.0; 2474 local_service_demand = (float) -1.0; 2475 remote_cpu_utilization = (float) -1.0; 2476 remote_service_demand = (float) -1.0; 2477 } 2478 2479 /* at this point, we want to calculate the confidence information. */ 2480 /* if debugging is on, calculate_confidence will print-out the */ 2481 /* parameters we pass it */ 2482 2483 calculate_confidence(confidence_iteration, 2484 elapsed_time, 2485 thruput, 2486 local_cpu_utilization, 2487 remote_cpu_utilization, 2488 local_service_demand, 2489 remote_service_demand); 2490 2491 2492 confidence_iteration++; 2493 } 2494 2495 /* at this point, we have finished making all the runs that we */ 2496 /* will be making. so, we should extract what the calcuated values */ 2497 /* are for all the confidence stuff. we could make the values */ 2498 /* global, but that seemed a little messy, and it did not seem worth */ 2499 /* all the mucking with header files. so, we create a routine much */ 2500 /* like calcualte_confidence, which just returns the mean values. */ 2501 /* raj 11/94 */ 2502 2503 retrieve_confident_values(&elapsed_time, 2504 &thruput, 2505 &local_cpu_utilization, 2506 &remote_cpu_utilization, 2507 &local_service_demand, 2508 &remote_service_demand); 2509 2510 /* We are now ready to print all the information. If the user */ 2511 /* has specified zero-level verbosity, we will just print the */ 2512 /* local service demand, or the remote service demand. If the */ 2513 /* user has requested verbosity level 1, he will get the basic */ 2514 /* "streamperf" numbers. If the user has specified a verbosity */ 2515 /* of greater than 1, we will display a veritable plethora of */ 2516 /* background information from outside of this block as it it */ 2517 /* not cpu_measurement specific... */ 2518 2519 if (confidence < 0) { 2520 /* we did not hit confidence, but were we asked to look for it? */ 2521 if (iteration_max > 1) { 2522 display_confidence(); 2523 } 2524 } 2525 2526 if (local_cpu_usage || remote_cpu_usage) { 2527 local_cpu_method = format_cpu_method(cpu_method); 2528 remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method); 2529 2530 switch (verbosity) { 2531 case 0: 2532 if (local_cpu_usage) { 2533 fprintf(where, 2534 cpu_fmt_0, 2535 local_service_demand, 2536 local_cpu_method, 2537 ((print_headers) || 2538 (result_brand == NULL)) ? "" : result_brand); 2539 } 2540 else { 2541 fprintf(where, 2542 cpu_fmt_0, 2543 remote_service_demand, 2544 remote_cpu_method, 2545 ((print_headers) || 2546 (result_brand == NULL)) ? "" : result_brand); 2547 } 2548 break; 2549 case 1: 2550 case 2: 2551 if (print_headers) { 2552 fprintf(where, 2553 cpu_title, 2554 format_units(), 2555 local_cpu_method, 2556 remote_cpu_method); 2557 } 2558 2559 fprintf(where, 2560 cpu_fmt_1, /* the format string */ 2561 rsr_size, /* remote recvbuf size */ 2562 lss_size, /* local sendbuf size */ 2563 send_size, /* how large were the recvs */ 2564 elapsed_time, /* how long was the test */ 2565 thruput, /* what was the xfer rate */ 2566 local_cpu_utilization, /* local cpu */ 2567 remote_cpu_utilization, /* remote cpu */ 2568 local_service_demand, /* local service demand */ 2569 remote_service_demand, /* remote service demand */ 2570 ((print_headers) || 2571 (result_brand == NULL)) ? "" : result_brand); 2572 break; 2573 } 2574 } 2575 else { 2576 /* The tester did not wish to measure service demand. */ 2577 2578 switch (verbosity) { 2579 case 0: 2580 fprintf(where, 2581 tput_fmt_0, 2582 thruput, 2583 ((print_headers) || 2584 (result_brand == NULL)) ? "" : result_brand); 2585 break; 2586 case 1: 2587 case 2: 2588 if (print_headers) { 2589 fprintf(where,tput_title,format_units()); 2590 } 2591 fprintf(where, 2592 tput_fmt_1, /* the format string */ 2593 lsr_size, /* local recvbuf size */ 2594 rss_size, /* remot sendbuf size */ 2595 send_size, /* how large were the recvs */ 2596 elapsed_time, /* how long did it take */ 2597 thruput, /* how fast did it go */ 2598 ((print_headers) || 2599 (result_brand == NULL)) ? "" : result_brand); 2600 break; 2601 } 2602 } 2603 2604 /* it would be a good thing to include information about some of the */ 2605 /* other parameters that may have been set for this test, but at the */ 2606 /* moment, I do not wish to figure-out all the formatting, so I will */ 2607 /* just put this comment here to help remind me that it is something */ 2608 /* that should be done at a later time. */ 2609 2610 if (verbosity > 1) { 2611 /* The user wanted to know it all, so we will give it to him. */ 2612 /* This information will include as much as we can find about */ 2613 /* TCP statistics, the alignments of the sends and receives */ 2614 /* and all that sort of rot... */ 2615 2616 /* this stuff needs to be worked-out in the presence of confidence */ 2617 /* intervals and multiple iterations of the test... raj 11/94 */ 2618 2619 fprintf(where, 2620 ksink_fmt, 2621 "Bytes", 2622 "Bytes", 2623 "Bytes", 2624 local_recv_align, 2625 remote_recv_align, 2626 local_recv_offset, 2627 remote_recv_offset, 2628 bytes_sent, 2629 bytes_sent / (double)nummessages, 2630 nummessages, 2631 bytes_sent / (double)tcp_maerts_result->send_calls, 2632 tcp_maerts_result->send_calls); 2633 fprintf(where, 2634 ksink_fmt2, 2635 tcp_mss); 2636 fflush(where); 2637 #ifdef WANT_HISTOGRAM 2638 fprintf(where,"\n\nHistogram of time spent in recv() call.\n"); 2639 fflush(where); 2640 HIST_report(time_hist); 2641 #endif /* WANT_HISTOGRAM */ 2642 } 2643 2644 } 2645 2646 2647 2649 #ifdef HAVE_ICSC_EXS 2650 2651 #include <sys/exs.h> 2652 2653 2654 /* This routine implements the TCP unidirectional data transfer test */ 2655 /* (a.k.a. stream) for the sockets interface. It receives its */ 2656 /* parameters via global variables from the shell and writes its */ 2657 /* output to the standard output. */ 2658 2659 void 2660 send_exs_tcp_stream(char remote_host[]) 2661 { 2662 2663 char *tput_title = "\ 2664 Recv Send Send \n\ 2665 Socket Socket Message Elapsed \n\ 2666 Size Size Size Time Throughput \n\ 2667 bytes bytes bytes secs. %s/sec \n\n"; 2668 2669 char *tput_fmt_0 = 2670 "%7.2f\n"; 2671 2672 char *tput_fmt_1 = 2673 "%6d %6d %6d %-6.2f %7.2f \n"; 2674 2675 char *cpu_title = "\ 2676 Recv Send Send Utilization Service Demand\n\ 2677 Socket Socket Message Elapsed Send Recv Send Recv\n\ 2678 Size Size Size Time Throughput local remote local remote\n\ 2679 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 2680 2681 char *cpu_fmt_0 = 2682 "%6.3f %c\n"; 2683 2684 char *cpu_fmt_1 = 2685 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 2686 2687 char *ksink_fmt = "\n\ 2688 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 2689 Local Remote Local Remote Xfered Per Per\n\ 2690 Send Recv Send Recv Send (avg) Recv (avg)\n\ 2691 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 2692 2693 char *ksink_fmt2 = "\n\ 2694 Maximum\n\ 2695 Segment\n\ 2696 Size (bytes)\n\ 2697 %6d\n"; 2698 2699 2700 float elapsed_time; 2701 2702 /* what we want is to have a buffer space that is at least one */ 2703 /* send-size greater than our send window. this will insure that we */ 2704 /* are never trying to re-use a buffer that may still be in the hands */ 2705 /* of the transport. This buffer will be malloc'd after we have found */ 2706 /* the size of the local senc socket buffer. We will want to deal */ 2707 /* with alignment and offset concerns as well. */ 2708 2709 struct ring_elt *send_ring; 2710 2711 int len; 2712 unsigned int nummessages = 0; 2713 SOCKET send_socket; 2714 int bytes_remaining; 2715 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 2716 2717 exs_mhandle_t exs_mhandle; 2718 exs_qhandle_t exs_qhandle; 2719 #define NETPERF_EXS_PENDING 16 2720 int exs_aio_pending; 2721 int exs_aio_eagain; 2722 int exs_aio_dequeued; 2723 int exs_aio_dequeuecnt; 2724 int exs_evtcnt; 2725 #define NETPERF_EXS_QSIZE 128 2726 exs_event_t exs_evtvec[NETPERF_EXS_QSIZE]; 2727 2728 /* with links like fddi, one can send > 32 bits worth of bytes */ 2729 /* during a test... ;-) at some point, this should probably become a */ 2730 /* 64bit integral type, but those are not entirely common yet */ 2731 2732 double bytes_sent = 0.0; 2733 2734 float local_cpu_utilization; 2735 float local_service_demand; 2736 float remote_cpu_utilization; 2737 float remote_service_demand; 2738 2739 double thruput; 2740 2741 struct addrinfo *remote_res; 2742 struct addrinfo *local_res; 2743 2744 struct tcp_stream_request_struct *tcp_stream_request; 2745 struct tcp_stream_response_struct *tcp_stream_response; 2746 struct tcp_stream_results_struct *tcp_stream_result; 2747 2748 tcp_stream_request = 2749 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 2750 tcp_stream_response = 2751 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 2752 tcp_stream_result = 2753 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 2754 2755 #if 0 /* def WANT_HISTOGRAM */ 2756 time_hist = HIST_new(); 2757 #endif /* WANT_HISTOGRAM */ 2758 /* since we are now disconnected from the code that established the */ 2759 /* control socket, and since we want to be able to use different */ 2760 /* protocols and such, we are passed the name of the remote host and */ 2761 /* must turn that into the test specific addressing information. */ 2762 2763 /* complete_addrinfos will either succede or exit the process */ 2764 complete_addrinfos(&remote_res, 2765 &local_res, 2766 remote_host, 2767 SOCK_STREAM, 2768 IPPROTO_TCP, 2769 0); 2770 2771 if ( print_headers ) { 2772 print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res); 2773 } 2774 2775 send_ring = NULL; 2776 confidence_iteration = 1; 2777 init_stat(); 2778 2779 /* initialize EXS API and create event queue */ 2780 if (exs_init (EXS_VERSION) == -1) { 2781 perror ("netperf: send_exs_tcp_stream: exs_init failed"); 2782 exit (1); 2783 } 2784 2785 if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) { 2786 perror ("netperf: send_exs_tcp_stream: exs_qcreate failed"); 2787 exit (1); 2788 } 2789 if (debug) { 2790 fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle); 2791 } 2792 2793 /* we have a great-big while loop which controls the number of times */ 2794 /* we run a particular test. this is for the calculation of a */ 2795 /* confidence interval (I really should have stayed awake during */ 2796 /* probstats :). If the user did not request confidence measurement */ 2797 /* (no confidence is the default) then we will only go though the */ 2798 /* loop once. the confidence stuff originates from the folks at IBM */ 2799 2800 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 2801 (confidence_iteration <= iteration_min)) { 2802 2803 /* initialize a few counters. we have to remember that we might be */ 2804 /* going through the loop more than once. */ 2805 2806 nummessages = 0; 2807 bytes_sent = 0.0; 2808 times_up = 0; 2809 2810 /*set up the data socket */ 2811 send_socket = create_data_socket(local_res); 2812 2813 if (send_socket == INVALID_SOCKET){ 2814 perror("netperf: send_tcp_stream: tcp stream data socket"); 2815 exit(1); 2816 } 2817 2818 if (debug) { 2819 fprintf(where,"send_tcp_stream: send_socket obtained...\n"); 2820 } 2821 2822 /* at this point, we have either retrieved the socket buffer sizes, */ 2823 /* or have tried to set them, so now, we may want to set the send */ 2824 /* size based on that (because the user either did not use a -m */ 2825 /* option, or used one with an argument of 0). If the socket buffer */ 2826 /* size is not available, we will set the send size to 4KB - no */ 2827 /* particular reason, just arbitrary... */ 2828 if (send_size == 0) { 2829 if (lss_size > 0) { 2830 send_size = lss_size; 2831 } 2832 else { 2833 send_size = 4096; 2834 } 2835 } 2836 2837 /* set-up the data buffer ring with the requested alignment and offset. */ 2838 /* note also that we have allocated a quantity */ 2839 /* of memory that is at least one send-size greater than our socket */ 2840 /* buffer size. We want to be sure that there are at least two */ 2841 /* buffers allocated - this can be a bit of a problem when the */ 2842 /* send_size is bigger than the socket size, so we must check... the */ 2843 /* user may have wanted to explicitly set the "width" of our send */ 2844 /* buffers, we should respect that wish... */ 2845 if (send_width == 0) { 2846 send_width = (lss_size/send_size) + 1; 2847 if (send_width == 1) send_width++; 2848 } 2849 2850 if (send_ring == NULL) { 2851 /* only allocate the send ring once. this is a networking test, */ 2852 /* not a memory allocation test. this way, we do not need a */ 2853 /* deallocate_buffer_ring() routine, and I don't feel like */ 2854 /* writing one anyway :) raj 11/94 */ 2855 send_ring = allocate_exs_buffer_ring(send_width, 2856 send_size, 2857 local_send_align, 2858 local_send_offset, 2859 &exs_mhandle); 2860 } 2861 2862 /* If the user has requested cpu utilization measurements, we must */ 2863 /* calibrate the cpu(s). We will perform this task within the tests */ 2864 /* themselves. If the user has specified the cpu rate, then */ 2865 /* calibrate_local_cpu will return rather quickly as it will have */ 2866 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 2867 /* all the "normal" calibration stuff and return the rate back. */ 2868 2869 if (local_cpu_usage) { 2870 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 2871 } 2872 2873 /* Tell the remote end to do a listen. The server alters the socket */ 2874 /* paramters on the other side at this point, hence the reason for */ 2875 /* all the values being passed in the setup message. If the user did */ 2876 /* not specify any of the parameters, they will be passed as 0, which */ 2877 /* will indicate to the remote that no changes beyond the system's */ 2878 /* default should be used. Alignment is the exception, it will */ 2879 /* default to 1, which will be no alignment alterations. */ 2880 2881 netperf_request.content.request_type = DO_TCP_STREAM; 2882 tcp_stream_request->send_buf_size = rss_size_req; 2883 tcp_stream_request->recv_buf_size = rsr_size_req; 2884 tcp_stream_request->receive_size = recv_size; 2885 tcp_stream_request->no_delay = rem_nodelay; 2886 tcp_stream_request->recv_alignment = remote_recv_align; 2887 tcp_stream_request->recv_offset = remote_recv_offset; 2888 tcp_stream_request->measure_cpu = remote_cpu_usage; 2889 tcp_stream_request->cpu_rate = remote_cpu_rate; 2890 if (test_time) { 2891 tcp_stream_request->test_length = test_time; 2892 } 2893 else { 2894 tcp_stream_request->test_length = test_bytes; 2895 } 2896 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 2897 tcp_stream_request->so_sndavoid = rem_sndavoid; 2898 #ifdef DIRTY 2899 tcp_stream_request->dirty_count = rem_dirty_count; 2900 tcp_stream_request->clean_count = rem_clean_count; 2901 #endif /* DIRTY */ 2902 tcp_stream_request->port = atoi(remote_data_port); 2903 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 2904 if (debug > 1) { 2905 fprintf(where, 2906 "netperf: send_tcp_stream: requesting TCP stream test\n"); 2907 } 2908 2909 send_request(); 2910 2911 /* The response from the remote will contain all of the relevant */ 2912 /* socket parameters for this test type. We will put them back into */ 2913 /* the variables here so they can be displayed if desired. The */ 2914 /* remote will have calibrated CPU if necessary, and will have done */ 2915 /* all the needed set-up we will have calibrated the cpu locally */ 2916 /* before sending the request, and will grab the counter value right*/ 2917 /* after the connect returns. The remote will grab the counter right*/ 2918 /* after the accept call. This saves the hassle of extra messages */ 2919 /* being sent for the TCP tests. */ 2920 2921 recv_response(); 2922 2923 if (!netperf_response.content.serv_errno) { 2924 if (debug) 2925 fprintf(where,"remote listen done.\n"); 2926 rsr_size = tcp_stream_response->recv_buf_size; 2927 rss_size = tcp_stream_response->send_buf_size; 2928 rem_nodelay = tcp_stream_response->no_delay; 2929 remote_cpu_usage= tcp_stream_response->measure_cpu; 2930 remote_cpu_rate = tcp_stream_response->cpu_rate; 2931 2932 /* we have to make sure that the server port number is in */ 2933 /* network order */ 2934 set_port_number(remote_res,(short)tcp_stream_response->data_port_number); 2935 2936 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 2937 rem_sndavoid = tcp_stream_response->so_sndavoid; 2938 } 2939 else { 2940 Set_errno(netperf_response.content.serv_errno); 2941 fprintf(where, 2942 "netperf: remote error %d", 2943 netperf_response.content.serv_errno); 2944 perror(""); 2945 fflush(where); 2946 2947 exit(1); 2948 } 2949 2950 #if 0 /* def WANT_DEMO */ 2951 DEMO_STREAM_SETUP(lss_size,rsr_size) 2952 #endif 2953 2954 /*Connect up to the remote port on the data socket */ 2955 if (connect(send_socket, 2956 remote_res->ai_addr, 2957 remote_res->ai_addrlen) == INVALID_SOCKET){ 2958 perror("netperf: send_tcp_stream: data socket connect failed"); 2959 exit(1); 2960 } 2961 2962 /* Data Socket set-up is finished. If there were problems, either */ 2963 /* the connect would have failed, or the previous response would */ 2964 /* have indicated a problem. I failed to see the value of the */ 2965 /* extra message after the accept on the remote. If it failed, */ 2966 /* we'll see it here. If it didn't, we might as well start pumping */ 2967 /* data. */ 2968 2969 /* Set-up the test end conditions. For a stream test, they can be */ 2970 /* either time or byte-count based. */ 2971 2972 if (test_time) { 2973 /* The user wanted to end the test after a period of time. */ 2974 times_up = 0; 2975 bytes_remaining = 0; 2976 /* in previous revisions, we had the same code repeated throught */ 2977 /* all the test suites. this was unnecessary, and meant more */ 2978 /* work for me when I wanted to switch to POSIX signals, so I */ 2979 /* have abstracted this out into a routine in netlib.c. if you */ 2980 /* are experiencing signal problems, you might want to look */ 2981 /* there. raj 11/94 */ 2982 start_timer(test_time); 2983 } 2984 else { 2985 /* The tester wanted to send a number of bytes. */ 2986 bytes_remaining = test_bytes; 2987 times_up = 1; 2988 } 2989 2990 /* The cpu_start routine will grab the current time and possibly */ 2991 /* value of the idle counter for later use in measuring cpu */ 2992 /* utilization and/or service demand and thruput. */ 2993 2994 cpu_start(local_cpu_usage); 2995 2996 #if 0 /* def WANT_INTERVALS */ 2997 INTERVALS_INIT(); 2998 #endif /* WANT_INTERVALS */ 2999 3000 /* before we start, initialize a few variables */ 3001 3002 #if 0 /* def WANT_DEMO */ 3003 if (demo_mode) { 3004 HIST_timestamp(demo_one_ptr); 3005 } 3006 #endif 3007 3008 3009 /* We use an "OR" to control test execution. When the test is */ 3010 /* controlled by time, the byte count check will always return false. */ 3011 /* When the test is controlled by byte count, the time test will */ 3012 /* always return false. When the test is finished, the whole */ 3013 /* expression will go false and we will stop sending data. */ 3014 3015 exs_aio_pending = 0; 3016 exs_aio_eagain = 0; 3017 exs_aio_dequeuecnt = 0; 3018 3019 while ((!times_up) || (bytes_remaining > 0)) { 3020 3021 #ifdef DIRTY 3022 access_buffer(send_ring->buffer_ptr, 3023 send_size, 3024 loc_dirty_count, 3025 loc_clean_count); 3026 #endif /* DIRTY */ 3027 3028 #if 0 /* def WANT_HISTOGRAM */ 3029 /* timestamp just before we go into send and then again just after */ 3030 /* we come out raj 8/94 */ 3031 HIST_timestamp(&time_one); 3032 #endif /* WANT_HISTOGRAM */ 3033 3034 3035 /* post up to NETPERF_EXS_PENDING I/Os */ 3036 while ((exs_aio_pending < NETPERF_EXS_PENDING) && 3037 (exs_send (send_socket, send_ring->buffer_ptr, send_size, 3038 0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) { 3039 exs_aio_pending++; 3040 3041 /* now we want to move our pointer to the next 3042 position in the data buffer...we may also want to 3043 wrap back to the "beginning" of the bufferspace, so 3044 we will mod the number of messages sent by the send 3045 width, and use that to calculate the offset to add 3046 to the base pointer. */ 3047 3048 nummessages++; 3049 send_ring = send_ring->next; 3050 if (bytes_remaining) { 3051 bytes_remaining -= send_size; 3052 } 3053 } 3054 3055 /* check exs_send result */ 3056 if (exs_aio_pending < NETPERF_EXS_PENDING) { 3057 /* standard flow control case */ 3058 if (errno == EAGAIN) 3059 exs_aio_eagain++; 3060 /* case of times_up */ 3061 else if (errno == EINTR) 3062 break; 3063 /* strange, let's stop */ 3064 else { 3065 perror ("netperf: exs_send error"); 3066 exit (1); 3067 } 3068 } 3069 3070 /* dequeue events with "threshold" on 1/2 posted */ 3071 exs_aio_dequeued = 3072 exs_qdequeue (exs_qhandle, exs_evtvec, 3073 -(exs_aio_pending>>1), NULL); 3074 exs_aio_dequeuecnt++; 3075 3076 /* check exs_dequeue result */ 3077 if (exs_aio_dequeued < 0) { 3078 /* case of times_up */ 3079 if (errno == EINTR) 3080 break; 3081 /* strange, let's stop */ 3082 else { 3083 perror ("netperf: exs_send error"); 3084 exit (1); 3085 } 3086 } 3087 /* update number of pending I/Os */ 3088 else { 3089 exs_aio_pending -= exs_aio_dequeued; 3090 } 3091 3092 3093 #if 0 /* def WANT_HISTOGRAM */ 3094 /* timestamp the exit from the send call and update the histogram */ 3095 HIST_timestamp(&time_two); 3096 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 3097 #endif /* WANT_HISTOGRAM */ 3098 3099 #if 0 /* def WANT_DEMO */ 3100 DEMO_STREAM_INTERVAL(send_size); 3101 #endif 3102 3103 #if 0 /* def WANT_INTERVALS */ 3104 INTERVALS_WAIT(); 3105 #endif /* WANT_INTERVALS */ 3106 3107 } 3108 3109 /* Collect the last completion events */ 3110 exs_aio_dequeued = 3111 exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL); 3112 exs_aio_dequeuecnt++; 3113 /* check exs_dequeue result and update number of pending I/Os */ 3114 if (exs_aio_dequeued < 0) { 3115 perror ("netperf: exs_send error"); 3116 exit (1); 3117 } 3118 exs_aio_pending -= exs_aio_dequeued; 3119 3120 /* Display some async I/O debug info */ 3121 if (debug) { 3122 fprintf (where, "send_exs_tcp_stream: " 3123 "aio sent=%d eagain=%d dequeue=%d pending=%d\n", 3124 nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending); 3125 } 3126 3127 /* The test is over. Flush the buffers to the remote end. We do a */ 3128 /* graceful release to insure that all data has been taken by the */ 3129 /* remote. */ 3130 3131 /* but first, if the verbosity is greater than 1, find-out what */ 3132 /* the TCP maximum segment_size was (if possible) */ 3133 if (verbosity > 1) { 3134 tcp_mss = -1; 3135 get_tcp_info(send_socket,&tcp_mss); 3136 } 3137 3138 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 3139 perror("netperf: cannot shutdown tcp stream socket"); 3140 exit(1); 3141 } 3142 3143 /* hang a recv() off the socket to block until the remote has */ 3144 /* brought all the data up into the application. it will do a */ 3145 /* shutdown to cause a FIN to be sent our way. We will assume that */ 3146 /* any exit from the recv() call is good... raj 4/93 */ 3147 3148 recv(send_socket, send_ring->buffer_ptr, send_size, 0); 3149 3150 /* this call will always give us the elapsed time for the test, and */ 3151 /* will also store-away the necessaries for cpu utilization */ 3152 3153 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 3154 /* measured and how */ 3155 /* long did we really */ 3156 /* run? */ 3157 3158 /* we are finished with the socket, so close it to prevent hitting */ 3159 /* the limit on maximum open files. */ 3160 3161 close(send_socket); 3162 3163 /* Get the statistics from the remote end. The remote will have */ 3164 /* calculated service demand and all those interesting things. If it */ 3165 /* wasn't supposed to care, it will return obvious values. */ 3166 3167 recv_response(); 3168 if (!netperf_response.content.serv_errno) { 3169 if (debug) 3170 fprintf(where,"remote results obtained\n"); 3171 } 3172 else { 3173 Set_errno(netperf_response.content.serv_errno); 3174 fprintf(where, 3175 "netperf: remote error %d", 3176 netperf_response.content.serv_errno); 3177 perror(""); 3178 fflush(where); 3179 3180 exit(1); 3181 } 3182 3183 /* We now calculate what our thruput was for the test. In the future, */ 3184 /* we may want to include a calculation of the thruput measured by */ 3185 /* the remote, but it should be the case that for a TCP stream test, */ 3186 /* that the two numbers should be *very* close... We calculate */ 3187 /* bytes_sent regardless of the way the test length was controlled. */ 3188 /* If it was time, we needed to, and if it was by bytes, the user may */ 3189 /* have specified a number of bytes that wasn't a multiple of the */ 3190 /* send_size, so we really didn't send what he asked for ;-) */ 3191 3192 bytes_sent = ntohd(tcp_stream_result->bytes_received); 3193 3194 thruput = calc_thruput(bytes_sent); 3195 3196 if (local_cpu_usage || remote_cpu_usage) { 3197 /* We must now do a little math for service demand and cpu */ 3198 /* utilization for the system(s) */ 3199 /* Of course, some of the information might be bogus because */ 3200 /* there was no idle counter in the kernel(s). We need to make */ 3201 /* a note of this for the user's benefit...*/ 3202 if (local_cpu_usage) { 3203 3204 local_cpu_utilization = calc_cpu_util(0.0); 3205 local_service_demand = calc_service_demand(bytes_sent, 3206 0.0, 3207 0.0, 3208 0); 3209 } 3210 else { 3211 local_cpu_utilization = (float) -1.0; 3212 local_service_demand = (float) -1.0; 3213 } 3214 3215 if (remote_cpu_usage) { 3216 3217 remote_cpu_utilization = tcp_stream_result->cpu_util; 3218 remote_service_demand = calc_service_demand(bytes_sent, 3219 0.0, 3220 remote_cpu_utilization, 3221 tcp_stream_result->num_cpus); 3222 } 3223 else { 3224 remote_cpu_utilization = (float) -1.0; 3225 remote_service_demand = (float) -1.0; 3226 } 3227 } 3228 else { 3229 /* we were not measuring cpu, for the confidence stuff, we */ 3230 /* should make it -1.0 */ 3231 local_cpu_utilization = (float) -1.0; 3232 local_service_demand = (float) -1.0; 3233 remote_cpu_utilization = (float) -1.0; 3234 remote_service_demand = (float) -1.0; 3235 } 3236 3237 /* at this point, we want to calculate the confidence information. */ 3238 /* if debugging is on, calculate_confidence will print-out the */ 3239 /* parameters we pass it */ 3240 3241 calculate_confidence(confidence_iteration, 3242 elapsed_time, 3243 thruput, 3244 local_cpu_utilization, 3245 remote_cpu_utilization, 3246 local_service_demand, 3247 remote_service_demand); 3248 3249 3250 confidence_iteration++; 3251 } 3252 3253 /* at this point, we have finished making all the runs that we */ 3254 /* will be making. so, we should extract what the calcuated values */ 3255 /* are for all the confidence stuff. we could make the values */ 3256 /* global, but that seemed a little messy, and it did not seem worth */ 3257 /* all the mucking with header files. so, we create a routine much */ 3258 /* like calcualte_confidence, which just returns the mean values. */ 3259 /* raj 11/94 */ 3260 3261 retrieve_confident_values(&elapsed_time, 3262 &thruput, 3263 &local_cpu_utilization, 3264 &remote_cpu_utilization, 3265 &local_service_demand, 3266 &remote_service_demand); 3267 3268 /* We are now ready to print all the information. If the user */ 3269 /* has specified zero-level verbosity, we will just print the */ 3270 /* local service demand, or the remote service demand. If the */ 3271 /* user has requested verbosity level 1, he will get the basic */ 3272 /* "streamperf" numbers. If the user has specified a verbosity */ 3273 /* of greater than 1, we will display a veritable plethora of */ 3274 /* background information from outside of this block as it it */ 3275 /* not cpu_measurement specific... */ 3276 3277 if (confidence < 0) { 3278 /* we did not hit confidence, but were we asked to look for it? */ 3279 if (iteration_max > 1) { 3280 display_confidence(); 3281 } 3282 } 3283 3284 if (local_cpu_usage || remote_cpu_usage) { 3285 local_cpu_method = format_cpu_method(cpu_method); 3286 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 3287 3288 switch (verbosity) { 3289 case 0: 3290 if (local_cpu_usage) { 3291 fprintf(where, 3292 cpu_fmt_0, 3293 local_service_demand, 3294 local_cpu_method); 3295 } 3296 else { 3297 fprintf(where, 3298 cpu_fmt_0, 3299 remote_service_demand, 3300 remote_cpu_method); 3301 } 3302 break; 3303 case 1: 3304 case 2: 3305 if (print_headers) { 3306 fprintf(where, 3307 cpu_title, 3308 format_units(), 3309 local_cpu_method, 3310 remote_cpu_method); 3311 } 3312 3313 fprintf(where, 3314 cpu_fmt_1, /* the format string */ 3315 rsr_size, /* remote recvbuf size */ 3316 lss_size, /* local sendbuf size */ 3317 send_size, /* how large were the sends */ 3318 elapsed_time, /* how long was the test */ 3319 thruput, /* what was the xfer rate */ 3320 local_cpu_utilization, /* local cpu */ 3321 remote_cpu_utilization, /* remote cpu */ 3322 local_service_demand, /* local service demand */ 3323 remote_service_demand); /* remote service demand */ 3324 break; 3325 } 3326 } 3327 else { 3328 /* The tester did not wish to measure service demand. */ 3329 3330 switch (verbosity) { 3331 case 0: 3332 fprintf(where, 3333 tput_fmt_0, 3334 thruput); 3335 break; 3336 case 1: 3337 case 2: 3338 if (print_headers) { 3339 fprintf(where,tput_title,format_units()); 3340 } 3341 fprintf(where, 3342 tput_fmt_1, /* the format string */ 3343 rsr_size, /* remote recvbuf size */ 3344 lss_size, /* local sendbuf size */ 3345 send_size, /* how large were the sends */ 3346 elapsed_time, /* how long did it take */ 3347 thruput);/* how fast did it go */ 3348 break; 3349 } 3350 } 3351 3352 /* it would be a good thing to include information about some of the */ 3353 /* other parameters that may have been set for this test, but at the */ 3354 /* moment, I do not wish to figure-out all the formatting, so I will */ 3355 /* just put this comment here to help remind me that it is something */ 3356 /* that should be done at a later time. */ 3357 3358 if (verbosity > 1) { 3359 /* The user wanted to know it all, so we will give it to him. */ 3360 /* This information will include as much as we can find about */ 3361 /* TCP statistics, the alignments of the sends and receives */ 3362 /* and all that sort of rot... */ 3363 3364 /* this stuff needs to be worked-out in the presence of confidence */ 3365 /* intervals and multiple iterations of the test... raj 11/94 */ 3366 3367 fprintf(where, 3368 ksink_fmt, 3369 "Bytes", 3370 "Bytes", 3371 "Bytes", 3372 local_send_align, 3373 remote_recv_align, 3374 local_send_offset, 3375 remote_recv_offset, 3376 bytes_sent, 3377 bytes_sent / (double)nummessages, 3378 nummessages, 3379 bytes_sent / (double)tcp_stream_result->recv_calls, 3380 tcp_stream_result->recv_calls); 3381 fprintf(where, 3382 ksink_fmt2, 3383 tcp_mss); 3384 fflush(where); 3385 #if 0 /* def WANT_HISTOGRAM */ 3386 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 3387 fflush(where); 3388 HIST_report(time_hist); 3389 #endif /* WANT_HISTOGRAM */ 3390 } 3391 3392 } 3393 3394 #endif /* HAVE_ICSC_EXS */ 3395 3396 3397 3399 #if defined(HAVE_SENDFILE) 3400 3401 #if defined(QUICK_SENDPATH) 3402 3403 /* 3404 * a temporary stub for the sendpath() system call 3405 * which is defined & implemented in the kernel 3406 * but which has no libc stub. 3407 */ 3408 #include <sys/types.h> 3409 #include <sys/scall_define.h> 3410 #include <sys/uio.h> 3411 3412 ssize_t 3413 sendpath(int s, char *path, off_t offset, size_t nbytes, 3414 const struct iovec *hdtrl, int flags) 3415 { 3416 return syscall(SYS_sendpath, s, path, offset, nbytes, hdtrl, flags); 3417 } 3418 #endif /* QUICK_SENDPATH */ 3419 3420 /* This routine implements the TCP unidirectional data transfer test 3421 (a.k.a. stream) for the sockets interface using the sendfile() 3422 system call - TCP_SENDFILE. It receives its parameters via global 3423 variables from the shell and writes its output to the standard 3424 output. Basically, this is the same test as the send_tcp_stream() 3425 logic and we even tell the remote to do a TCP_STREAM test since for 3426 all it knows, nothig is different. */ 3427 3428 void 3429 sendfile_tcp_stream(remote_host) 3430 char remote_host[]; 3431 { 3432 3433 char *tput_title = "\ 3434 Recv Send Send \n\ 3435 Socket Socket Message Elapsed \n\ 3436 Size Size Size Time Throughput \n\ 3437 bytes bytes bytes secs. %s/sec \n\n"; 3438 3439 char *tput_fmt_0 = 3440 "%7.2f\n"; 3441 3442 char *tput_fmt_1 = 3443 "%6d %6d %6d %-6.2f %7.2f \n"; 3444 3445 char *cpu_title = "\ 3446 Recv Send Send Utilization Service Demand\n\ 3447 Socket Socket Message Elapsed Send Recv Send Recv\n\ 3448 Size Size Size Time Throughput local remote local remote\n\ 3449 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 3450 3451 char *cpu_fmt_0 = 3452 "%6.3f %c\n"; 3453 char *cpu_fmt_1 = 3454 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 3455 3456 char *ksink_fmt = "\n\ 3457 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 3458 Local Remote Local Remote Xfered Per Per\n\ 3459 Send Recv Send Recv Send (avg) Recv (avg)\n\ 3460 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 3461 3462 char *ksink_fmt2 = "\n\ 3463 Maximum\n\ 3464 Segment\n\ 3465 Size (bytes)\n\ 3466 %6d\n"; 3467 3468 float elapsed_time; 3469 3470 /* what we want is to have a buffer space that is at least one */ 3471 /* send-size greater than our send window. this will insure that we */ 3472 /* are never trying to re-use a buffer that may still be in the hands */ 3473 /* of the transport. This buffer will be malloc'd after we have found */ 3474 /* the size of the local senc socket buffer. We will want to deal */ 3475 /* with alignment and offset concerns as well. */ 3476 3477 struct sendfile_ring_elt *send_ring; 3478 3479 int len; 3480 unsigned int nummessages = 0; 3481 SOCKET send_socket; 3482 int bytes_remaining; 3483 int tcp_mss = -1; /* possibly uninitialized on printf far below */ 3484 3485 /* with links like fddi, one can send > 32 bits worth of bytes */ 3486 /* during a test... ;-) at some point, this should probably become a */ 3487 /* 64bit integral type, but those are not entirely common yet */ 3488 double bytes_sent = 0.0; 3489 3490 float local_cpu_utilization; 3491 float local_service_demand; 3492 float remote_cpu_utilization; 3493 float remote_service_demand; 3494 3495 double thruput; 3496 3497 struct addrinfo *remote_res; 3498 struct addrinfo *local_res; 3499 struct sockaddr_in server; 3500 3501 #if defined(__linux) || defined(__sun__) 3502 off_t scratch_offset; /* the linux sendfile() call will update 3503 the offset variable, which is 3504 something we do _not_ want to happen 3505 to the value in the send_ring! so, we 3506 have to use a scratch variable. */ 3507 #endif /* __linux || defined(__sun__) */ 3508 #if defined (USE_OSX) 3509 off_t scratch_len; /* Darwin 9.x need a value-result parameter */ 3510 #endif 3511 #if defined (__sun__) 3512 size_t scratch_len; /* the sun sendfilev() needs a place to 3513 tell us how many bytes were written, 3514 even though it also returns the value */ 3515 sendfilevec_t sv; 3516 #endif /* __sun__ */ 3517 3518 struct tcp_stream_request_struct *tcp_stream_request; 3519 struct tcp_stream_response_struct *tcp_stream_response; 3520 struct tcp_stream_results_struct *tcp_stream_result; 3521 3522 tcp_stream_request = 3523 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 3524 tcp_stream_response = 3525 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 3526 tcp_stream_result = 3527 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 3528 3529 #ifdef WANT_HISTOGRAM 3530 if (verbosity > 1) { 3531 time_hist = HIST_new(); 3532 } 3533 #endif /* WANT_HISTOGRAM */ 3534 3535 /* since we are now disconnected from the code that established the */ 3536 /* control socket, and since we want to be able to use different */ 3537 /* protocols and such, we are passed the name of the remote host and */ 3538 /* must turn that into the test specific addressing information. */ 3539 3540 bzero((char *)&server, 3541 sizeof(server)); 3542 3543 complete_addrinfos(&remote_res, 3544 &local_res, 3545 remote_host, 3546 SOCK_STREAM, 3547 IPPROTO_TCP, 3548 0); 3549 3550 if ( print_headers ) { 3551 /* we want to have some additional, interesting information in */ 3552 /* the headers. we know some of it here, but not all, so we will */ 3553 /* only print the test title here and will print the results */ 3554 /* titles after the test is finished */ 3555 #ifdef QUICK_SENDPATH 3556 print_top_test_header("TCP SENDPATH TEST",local_res,remote_res); 3557 #else 3558 print_top_test_header("TCP SENDFILE TEST",local_res,remote_res); 3559 #endif /* QUICK_SENDPATH */ 3560 } 3561 send_ring = NULL; 3562 confidence_iteration = 1; 3563 init_stat(); 3564 3565 /* we have a great-big while loop which controls the number of times */ 3566 /* we run a particular test. this is for the calculation of a */ 3567 /* confidence interval (I really should have stayed awake during */ 3568 /* probstats :). If the user did not request confidence measurement */ 3569 /* (no confidence is the default) then we will only go though the */ 3570 /* loop once. the confidence stuff originates from the folks at IBM */ 3571 3572 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 3573 (confidence_iteration <= iteration_min)) { 3574 3575 /* initialize a few counters. we have to remember that we might be */ 3576 /* going through the loop more than once. */ 3577 3578 nummessages = 0; 3579 bytes_sent = 0.0; 3580 times_up = 0; 3581 3582 /* set up the data socket */ 3583 send_socket = create_data_socket(local_res); 3584 3585 if (send_socket == INVALID_SOCKET){ 3586 perror("netperf: sendfile_tcp_stream: tcp stream data socket"); 3587 exit(1); 3588 } 3589 3590 if (debug) { 3591 fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n"); 3592 } 3593 3594 #if defined(TCP_CORK) 3595 /* should this even be here?!? */ 3596 if (loc_tcpcork != 0) { 3597 /* the user wishes for us to set TCP_CORK on the socket */ 3598 int one = 1; 3599 if (setsockopt(send_socket, 3600 getprotobyname("tcp")->p_proto, 3601 TCP_CORK, 3602 (char *)&one, 3603 sizeof(one)) == SOCKET_ERROR) { 3604 perror("netperf: sendfile_tcp_stream: tcp_cork"); 3605 exit(1); 3606 } 3607 if (debug) { 3608 fprintf(where,"sendfile_tcp_stream: tcp_cork...\n"); 3609 } 3610 } 3611 3612 #endif /* TCP_CORK */ 3613 3614 /* at this point, we have either retrieved the socket buffer sizes, */ 3615 /* or have tried to set them, so now, we may want to set the send */ 3616 /* size based on that (because the user either did not use a -m */ 3617 /* option, or used one with an argument of 0). If the socket buffer */ 3618 /* size is not available, we will set the send size to 4KB - no */ 3619 /* particular reason, just arbitrary... */ 3620 3621 /*check for file size/ min file size here? create file here/ back out???*/ 3622 3623 if (send_size == 0) { 3624 if (lss_size > 0) { 3625 send_size = lss_size; 3626 } 3627 else { 3628 send_size = 4096; 3629 } 3630 } 3631 3632 /* set-up the data buffer ring with the requested alignment and 3633 offset. note also that we have allocated a quantity of memory 3634 that is at least one send-size greater than our socket buffer 3635 size. We want to be sure that there are at least two buffers 3636 allocated - this can be a bit of a problem when the send_size 3637 is bigger than the socket size, so we must check... the user 3638 may have wanted to explicitly set the "width" of our send 3639 buffers, we should respect that wish... */ 3640 3641 /*sendring -> an offset index that will shift the starting point of the*/ 3642 /*section of the file sent throughout the file*/ 3643 3644 if (send_width == 0) { 3645 send_width = (lss_size/send_size) + 1; 3646 if (send_width == 1) send_width++; 3647 } 3648 3649 if (send_ring == NULL) { 3650 3651 /* only allocate the send ring once. this is a networking test, 3652 not a memory allocation test. this way, we do not need a 3653 deallocate_buffer_ring() routine, and I don't feel like 3654 writing one anyway :) raj 11/94 */ 3655 3656 send_ring = alloc_sendfile_buf_ring(send_width, 3657 send_size, 3658 local_send_align, 3659 local_send_offset); 3660 } 3661 3662 /* If the user has requested cpu utilization measurements, we must 3663 calibrate the cpu(s). We will perform this task within the 3664 tests themselves. If the user has specified the cpu rate, then 3665 calibrate_local_cpu will return rather quickly as it will have 3666 nothing to do. If local_cpu_rate is zero, then we will go 3667 through all the "normal" calibration stuff and return the rate 3668 back. */ 3669 3670 if (local_cpu_usage) { 3671 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 3672 } 3673 3674 /* Tell the remote end to do a listen. The server alters the 3675 socket paramters on the other side at this point, hence the 3676 reason for all the values being passed in the setup 3677 message. If the user did not specify any of the parameters, 3678 they will be passed as 0, which will indicate to the remote 3679 that no changes beyond the system's default should be 3680 used. Alignment is the exception, it will default to 1, which 3681 will be no alignment alterations. */ 3682 3683 netperf_request.content.request_type = DO_TCP_STREAM; 3684 tcp_stream_request->send_buf_size = rss_size_req; 3685 tcp_stream_request->recv_buf_size = rsr_size_req; 3686 tcp_stream_request->receive_size = recv_size; 3687 tcp_stream_request->no_delay = rem_nodelay; 3688 tcp_stream_request->recv_alignment = remote_recv_align; 3689 tcp_stream_request->recv_offset = remote_recv_offset; 3690 tcp_stream_request->measure_cpu = remote_cpu_usage; 3691 tcp_stream_request->cpu_rate = remote_cpu_rate; 3692 3693 if (test_time) { 3694 tcp_stream_request->test_length = test_time; 3695 } 3696 else { 3697 tcp_stream_request->test_length = test_bytes; 3698 } 3699 3700 tcp_stream_request->so_rcvavoid = rem_rcvavoid; 3701 tcp_stream_request->so_sndavoid = rem_sndavoid; 3702 3703 #ifdef DIRTY 3704 tcp_stream_request->dirty_count = rem_dirty_count; 3705 tcp_stream_request->clean_count = rem_clean_count; 3706 #endif /* DIRTY */ 3707 tcp_stream_request->port = atoi(remote_data_port); 3708 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 3709 3710 if (debug > 1) { 3711 fprintf(where, 3712 "netperf: send_tcp_stream: requesting TCP stream test\n"); 3713 } 3714 3715 send_request(); 3716 3717 /* The response from the remote will contain all of the relevant 3718 socket parameters for this test type. We will put them back 3719 into the variables here so they can be displayed if desired. 3720 The remote will have calibrated CPU if necessary, and will have 3721 done all the needed set-up we will have calibrated the cpu 3722 locally before sending the request, and will grab the counter 3723 value right after the connect returns. The remote will grab the 3724 counter right after the accept call. This saves the hassle of 3725 extra messages being sent for the TCP tests. */ 3726 3727 recv_response(); 3728 3729 if (!netperf_response.content.serv_errno) { 3730 if (debug) 3731 fprintf(where,"remote listen done.\n"); 3732 rsr_size = tcp_stream_response->recv_buf_size; 3733 rss_size = tcp_stream_response->send_buf_size; 3734 rem_nodelay = tcp_stream_response->no_delay; 3735 remote_cpu_usage= tcp_stream_response->measure_cpu; 3736 remote_cpu_rate = tcp_stream_response->cpu_rate; 3737 3738 /* we have to make sure that the server port number is in */ 3739 /* network order */ 3740 set_port_number(remote_res,(short)tcp_stream_response->data_port_number); 3741 rem_rcvavoid = tcp_stream_response->so_rcvavoid; 3742 rem_sndavoid = tcp_stream_response->so_sndavoid; 3743 } 3744 else { 3745 Set_errno(netperf_response.content.serv_errno); 3746 fprintf(where, 3747 "netperf: remote error %d", 3748 netperf_response.content.serv_errno); 3749 perror(""); 3750 fflush(where); 3751 3752 exit(1); 3753 } 3754 3755 #ifdef WANT_DEMO 3756 DEMO_STREAM_SETUP(lss_size,rsr_size) 3757 #endif 3758 3759 /*Connect up to the remote port on the data socket */ 3760 if (connect(send_socket, 3761 remote_res->ai_addr, 3762 remote_res->ai_addrlen) == INVALID_SOCKET){ 3763 perror("netperf: send_tcp_stream: data socket connect failed"); 3764 printf(" port: %d\n",ntohs(server.sin_port)); 3765 exit(1); 3766 } 3767 3768 /* Data Socket set-up is finished. If there were problems, either 3769 the connect would have failed, or the previous response would 3770 have indicated a problem. I failed to see the value of the 3771 extra message after the accept on the remote. If it failed, 3772 we'll see it here. If it didn't, we might as well start pumping 3773 data. */ 3774 3775 /* Set-up the test end conditions. For a stream test, they can be */ 3776 /* either time or byte-count based. */ 3777 3778 if (test_time) { 3779 /* The user wanted to end the test after a period of time. */ 3780 times_up = 0; 3781 bytes_remaining = 0; 3782 3783 /* in previous revisions, we had the same code repeated throught 3784 all the test suites. this was unnecessary, and meant more 3785 work for me when I wanted to switch to POSIX signals, so I 3786 have abstracted this out into a routine in netlib.c. if you 3787 are experiencing signal problems, you might want to look 3788 there. raj 11/94 */ 3789 3790 start_timer(test_time); 3791 } 3792 else { 3793 /* The tester wanted to send a number of bytes. */ 3794 bytes_remaining = test_bytes; 3795 times_up = 1; 3796 } 3797 3798 /* The cpu_start routine will grab the current time and possibly */ 3799 /* value of the idle counter for later use in measuring cpu */ 3800 /* utilization and/or service demand and thruput. */ 3801 3802 cpu_start(local_cpu_usage); 3803 3804 #ifdef WANT_INTERVALS 3805 INTERVALS_INIT(); 3806 #endif /* WANT_INTERVALS */ 3807 3808 3809 /* before we start, initialize a few variables */ 3810 3811 #ifdef WANT_DEMO 3812 if (demo_mode) { 3813 HIST_timestamp(demo_one_ptr); 3814 } 3815 #endif 3816 3817 /* We use an "OR" to control test execution. When the test is 3818 controlled by time, the byte count check will always return 3819 false. When the test is controlled by byte count, the time test 3820 will always return false. When the test is finished, the whole 3821 expression will go false and we will stop sending data. */ 3822 3823 while ((!times_up) || (bytes_remaining > 0)) { 3824 3825 /* the sendfile_tcp_stream test does not support making the buffers 3826 dirty. 08/2000 */ 3827 3828 #ifdef WANT_HISTOGRAM 3829 if (verbosity > 1) { 3830 /* timestamp just before we go into sendfile() and then again 3831 just after we come out raj 08/2000 */ 3832 /* but only if we are actually going to display a histogram */ 3833 HIST_timestamp(&time_one); 3834 } 3835 #endif /* WANT_HISTOGRAM */ 3836 3837 /* you can look at netlib.h for a description of the fields we 3838 are passing to sendfile(). 08/2000 */ 3839 #ifdef QUICK_SENDPATH 3840 if ((len=sendpath(send_socket, 3841 fill_file, 3842 send_ring->offset, 3843 send_ring->length, 3844 send_ring->hdtrl, 3845 send_ring->flags)) != send_size) 3846 #elif defined(__linux) 3847 scratch_offset = send_ring->offset; 3848 if ((len=sendfile(send_socket, 3849 send_ring->fildes, 3850 &scratch_offset, /* modified after the call! */ 3851 send_ring->length)) != send_size) 3852 #elif defined (__sun__) 3853 /* We must call with SFV_NOWAIT and a large file size (>= 16MB) to 3854 get zero-copy, as well as compiling with -D_LARGEFILE_SOURCE 3855 -D_FILE_OFFSET_BITS=64 */ 3856 sv.sfv_fd = send_ring->fildes; 3857 sv.sfv_flag = SFV_NOWAIT; 3858 sv.sfv_off = send_ring->offset; 3859 sv.sfv_len = send_ring->length; 3860 if ((len = sendfilev(send_socket, &sv, 1, &scratch_len)) != send_size) 3861 #elif defined(__FreeBSD__) 3862 /* so close to HP-UX and yet so far away... :) */ 3863 if ((sendfile(send_ring->fildes, 3864 send_socket, 3865 send_ring->offset, 3866 send_ring->length, 3867 NULL, 3868 (off_t *)&len, 3869 send_ring->flags) != 0) || 3870 (len != send_size)) 3871 #elif defined(USE_OSX) 3872 scratch_len = send_ring->length; 3873 if ((sendfile(send_ring->fildes, 3874 send_socket, 3875 send_ring->offset, 3876 (off_t *)&scratch_len, 3877 NULL, 3878 send_ring->flags) != 0) || 3879 (scratch_len != send_size)) 3880 #else /* original sendile HP-UX */ 3881 if ((len=sendfile(send_socket, 3882 send_ring->fildes, 3883 send_ring->offset, 3884 send_ring->length, 3885 send_ring->hdtrl, 3886 send_ring->flags)) != send_size) 3887 #endif /* QUICK_SENDPATH */ 3888 { 3889 /* the test was interrupted, must be the end of test. the 3890 send_tcp_stream code has some WIN32 ifdefs that we do not 3891 need here. */ 3892 if ((len >=0) || SOCKET_EINTR(len)) { 3893 break; 3894 } 3895 perror("netperf: data send error: sendfile"); 3896 fprintf(stderr, 3897 "len was %d send_size was %d\n", 3898 len, 3899 send_size); 3900 fflush(stderr); 3901 exit(1); 3902 } 3903 3904 /* offset += len;*/ 3905 3906 #ifdef WANT_HISTOGRAM 3907 if (verbosity > 1) { 3908 /* timestamp the exit from the send call and update the 3909 histogram */ 3910 3911 HIST_timestamp(&time_two); 3912 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 3913 } 3914 #endif /* WANT_HISTOGRAM */ 3915 3916 #ifdef WANT_DEMO 3917 DEMO_STREAM_INTERVAL(send_size); 3918 #endif 3919 3920 #ifdef WANT_INTERVALS 3921 INTERVALS_WAIT(); 3922 #endif /* WANT_INTERVALS */ 3923 3924 /* now we want to move our pointer to the next position in the */ 3925 /* data buffer...we may also want to wrap back to the "beginning" */ 3926 /* of the bufferspace, so we will mod the number of messages sent */ 3927 /* by the send width, and use that to calculate the offset to add */ 3928 /* to the base pointer. */ 3929 3930 nummessages++; 3931 send_ring = send_ring->next; 3932 if (bytes_remaining) { 3933 bytes_remaining -= send_size; 3934 } 3935 } 3936 3937 /* The test is over. Flush the buffers to the remote end. We do a 3938 graceful release to insure that all data has been taken by the 3939 remote. */ 3940 3941 /* but first, if the verbosity is greater than 1, find-out what */ 3942 /* the TCP maximum segment_size was (if possible) */ 3943 if (verbosity > 1) { 3944 tcp_mss = -1; 3945 get_tcp_info(send_socket,&tcp_mss); 3946 } 3947 3948 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 3949 perror("netperf: cannot shutdown tcp stream socket"); 3950 exit(1); 3951 } 3952 3953 /* hang a recv() off the socket to block until the remote has */ 3954 /* brought all the data up into the application. it will do a */ 3955 /* shutdown to cause a FIN to be sent our way. We will assume that */ 3956 /* any exit from the recv() call is good... raj 4/93 */ 3957 3958 /* since we are using sendfile() instead of send, we have no 3959 scratch buffer from the send_ring to use for the 3960 receive. however, since we "know" that the recv should be 3961 returning zero bytes (not that we are making the checks we 3962 should) we can pass the address of the flags field. raj 08/2000 3963 */ 3964 3965 recv(send_socket, 3966 &(send_ring->flags), 3967 sizeof(send_ring->flags), 3968 0); 3969 3970 /* this call will always give us the elapsed time for the test, and */ 3971 /* will also store-away the necessaries for cpu utilization */ 3972 3973 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 3974 /* measured and how */ 3975 /* long did we really */ 3976 /* run? */ 3977 3978 /* we are finished with the socket, so close it to prevent hitting */ 3979 /* the limit on maximum open files. */ 3980 3981 close(send_socket); 3982 3983 /* Get the statistics from the remote end. The remote will have */ 3984 /* calculated service demand and all those interesting things. If it */ 3985 /* wasn't supposed to care, it will return obvious values. */ 3986 3987 recv_response(); 3988 3989 if (!netperf_response.content.serv_errno) { 3990 if (debug) 3991 fprintf(where,"remote results obtained\n"); 3992 } 3993 3994 else { 3995 Set_errno(netperf_response.content.serv_errno); 3996 fprintf(where, 3997 "netperf: remote error %d", 3998 netperf_response.content.serv_errno); 3999 perror(""); 4000 fflush(where); 4001 4002 exit(1); 4003 } 4004 4005 /* We now calculate what our thruput was for the test. In the future, */ 4006 /* we may want to include a calculation of the thruput measured by */ 4007 /* the remote, but it should be the case that for a TCP stream test, */ 4008 /* that the two numbers should be *very* close... We calculate */ 4009 /* bytes_sent regardless of the way the test length was controlled. */ 4010 /* If it was time, we needed to, and if it was by bytes, the user may */ 4011 /* have specified a number of bytes that wasn't a multiple of the */ 4012 /* send_size, so we really didn't send what he asked for ;-) */ 4013 4014 bytes_sent = ntohd(tcp_stream_result->bytes_received); 4015 4016 thruput = calc_thruput(bytes_sent); 4017 4018 if (local_cpu_usage || remote_cpu_usage) { 4019 4020 /* We must now do a little math for service demand and cpu */ 4021 /* utilization for the system(s) */ 4022 /* Of course, some of the information might be bogus because */ 4023 /* there was no idle counter in the kernel(s). We need to make */ 4024 /* a note of this for the user's benefit...*/ 4025 if (local_cpu_usage) { 4026 4027 local_cpu_utilization = calc_cpu_util(0.0); 4028 local_service_demand = calc_service_demand(bytes_sent, 4029 0.0, 4030 0.0, 4031 0); 4032 } 4033 else { 4034 local_cpu_utilization = (float) -1.0; 4035 local_service_demand = (float) -1.0; 4036 } 4037 4038 if (remote_cpu_usage) { 4039 4040 remote_cpu_utilization = tcp_stream_result->cpu_util; 4041 remote_service_demand = calc_service_demand(bytes_sent, 4042 0.0, 4043 remote_cpu_utilization, 4044 tcp_stream_result->num_cpus); 4045 } 4046 else { 4047 remote_cpu_utilization = (float) -1.0; 4048 remote_service_demand = (float) -1.0; 4049 } 4050 } 4051 else { 4052 /* we were not measuring cpu, for the confidence stuff, we */ 4053 /* should make it -1.0 */ 4054 local_cpu_utilization = (float) -1.0; 4055 local_service_demand = (float) -1.0; 4056 remote_cpu_utilization = (float) -1.0; 4057 remote_service_demand = (float) -1.0; 4058 } 4059 4060 /* at this point, we want to calculate the confidence information. */ 4061 /* if debugging is on, calculate_confidence will print-out the */ 4062 /* parameters we pass it */ 4063 4064 calculate_confidence(confidence_iteration, 4065 elapsed_time, 4066 thruput, 4067 local_cpu_utilization, 4068 remote_cpu_utilization, 4069 local_service_demand, 4070 remote_service_demand); 4071 4072 confidence_iteration++; 4073 } 4074 4075 /* at this point, we have finished making all the runs that we */ 4076 /* will be making. so, we should extract what the calcuated values */ 4077 /* are for all the confidence stuff. we could make the values */ 4078 /* global, but that seemed a little messy, and it did not seem worth */ 4079 /* all the mucking with header files. so, we create a routine much */ 4080 /* like calcualte_confidence, which just returns the mean values. */ 4081 /* raj 11/94 */ 4082 4083 retrieve_confident_values(&elapsed_time, 4084 &thruput, 4085 &local_cpu_utilization, 4086 &remote_cpu_utilization, 4087 &local_service_demand, 4088 &remote_service_demand); 4089 4090 /* We are now ready to print all the information. If the user */ 4091 /* has specified zero-level verbosity, we will just print the */ 4092 /* local service demand, or the remote service demand. If the */ 4093 /* user has requested verbosity level 1, he will get the basic */ 4094 /* "streamperf" numbers. If the user has specified a verbosity */ 4095 /* of greater than 1, we will display a veritable plethora of */ 4096 /* background information from outside of this block as it it */ 4097 /* not cpu_measurement specific... */ 4098 4099 if (confidence < 0) { 4100 /* we did not hit confidence, but were we asked to look for it? */ 4101 if (iteration_max > 1) { 4102 display_confidence(); 4103 } 4104 } 4105 4106 if (local_cpu_usage || remote_cpu_usage) { 4107 local_cpu_method = format_cpu_method(cpu_method); 4108 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method); 4109 4110 switch (verbosity) { 4111 case 0: 4112 4113 if (local_cpu_usage) { 4114 fprintf(where, 4115 cpu_fmt_0, 4116 local_service_demand, 4117 local_cpu_method); 4118 } 4119 4120 else { 4121 fprintf(where, 4122 cpu_fmt_0, 4123 remote_service_demand, 4124 remote_cpu_method); 4125 } 4126 4127 break; 4128 4129 case 1: 4130 case 2: 4131 if (print_headers) { 4132 fprintf(where, 4133 cpu_title, 4134 format_units(), 4135 local_cpu_method, 4136 remote_cpu_method); 4137 } 4138 4139 fprintf(where, 4140 cpu_fmt_1, /* the format string */ 4141 rsr_size, /* remote recvbuf size */ 4142 lss_size, /* local sendbuf size */ 4143 send_size, /* how large were the sends */ 4144 elapsed_time, /* how long was the test */ 4145 thruput, /* what was the xfer rate */ 4146 local_cpu_utilization, /* local cpu */ 4147 remote_cpu_utilization, /* remote cpu */ 4148 local_service_demand, /* local service demand */ 4149 remote_service_demand); /* remote service demand */ 4150 break; 4151 } 4152 4153 } 4154 4155 else { 4156 /* The tester did not wish to measure service demand. */ 4157 4158 switch (verbosity) { 4159 4160 case 0: 4161 4162 fprintf(where, 4163 tput_fmt_0, 4164 thruput); 4165 break; 4166 4167 case 1: 4168 case 2: 4169 4170 if (print_headers) { 4171 fprintf(where,tput_title,format_units()); 4172 } 4173 4174 fprintf(where, 4175 tput_fmt_1, /* the format string */ 4176 rsr_size, /* remote recvbuf size */ 4177 lss_size, /* local sendbuf size */ 4178 send_size, /* how large were the sends */ 4179 elapsed_time, /* how long did it take */ 4180 thruput);/* how fast did it go */ 4181 break; 4182 } 4183 } 4184 4185 /* it would be a good thing to include information about some of the */ 4186 /* other parameters that may have been set for this test, but at the */ 4187 /* moment, I do not wish to figure-out all the formatting, so I will */ 4188 /* just put this comment here to help remind me that it is something */ 4189 /* that should be done at a later time. */ 4190 4191 if (verbosity > 1) { 4192 4193 /* The user wanted to know it all, so we will give it to him. */ 4194 /* This information will include as much as we can find about */ 4195 /* TCP statistics, the alignments of the sends and receives */ 4196 /* and all that sort of rot... */ 4197 4198 /* this stuff needs to be worked-out in the presence of confidence */ 4199 /* intervals and multiple iterations of the test... raj 11/94 */ 4200 4201 fprintf(where, 4202 ksink_fmt, 4203 "Bytes", 4204 "Bytes", 4205 "Bytes", 4206 local_send_align, 4207 remote_recv_align, 4208 local_send_offset, 4209 remote_recv_offset, 4210 bytes_sent, 4211 bytes_sent / (double)nummessages, 4212 nummessages, 4213 bytes_sent / (double)tcp_stream_result->recv_calls, 4214 tcp_stream_result->recv_calls); 4215 4216 fprintf(where, 4217 ksink_fmt2, 4218 tcp_mss); 4219 4220 fflush(where); 4221 4222 #ifdef WANT_HISTOGRAM 4223 4224 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 4225 fflush(where); 4226 HIST_report(time_hist); 4227 #endif /* WANT_HISTOGRAM */ 4228 } 4229 } 4230 4231 #endif /* HAVE_SENDFILE */ 4232 4233 /* This is the server-side routine for the tcp stream test. It is */ 4234 /* implemented as one routine. I could break things-out somewhat, but */ 4235 /* didn't feel it was necessary. */ 4236 4237 void 4238 recv_tcp_stream() 4239 { 4240 4241 struct sockaddr_storage myaddr_in, peeraddr_in; 4242 SOCKET s_listen,s_data; 4243 netperf_socklen_t addrlen; 4244 int len; 4245 unsigned int receive_calls; 4246 float elapsed_time; 4247 double bytes_received; 4248 4249 struct ring_elt *recv_ring; 4250 4251 struct addrinfo *local_res; 4252 char local_name[BUFSIZ]; 4253 char port_buffer[PORTBUFSIZE]; 4254 4255 #ifdef DO_SELECT 4256 fd_set readfds; 4257 struct timeval timeout; 4258 #endif /* DO_SELECT */ 4259 4260 struct tcp_stream_request_struct *tcp_stream_request; 4261 struct tcp_stream_response_struct *tcp_stream_response; 4262 struct tcp_stream_results_struct *tcp_stream_results; 4263 4264 #ifdef DO_SELECT 4265 FD_ZERO(&readfds); 4266 timeout.tv_sec = 1; 4267 timeout.tv_usec = 0; 4268 #endif /* DO_SELECT */ 4269 4270 tcp_stream_request = 4271 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data; 4272 tcp_stream_response = 4273 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data; 4274 tcp_stream_results = 4275 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data; 4276 4277 if (debug) { 4278 fprintf(where,"netserver: recv_tcp_stream: entered...\n"); 4279 fflush(where); 4280 } 4281 4282 /* We want to set-up the listen socket with all the desired */ 4283 /* parameters and then let the initiator know that all is ready. If */ 4284 /* socket size defaults are to be used, then the initiator will have */ 4285 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 4286 /* send-back what they are. If that information cannot be determined, */ 4287 /* then we send-back -1's for the sizes. If things go wrong for any */ 4288 /* reason, we will drop back ten yards and punt. */ 4289 4290 /* If anything goes wrong, we want the remote to know about it. It */ 4291 /* would be best if the error that the remote reports to the user is */ 4292 /* the actual error we encountered, rather than some bogus unexpected */ 4293 /* response type message. */ 4294 4295 if (debug) { 4296 fprintf(where,"recv_tcp_stream: setting the response type...\n"); 4297 fflush(where); 4298 } 4299 4300 netperf_response.content.response_type = TCP_STREAM_RESPONSE; 4301 4302 if (debug) { 4303 fprintf(where,"recv_tcp_stream: the response type is set...\n"); 4304 fflush(where); 4305 } 4306 4307 /* We now alter the message_ptr variable to be at the desired */ 4308 /* alignment with the desired offset. */ 4309 4310 if (debug) { 4311 fprintf(where,"recv_tcp_stream: requested alignment of %d\n", 4312 tcp_stream_request->recv_alignment); 4313 fflush(where); 4314 } 4315 4316 /* create_data_socket expects to find some things in the global */ 4317 /* variables, so set the globals based on the values in the request. */ 4318 /* once the socket has been created, we will set the response values */ 4319 /* based on the updated value of those globals. raj 7/94 */ 4320 lss_size_req = tcp_stream_request->send_buf_size; 4321 lsr_size_req = tcp_stream_request->recv_buf_size; 4322 loc_nodelay = tcp_stream_request->no_delay; 4323 loc_rcvavoid = tcp_stream_request->so_rcvavoid; 4324 loc_sndavoid = tcp_stream_request->so_sndavoid; 4325 4326 set_hostname_and_port(local_name, 4327 port_buffer, 4328 nf_to_af(tcp_stream_request->ipfamily), 4329 tcp_stream_request->port); 4330 4331 local_res = complete_addrinfo(local_name, 4332 local_name, 4333 port_buffer, 4334 nf_to_af(tcp_stream_request->ipfamily), 4335 SOCK_STREAM, 4336 IPPROTO_TCP, 4337 0); 4338 4339 s_listen = create_data_socket(local_res); 4340 4341 if (s_listen == INVALID_SOCKET) { 4342 netperf_response.content.serv_errno = errno; 4343 send_response(); 4344 exit(1); 4345 } 4346 4347 #ifdef WIN32 4348 /* The test timer can fire during operations on the listening socket, 4349 so to make the start_timer below work we have to move 4350 it to close s_listen while we are blocked on accept. */ 4351 win_kludge_socket2 = s_listen; 4352 #endif 4353 4354 /* what sort of sizes did we end-up with? */ 4355 if (tcp_stream_request->receive_size == 0) { 4356 if (lsr_size > 0) { 4357 recv_size = lsr_size; 4358 } 4359 else { 4360 recv_size = 4096; 4361 } 4362 } 4363 else { 4364 recv_size = tcp_stream_request->receive_size; 4365 } 4366 4367 /* we want to set-up our recv_ring in a manner analagous to what we */ 4368 /* do on the sending side. this is more for the sake of symmetry */ 4369 /* than for the needs of say copy avoidance, but it might also be */ 4370 /* more realistic - this way one could conceivably go with a */ 4371 /* double-buffering scheme when taking the data an putting it into */ 4372 /* the filesystem or something like that. raj 7/94 */ 4373 4374 if (recv_width == 0) { 4375 recv_width = (lsr_size/recv_size) + 1; 4376 if (recv_width == 1) recv_width++; 4377 } 4378 4379 recv_ring = allocate_buffer_ring(recv_width, 4380 recv_size, 4381 tcp_stream_request->recv_alignment, 4382 tcp_stream_request->recv_offset); 4383 4384 if (debug) { 4385 fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n"); 4386 fflush(where); 4387 } 4388 4389 /* Now, let's set-up the socket to listen for connections */ 4390 if (listen(s_listen, 5) == SOCKET_ERROR) { 4391 netperf_response.content.serv_errno = errno; 4392 close(s_listen); 4393 send_response(); 4394 4395 exit(1); 4396 } 4397 4398 4399 /* now get the port number assigned by the system */ 4400 addrlen = sizeof(myaddr_in); 4401 if (getsockname(s_listen, 4402 (struct sockaddr *)&myaddr_in, 4403 &addrlen) == SOCKET_ERROR){ 4404 netperf_response.content.serv_errno = errno; 4405 close(s_listen); 4406 send_response(); 4407 4408 exit(1); 4409 } 4410 4411 /* Now myaddr_in contains the port and the internet address this is */ 4412 /* returned to the sender also implicitly telling the sender that the */ 4413 /* socket buffer sizing has been done. */ 4414 4415 tcp_stream_response->data_port_number = 4416 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 4417 netperf_response.content.serv_errno = 0; 4418 4419 /* But wait, there's more. If the initiator wanted cpu measurements, */ 4420 /* then we must call the calibrate routine, which will return the max */ 4421 /* rate back to the initiator. If the CPU was not to be measured, or */ 4422 /* something went wrong with the calibration, we will return a -1 to */ 4423 /* the initiator. */ 4424 4425 tcp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 4426 if (tcp_stream_request->measure_cpu) { 4427 tcp_stream_response->measure_cpu = 1; 4428 tcp_stream_response->cpu_rate = 4429 calibrate_local_cpu(tcp_stream_request->cpu_rate); 4430 } 4431 else { 4432 tcp_stream_response->measure_cpu = 0; 4433 } 4434 4435 /* before we send the response back to the initiator, pull some of */ 4436 /* the socket parms from the globals */ 4437 tcp_stream_response->send_buf_size = lss_size; 4438 tcp_stream_response->recv_buf_size = lsr_size; 4439 tcp_stream_response->no_delay = loc_nodelay; 4440 tcp_stream_response->so_rcvavoid = loc_rcvavoid; 4441 tcp_stream_response->so_sndavoid = loc_sndavoid; 4442 tcp_stream_response->receive_size = recv_size; 4443 4444 send_response(); 4445 4446 addrlen = sizeof(peeraddr_in); 4447 4448 if ((s_data=accept(s_listen, 4449 (struct sockaddr *)&peeraddr_in, 4450 &addrlen)) == INVALID_SOCKET) { 4451 /* Let's just punt. The remote will be given some information */ 4452 close(s_listen); 4453 exit(1); 4454 } 4455 4456 #ifdef KLUDGE_SOCKET_OPTIONS 4457 /* this is for those systems which *INCORRECTLY* fail to pass */ 4458 /* attributes across an accept() call. Including this goes against */ 4459 /* my better judgement :( raj 11/95 */ 4460 4461 kludge_socket_options(s_data); 4462 4463 #endif /* KLUDGE_SOCKET_OPTIONS */ 4464 4465 /* Now it's time to start receiving data on the connection. We will */ 4466 /* first grab the apropriate counters and then start grabbing. */ 4467 4468 cpu_start(tcp_stream_request->measure_cpu); 4469 4470 /* The loop will exit when the sender does a shutdown, which will */ 4471 /* return a length of zero */ 4472 4473 /* there used to be an #ifdef DIRTY call to access_buffer() here, 4474 but we have switched from accessing the buffer before the recv() 4475 call to accessing the buffer after the recv() call. The 4476 accessing before was, IIRC, related to having dirty data when 4477 doing page-flipping copy avoidance. */ 4478 4479 bytes_received = 0; 4480 receive_calls = 0; 4481 4482 while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) { 4483 if (len == SOCKET_ERROR ) 4484 { 4485 netperf_response.content.serv_errno = errno; 4486 send_response(); 4487 exit(1); 4488 } 4489 bytes_received += len; 4490 receive_calls++; 4491 4492 #ifdef DIRTY 4493 /* we access the buffer after the recv() call now, rather than before */ 4494 access_buffer(recv_ring->buffer_ptr, 4495 recv_size, 4496 tcp_stream_request->dirty_count, 4497 tcp_stream_request->clean_count); 4498 #endif /* DIRTY */ 4499 4500 4501 /* move to the next buffer in the recv_ring */ 4502 recv_ring = recv_ring->next; 4503 4504 #ifdef PAUSE 4505 sleep(1); 4506 #endif /* PAUSE */ 4507 4508 #ifdef DO_SELECT 4509 FD_SET(s_data,&readfds); 4510 select(s_data+1,&readfds,NULL,NULL,&timeout); 4511 #endif /* DO_SELECT */ 4512 4513 } 4514 4515 /* perform a shutdown to signal the sender that */ 4516 /* we have received all the data sent. raj 4/93 */ 4517 4518 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) { 4519 netperf_response.content.serv_errno = errno; 4520 send_response(); 4521 exit(1); 4522 } 4523 4524 cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time); 4525 4526 /* send the results to the sender */ 4527 4528 if (debug) { 4529 fprintf(where, 4530 "recv_tcp_stream: got %g bytes\n", 4531 bytes_received); 4532 fprintf(where, 4533 "recv_tcp_stream: got %d recvs\n", 4534 receive_calls); 4535 fflush(where); 4536 } 4537 4538 tcp_stream_results->bytes_received = htond(bytes_received); 4539 tcp_stream_results->elapsed_time = elapsed_time; 4540 tcp_stream_results->recv_calls = receive_calls; 4541 4542 tcp_stream_results->cpu_method = cpu_method; 4543 tcp_stream_results->num_cpus = lib_num_loc_cpus; 4544 4545 if (tcp_stream_request->measure_cpu) { 4546 tcp_stream_results->cpu_util = calc_cpu_util(0.0); 4547 }; 4548 4549 if (debug) { 4550 fprintf(where, 4551 "recv_tcp_stream: test complete, sending results.\n"); 4552 fprintf(where, 4553 " bytes_received %g receive_calls %d\n", 4554 bytes_received, 4555 receive_calls); 4556 fprintf(where, 4557 " len %d\n", 4558 len); 4559 fflush(where); 4560 } 4561 4562 send_response(); 4563 4564 /* we are now done with the sockets */ 4565 close(s_data); 4566 close(s_listen); 4567 4568 } 4569 4570 /* This is the server-side routine for the tcp maerts test. It is 4572 implemented as one routine. I could break things-out somewhat, but 4573 didn't feel it was necessary. */ 4574 4575 void 4576 recv_tcp_maerts() 4577 { 4578 4579 struct sockaddr_storage myaddr_in, peeraddr_in; 4580 struct addrinfo *local_res; 4581 char local_name[BUFSIZ]; 4582 char port_buffer[PORTBUFSIZE]; 4583 4584 SOCKET s_listen,s_data; 4585 netperf_socklen_t addrlen; 4586 int len; 4587 unsigned int send_calls; 4588 float elapsed_time; 4589 double bytes_sent = 0.0 ; 4590 4591 struct ring_elt *send_ring; 4592 4593 struct tcp_maerts_request_struct *tcp_maerts_request; 4594 struct tcp_maerts_response_struct *tcp_maerts_response; 4595 struct tcp_maerts_results_struct *tcp_maerts_results; 4596 4597 tcp_maerts_request = 4598 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data; 4599 tcp_maerts_response = 4600 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data; 4601 tcp_maerts_results = 4602 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data; 4603 4604 if (debug) { 4605 fprintf(where,"netserver: recv_tcp_maerts: entered...\n"); 4606 fflush(where); 4607 } 4608 4609 /* We want to set-up the listen socket with all the desired 4610 parameters and then let the initiator know that all is ready. If 4611 socket size defaults are to be used, then the initiator will have 4612 sent us 0's. If the socket sizes cannot be changed, then we will 4613 send-back what they are. If that information cannot be 4614 determined, then we send-back -1's for the sizes. If things go 4615 wrong for any reason, we will drop back ten yards and punt. */ 4616 4617 /* If anything goes wrong, we want the remote to know about it. It 4618 would be best if the error that the remote reports to the user is 4619 the actual error we encountered, rather than some bogus 4620 unexpected response type message. */ 4621 4622 if (debug) { 4623 fprintf(where,"recv_tcp_maerts: setting the response type...\n"); 4624 fflush(where); 4625 } 4626 4627 netperf_response.content.response_type = TCP_MAERTS_RESPONSE; 4628 4629 if (debug) { 4630 fprintf(where,"recv_tcp_maerts: the response type is set...\n"); 4631 fflush(where); 4632 } 4633 4634 /* We now alter the message_ptr variable to be at the desired */ 4635 /* alignment with the desired offset. */ 4636 4637 if (debug) { 4638 fprintf(where,"recv_tcp_maerts: requested alignment of %d\n", 4639 tcp_maerts_request->send_alignment); 4640 fflush(where); 4641 } 4642 4643 /* Grab a socket to listen on, and then listen on it. */ 4644 4645 if (debug) { 4646 fprintf(where,"recv_tcp_maerts: grabbing a socket...\n"); 4647 fflush(where); 4648 } 4649 4650 /* create_data_socket expects to find some things in the global */ 4651 /* variables, so set the globals based on the values in the request. */ 4652 /* once the socket has been created, we will set the response values */ 4653 /* based on the updated value of those globals. raj 7/94 */ 4654 lss_size_req = tcp_maerts_request->send_buf_size; 4655 lsr_size_req = tcp_maerts_request->recv_buf_size; 4656 loc_nodelay = tcp_maerts_request->no_delay; 4657 loc_rcvavoid = tcp_maerts_request->so_rcvavoid; 4658 loc_sndavoid = tcp_maerts_request->so_sndavoid; 4659 4660 set_hostname_and_port(local_name, 4661 port_buffer, 4662 nf_to_af(tcp_maerts_request->ipfamily), 4663 tcp_maerts_request->port); 4664 4665 local_res = complete_addrinfo(local_name, 4666 local_name, 4667 port_buffer, 4668 nf_to_af(tcp_maerts_request->ipfamily), 4669 SOCK_STREAM, 4670 IPPROTO_TCP, 4671 0); 4672 4673 s_listen = create_data_socket(local_res); 4674 4675 if (s_listen == INVALID_SOCKET) { 4676 netperf_response.content.serv_errno = errno; 4677 send_response(); 4678 exit(1); 4679 } 4680 4681 #ifdef WIN32 4682 /* The test timer can fire during operations on the listening socket, 4683 so to make the start_timer below work we have to move 4684 it to close s_listen while we are blocked on accept. */ 4685 win_kludge_socket2 = s_listen; 4686 #endif 4687 4688 4689 /* what sort of sizes did we end-up with? */ 4690 if (tcp_maerts_request->send_size == 0) { 4691 if (lss_size > 0) { 4692 send_size = lss_size; 4693 } 4694 else { 4695 send_size = 4096; 4696 } 4697 } 4698 else { 4699 send_size = tcp_maerts_request->send_size; 4700 } 4701 4702 /* we want to set-up our recv_ring in a manner analagous to what we */ 4703 /* do on the recving side. this is more for the sake of symmetry */ 4704 /* than for the needs of say copy avoidance, but it might also be */ 4705 /* more realistic - this way one could conceivably go with a */ 4706 /* double-buffering scheme when taking the data an putting it into */ 4707 /* the filesystem or something like that. raj 7/94 */ 4708 4709 if (send_width == 0) { 4710 send_width = (lsr_size/send_size) + 1; 4711 if (send_width == 1) send_width++; 4712 } 4713 4714 send_ring = allocate_buffer_ring(send_width, 4715 send_size, 4716 tcp_maerts_request->send_alignment, 4717 tcp_maerts_request->send_offset); 4718 4719 if (debug) { 4720 fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n"); 4721 fflush(where); 4722 } 4723 4724 /* Now, let's set-up the socket to listen for connections */ 4725 if (listen(s_listen, 5) == SOCKET_ERROR) { 4726 netperf_response.content.serv_errno = errno; 4727 close(s_listen); 4728 send_response(); 4729 4730 exit(1); 4731 } 4732 4733 4734 /* now get the port number assigned by the system */ 4735 addrlen = sizeof(myaddr_in); 4736 if (getsockname(s_listen, 4737 (struct sockaddr *)&myaddr_in, 4738 &addrlen) == SOCKET_ERROR){ 4739 netperf_response.content.serv_errno = errno; 4740 close(s_listen); 4741 send_response(); 4742 4743 exit(1); 4744 } 4745 4746 /* Now myaddr_in contains the port and the internet address this is */ 4747 /* returned to the sender also implicitly telling the sender that the */ 4748 /* socket buffer sizing has been done. */ 4749 4750 tcp_maerts_response->data_port_number = 4751 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 4752 netperf_response.content.serv_errno = 0; 4753 4754 /* But wait, there's more. If the initiator wanted cpu measurements, */ 4755 /* then we must call the calibrate routine, which will return the max */ 4756 /* rate back to the initiator. If the CPU was not to be measured, or */ 4757 /* something went wrong with the calibration, we will return a -1 to */ 4758 /* the initiator. */ 4759 4760 tcp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */ 4761 if (tcp_maerts_request->measure_cpu) { 4762 tcp_maerts_response->measure_cpu = 1; 4763 tcp_maerts_response->cpu_rate = 4764 calibrate_local_cpu(tcp_maerts_request->cpu_rate); 4765 } 4766 else { 4767 tcp_maerts_response->measure_cpu = 0; 4768 } 4769 4770 /* before we send the response back to the initiator, pull some of */ 4771 /* the socket parms from the globals */ 4772 tcp_maerts_response->send_buf_size = lss_size; 4773 tcp_maerts_response->recv_buf_size = lsr_size; 4774 tcp_maerts_response->no_delay = loc_nodelay; 4775 tcp_maerts_response->so_rcvavoid = loc_rcvavoid; 4776 tcp_maerts_response->so_sndavoid = loc_sndavoid; 4777 tcp_maerts_response->send_size = send_size; 4778 4779 send_response(); 4780 4781 addrlen = sizeof(peeraddr_in); 4782 4783 /* we will start the timer before the accept() to be somewhat 4784 analagous to the starting of the timer before the connect() call 4785 in the TCP_STREAM test. raj 2002-06-21 */ 4786 4787 start_timer(tcp_maerts_request->test_length); 4788 4789 /* Now it's time to start receiving data on the connection. We will 4790 first grab the apropriate counters and then start grabbing. */ 4791 4792 cpu_start(tcp_maerts_request->measure_cpu); 4793 4794 4795 if ((s_data=accept(s_listen, 4796 (struct sockaddr *)&peeraddr_in, 4797 &addrlen)) == INVALID_SOCKET) { 4798 /* Let's just punt. The remote will be given some information */ 4799 close(s_listen); 4800 exit(1); 4801 } 4802 4803 #ifdef KLUDGE_SOCKET_OPTIONS 4804 4805 /* this is for those systems which *INCORRECTLY* fail to pass 4806 attributes across an accept() call. Including this goes against 4807 my better judgement :( raj 11/95 */ 4808 4809 kludge_socket_options(s_data); 4810 4811 #endif /* KLUDGE_SOCKET_OPTIONS */ 4812 4813 /* The loop will exit when the sender does a shutdown, which will */ 4814 /* return a length of zero */ 4815 4816 bytes_sent = 0.0; 4817 send_calls = 0; 4818 4819 len = 0; /* nt-lint; len is not initialized (printf far below) if 4820 times_up initially true.*/ 4821 times_up = 0; /* must remember to initialize this little beauty */ 4822 while (!times_up) { 4823 4824 #ifdef DIRTY 4825 /* we want to dirty some number of consecutive integers in the buffer */ 4826 /* we are about to send. we may also want to bring some number of */ 4827 /* them cleanly into the cache. The clean ones will follow any dirty */ 4828 /* ones into the cache. */ 4829 4830 access_buffer(send_ring->buffer_ptr, 4831 send_size, 4832 tcp_maerts_request->dirty_count, 4833 tcp_maerts_request->clean_count); 4834 4835 #endif /* DIRTY */ 4836 4837 if((len=send(s_data, 4838 send_ring->buffer_ptr, 4839 send_size, 4840 0)) != send_size) { 4841 if ((len >=0) || SOCKET_EINTR(len)) { 4842 /* the test was interrupted, must be the end of test */ 4843 break; 4844 } 4845 netperf_response.content.serv_errno = errno; 4846 send_response(); 4847 exit(1); 4848 } 4849 4850 bytes_sent += len; 4851 send_calls++; 4852 4853 /* more to the next buffer in the send_ring */ 4854 send_ring = send_ring->next; 4855 4856 } 4857 4858 /* perform a shutdown to signal the sender that */ 4859 /* we have received all the data sent. raj 4/93 */ 4860 4861 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) { 4862 netperf_response.content.serv_errno = errno; 4863 send_response(); 4864 exit(1); 4865 } 4866 4867 /* hang a recv() off the socket to block until the remote has 4868 brought all the data up into the application. it will do a 4869 shutdown to cause a FIN to be sent our way. We will assume that 4870 any exit from the recv() call is good... raj 4/93 */ 4871 4872 recv(s_data, send_ring->buffer_ptr, send_size, 0); 4873 4874 4875 cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time); 4876 4877 /* send the results to the sender */ 4878 4879 if (debug) { 4880 fprintf(where, 4881 "recv_tcp_maerts: got %g bytes\n", 4882 bytes_sent); 4883 fprintf(where, 4884 "recv_tcp_maerts: got %d sends\n", 4885 send_calls); 4886 fflush(where); 4887 } 4888 4889 tcp_maerts_results->bytes_sent = htond(bytes_sent); 4890 tcp_maerts_results->elapsed_time = elapsed_time; 4891 tcp_maerts_results->send_calls = send_calls; 4892 4893 if (tcp_maerts_request->measure_cpu) { 4894 tcp_maerts_results->cpu_util = calc_cpu_util(0.0); 4895 }; 4896 4897 if (debug) { 4898 fprintf(where, 4899 "recv_tcp_maerts: test complete, sending results.\n"); 4900 fprintf(where, 4901 " bytes_sent %g send_calls %d\n", 4902 bytes_sent, 4903 send_calls); 4904 fprintf(where, 4905 " len %d\n", 4906 len); 4907 fflush(where); 4908 } 4909 4910 tcp_maerts_results->cpu_method = cpu_method; 4911 tcp_maerts_results->num_cpus = lib_num_loc_cpus; 4912 send_response(); 4913 4914 /* we are now done with the sockets */ 4915 close(s_data); 4916 close(s_listen); 4917 4918 } 4919 4920 4922 /* this routine implements the sending (netperf) side of the TCP_RR */ 4923 /* test. */ 4924 4925 void 4926 send_tcp_rr(char remote_host[]) 4927 { 4928 4929 char *tput_title = "\ 4930 Local /Remote\n\ 4931 Socket Size Request Resp. Elapsed Trans.\n\ 4932 Send Recv Size Size Time Rate \n\ 4933 bytes Bytes bytes bytes secs. per sec \n\n"; 4934 4935 char *tput_title_band = "\ 4936 Local /Remote\n\ 4937 Socket Size Request Resp. Elapsed \n\ 4938 Send Recv Size Size Time Throughput \n\ 4939 bytes Bytes bytes bytes secs. %s/sec \n\n"; 4940 4941 char *tput_fmt_0 = 4942 "%7.2f %s\n"; 4943 4944 char *tput_fmt_1_line_1 = "\ 4945 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 4946 char *tput_fmt_1_line_2 = "\ 4947 %-6d %-6d\n"; 4948 4949 char *cpu_title = "\ 4950 Local /Remote\n\ 4951 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 4952 Send Recv Size Size Time Rate local remote local remote\n\ 4953 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 4954 4955 char *cpu_title_tput = "\ 4956 Local /Remote\n\ 4957 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\ 4958 Send Recv Size Size Time %-8.8s local remote local remote\n\ 4959 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 4960 4961 char *cpu_fmt_0 = 4962 "%6.3f %c %s\n"; 4963 4964 char *cpu_fmt_1_line_1 = "\ 4965 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 4966 4967 char *cpu_fmt_1_line_2 = "\ 4968 %-6d %-6d\n"; 4969 4970 char *ksink_fmt = "\ 4971 Alignment Offset RoundTrip Trans Throughput\n\ 4972 Local Remote Local Remote Latency Rate %-8.8s/s\n\ 4973 Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\ 4974 %5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n"; 4975 4976 4977 int timed_out = 0; 4978 float elapsed_time; 4979 4980 int len; 4981 char *temp_message_ptr; 4982 int nummessages; 4983 SOCKET send_socket; 4984 int trans_remaining; 4985 double bytes_xferd; 4986 4987 struct ring_elt *send_ring; 4988 struct ring_elt *recv_ring; 4989 4990 int rsp_bytes_left; 4991 int rsp_bytes_recvd; 4992 4993 float local_cpu_utilization; 4994 float local_service_demand; 4995 float remote_cpu_utilization; 4996 float remote_service_demand; 4997 double thruput; 4998 4999 struct addrinfo *local_res; 5000 struct addrinfo *remote_res; 5001 5002 struct tcp_rr_request_struct *tcp_rr_request; 5003 struct tcp_rr_response_struct *tcp_rr_response; 5004 struct tcp_rr_results_struct *tcp_rr_result; 5005 5006 #ifdef WANT_FIRST_BURST 5007 #define REQUEST_CWND_INITIAL 2 5008 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both 5009 Unix and the state of New Jersey - both were simple an unspoiled. 5010 then it was realized that some stacks are quite picky about 5011 initial congestion windows and a non-trivial initial burst of 5012 requests would not be individual segments even with TCP_NODELAY 5013 set. so, we have to start tracking a poor-man's congestion window 5014 up here in window space because we want to try to make something 5015 happen that frankly, we cannot guarantee with the specification 5016 of TCP. ain't that grand?-) raj 2006-01-30 */ 5017 int requests_outstanding = 0; 5018 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having 5019 three requests 5020 outstanding at the 5021 beginning of the test 5022 is ok with TCP stacks 5023 of interest. the first 5024 two will come from our 5025 first_burst loop, and 5026 the third from our 5027 regularly scheduled 5028 send */ 5029 #endif 5030 5031 tcp_rr_request = 5032 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 5033 tcp_rr_response= 5034 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 5035 tcp_rr_result = 5036 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 5037 5038 #ifdef WANT_HISTOGRAM 5039 if (verbosity > 1) { 5040 time_hist = HIST_new(); 5041 } 5042 #endif /* WANT_HISTOGRAM */ 5043 5044 /* since we are now disconnected from the code that established the */ 5045 /* control socket, and since we want to be able to use different */ 5046 /* protocols and such, we are passed the name of the remote host and */ 5047 /* must turn that into the test specific addressing information. */ 5048 5049 complete_addrinfos(&remote_res, 5050 &local_res, 5051 remote_host, 5052 SOCK_STREAM, 5053 IPPROTO_TCP, 5054 0); 5055 5056 if ( print_headers ) { 5057 print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res); 5058 } 5059 5060 /* initialize a few counters */ 5061 5062 send_ring = NULL; 5063 recv_ring = NULL; 5064 confidence_iteration = 1; 5065 init_stat(); 5066 5067 /* we have a great-big while loop which controls the number of times */ 5068 /* we run a particular test. this is for the calculation of a */ 5069 /* confidence interval (I really should have stayed awake during */ 5070 /* probstats :). If the user did not request confidence measurement */ 5071 /* (no confidence is the default) then we will only go though the */ 5072 /* loop once. the confidence stuff originates from the folks at IBM */ 5073 5074 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 5075 (confidence_iteration <= iteration_min)) { 5076 5077 /* initialize a few counters. we have to remember that we might be */ 5078 /* going through the loop more than once. */ 5079 5080 nummessages = 0; 5081 bytes_xferd = 0.0; 5082 times_up = 0; 5083 timed_out = 0; 5084 trans_remaining = 0; 5085 5086 #ifdef WANT_FIRST_BURST 5087 /* we have to remember to reset the number of transactions 5088 outstanding and the "congestion window for each new 5089 iteration. raj 2006-01-31 */ 5090 requests_outstanding = 0; 5091 request_cwnd = REQUEST_CWND_INITIAL; 5092 #endif 5093 5094 5095 /* set-up the data buffers with the requested alignment and offset. */ 5096 /* since this is a request/response test, default the send_width and */ 5097 /* recv_width to 1 and not two raj 7/94 */ 5098 5099 if (send_width == 0) send_width = 1; 5100 if (recv_width == 0) recv_width = 1; 5101 5102 if (send_ring == NULL) { 5103 send_ring = allocate_buffer_ring(send_width, 5104 req_size, 5105 local_send_align, 5106 local_send_offset); 5107 } 5108 5109 if (recv_ring == NULL) { 5110 recv_ring = allocate_buffer_ring(recv_width, 5111 rsp_size, 5112 local_recv_align, 5113 local_recv_offset); 5114 } 5115 5116 /*set up the data socket */ 5117 send_socket = create_data_socket(local_res); 5118 5119 if (send_socket == INVALID_SOCKET){ 5120 perror("netperf: send_tcp_rr: tcp stream data socket"); 5121 exit(1); 5122 } 5123 5124 if (debug) { 5125 fprintf(where,"send_tcp_rr: send_socket obtained...\n"); 5126 } 5127 5128 /* If the user has requested cpu utilization measurements, we must */ 5129 /* calibrate the cpu(s). We will perform this task within the tests */ 5130 /* themselves. If the user has specified the cpu rate, then */ 5131 /* calibrate_local_cpu will return rather quickly as it will have */ 5132 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 5133 /* all the "normal" calibration stuff and return the rate back.*/ 5134 5135 if (local_cpu_usage) { 5136 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 5137 } 5138 5139 if (!no_control) { 5140 /* Tell the remote end to do a listen. The server alters the 5141 socket paramters on the other side at this point, hence the 5142 reason for all the values being passed in the setup 5143 message. If the user did not specify any of the parameters, 5144 they will be passed as 0, which will indicate to the remote 5145 that no changes beyond the system's default should be 5146 used. Alignment is the exception, it will default to 8, which 5147 will be no alignment alterations. */ 5148 5149 netperf_request.content.request_type = DO_TCP_RR; 5150 tcp_rr_request->recv_buf_size = rsr_size_req; 5151 tcp_rr_request->send_buf_size = rss_size_req; 5152 tcp_rr_request->recv_alignment = remote_recv_align; 5153 tcp_rr_request->recv_offset = remote_recv_offset; 5154 tcp_rr_request->send_alignment = remote_send_align; 5155 tcp_rr_request->send_offset = remote_send_offset; 5156 tcp_rr_request->request_size = req_size; 5157 tcp_rr_request->response_size = rsp_size; 5158 tcp_rr_request->no_delay = rem_nodelay; 5159 tcp_rr_request->measure_cpu = remote_cpu_usage; 5160 tcp_rr_request->cpu_rate = remote_cpu_rate; 5161 tcp_rr_request->so_rcvavoid = rem_rcvavoid; 5162 tcp_rr_request->so_sndavoid = rem_sndavoid; 5163 if (test_time) { 5164 tcp_rr_request->test_length = test_time; 5165 } 5166 else { 5167 tcp_rr_request->test_length = test_trans * -1; 5168 } 5169 tcp_rr_request->port = atoi(remote_data_port); 5170 tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 5171 5172 if (debug > 1) { 5173 fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n"); 5174 } 5175 5176 send_request(); 5177 5178 /* The response from the remote will contain all of the relevant 5179 socket parameters for this test type. We will put them back 5180 into the variables here so they can be displayed if desired. 5181 The remote will have calibrated CPU if necessary, and will 5182 have done all the needed set-up we will have calibrated the 5183 cpu locally before sending the request, and will grab the 5184 counter value right after the connect returns. The remote 5185 will grab the counter right after the accept call. This saves 5186 the hassle of extra messages being sent for the TCP 5187 tests. */ 5188 5189 recv_response(); 5190 5191 if (!netperf_response.content.serv_errno) { 5192 if (debug) 5193 fprintf(where,"remote listen done.\n"); 5194 rsr_size = tcp_rr_response->recv_buf_size; 5195 rss_size = tcp_rr_response->send_buf_size; 5196 rem_nodelay = tcp_rr_response->no_delay; 5197 remote_cpu_usage = tcp_rr_response->measure_cpu; 5198 remote_cpu_rate = tcp_rr_response->cpu_rate; 5199 /* make sure that port numbers are in network order */ 5200 set_port_number(remote_res,(short)tcp_rr_response->data_port_number); 5201 } 5202 else { 5203 Set_errno(netperf_response.content.serv_errno); 5204 fprintf(where, 5205 "netperf: remote error %d", 5206 netperf_response.content.serv_errno); 5207 perror(""); 5208 fflush(where); 5209 5210 exit(1); 5211 } 5212 } 5213 5214 #ifdef WANT_DEMO 5215 DEMO_RR_SETUP(1000) 5216 #endif 5217 5218 /*Connect up to the remote port on the data socket */ 5219 if (connect(send_socket, 5220 remote_res->ai_addr, 5221 remote_res->ai_addrlen) == INVALID_SOCKET){ 5222 perror("netperf: data socket connect failed"); 5223 5224 exit(1); 5225 } 5226 5227 /* Data Socket set-up is finished. If there were problems, either the */ 5228 /* connect would have failed, or the previous response would have */ 5229 /* indicated a problem. I failed to see the value of the extra */ 5230 /* message after the accept on the remote. If it failed, we'll see it */ 5231 /* here. If it didn't, we might as well start pumping data. */ 5232 5233 /* Set-up the test end conditions. For a request/response test, they */ 5234 /* can be either time or transaction based. */ 5235 5236 if (test_time) { 5237 /* The user wanted to end the test after a period of time. */ 5238 times_up = 0; 5239 trans_remaining = 0; 5240 start_timer(test_time); 5241 } 5242 else { 5243 /* The tester wanted to send a number of bytes. */ 5244 trans_remaining = test_bytes; 5245 times_up = 1; 5246 } 5247 5248 /* The cpu_start routine will grab the current time and possibly */ 5249 /* value of the idle counter for later use in measuring cpu */ 5250 /* utilization and/or service demand and thruput. */ 5251 5252 cpu_start(local_cpu_usage); 5253 5254 #ifdef WANT_INTERVALS 5255 INTERVALS_INIT(); 5256 #endif /* WANT_INTERVALS */ 5257 5258 /* We use an "OR" to control test execution. When the test is */ 5259 /* controlled by time, the byte count check will always return false. */ 5260 /* When the test is controlled by byte count, the time test will */ 5261 /* always return false. When the test is finished, the whole */ 5262 /* expression will go false and we will stop sending data. I think I */ 5263 /* just arbitrarily decrement trans_remaining for the timed test, but */ 5264 /* will not do that just yet... One other question is whether or not */ 5265 /* the send buffer and the receive buffer should be the same buffer. */ 5266 5267 #ifdef WANT_DEMO 5268 if (demo_mode) { 5269 HIST_timestamp(demo_one_ptr); 5270 } 5271 #endif 5272 5273 while ((!times_up) || (trans_remaining > 0)) { 5274 /* send the request. we assume that if we use a blocking socket, */ 5275 /* the request will be sent at one shot. */ 5276 5277 #ifdef WANT_FIRST_BURST 5278 /* we can inject no more than request_cwnd, which will grow with 5279 time, and no more than first_burst_size. we don't use <= to 5280 account for the "regularly scheduled" send call. of course 5281 that makes it more a "max_outstanding_ than a 5282 "first_burst_size" but for now we won't fix the names. also, 5283 I suspect the extra check against < first_burst_size is 5284 redundant since later I expect to make sure that request_cwnd 5285 can never get larger than first_burst_size, but just at the 5286 moment I'm feeling like a belt and suspenders kind of 5287 programmer. raj 2006-01-30 */ 5288 while ((first_burst_size > 0) && 5289 (requests_outstanding < request_cwnd) && 5290 (requests_outstanding < first_burst_size)) { 5291 if (debug) { 5292 fprintf(where, 5293 "injecting, req_outstndng %d req_cwnd %d burst %d\n", 5294 requests_outstanding, 5295 request_cwnd, 5296 first_burst_size); 5297 } 5298 if ((len = send(send_socket, 5299 send_ring->buffer_ptr, 5300 req_size, 5301 0)) != req_size) { 5302 /* we should never hit the end of the test in the first burst */ 5303 perror("send_tcp_rr: initial burst data send error"); 5304 exit(-1); 5305 } 5306 requests_outstanding += 1; 5307 } 5308 5309 #endif /* WANT_FIRST_BURST */ 5310 5311 #ifdef WANT_HISTOGRAM 5312 if (verbosity > 1) { 5313 /* timestamp just before our call to send, and then again just 5314 after the receive raj 8/94 */ 5315 /* but only if we are actually going to display one. raj 5316 2007-02-07 */ 5317 5318 HIST_timestamp(&time_one); 5319 } 5320 #endif /* WANT_HISTOGRAM */ 5321 5322 if ((len = send(send_socket, 5323 send_ring->buffer_ptr, 5324 req_size, 5325 0)) != req_size) { 5326 if (SOCKET_EINTR(len) || (errno == 0)) { 5327 /* we hit the end of a */ 5328 /* timed test. */ 5329 timed_out = 1; 5330 break; 5331 } 5332 perror("send_tcp_rr: data send error"); 5333 exit(1); 5334 } 5335 send_ring = send_ring->next; 5336 5337 #ifdef WANT_FIRST_BURST 5338 requests_outstanding += 1; 5339 #endif 5340 5341 /* receive the response */ 5342 rsp_bytes_left = rsp_size; 5343 temp_message_ptr = recv_ring->buffer_ptr; 5344 while(rsp_bytes_left > 0) { 5345 if((rsp_bytes_recvd=recv(send_socket, 5346 temp_message_ptr, 5347 rsp_bytes_left, 5348 0)) == SOCKET_ERROR) { 5349 if ( SOCKET_EINTR(rsp_bytes_recvd) ) { 5350 /* We hit the end of a timed test. */ 5351 timed_out = 1; 5352 break; 5353 } 5354 perror("send_tcp_rr: data recv error"); 5355 exit(1); 5356 } 5357 rsp_bytes_left -= rsp_bytes_recvd; 5358 temp_message_ptr += rsp_bytes_recvd; 5359 } 5360 recv_ring = recv_ring->next; 5361 5362 #ifdef WANT_FIRST_BURST 5363 /* so, since we've gotten a response back, update the 5364 bookkeeping accordingly. there is one less request 5365 outstanding and we can put one more out there than before. */ 5366 requests_outstanding -= 1; 5367 if (request_cwnd < first_burst_size) { 5368 request_cwnd += 1; 5369 if (debug) { 5370 fprintf(where, 5371 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n", 5372 request_cwnd, 5373 first_burst_size, 5374 requests_outstanding); 5375 } 5376 } 5377 #endif 5378 if (timed_out) { 5379 /* we may have been in a nested while loop - we need */ 5380 /* another call to break. */ 5381 break; 5382 } 5383 5384 #ifdef WANT_HISTOGRAM 5385 if (verbosity > 1) { 5386 HIST_timestamp(&time_two); 5387 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 5388 } 5389 #endif /* WANT_HISTOGRAM */ 5390 5391 #ifdef WANT_DEMO 5392 DEMO_RR_INTERVAL(1); 5393 #endif 5394 5395 #ifdef WANT_INTERVALS 5396 INTERVALS_WAIT(); 5397 #endif /* WANT_INTERVALS */ 5398 5399 nummessages++; 5400 if (trans_remaining) { 5401 trans_remaining--; 5402 } 5403 5404 if (debug > 3) { 5405 if ((nummessages % 100) == 0) { 5406 fprintf(where, 5407 "Transaction %d completed\n", 5408 nummessages); 5409 fflush(where); 5410 } 5411 } 5412 } 5413 5414 /* At this point we used to call shutdown on the data socket to be 5415 sure all the data was delivered, but this was not germane in a 5416 request/response test, and it was causing the tests to "hang" 5417 when they were being controlled by time. So, I have replaced 5418 this shutdown call with a call to close that can be found later 5419 in the procedure. */ 5420 5421 /* this call will always give us the elapsed time for the test, 5422 and will also store-away the necessaries for cpu utilization */ 5423 5424 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 5425 /* measured? how long */ 5426 /* did we really run? */ 5427 5428 if (!no_control) { 5429 /* Get the statistics from the remote end. The remote will have 5430 calculated CPU utilization. If it wasn't supposed to care, it 5431 will return obvious values. */ 5432 5433 recv_response(); 5434 if (!netperf_response.content.serv_errno) { 5435 if (debug) 5436 fprintf(where,"remote results obtained\n"); 5437 } 5438 else { 5439 Set_errno(netperf_response.content.serv_errno); 5440 fprintf(where,"netperf: remote error %d", 5441 netperf_response.content.serv_errno); 5442 perror(""); 5443 fflush(where); 5444 exit(1); 5445 } 5446 } 5447 5448 /* We now calculate what our "throughput" was for the test. */ 5449 5450 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 5451 thruput = nummessages/elapsed_time; 5452 5453 if (local_cpu_usage || remote_cpu_usage) { 5454 /* We must now do a little math for service demand and cpu 5455 utilization for the system(s) Of course, some of the 5456 information might be bogus because there was no idle counter in 5457 the kernel(s). We need to make a note of this for the user's 5458 benefit... */ 5459 if (local_cpu_usage) { 5460 local_cpu_utilization = calc_cpu_util(0.0); 5461 /* since calc_service demand is doing ms/Kunit we will 5462 multiply the number of transaction by 1024 to get "good" 5463 numbers */ 5464 local_service_demand = calc_service_demand((double) nummessages*1024, 5465 0.0, 5466 0.0, 5467 0); 5468 } 5469 else { 5470 local_cpu_utilization = (float) -1.0; 5471 local_service_demand = (float) -1.0; 5472 } 5473 5474 if (remote_cpu_usage) { 5475 remote_cpu_utilization = tcp_rr_result->cpu_util; 5476 /* since calc_service demand is doing ms/Kunit we will 5477 multiply the number of transaction by 1024 to get "good" 5478 numbers */ 5479 remote_service_demand = calc_service_demand((double) nummessages*1024, 5480 0.0, 5481 remote_cpu_utilization, 5482 tcp_rr_result->num_cpus); 5483 } 5484 else { 5485 remote_cpu_utilization = (float) -1.0; 5486 remote_service_demand = (float) -1.0; 5487 } 5488 5489 } 5490 else { 5491 /* we were not measuring cpu, for the confidence stuff, we */ 5492 /* should make it -1.0 */ 5493 local_cpu_utilization = (float) -1.0; 5494 local_service_demand = (float) -1.0; 5495 remote_cpu_utilization = (float) -1.0; 5496 remote_service_demand = (float) -1.0; 5497 } 5498 5499 /* at this point, we want to calculate the confidence information. 5500 if debugging is on, calculate_confidence will print-out the 5501 parameters we pass it */ 5502 5503 calculate_confidence(confidence_iteration, 5504 elapsed_time, 5505 thruput, 5506 local_cpu_utilization, 5507 remote_cpu_utilization, 5508 local_service_demand, 5509 remote_service_demand); 5510 5511 5512 confidence_iteration++; 5513 5514 /* we are now done with the socket, so close it */ 5515 close(send_socket); 5516 5517 } 5518 5519 retrieve_confident_values(&elapsed_time, 5520 &thruput, 5521 &local_cpu_utilization, 5522 &remote_cpu_utilization, 5523 &local_service_demand, 5524 &remote_service_demand); 5525 5526 /* We are now ready to print all the information. If the user has 5527 specified zero-level verbosity, we will just print the local 5528 service demand, or the remote service demand. If the user has 5529 requested verbosity level 1, he will get the basic "streamperf" 5530 numbers. If the user has specified a verbosity of greater than 1, 5531 we will display a veritable plethora of background information 5532 from outside of this block as it it not cpu_measurement 5533 specific... */ 5534 5535 if (confidence < 0) { 5536 /* we did not hit confidence, but were we asked to look for it? */ 5537 if (iteration_max > 1) { 5538 display_confidence(); 5539 } 5540 } 5541 5542 if (local_cpu_usage || remote_cpu_usage) { 5543 local_cpu_method = format_cpu_method(cpu_method); 5544 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method); 5545 5546 switch (verbosity) { 5547 case 0: 5548 if (local_cpu_usage) { 5549 fprintf(where, 5550 cpu_fmt_0, 5551 local_service_demand, 5552 local_cpu_method, 5553 ((print_headers) || 5554 (result_brand == NULL)) ? "" : result_brand); 5555 } 5556 else { 5557 fprintf(where, 5558 cpu_fmt_0, 5559 remote_service_demand, 5560 remote_cpu_method, 5561 ((print_headers) || 5562 (result_brand == NULL)) ? "" : result_brand); 5563 } 5564 break; 5565 case 1: 5566 case 2: 5567 if (print_headers) { 5568 if ('x' == libfmt) { 5569 fprintf(where, 5570 cpu_title, 5571 local_cpu_method, 5572 remote_cpu_method); 5573 } 5574 else { 5575 fprintf(where, 5576 cpu_title_tput, 5577 format_units(), 5578 local_cpu_method, 5579 remote_cpu_method); 5580 } 5581 } 5582 5583 fprintf(where, 5584 cpu_fmt_1_line_1, /* the format string */ 5585 lss_size, /* local sendbuf size */ 5586 lsr_size, 5587 req_size, /* how large were the requests */ 5588 rsp_size, /* guess */ 5589 elapsed_time, /* how long was the test */ 5590 ('x' == libfmt) ? thruput : 5591 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 5592 1.0), 5593 local_cpu_utilization, /* local cpu */ 5594 remote_cpu_utilization, /* remote cpu */ 5595 local_service_demand, /* local service demand */ 5596 remote_service_demand, /* remote service demand */ 5597 ((print_headers) || 5598 (result_brand == NULL)) ? "" : result_brand); 5599 fprintf(where, 5600 cpu_fmt_1_line_2, 5601 rss_size, 5602 rsr_size); 5603 break; 5604 } 5605 } 5606 else { 5607 /* The tester did not wish to measure service demand. */ 5608 5609 switch (verbosity) { 5610 case 0: 5611 fprintf(where, 5612 tput_fmt_0, 5613 ('x' == libfmt) ? thruput : 5614 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 5615 1.0), 5616 ((print_headers) || 5617 (result_brand == NULL)) ? "" : result_brand); 5618 break; 5619 case 1: 5620 case 2: 5621 if (print_headers) { 5622 fprintf(where, 5623 ('x' == libfmt) ? tput_title : tput_title_band, 5624 format_units()); 5625 } 5626 5627 fprintf(where, 5628 tput_fmt_1_line_1, /* the format string */ 5629 lss_size, 5630 lsr_size, 5631 req_size, /* how large were the requests */ 5632 rsp_size, /* how large were the responses */ 5633 elapsed_time, /* how long did it take */ 5634 /* are we trans or do we need to convert to bytes then 5635 bits? at this point, thruput is in our "confident" 5636 transactions per second. we can convert to a 5637 bidirectional bitrate by multiplying that by the sum 5638 of the req_size and rsp_size. we pass that to 5639 calc_thruput_interval_omni with an elapsed time of 5640 1.0 s to get it converted to [kmg]bits/s or 5641 [KMG]Bytes/s */ 5642 ('x' == libfmt) ? thruput : 5643 calc_thruput_interval_omni(thruput * (req_size+rsp_size), 5644 1.0), 5645 ((print_headers) || 5646 (result_brand == NULL)) ? "" : result_brand); 5647 fprintf(where, 5648 tput_fmt_1_line_2, 5649 rss_size, /* remote recvbuf size */ 5650 rsr_size); 5651 5652 break; 5653 } 5654 } 5655 5656 /* it would be a good thing to include information about some of the */ 5657 /* other parameters that may have been set for this test, but at the */ 5658 /* moment, I do not wish to figure-out all the formatting, so I will */ 5659 /* just put this comment here to help remind me that it is something */ 5660 /* that should be done at a later time. */ 5661 5662 /* how to handle the verbose information in the presence of */ 5663 /* confidence intervals is yet to be determined... raj 11/94 */ 5664 if (verbosity > 1) { 5665 /* The user wanted to know it all, so we will give it to him. */ 5666 /* This information will include as much as we can find about */ 5667 /* TCP statistics, the alignments of the sends and receives */ 5668 /* and all that sort of rot... */ 5669 5670 /* normally, you might think that if we were messing about with 5671 the value of libfmt we would need to put it back again, but 5672 since this is basically the last thing we are going to do with 5673 it, it does not matter. so there :) raj 2007-06-08 */ 5674 /* if the user was asking for transactions, then we report 5675 megabits per sedcond for the unidirectional throughput, 5676 otherwise we use the desired units. */ 5677 if ('x' == libfmt) { 5678 libfmt = 'm'; 5679 } 5680 5681 fprintf(where, 5682 ksink_fmt, 5683 format_units(), 5684 local_send_align, 5685 remote_recv_offset, 5686 local_send_offset, 5687 remote_recv_offset, 5688 /* if the user has enable burst mode, we have to remember 5689 to account for that in the number of transactions 5690 outstanding at any one time. otherwise we will 5691 underreport the latency of individual 5692 transactions. learned from saf by raj 2007-06-08 */ 5693 (((double)1.0/thruput)*(double)1000000.0) * 5694 (double) (1+first_burst_size), 5695 thruput, 5696 calc_thruput_interval_omni(thruput * (double)req_size,1.0), 5697 calc_thruput_interval_omni(thruput * (double)rsp_size,1.0)); 5698 5699 #ifdef WANT_HISTOGRAM 5700 fprintf(where,"\nHistogram of request/response times\n"); 5701 fflush(where); 5702 HIST_report(time_hist); 5703 #endif /* WANT_HISTOGRAM */ 5704 5705 } 5706 5707 } 5708 5709 void 5711 send_udp_stream(char remote_host[]) 5712 { 5713 /**********************************************************************/ 5714 /* */ 5715 /* UDP Unidirectional Send Test */ 5716 /* */ 5717 /**********************************************************************/ 5718 5719 #define UDP_LENGTH_MAX 0XFFFF - 28 5720 5721 char *tput_title = "\ 5722 Socket Message Elapsed Messages \n\ 5723 Size Size Time Okay Errors Throughput\n\ 5724 bytes bytes secs # # %s/sec\n\n"; 5725 5726 char *tput_fmt_0 = 5727 "%7.2f\n"; 5728 5729 char *tput_fmt_1 = "\ 5730 %6d %6d %-7.2f %7d %6d %7.2f\n\ 5731 %6d %-7.2f %7d %7.2f\n\n"; 5732 5733 5734 char *cpu_title = "\ 5735 Socket Message Elapsed Messages CPU Service\n\ 5736 Size Size Time Okay Errors Throughput Util Demand\n\ 5737 bytes bytes secs # # %s/sec %% %c%c us/KB\n\n"; 5738 5739 char *cpu_fmt_0 = 5740 "%6.2f %c\n"; 5741 5742 char *cpu_fmt_1 = "\ 5743 %6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\ 5744 %6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n"; 5745 5746 unsigned int messages_recvd; 5747 unsigned int messages_sent; 5748 unsigned int failed_sends; 5749 5750 float elapsed_time, 5751 local_cpu_utilization, 5752 remote_cpu_utilization; 5753 5754 float local_service_demand, remote_service_demand; 5755 double local_thruput, remote_thruput; 5756 double bytes_sent; 5757 double bytes_recvd; 5758 5759 5760 int len; 5761 struct ring_elt *send_ring; 5762 SOCKET data_socket; 5763 5764 unsigned int sum_messages_sent; 5765 unsigned int sum_messages_recvd; 5766 unsigned int sum_failed_sends; 5767 double sum_local_thruput; 5768 5769 struct addrinfo *local_res; 5770 struct addrinfo *remote_res; 5771 5772 struct udp_stream_request_struct *udp_stream_request; 5773 struct udp_stream_response_struct *udp_stream_response; 5774 struct udp_stream_results_struct *udp_stream_results; 5775 5776 udp_stream_request = 5777 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data; 5778 udp_stream_response = 5779 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data; 5780 udp_stream_results = 5781 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data; 5782 5783 #ifdef WANT_HISTOGRAM 5784 if (verbosity > 1) { 5785 time_hist = HIST_new(); 5786 } 5787 #endif /* WANT_HISTOGRAM */ 5788 5789 /* since we are now disconnected from the code that established the */ 5790 /* control socket, and since we want to be able to use different */ 5791 /* protocols and such, we are passed the name of the remote host and */ 5792 /* must turn that into the test specific addressing information. */ 5793 5794 complete_addrinfos(&remote_res, 5795 &local_res, 5796 remote_host, 5797 SOCK_DGRAM, 5798 IPPROTO_UDP, 5799 0); 5800 5801 if ( print_headers ) { 5802 print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res); 5803 } 5804 5805 send_ring = NULL; 5806 confidence_iteration = 1; 5807 init_stat(); 5808 sum_messages_sent = 0; 5809 sum_messages_recvd = 0; 5810 sum_failed_sends = 0; 5811 sum_local_thruput = 0.0; 5812 5813 /* we have a great-big while loop which controls the number of times */ 5814 /* we run a particular test. this is for the calculation of a */ 5815 /* confidence interval (I really should have stayed awake during */ 5816 /* probstats :). If the user did not request confidence measurement */ 5817 /* (no confidence is the default) then we will only go though the */ 5818 /* loop once. the confidence stuff originates from the folks at IBM */ 5819 5820 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 5821 (confidence_iteration <= iteration_min)) { 5822 5823 /* initialize a few counters. we have to remember that we might be */ 5824 /* going through the loop more than once. */ 5825 messages_sent = 0; 5826 messages_recvd = 0; 5827 failed_sends = 0; 5828 times_up = 0; 5829 5830 /*set up the data socket */ 5831 data_socket = create_data_socket(local_res); 5832 5833 if (data_socket == INVALID_SOCKET){ 5834 perror("udp_send: data socket"); 5835 exit(1); 5836 } 5837 5838 /* now, we want to see if we need to set the send_size */ 5839 if (send_size == 0) { 5840 if (lss_size > 0) { 5841 send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX); 5842 } 5843 else { 5844 send_size = 4096; 5845 } 5846 } 5847 5848 5849 /* set-up the data buffer with the requested alignment and offset, */ 5850 /* most of the numbers here are just a hack to pick something nice */ 5851 /* and big in an attempt to never try to send a buffer a second time */ 5852 /* before it leaves the node...unless the user set the width */ 5853 /* explicitly. */ 5854 if (send_width == 0) send_width = 32; 5855 5856 if (send_ring == NULL ) { 5857 send_ring = allocate_buffer_ring(send_width, 5858 send_size, 5859 local_send_align, 5860 local_send_offset); 5861 } 5862 5863 5864 /* if the user supplied a cpu rate, this call will complete rather */ 5865 /* quickly, otherwise, the cpu rate will be retured to us for */ 5866 /* possible display. The Library will keep it's own copy of this data */ 5867 /* for use elsewhere. We will only display it. (Does that make it */ 5868 /* "opaque" to us?) */ 5869 5870 if (local_cpu_usage) 5871 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 5872 5873 if (!no_control) { 5874 /* Tell the remote end to set up the data connection. The server 5875 sends back the port number and alters the socket parameters 5876 there. Of course this is a datagram service so no connection 5877 is actually set up, the server just sets up the socket and 5878 binds it. */ 5879 5880 netperf_request.content.request_type = DO_UDP_STREAM; 5881 udp_stream_request->recv_buf_size = rsr_size_req; 5882 udp_stream_request->message_size = send_size; 5883 udp_stream_request->recv_connected = remote_connected; 5884 udp_stream_request->recv_alignment = remote_recv_align; 5885 udp_stream_request->recv_offset = remote_recv_offset; 5886 udp_stream_request->measure_cpu = remote_cpu_usage; 5887 udp_stream_request->cpu_rate = remote_cpu_rate; 5888 udp_stream_request->test_length = test_time; 5889 udp_stream_request->so_rcvavoid = rem_rcvavoid; 5890 udp_stream_request->so_sndavoid = rem_sndavoid; 5891 udp_stream_request->port = atoi(remote_data_port); 5892 udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 5893 5894 send_request(); 5895 5896 recv_response(); 5897 5898 if (!netperf_response.content.serv_errno) { 5899 if (debug) 5900 fprintf(where,"send_udp_stream: remote data connection done.\n"); 5901 } 5902 else { 5903 Set_errno(netperf_response.content.serv_errno); 5904 perror("send_udp_stream: error on remote"); 5905 exit(1); 5906 } 5907 5908 /* Place the port number returned by the remote into the sockaddr */ 5909 /* structure so our sends can be sent to the correct place. Also get */ 5910 /* some of the returned socket buffer information for user display. */ 5911 5912 /* make sure that port numbers are in the proper order */ 5913 set_port_number(remote_res,(short)udp_stream_response->data_port_number); 5914 5915 rsr_size = udp_stream_response->recv_buf_size; 5916 rss_size = udp_stream_response->send_buf_size; 5917 remote_cpu_rate = udp_stream_response->cpu_rate; 5918 } 5919 5920 #ifdef WANT_DEMO 5921 DEMO_STREAM_SETUP(lss_size,rsr_size) 5922 #endif 5923 5924 /* We "connect" up to the remote post to allow is to use the send */ 5925 /* call instead of the sendto call. Presumeably, this is a little */ 5926 /* simpler, and a little more efficient. I think that it also means */ 5927 /* that we can be informed of certain things, but am not sure */ 5928 /* yet...also, this is the way I would expect a client to behave */ 5929 /* when talking to a server */ 5930 if (local_connected) { 5931 if (connect(data_socket, 5932 remote_res->ai_addr, 5933 remote_res->ai_addrlen) == INVALID_SOCKET){ 5934 perror("send_udp_stream: data socket connect failed"); 5935 exit(1); 5936 } else if (debug) { 5937 fprintf(where,"send_udp_stream: connected data socket.\n"); 5938 fflush(where); 5939 } 5940 } 5941 5942 /* set up the timer to call us after test_time. one of these days, */ 5943 /* it might be nice to figure-out a nice reliable way to have the */ 5944 /* test controlled by a byte count as well, but since UDP is not */ 5945 /* reliable, that could prove difficult. so, in the meantime, we */ 5946 /* only allow a UDP_STREAM test to be a timed test. */ 5947 5948 if (test_time) { 5949 times_up = 0; 5950 start_timer(test_time); 5951 } 5952 else { 5953 fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n"); 5954 fflush(where); 5955 } 5956 5957 /* Get the start count for the idle counter and the start time */ 5958 5959 cpu_start(local_cpu_usage); 5960 5961 #ifdef WANT_INTERVALS 5962 INTERVALS_INIT(); 5963 #endif /* WANT_INTERVALS */ 5964 5965 #ifdef WANT_DEMO 5966 if (demo_mode) { 5967 HIST_timestamp(demo_one_ptr); 5968 } 5969 #endif 5970 5971 /* Send datagrams like there was no tomorrow. at somepoint it might */ 5972 /* be nice to set this up so that a quantity of bytes could be sent, */ 5973 /* but we still need some sort of end of test trigger on the receive */ 5974 /* side. that could be a select with a one second timeout, but then */ 5975 /* if there is a test where none of the data arrives for awile and */ 5976 /* then starts again, we would end the test too soon. something to */ 5977 /* think about... */ 5978 while (!times_up) { 5979 5980 #ifdef DIRTY 5981 /* we want to dirty some number of consecutive integers in the buffer */ 5982 /* we are about to send. we may also want to bring some number of */ 5983 /* them cleanly into the cache. The clean ones will follow any dirty */ 5984 /* ones into the cache. */ 5985 5986 access_buffer(send_ring->buffer_ptr, 5987 send_size, 5988 loc_dirty_count, 5989 loc_clean_count); 5990 #endif /* DIRTY */ 5991 5992 #ifdef WANT_HISTOGRAM 5993 if (verbosity > 1) { 5994 HIST_timestamp(&time_one); 5995 } 5996 #endif /* WANT_HISTOGRAM */ 5997 5998 if (local_connected) { 5999 len = send(data_socket, 6000 send_ring->buffer_ptr, 6001 send_size, 6002 0); 6003 } else { 6004 len = sendto(data_socket, 6005 send_ring->buffer_ptr, 6006 send_size, 6007 0, 6008 remote_res->ai_addr, 6009 remote_res->ai_addrlen); 6010 } 6011 6012 if (len != send_size) { 6013 if ((len >= 0) || 6014 SOCKET_EINTR(len)) 6015 break; 6016 if (errno == ENOBUFS) { 6017 failed_sends++; 6018 continue; 6019 } 6020 perror("udp_send: data send error"); 6021 exit(1); 6022 } 6023 messages_sent++; 6024 6025 /* now we want to move our pointer to the next position in the */ 6026 /* data buffer... */ 6027 6028 send_ring = send_ring->next; 6029 6030 6031 #ifdef WANT_HISTOGRAM 6032 if (verbosity > 1) { 6033 /* get the second timestamp */ 6034 HIST_timestamp(&time_two); 6035 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 6036 } 6037 #endif /* WANT_HISTOGRAM */ 6038 6039 #ifdef WANT_DEMO 6040 DEMO_STREAM_INTERVAL(send_size) 6041 #endif 6042 6043 #ifdef WANT_INTERVALS 6044 INTERVALS_WAIT(); 6045 #endif /* WANT_INTERVALS */ 6046 6047 } 6048 6049 /* This is a timed test, so the remote will be returning to us after */ 6050 /* a time. We should not need to send any "strange" messages to tell */ 6051 /* the remote that the test is completed, unless we decide to add a */ 6052 /* number of messages to the test. */ 6053 6054 /* the test is over, so get stats and stuff */ 6055 cpu_stop(local_cpu_usage, 6056 &elapsed_time); 6057 6058 if (!no_control) { 6059 /* Get the statistics from the remote end */ 6060 recv_response(); 6061 if (!netperf_response.content.serv_errno) { 6062 if (debug) 6063 fprintf(where,"send_udp_stream: remote results obtained\n"); 6064 } 6065 else { 6066 Set_errno(netperf_response.content.serv_errno); 6067 perror("send_udp_stream: error on remote"); 6068 exit(1); 6069 } 6070 messages_recvd = udp_stream_results->messages_recvd; 6071 bytes_recvd = (double) send_size * (double) messages_recvd; 6072 } 6073 else { 6074 /* since there was no control connection, we've no idea what was 6075 actually received. raj 2007-02-08 */ 6076 messages_recvd = -1; 6077 bytes_recvd = -1.0; 6078 } 6079 6080 bytes_sent = (double) send_size * (double) messages_sent; 6081 local_thruput = calc_thruput(bytes_sent); 6082 6083 6084 /* we asume that the remote ran for as long as we did */ 6085 6086 remote_thruput = calc_thruput(bytes_recvd); 6087 6088 /* print the results for this socket and message size */ 6089 6090 if (local_cpu_usage || remote_cpu_usage) { 6091 /* We must now do a little math for service demand and cpu */ 6092 /* utilization for the system(s) We pass zeros for the local */ 6093 /* cpu utilization and elapsed time to tell the routine to use */ 6094 /* the libraries own values for those. */ 6095 if (local_cpu_usage) { 6096 local_cpu_utilization = calc_cpu_util(0.0); 6097 /* shouldn't this really be based on bytes_recvd, since that is */ 6098 /* the effective throughput of the test? I think that it should, */ 6099 /* so will make the change raj 11/94 */ 6100 local_service_demand = calc_service_demand(bytes_recvd, 6101 0.0, 6102 0.0, 6103 0); 6104 } 6105 else { 6106 local_cpu_utilization = (float) -1.0; 6107 local_service_demand = (float) -1.0; 6108 } 6109 6110 /* The local calculations could use variables being kept by */ 6111 /* the local netlib routines. The remote calcuations need to */ 6112 /* have a few things passed to them. */ 6113 if (remote_cpu_usage) { 6114 remote_cpu_utilization = udp_stream_results->cpu_util; 6115 remote_service_demand = calc_service_demand(bytes_recvd, 6116 0.0, 6117 remote_cpu_utilization, 6118 udp_stream_results->num_cpus); 6119 } 6120 else { 6121 remote_cpu_utilization = (float) -1.0; 6122 remote_service_demand = (float) -1.0; 6123 } 6124 } 6125 else { 6126 /* we were not measuring cpu, for the confidence stuff, we */ 6127 /* should make it -1.0 */ 6128 local_cpu_utilization = (float) -1.0; 6129 local_service_demand = (float) -1.0; 6130 remote_cpu_utilization = (float) -1.0; 6131 remote_service_demand = (float) -1.0; 6132 } 6133 6134 /* at this point, we want to calculate the confidence information. */ 6135 /* if debugging is on, calculate_confidence will print-out the */ 6136 /* parameters we pass it */ 6137 6138 calculate_confidence(confidence_iteration, 6139 elapsed_time, 6140 remote_thruput, 6141 local_cpu_utilization, 6142 remote_cpu_utilization, 6143 local_service_demand, 6144 remote_service_demand); 6145 6146 /* since the routine calculate_confidence is rather generic, and */ 6147 /* we have a few other parms of interest, we will do a little work */ 6148 /* here to caclulate their average. */ 6149 sum_messages_sent += messages_sent; 6150 sum_messages_recvd += messages_recvd; 6151 sum_failed_sends += failed_sends; 6152 sum_local_thruput += local_thruput; 6153 6154 confidence_iteration++; 6155 6156 /* this datapoint is done, so we don't need the socket any longer */ 6157 close(data_socket); 6158 6159 } 6160 6161 /* we should reach this point once the test is finished */ 6162 6163 retrieve_confident_values(&elapsed_time, 6164 &remote_thruput, 6165 &local_cpu_utilization, 6166 &remote_cpu_utilization, 6167 &local_service_demand, 6168 &remote_service_demand); 6169 6170 /* some of the interesting values aren't covered by the generic */ 6171 /* confidence routine */ 6172 messages_sent = sum_messages_sent / (confidence_iteration -1); 6173 messages_recvd = sum_messages_recvd / (confidence_iteration -1); 6174 failed_sends = sum_failed_sends / (confidence_iteration -1); 6175 local_thruput = sum_local_thruput / (confidence_iteration -1); 6176 6177 /* We are now ready to print all the information. If the user */ 6178 /* has specified zero-level verbosity, we will just print the */ 6179 /* local service demand, or the remote service demand. If the */ 6180 /* user has requested verbosity level 1, he will get the basic */ 6181 /* "streamperf" numbers. If the user has specified a verbosity */ 6182 /* of greater than 1, we will display a veritable plethora of */ 6183 /* background information from outside of this block as it it */ 6184 /* not cpu_measurement specific... */ 6185 6186 6187 if (confidence < 0) { 6188 /* we did not hit confidence, but were we asked to look for it? */ 6189 if (iteration_max > 1) { 6190 display_confidence(); 6191 } 6192 } 6193 6194 if (local_cpu_usage || remote_cpu_usage) { 6195 local_cpu_method = format_cpu_method(cpu_method); 6196 remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method); 6197 6198 switch (verbosity) { 6199 case 0: 6200 if (local_cpu_usage) { 6201 fprintf(where, 6202 cpu_fmt_0, 6203 local_service_demand, 6204 local_cpu_method); 6205 } 6206 else { 6207 fprintf(where, 6208 cpu_fmt_0, 6209 remote_service_demand, 6210 local_cpu_method); 6211 } 6212 break; 6213 case 1: 6214 case 2: 6215 if (print_headers) { 6216 fprintf(where, 6217 cpu_title, 6218 format_units(), 6219 local_cpu_method, 6220 remote_cpu_method); 6221 } 6222 6223 fprintf(where, 6224 cpu_fmt_1, /* the format string */ 6225 lss_size, /* local sendbuf size */ 6226 send_size, /* how large were the sends */ 6227 elapsed_time, /* how long was the test */ 6228 messages_sent, 6229 failed_sends, 6230 local_thruput, /* what was the xfer rate */ 6231 local_cpu_utilization, /* local cpu */ 6232 local_service_demand, /* local service demand */ 6233 rsr_size, 6234 elapsed_time, 6235 messages_recvd, 6236 remote_thruput, 6237 remote_cpu_utilization, /* remote cpu */ 6238 remote_service_demand); /* remote service demand */ 6239 break; 6240 } 6241 } 6242 else { 6243 /* The tester did not wish to measure service demand. */ 6244 switch (verbosity) { 6245 case 0: 6246 fprintf(where, 6247 tput_fmt_0, 6248 local_thruput); 6249 break; 6250 case 1: 6251 case 2: 6252 if (print_headers) { 6253 fprintf(where,tput_title,format_units()); 6254 } 6255 fprintf(where, 6256 tput_fmt_1, /* the format string */ 6257 lss_size, /* local sendbuf size */ 6258 send_size, /* how large were the sends */ 6259 elapsed_time, /* how long did it take */ 6260 messages_sent, 6261 failed_sends, 6262 local_thruput, 6263 rsr_size, /* remote recvbuf size */ 6264 elapsed_time, 6265 messages_recvd, 6266 remote_thruput); 6267 break; 6268 } 6269 } 6270 6271 fflush(where); 6272 #ifdef WANT_HISTOGRAM 6273 if (verbosity > 1) { 6274 fprintf(where,"\nHistogram of time spent in send() call\n"); 6275 fflush(where); 6276 HIST_report(time_hist); 6277 } 6278 #endif /* WANT_HISTOGRAM */ 6279 6280 } 6281 6282 6284 /* this routine implements the receive side (netserver) of the */ 6285 /* UDP_STREAM performance test. */ 6286 6287 void 6288 recv_udp_stream() 6289 { 6290 struct ring_elt *recv_ring; 6291 struct addrinfo *local_res; 6292 char local_name[BUFSIZ]; 6293 char port_buffer[PORTBUFSIZE]; 6294 6295 struct sockaddr_storage myaddr_in; 6296 SOCKET s_data; 6297 netperf_socklen_t addrlen; 6298 struct sockaddr_storage remote_addr; 6299 netperf_socklen_t remote_addrlen; 6300 6301 int len = 0; 6302 unsigned int bytes_received = 0; 6303 float elapsed_time; 6304 6305 int message_size; 6306 unsigned int messages_recvd = 0; 6307 6308 struct udp_stream_request_struct *udp_stream_request; 6309 struct udp_stream_response_struct *udp_stream_response; 6310 struct udp_stream_results_struct *udp_stream_results; 6311 6312 udp_stream_request = 6313 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data; 6314 udp_stream_response = 6315 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data; 6316 udp_stream_results = 6317 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data; 6318 6319 if (debug) { 6320 fprintf(where,"netserver: recv_udp_stream: entered...\n"); 6321 fflush(where); 6322 } 6323 6324 /* We want to set-up the listen socket with all the desired */ 6325 /* parameters and then let the initiator know that all is ready. If */ 6326 /* socket size defaults are to be used, then the initiator will have */ 6327 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 6328 /* send-back what they are. If that information cannot be determined, */ 6329 /* then we send-back -1's for the sizes. If things go wrong for any */ 6330 /* reason, we will drop back ten yards and punt. */ 6331 6332 /* If anything goes wrong, we want the remote to know about it. It */ 6333 /* would be best if the error that the remote reports to the user is */ 6334 /* the actual error we encountered, rather than some bogus unexpected */ 6335 /* response type message. */ 6336 6337 if (debug > 1) { 6338 fprintf(where,"recv_udp_stream: setting the response type...\n"); 6339 fflush(where); 6340 } 6341 6342 netperf_response.content.response_type = UDP_STREAM_RESPONSE; 6343 6344 if (debug > 2) { 6345 fprintf(where,"recv_udp_stream: the response type is set...\n"); 6346 fflush(where); 6347 } 6348 6349 /* We now alter the message_ptr variable to be at the desired */ 6350 /* alignment with the desired offset. */ 6351 6352 if (debug > 1) { 6353 fprintf(where,"recv_udp_stream: requested alignment of %d\n", 6354 udp_stream_request->recv_alignment); 6355 fflush(where); 6356 } 6357 6358 if (recv_width == 0) recv_width = 1; 6359 6360 recv_ring = allocate_buffer_ring(recv_width, 6361 udp_stream_request->message_size, 6362 udp_stream_request->recv_alignment, 6363 udp_stream_request->recv_offset); 6364 6365 if (debug > 1) { 6366 fprintf(where,"recv_udp_stream: receive alignment and offset set...\n"); 6367 fflush(where); 6368 } 6369 6370 /* Grab a socket to listen on, and then listen on it. */ 6371 6372 if (debug > 1) { 6373 fprintf(where,"recv_udp_stream: grabbing a socket...\n"); 6374 fflush(where); 6375 } 6376 6377 /* create_data_socket expects to find some things in the global */ 6378 /* variables, so set the globals based on the values in the request. */ 6379 /* once the socket has been created, we will set the response values */ 6380 /* based on the updated value of those globals. raj 7/94 */ 6381 lsr_size_req = udp_stream_request->recv_buf_size; 6382 loc_rcvavoid = udp_stream_request->so_rcvavoid; 6383 loc_sndavoid = udp_stream_request->so_sndavoid; 6384 local_connected = udp_stream_request->recv_connected; 6385 6386 set_hostname_and_port(local_name, 6387 port_buffer, 6388 nf_to_af(udp_stream_request->ipfamily), 6389 udp_stream_request->port); 6390 6391 local_res = complete_addrinfo(local_name, 6392 local_name, 6393 port_buffer, 6394 nf_to_af(udp_stream_request->ipfamily), 6395 SOCK_DGRAM, 6396 IPPROTO_UDP, 6397 0); 6398 6399 s_data = create_data_socket(local_res); 6400 6401 if (s_data == INVALID_SOCKET) { 6402 netperf_response.content.serv_errno = errno; 6403 send_response(); 6404 exit(1); 6405 } 6406 6407 udp_stream_response->test_length = udp_stream_request->test_length; 6408 6409 /* now get the port number assigned by the system */ 6410 addrlen = sizeof(myaddr_in); 6411 if (getsockname(s_data, 6412 (struct sockaddr *)&myaddr_in, 6413 &addrlen) == SOCKET_ERROR){ 6414 netperf_response.content.serv_errno = errno; 6415 close(s_data); 6416 send_response(); 6417 6418 exit(1); 6419 } 6420 6421 /* Now myaddr_in contains the port and the internet address this is */ 6422 /* returned to the sender also implicitly telling the sender that the */ 6423 /* socket buffer sizing has been done. */ 6424 6425 udp_stream_response->data_port_number = 6426 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 6427 netperf_response.content.serv_errno = 0; 6428 6429 /* But wait, there's more. If the initiator wanted cpu measurements, */ 6430 /* then we must call the calibrate routine, which will return the max */ 6431 /* rate back to the initiator. If the CPU was not to be measured, or */ 6432 /* something went wrong with the calibration, we will return a -1 to */ 6433 /* the initiator. */ 6434 6435 udp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 6436 udp_stream_response->measure_cpu = 0; 6437 if (udp_stream_request->measure_cpu) { 6438 /* We will pass the rate into the calibration routine. If the */ 6439 /* user did not specify one, it will be 0.0, and we will do a */ 6440 /* "real" calibration. Otherwise, all it will really do is */ 6441 /* store it away... */ 6442 udp_stream_response->measure_cpu = 1; 6443 udp_stream_response->cpu_rate = 6444 calibrate_local_cpu(udp_stream_request->cpu_rate); 6445 } 6446 6447 message_size = udp_stream_request->message_size; 6448 test_time = udp_stream_request->test_length; 6449 6450 /* before we send the response back to the initiator, pull some of */ 6451 /* the socket parms from the globals */ 6452 udp_stream_response->send_buf_size = lss_size; 6453 udp_stream_response->recv_buf_size = lsr_size; 6454 udp_stream_response->so_rcvavoid = loc_rcvavoid; 6455 udp_stream_response->so_sndavoid = loc_sndavoid; 6456 6457 send_response(); 6458 6459 /* Now it's time to start receiving data on the connection. We will */ 6460 /* first grab the apropriate counters and then start grabbing. */ 6461 6462 cpu_start(udp_stream_request->measure_cpu); 6463 6464 #ifdef WIN32 6465 /* this is used so the timer thread can close the socket out from */ 6466 /* under us, which to date is the easiest/cleanest/least */ 6467 /* Windows-specific way I can find to force the winsock calls to */ 6468 /* return WSAEINTR with the test is over. anything that will run on */ 6469 /* 95 and NT and is closer to what netperf expects from Unix signals */ 6470 /* and such would be appreciated raj 1/96 */ 6471 win_kludge_socket = s_data; 6472 #endif /* WIN32 */ 6473 6474 /* The loop will exit when the timer pops, or if we happen to recv a */ 6475 /* message of less than send_size bytes... */ 6476 6477 times_up = 0; 6478 6479 start_timer(test_time + PAD_TIME); 6480 6481 if (debug) { 6482 fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n"); 6483 fflush(where); 6484 } 6485 6486 /* We "connect" up to the remote post to allow us to use the recv */ 6487 /* call instead of the recvfrom call. Presumeably, this is a little */ 6488 /* simpler, and a little more efficient. */ 6489 6490 if (local_connected) { 6491 6492 /* Receive the first message using recvfrom to find the remote address */ 6493 remote_addrlen = sizeof(remote_addr); 6494 len = recvfrom(s_data, recv_ring->buffer_ptr, 6495 message_size, 0, 6496 (struct sockaddr*)&remote_addr, &remote_addrlen); 6497 if (len != message_size) { 6498 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) { 6499 netperf_response.content.serv_errno = errno; 6500 send_response(); 6501 exit(1); 6502 } 6503 } 6504 messages_recvd++; 6505 recv_ring = recv_ring->next; 6506 6507 6508 /* Now connect with the remote socket address */ 6509 if (connect(s_data, 6510 (struct sockaddr*)&remote_addr, 6511 remote_addrlen )== INVALID_SOCKET) { 6512 netperf_response.content.serv_errno = errno; 6513 close(s_data); 6514 send_response(); 6515 exit(1); 6516 } 6517 6518 if (debug) { 6519 fprintf(where,"recv_udp_stream: connected data socket\n"); 6520 fflush(where); 6521 } 6522 } 6523 6524 while (!times_up) { 6525 if(local_connected) { 6526 len = recv(s_data, 6527 recv_ring->buffer_ptr, 6528 message_size, 6529 0); 6530 } else { 6531 len = recvfrom(s_data, 6532 recv_ring->buffer_ptr, 6533 message_size, 6534 0,0,0); 6535 } 6536 6537 if (len != message_size) { 6538 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) { 6539 netperf_response.content.serv_errno = errno; 6540 send_response(); 6541 exit(1); 6542 } 6543 break; 6544 } 6545 messages_recvd++; 6546 recv_ring = recv_ring->next; 6547 } 6548 6549 if (debug) { 6550 fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd); 6551 fflush(where); 6552 } 6553 6554 6555 /* The loop now exits due timer or < send_size bytes received. in */ 6556 /* reality, we only really support a timed UDP_STREAM test. raj */ 6557 /* 12/95 */ 6558 6559 cpu_stop(udp_stream_request->measure_cpu,&elapsed_time); 6560 6561 if (times_up) { 6562 /* we ended on a timer, subtract the PAD_TIME */ 6563 elapsed_time -= (float)PAD_TIME; 6564 } 6565 else { 6566 stop_timer(); 6567 } 6568 6569 if (debug) { 6570 fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time); 6571 fflush(where); 6572 } 6573 6574 6575 /* We will count the "off" message that got us out of the loop */ 6576 bytes_received = (messages_recvd * message_size) + len; 6577 6578 /* send the results to the sender */ 6579 6580 if (debug) { 6581 fprintf(where, 6582 "recv_udp_stream: got %d bytes\n", 6583 bytes_received); 6584 fflush(where); 6585 } 6586 6587 netperf_response.content.response_type = UDP_STREAM_RESULTS; 6588 udp_stream_results->bytes_received = htonl(bytes_received); 6589 udp_stream_results->messages_recvd = messages_recvd; 6590 udp_stream_results->elapsed_time = elapsed_time; 6591 udp_stream_results->cpu_method = cpu_method; 6592 udp_stream_results->num_cpus = lib_num_loc_cpus; 6593 if (udp_stream_request->measure_cpu) { 6594 udp_stream_results->cpu_util = calc_cpu_util(elapsed_time); 6595 } 6596 else { 6597 udp_stream_results->cpu_util = (float) -1.0; 6598 } 6599 6600 if (debug > 1) { 6601 fprintf(where, 6602 "recv_udp_stream: test complete, sending results.\n"); 6603 fflush(where); 6604 } 6605 6606 send_response(); 6607 6608 close(s_data); 6609 6610 } 6611 6612 void 6614 send_udp_rr(char remote_host[]) 6615 { 6616 6617 char *tput_title = "\ 6618 Local /Remote\n\ 6619 Socket Size Request Resp. Elapsed Trans.\n\ 6620 Send Recv Size Size Time Rate \n\ 6621 bytes Bytes bytes bytes secs. per sec \n\n"; 6622 6623 char *tput_fmt_0 = 6624 "%7.2f\n"; 6625 6626 char *tput_fmt_1_line_1 = "\ 6627 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 6628 char *tput_fmt_1_line_2 = "\ 6629 %-6d %-6d\n"; 6630 6631 char *cpu_title = "\ 6632 Local /Remote\n\ 6633 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 6634 Send Recv Size Size Time Rate local remote local remote\n\ 6635 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 6636 6637 char *cpu_fmt_0 = 6638 "%6.3f %c\n"; 6639 6640 char *cpu_fmt_1_line_1 = "\ 6641 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 6642 6643 char *cpu_fmt_1_line_2 = "\ 6644 %-6d %-6d\n"; 6645 6646 float elapsed_time; 6647 6648 struct ring_elt *send_ring; 6649 struct ring_elt *recv_ring; 6650 6651 int len; 6652 int nummessages; 6653 SOCKET send_socket; 6654 int trans_remaining; 6655 int bytes_xferd; 6656 6657 int rsp_bytes_recvd; 6658 6659 float local_cpu_utilization; 6660 float local_service_demand; 6661 float remote_cpu_utilization; 6662 float remote_service_demand; 6663 double thruput; 6664 6665 struct addrinfo *local_res; 6666 struct addrinfo *remote_res; 6667 6668 struct udp_rr_request_struct *udp_rr_request; 6669 struct udp_rr_response_struct *udp_rr_response; 6670 struct udp_rr_results_struct *udp_rr_result; 6671 6672 udp_rr_request = 6673 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data; 6674 udp_rr_response = 6675 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data; 6676 udp_rr_result = 6677 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data; 6678 6679 #ifdef WANT_HISTOGRAM 6680 if (verbosity > 1) { 6681 time_hist = HIST_new(); 6682 } 6683 #endif 6684 6685 /* since we are now disconnected from the code that established the */ 6686 /* control socket, and since we want to be able to use different */ 6687 /* protocols and such, we are passed the name of the remote host and */ 6688 /* must turn that into the test specific addressing information. */ 6689 6690 complete_addrinfos(&remote_res, 6691 &local_res, 6692 remote_host, 6693 SOCK_DGRAM, 6694 IPPROTO_UDP, 6695 0); 6696 6697 if ( print_headers ) { 6698 print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res); 6699 } 6700 6701 /* initialize a few counters */ 6702 6703 send_ring = NULL; 6704 recv_ring = NULL; 6705 nummessages = 0; 6706 bytes_xferd = 0; 6707 times_up = 0; 6708 confidence_iteration = 1; 6709 init_stat(); 6710 6711 /* we have a great-big while loop which controls the number of times */ 6712 /* we run a particular test. this is for the calculation of a */ 6713 /* confidence interval (I really should have stayed awake during */ 6714 /* probstats :). If the user did not request confidence measurement */ 6715 /* (no confidence is the default) then we will only go though the */ 6716 /* loop once. the confidence stuff originates from the folks at IBM */ 6717 6718 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 6719 (confidence_iteration <= iteration_min)) { 6720 6721 nummessages = 0; 6722 bytes_xferd = 0; 6723 times_up = 0; 6724 trans_remaining = 0; 6725 6726 /* set-up the data buffers with the requested alignment and offset */ 6727 6728 if (send_width == 0) send_width = 1; 6729 if (recv_width == 0) recv_width = 1; 6730 6731 if (send_ring == NULL) { 6732 send_ring = allocate_buffer_ring(send_width, 6733 req_size, 6734 local_send_align, 6735 local_send_offset); 6736 } 6737 6738 if (recv_ring == NULL) { 6739 recv_ring = allocate_buffer_ring(recv_width, 6740 rsp_size, 6741 local_recv_align, 6742 local_recv_offset); 6743 } 6744 6745 /*set up the data socket */ 6746 send_socket = create_data_socket(local_res); 6747 6748 if (send_socket == INVALID_SOCKET){ 6749 perror("netperf: send_udp_rr: udp rr data socket"); 6750 exit(1); 6751 } 6752 6753 if (debug) { 6754 fprintf(where,"send_udp_rr: send_socket obtained...\n"); 6755 } 6756 6757 /* If the user has requested cpu utilization measurements, we must */ 6758 /* calibrate the cpu(s). We will perform this task within the tests */ 6759 /* themselves. If the user has specified the cpu rate, then */ 6760 /* calibrate_local_cpu will return rather quickly as it will have */ 6761 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 6762 /* all the "normal" calibration stuff and return the rate back. If */ 6763 /* there is no idle counter in the kernel idle loop, the */ 6764 /* local_cpu_rate will be set to -1. */ 6765 6766 if (local_cpu_usage) { 6767 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 6768 } 6769 6770 if (!no_control) { 6771 /* Tell the remote end to do a listen. The server alters the 6772 socket paramters on the other side at this point, hence the 6773 reason for all the values being passed in the setup 6774 message. If the user did not specify any of the parameters, 6775 they will be passed as 0, which will indicate to the remote 6776 that no changes beyond the system's default should be 6777 used. Alignment is the exception, it will default to 8, which 6778 will be no alignment alterations. */ 6779 6780 netperf_request.content.request_type = DO_UDP_RR; 6781 udp_rr_request->recv_buf_size = rsr_size_req; 6782 udp_rr_request->send_buf_size = rss_size_req; 6783 udp_rr_request->recv_alignment = remote_recv_align; 6784 udp_rr_request->recv_offset = remote_recv_offset; 6785 udp_rr_request->send_alignment = remote_send_align; 6786 udp_rr_request->send_offset = remote_send_offset; 6787 udp_rr_request->request_size = req_size; 6788 udp_rr_request->response_size = rsp_size; 6789 udp_rr_request->measure_cpu = remote_cpu_usage; 6790 udp_rr_request->cpu_rate = remote_cpu_rate; 6791 udp_rr_request->so_rcvavoid = rem_rcvavoid; 6792 udp_rr_request->so_sndavoid = rem_sndavoid; 6793 if (test_time) { 6794 udp_rr_request->test_length = test_time; 6795 } 6796 else { 6797 udp_rr_request->test_length = test_trans * -1; 6798 } 6799 udp_rr_request->port = atoi(remote_data_port); 6800 udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 6801 6802 if (debug > 1) { 6803 fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n"); 6804 } 6805 6806 send_request(); 6807 6808 /* The response from the remote will contain all of the relevant 6809 socket parameters for this test type. We will put them back 6810 into the variables here so they can be displayed if desired. 6811 The remote will have calibrated CPU if necessary, and will 6812 have done all the needed set-up we will have calibrated the 6813 cpu locally before sending the request, and will grab the 6814 counter value right after the connect returns. The remote 6815 will grab the counter right after the accept call. This saves 6816 the hassle of extra messages being sent for the UDP 6817 tests. */ 6818 6819 recv_response(); 6820 6821 if (!netperf_response.content.serv_errno) { 6822 if (debug) 6823 fprintf(where,"remote listen done.\n"); 6824 rsr_size = udp_rr_response->recv_buf_size; 6825 rss_size = udp_rr_response->send_buf_size; 6826 remote_cpu_usage = udp_rr_response->measure_cpu; 6827 remote_cpu_rate = udp_rr_response->cpu_rate; 6828 /* port numbers in proper order */ 6829 set_port_number(remote_res,(short)udp_rr_response->data_port_number); 6830 } 6831 else { 6832 Set_errno(netperf_response.content.serv_errno); 6833 fprintf(where, 6834 "netperf: remote error %d", 6835 netperf_response.content.serv_errno); 6836 perror(""); 6837 fflush(where); 6838 exit(1); 6839 } 6840 } 6841 6842 #ifdef WANT_DEMO 6843 DEMO_RR_SETUP(100) 6844 #endif 6845 6846 /* Connect up to the remote port on the data socket. This will set */ 6847 /* the default destination address on this socket. With UDP, this */ 6848 /* does make a performance difference as we may not have to do as */ 6849 /* many routing lookups, however, I expect that a client would */ 6850 /* behave this way. raj 1/94 */ 6851 6852 if ( connect(send_socket, 6853 remote_res->ai_addr, 6854 remote_res->ai_addrlen) == INVALID_SOCKET ) { 6855 perror("netperf: data socket connect failed"); 6856 exit(1); 6857 } 6858 6859 /* Data Socket set-up is finished. If there were problems, either the */ 6860 /* connect would have failed, or the previous response would have */ 6861 /* indicated a problem. I failed to see the value of the extra */ 6862 /* message after the accept on the remote. If it failed, we'll see it */ 6863 /* here. If it didn't, we might as well start pumping data. */ 6864 6865 /* Set-up the test end conditions. For a request/response test, they */ 6866 /* can be either time or transaction based. */ 6867 6868 if (test_time) { 6869 /* The user wanted to end the test after a period of time. */ 6870 times_up = 0; 6871 trans_remaining = 0; 6872 start_timer(test_time); 6873 } 6874 else { 6875 /* The tester wanted to send a number of bytes. */ 6876 trans_remaining = test_bytes; 6877 times_up = 1; 6878 } 6879 6880 /* The cpu_start routine will grab the current time and possibly */ 6881 /* value of the idle counter for later use in measuring cpu */ 6882 /* utilization and/or service demand and thruput. */ 6883 6884 cpu_start(local_cpu_usage); 6885 6886 #ifdef WANT_DEMO 6887 if (demo_mode) { 6888 HIST_timestamp(demo_one_ptr); 6889 } 6890 #endif 6891 6892 #ifdef WANT_INTERVALS 6893 INTERVALS_INIT(); 6894 #endif /* WANT_INTERVALS */ 6895 6896 /* We use an "OR" to control test execution. When the test is */ 6897 /* controlled by time, the byte count check will always return */ 6898 /* false. When the test is controlled by byte count, the time test */ 6899 /* will always return false. When the test is finished, the whole */ 6900 /* expression will go false and we will stop sending data. I think */ 6901 /* I just arbitrarily decrement trans_remaining for the timed */ 6902 /* test, but will not do that just yet... One other question is */ 6903 /* whether or not the send buffer and the receive buffer should be */ 6904 /* the same buffer. */ 6905 6906 #ifdef WANT_FIRST_BURST 6907 { 6908 int i; 6909 for (i = 0; i < first_burst_size; i++) { 6910 if((len=send(send_socket, 6911 send_ring->buffer_ptr, 6912 req_size, 6913 0)) != req_size) { 6914 /* we should never hit the end of the test in the first burst */ 6915 perror("send_udp_rr: initial burst data send error"); 6916 exit(-1); 6917 } 6918 } 6919 } 6920 #endif /* WANT_FIRST_BURST */ 6921 6922 while ((!times_up) || (trans_remaining > 0)) { 6923 /* send the request */ 6924 #ifdef WANT_HISTOGRAM 6925 if (verbosity > 1) { 6926 HIST_timestamp(&time_one); 6927 } 6928 #endif 6929 if((len=send(send_socket, 6930 send_ring->buffer_ptr, 6931 req_size, 6932 0)) != req_size) { 6933 if (SOCKET_EINTR(len)) { 6934 /* We likely hit */ 6935 /* test-end time. */ 6936 break; 6937 } 6938 perror("send_udp_rr: data send error"); 6939 exit(1); 6940 } 6941 send_ring = send_ring->next; 6942 6943 /* receive the response. with UDP we will get it all, or nothing */ 6944 6945 if((rsp_bytes_recvd=recv(send_socket, 6946 recv_ring->buffer_ptr, 6947 rsp_size, 6948 0)) != rsp_size) { 6949 if (SOCKET_EINTR(rsp_bytes_recvd)) 6950 { 6951 /* Again, we have likely hit test-end time */ 6952 break; 6953 } 6954 perror("send_udp_rr: data recv error"); 6955 exit(1); 6956 } 6957 recv_ring = recv_ring->next; 6958 6959 #ifdef WANT_HISTOGRAM 6960 if (verbosity > 1) { 6961 HIST_timestamp(&time_two); 6962 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 6963 } 6964 6965 #endif 6966 6967 /* at this point, we may wish to sleep for some period of */ 6968 /* time, so we see how long that last transaction just took, */ 6969 /* and sleep for the difference of that and the interval. We */ 6970 /* will not sleep if the time would be less than a */ 6971 /* millisecond. */ 6972 6973 #ifdef WANT_DEMO 6974 DEMO_RR_INTERVAL(1); 6975 #endif 6976 6977 #ifdef WANT_INTERVALS 6978 INTERVALS_WAIT(); 6979 #endif /* WANT_INTERVALS */ 6980 6981 nummessages++; 6982 if (trans_remaining) { 6983 trans_remaining--; 6984 } 6985 6986 if (debug > 3) { 6987 if ((nummessages % 100) == 0) { 6988 fprintf(where,"Transaction %d completed\n",nummessages); 6989 fflush(where); 6990 } 6991 } 6992 6993 } 6994 6995 /* for some strange reason, I used to call shutdown on the UDP */ 6996 /* data socket here. I'm not sure why, because it would not have */ 6997 /* any effect... raj 11/94 */ 6998 6999 /* this call will always give us the elapsed time for the test, and */ 7000 /* will also store-away the necessaries for cpu utilization */ 7001 7002 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 7003 /* measured? how long */ 7004 /* did we really run? */ 7005 7006 if (!no_control) { 7007 /* Get the statistics from the remote end. The remote will have 7008 calculated service demand and all those interesting 7009 things. If it wasn't supposed to care, it will return obvious 7010 values. */ 7011 7012 recv_response(); 7013 if (!netperf_response.content.serv_errno) { 7014 if (debug) 7015 fprintf(where,"remote results obtained\n"); 7016 } 7017 else { 7018 Set_errno(netperf_response.content.serv_errno); 7019 fprintf(where, 7020 "netperf: remote error %d", 7021 netperf_response.content.serv_errno); 7022 perror(""); 7023 fflush(where); 7024 exit(1); 7025 } 7026 } 7027 7028 /* We now calculate what our thruput was for the test. In the */ 7029 /* future, we may want to include a calculation of the thruput */ 7030 /* measured by the remote, but it should be the case that for a */ 7031 /* UDP rr test, that the two numbers should be *very* close... */ 7032 /* We calculate bytes_sent regardless of the way the test length */ 7033 /* was controlled. */ 7034 7035 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 7036 thruput = nummessages / elapsed_time; 7037 7038 if (local_cpu_usage || remote_cpu_usage) { 7039 7040 /* We must now do a little math for service demand and cpu */ 7041 /* utilization for the system(s) Of course, some of the */ 7042 /* information might be bogus because there was no idle counter */ 7043 /* in the kernel(s). We need to make a note of this for the */ 7044 /* user's benefit by placing a code for the metod used in the */ 7045 /* test banner */ 7046 7047 if (local_cpu_usage) { 7048 local_cpu_utilization = calc_cpu_util(0.0); 7049 7050 /* since calc_service demand is doing ms/Kunit we will */ 7051 /* multiply the number of transaction by 1024 to get */ 7052 /* "good" numbers */ 7053 7054 local_service_demand = calc_service_demand((double) nummessages*1024, 7055 0.0, 7056 0.0, 7057 0); 7058 } 7059 else { 7060 local_cpu_utilization = (float) -1.0; 7061 local_service_demand = (float) -1.0; 7062 } 7063 7064 if (remote_cpu_usage) { 7065 remote_cpu_utilization = udp_rr_result->cpu_util; 7066 7067 /* since calc_service demand is doing ms/Kunit we will */ 7068 /* multiply the number of transaction by 1024 to get */ 7069 /* "good" numbers */ 7070 7071 remote_service_demand = calc_service_demand((double) nummessages*1024, 7072 0.0, 7073 remote_cpu_utilization, 7074 udp_rr_result->num_cpus); 7075 } 7076 else { 7077 remote_cpu_utilization = (float) -1.0; 7078 remote_service_demand = (float) -1.0; 7079 } 7080 } 7081 else { 7082 /* we were not measuring cpu, for the confidence stuff, we */ 7083 /* should make it -1.0 */ 7084 local_cpu_utilization = (float) -1.0; 7085 local_service_demand = (float) -1.0; 7086 remote_cpu_utilization = (float) -1.0; 7087 remote_service_demand = (float) -1.0; 7088 } 7089 7090 /* at this point, we want to calculate the confidence information. */ 7091 /* if debugging is on, calculate_confidence will print-out the */ 7092 /* parameters we pass it */ 7093 7094 calculate_confidence(confidence_iteration, 7095 elapsed_time, 7096 thruput, 7097 local_cpu_utilization, 7098 remote_cpu_utilization, 7099 local_service_demand, 7100 remote_service_demand); 7101 7102 7103 confidence_iteration++; 7104 7105 /* we are done with the socket */ 7106 close(send_socket); 7107 } 7108 7109 /* at this point, we have made all the iterations we are going to */ 7110 /* make. */ 7111 retrieve_confident_values(&elapsed_time, 7112 &thruput, 7113 &local_cpu_utilization, 7114 &remote_cpu_utilization, 7115 &local_service_demand, 7116 &remote_service_demand); 7117 7118 /* We are now ready to print all the information. If the user */ 7119 /* has specified zero-level verbosity, we will just print the */ 7120 /* local service demand, or the remote service demand. If the */ 7121 /* user has requested verbosity level 1, he will get the basic */ 7122 /* "streamperf" numbers. If the user has specified a verbosity */ 7123 /* of greater than 1, we will display a veritable plethora of */ 7124 /* background information from outside of this block as it it */ 7125 /* not cpu_measurement specific... */ 7126 7127 if (confidence < 0) { 7128 /* we did not hit confidence, but were we asked to look for it? */ 7129 if (iteration_max > 1) { 7130 display_confidence(); 7131 } 7132 } 7133 7134 if (local_cpu_usage || remote_cpu_usage) { 7135 local_cpu_method = format_cpu_method(cpu_method); 7136 remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method); 7137 7138 switch (verbosity) { 7139 case 0: 7140 if (local_cpu_usage) { 7141 fprintf(where, 7142 cpu_fmt_0, 7143 local_service_demand, 7144 local_cpu_method); 7145 } 7146 else { 7147 fprintf(where, 7148 cpu_fmt_0, 7149 remote_service_demand, 7150 remote_cpu_method); 7151 } 7152 break; 7153 case 1: 7154 case 2: 7155 if (print_headers) { 7156 fprintf(where, 7157 cpu_title, 7158 local_cpu_method, 7159 remote_cpu_method); 7160 } 7161 7162 fprintf(where, 7163 cpu_fmt_1_line_1, /* the format string */ 7164 lss_size, /* local sendbuf size */ 7165 lsr_size, 7166 req_size, /* how large were the requests */ 7167 rsp_size, /* guess */ 7168 elapsed_time, /* how long was the test */ 7169 nummessages/elapsed_time, 7170 local_cpu_utilization, /* local cpu */ 7171 remote_cpu_utilization, /* remote cpu */ 7172 local_service_demand, /* local service demand */ 7173 remote_service_demand); /* remote service demand */ 7174 fprintf(where, 7175 cpu_fmt_1_line_2, 7176 rss_size, 7177 rsr_size); 7178 break; 7179 } 7180 } 7181 else { 7182 /* The tester did not wish to measure service demand. */ 7183 switch (verbosity) { 7184 case 0: 7185 fprintf(where, 7186 tput_fmt_0, 7187 nummessages/elapsed_time); 7188 break; 7189 case 1: 7190 case 2: 7191 if (print_headers) { 7192 fprintf(where,tput_title,format_units()); 7193 } 7194 7195 fprintf(where, 7196 tput_fmt_1_line_1, /* the format string */ 7197 lss_size, 7198 lsr_size, 7199 req_size, /* how large were the requests */ 7200 rsp_size, /* how large were the responses */ 7201 elapsed_time, /* how long did it take */ 7202 nummessages/elapsed_time); 7203 fprintf(where, 7204 tput_fmt_1_line_2, 7205 rss_size, /* remote recvbuf size */ 7206 rsr_size); 7207 7208 break; 7209 } 7210 } 7211 fflush(where); 7212 7213 /* it would be a good thing to include information about some of the */ 7214 /* other parameters that may have been set for this test, but at the */ 7215 /* moment, I do not wish to figure-out all the formatting, so I will */ 7216 /* just put this comment here to help remind me that it is something */ 7217 /* that should be done at a later time. */ 7218 7219 /* how to handle the verbose information in the presence of */ 7220 /* confidence intervals is yet to be determined... raj 11/94 */ 7221 7222 if (verbosity > 1) { 7223 /* The user wanted to know it all, so we will give it to him. */ 7224 /* This information will include as much as we can find about */ 7225 /* UDP statistics, the alignments of the sends and receives */ 7226 /* and all that sort of rot... */ 7227 7228 #ifdef WANT_HISTOGRAM 7229 fprintf(where,"\nHistogram of request/reponse times.\n"); 7230 fflush(where); 7231 HIST_report(time_hist); 7232 #endif /* WANT_HISTOGRAM */ 7233 } 7234 } 7235 7236 /* this routine implements the receive side (netserver) of a UDP_RR */ 7238 /* test. */ 7239 void 7240 recv_udp_rr() 7241 { 7242 7243 struct ring_elt *recv_ring; 7244 struct ring_elt *send_ring; 7245 7246 struct addrinfo *local_res; 7247 char local_name[BUFSIZ]; 7248 char port_buffer[PORTBUFSIZE]; 7249 7250 struct sockaddr_storage myaddr_in; 7251 struct sockaddr_storage peeraddr; 7252 SOCKET s_data; 7253 netperf_socklen_t addrlen; 7254 int trans_received; 7255 int trans_remaining; 7256 int request_bytes_recvd; 7257 int response_bytes_sent; 7258 float elapsed_time; 7259 7260 struct udp_rr_request_struct *udp_rr_request; 7261 struct udp_rr_response_struct *udp_rr_response; 7262 struct udp_rr_results_struct *udp_rr_results; 7263 7264 udp_rr_request = 7265 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data; 7266 udp_rr_response = 7267 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data; 7268 udp_rr_results = 7269 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data; 7270 7271 if (debug) { 7272 fprintf(where,"netserver: recv_udp_rr: entered...\n"); 7273 fflush(where); 7274 } 7275 7276 /* We want to set-up the listen socket with all the desired */ 7277 /* parameters and then let the initiator know that all is ready. If */ 7278 /* socket size defaults are to be used, then the initiator will have */ 7279 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 7280 /* send-back what they are. If that information cannot be determined, */ 7281 /* then we send-back -1's for the sizes. If things go wrong for any */ 7282 /* reason, we will drop back ten yards and punt. */ 7283 7284 /* If anything goes wrong, we want the remote to know about it. It */ 7285 /* would be best if the error that the remote reports to the user is */ 7286 /* the actual error we encountered, rather than some bogus unexpected */ 7287 /* response type message. */ 7288 7289 if (debug) { 7290 fprintf(where,"recv_udp_rr: setting the response type...\n"); 7291 fflush(where); 7292 } 7293 7294 netperf_response.content.response_type = UDP_RR_RESPONSE; 7295 7296 if (debug) { 7297 fprintf(where,"recv_udp_rr: the response type is set...\n"); 7298 fflush(where); 7299 } 7300 7301 /* We now alter the message_ptr variables to be at the desired */ 7302 /* alignments with the desired offsets. */ 7303 7304 if (debug) { 7305 fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n", 7306 udp_rr_request->recv_alignment, 7307 udp_rr_request->recv_offset); 7308 fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n", 7309 udp_rr_request->send_alignment, 7310 udp_rr_request->send_offset); 7311 fflush(where); 7312 } 7313 7314 if (send_width == 0) send_width = 1; 7315 if (recv_width == 0) recv_width = 1; 7316 7317 recv_ring = allocate_buffer_ring(recv_width, 7318 udp_rr_request->request_size, 7319 udp_rr_request->recv_alignment, 7320 udp_rr_request->recv_offset); 7321 7322 send_ring = allocate_buffer_ring(send_width, 7323 udp_rr_request->response_size, 7324 udp_rr_request->send_alignment, 7325 udp_rr_request->send_offset); 7326 7327 if (debug) { 7328 fprintf(where,"recv_udp_rr: receive alignment and offset set...\n"); 7329 fflush(where); 7330 } 7331 7332 /* Grab a socket to listen on, and then listen on it. */ 7333 7334 if (debug) { 7335 fprintf(where,"recv_udp_rr: grabbing a socket...\n"); 7336 fflush(where); 7337 } 7338 7339 7340 /* create_data_socket expects to find some things in the global */ 7341 /* variables, so set the globals based on the values in the request. */ 7342 /* once the socket has been created, we will set the response values */ 7343 /* based on the updated value of those globals. raj 7/94 */ 7344 lss_size_req = udp_rr_request->send_buf_size; 7345 lsr_size_req = udp_rr_request->recv_buf_size; 7346 loc_rcvavoid = udp_rr_request->so_rcvavoid; 7347 loc_sndavoid = udp_rr_request->so_sndavoid; 7348 7349 set_hostname_and_port(local_name, 7350 port_buffer, 7351 nf_to_af(udp_rr_request->ipfamily), 7352 udp_rr_request->port); 7353 7354 local_res = complete_addrinfo(local_name, 7355 local_name, 7356 port_buffer, 7357 nf_to_af(udp_rr_request->ipfamily), 7358 SOCK_DGRAM, 7359 IPPROTO_UDP, 7360 0); 7361 7362 s_data = create_data_socket(local_res); 7363 7364 if (s_data == INVALID_SOCKET) { 7365 netperf_response.content.serv_errno = errno; 7366 send_response(); 7367 7368 exit(1); 7369 } 7370 7371 /* now get the port number assigned by the system */ 7372 addrlen = sizeof(myaddr_in); 7373 if (getsockname(s_data, 7374 (struct sockaddr *)&myaddr_in, 7375 &addrlen) == SOCKET_ERROR){ 7376 netperf_response.content.serv_errno = errno; 7377 close(s_data); 7378 send_response(); 7379 7380 exit(1); 7381 } 7382 7383 /* Now myaddr_in contains the port and the internet address this is */ 7384 /* returned to the sender also implicitly telling the sender that the */ 7385 /* socket buffer sizing has been done. */ 7386 7387 udp_rr_response->data_port_number = 7388 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 7389 netperf_response.content.serv_errno = 0; 7390 7391 if (debug) { 7392 fprintf(where, 7393 "recv port number %d\n", 7394 ((struct sockaddr_in *)&myaddr_in)->sin_port); 7395 fflush(where); 7396 } 7397 7398 /* But wait, there's more. If the initiator wanted cpu measurements, */ 7399 /* then we must call the calibrate routine, which will return the max */ 7400 /* rate back to the initiator. If the CPU was not to be measured, or */ 7401 /* something went wrong with the calibration, we will return a 0.0 to */ 7402 /* the initiator. */ 7403 7404 udp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 7405 udp_rr_response->measure_cpu = 0; 7406 if (udp_rr_request->measure_cpu) { 7407 udp_rr_response->measure_cpu = 1; 7408 udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate); 7409 } 7410 7411 /* before we send the response back to the initiator, pull some of */ 7412 /* the socket parms from the globals */ 7413 udp_rr_response->send_buf_size = lss_size; 7414 udp_rr_response->recv_buf_size = lsr_size; 7415 udp_rr_response->so_rcvavoid = loc_rcvavoid; 7416 udp_rr_response->so_sndavoid = loc_sndavoid; 7417 7418 send_response(); 7419 7420 7421 /* Now it's time to start receiving data on the connection. We will */ 7422 /* first grab the apropriate counters and then start grabbing. */ 7423 7424 cpu_start(udp_rr_request->measure_cpu); 7425 7426 #ifdef WIN32 7427 /* this is used so the timer thread can close the socket out from */ 7428 /* under us, which to date is the easiest/cleanest/least */ 7429 /* Windows-specific way I can find to force the winsock calls to */ 7430 /* return WSAEINTR with the test is over. anything that will run on */ 7431 /* 95 and NT and is closer to what netperf expects from Unix signals */ 7432 /* and such would be appreciated raj 1/96 */ 7433 win_kludge_socket = s_data; 7434 #endif /* WIN32 */ 7435 7436 if (udp_rr_request->test_length > 0) { 7437 times_up = 0; 7438 trans_remaining = 0; 7439 start_timer(udp_rr_request->test_length + PAD_TIME); 7440 } 7441 else { 7442 times_up = 1; 7443 trans_remaining = udp_rr_request->test_length * -1; 7444 } 7445 7446 addrlen = sizeof(peeraddr); 7447 bzero((char *)&peeraddr, addrlen); 7448 7449 trans_received = 0; 7450 7451 while ((!times_up) || (trans_remaining > 0)) { 7452 7453 /* receive the request from the other side */ 7454 if ((request_bytes_recvd = recvfrom(s_data, 7455 recv_ring->buffer_ptr, 7456 udp_rr_request->request_size, 7457 0, 7458 (struct sockaddr *)&peeraddr, 7459 &addrlen)) != udp_rr_request->request_size) { 7460 if ( SOCKET_EINTR(request_bytes_recvd) ) 7461 { 7462 /* we must have hit the end of test time. */ 7463 break; 7464 } 7465 netperf_response.content.serv_errno = errno; 7466 send_response(); 7467 exit(1); 7468 } 7469 recv_ring = recv_ring->next; 7470 7471 /* Now, send the response to the remote */ 7472 if ((response_bytes_sent = sendto(s_data, 7473 send_ring->buffer_ptr, 7474 udp_rr_request->response_size, 7475 0, 7476 (struct sockaddr *)&peeraddr, 7477 addrlen)) != 7478 udp_rr_request->response_size) { 7479 if ( SOCKET_EINTR(response_bytes_sent) ) 7480 { 7481 /* we have hit end of test time. */ 7482 break; 7483 } 7484 netperf_response.content.serv_errno = errno; 7485 send_response(); 7486 exit(1); 7487 } 7488 send_ring = send_ring->next; 7489 7490 trans_received++; 7491 if (trans_remaining) { 7492 trans_remaining--; 7493 } 7494 7495 if (debug) { 7496 fprintf(where, 7497 "recv_udp_rr: Transaction %d complete.\n", 7498 trans_received); 7499 fflush(where); 7500 } 7501 7502 } 7503 7504 7505 /* The loop now exits due to timeout or transaction count being */ 7506 /* reached */ 7507 7508 cpu_stop(udp_rr_request->measure_cpu,&elapsed_time); 7509 7510 if (times_up) { 7511 /* we ended the test by time, which was at least 2 seconds */ 7512 /* longer than we wanted to run. so, we want to subtract */ 7513 /* PAD_TIME from the elapsed_time. */ 7514 elapsed_time -= PAD_TIME; 7515 } 7516 /* send the results to the sender */ 7517 7518 if (debug) { 7519 fprintf(where, 7520 "recv_udp_rr: got %d transactions\n", 7521 trans_received); 7522 fflush(where); 7523 } 7524 7525 udp_rr_results->bytes_received = (trans_received * 7526 (udp_rr_request->request_size + 7527 udp_rr_request->response_size)); 7528 udp_rr_results->trans_received = trans_received; 7529 udp_rr_results->elapsed_time = elapsed_time; 7530 udp_rr_results->cpu_method = cpu_method; 7531 udp_rr_results->num_cpus = lib_num_loc_cpus; 7532 if (udp_rr_request->measure_cpu) { 7533 udp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 7534 } 7535 7536 if (debug) { 7537 fprintf(where, 7538 "recv_udp_rr: test complete, sending results.\n"); 7539 fflush(where); 7540 } 7541 7542 send_response(); 7543 7544 /* we are done with the socket now */ 7545 close(s_data); 7546 7547 } 7548 7549 7550 /* this routine implements the receive (netserver) side of a TCP_RR */ 7552 /* test */ 7553 void 7554 recv_tcp_rr() 7555 { 7556 7557 struct ring_elt *send_ring; 7558 struct ring_elt *recv_ring; 7559 7560 struct addrinfo *local_res; 7561 char local_name[BUFSIZ]; 7562 char port_buffer[PORTBUFSIZE]; 7563 7564 struct sockaddr_storage myaddr_in, 7565 peeraddr_in; 7566 SOCKET s_listen,s_data; 7567 netperf_socklen_t addrlen; 7568 char *temp_message_ptr; 7569 int trans_received; 7570 int trans_remaining; 7571 int bytes_sent; 7572 int request_bytes_recvd; 7573 int request_bytes_remaining; 7574 int timed_out = 0; 7575 int sock_closed = 0; 7576 float elapsed_time; 7577 7578 struct tcp_rr_request_struct *tcp_rr_request; 7579 struct tcp_rr_response_struct *tcp_rr_response; 7580 struct tcp_rr_results_struct *tcp_rr_results; 7581 7582 tcp_rr_request = 7583 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 7584 tcp_rr_response = 7585 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 7586 tcp_rr_results = 7587 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 7588 7589 if (debug) { 7590 fprintf(where,"netserver: recv_tcp_rr: entered...\n"); 7591 fflush(where); 7592 } 7593 7594 /* We want to set-up the listen socket with all the desired */ 7595 /* parameters and then let the initiator know that all is ready. If */ 7596 /* socket size defaults are to be used, then the initiator will have */ 7597 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 7598 /* send-back what they are. If that information cannot be determined, */ 7599 /* then we send-back -1's for the sizes. If things go wrong for any */ 7600 /* reason, we will drop back ten yards and punt. */ 7601 7602 /* If anything goes wrong, we want the remote to know about it. It */ 7603 /* would be best if the error that the remote reports to the user is */ 7604 /* the actual error we encountered, rather than some bogus unexpected */ 7605 /* response type message. */ 7606 7607 if (debug) { 7608 fprintf(where,"recv_tcp_rr: setting the response type...\n"); 7609 fflush(where); 7610 } 7611 7612 netperf_response.content.response_type = TCP_RR_RESPONSE; 7613 7614 if (debug) { 7615 fprintf(where,"recv_tcp_rr: the response type is set...\n"); 7616 fflush(where); 7617 } 7618 7619 /* allocate the recv and send rings with the requested alignments */ 7620 /* and offsets. raj 7/94 */ 7621 if (debug) { 7622 fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n", 7623 tcp_rr_request->recv_alignment, 7624 tcp_rr_request->recv_offset); 7625 fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n", 7626 tcp_rr_request->send_alignment, 7627 tcp_rr_request->send_offset); 7628 fflush(where); 7629 } 7630 7631 /* at some point, these need to come to us from the remote system */ 7632 if (send_width == 0) send_width = 1; 7633 if (recv_width == 0) recv_width = 1; 7634 7635 send_ring = allocate_buffer_ring(send_width, 7636 tcp_rr_request->response_size, 7637 tcp_rr_request->send_alignment, 7638 tcp_rr_request->send_offset); 7639 7640 recv_ring = allocate_buffer_ring(recv_width, 7641 tcp_rr_request->request_size, 7642 tcp_rr_request->recv_alignment, 7643 tcp_rr_request->recv_offset); 7644 7645 7646 /* Grab a socket to listen on, and then listen on it. */ 7647 7648 if (debug) { 7649 fprintf(where,"recv_tcp_rr: grabbing a socket...\n"); 7650 fflush(where); 7651 } 7652 7653 /* create_data_socket expects to find some things in the global */ 7654 /* variables, so set the globals based on the values in the request. */ 7655 /* once the socket has been created, we will set the response values */ 7656 /* based on the updated value of those globals. raj 7/94 */ 7657 lss_size_req = tcp_rr_request->send_buf_size; 7658 lsr_size_req = tcp_rr_request->recv_buf_size; 7659 loc_nodelay = tcp_rr_request->no_delay; 7660 loc_rcvavoid = tcp_rr_request->so_rcvavoid; 7661 loc_sndavoid = tcp_rr_request->so_sndavoid; 7662 7663 set_hostname_and_port(local_name, 7664 port_buffer, 7665 nf_to_af(tcp_rr_request->ipfamily), 7666 tcp_rr_request->port); 7667 7668 local_res = complete_addrinfo(local_name, 7669 local_name, 7670 port_buffer, 7671 nf_to_af(tcp_rr_request->ipfamily), 7672 SOCK_STREAM, 7673 IPPROTO_TCP, 7674 0); 7675 7676 s_listen = create_data_socket(local_res); 7677 7678 if (s_listen == INVALID_SOCKET) { 7679 netperf_response.content.serv_errno = errno; 7680 send_response(); 7681 7682 exit(1); 7683 } 7684 7685 7686 #ifdef WIN32 7687 /* The test timer can fire during operations on the listening socket, 7688 so to make the start_timer below work we have to move 7689 it to close s_listen while we are blocked on accept. */ 7690 win_kludge_socket2 = s_listen; 7691 #endif 7692 7693 7694 /* Now, let's set-up the socket to listen for connections */ 7695 if (listen(s_listen, 5) == SOCKET_ERROR) { 7696 netperf_response.content.serv_errno = errno; 7697 close(s_listen); 7698 send_response(); 7699 7700 exit(1); 7701 } 7702 7703 7704 /* now get the port number assigned by the system */ 7705 addrlen = sizeof(myaddr_in); 7706 if (getsockname(s_listen, 7707 (struct sockaddr *)&myaddr_in, 7708 &addrlen) == SOCKET_ERROR) { 7709 netperf_response.content.serv_errno = errno; 7710 close(s_listen); 7711 send_response(); 7712 7713 exit(1); 7714 } 7715 7716 /* Now myaddr_in contains the port and the internet address this is */ 7717 /* returned to the sender also implicitly telling the sender that the */ 7718 /* socket buffer sizing has been done. */ 7719 7720 tcp_rr_response->data_port_number = 7721 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 7722 netperf_response.content.serv_errno = 0; 7723 7724 /* But wait, there's more. If the initiator wanted cpu measurements, */ 7725 /* then we must call the calibrate routine, which will return the max */ 7726 /* rate back to the initiator. If the CPU was not to be measured, or */ 7727 /* something went wrong with the calibration, we will return a 0.0 to */ 7728 /* the initiator. */ 7729 7730 tcp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 7731 tcp_rr_response->measure_cpu = 0; 7732 7733 if (tcp_rr_request->measure_cpu) { 7734 tcp_rr_response->measure_cpu = 1; 7735 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate); 7736 } 7737 7738 7739 /* before we send the response back to the initiator, pull some of */ 7740 /* the socket parms from the globals */ 7741 tcp_rr_response->send_buf_size = lss_size; 7742 tcp_rr_response->recv_buf_size = lsr_size; 7743 tcp_rr_response->no_delay = loc_nodelay; 7744 tcp_rr_response->so_rcvavoid = loc_rcvavoid; 7745 tcp_rr_response->so_sndavoid = loc_sndavoid; 7746 tcp_rr_response->test_length = tcp_rr_request->test_length; 7747 send_response(); 7748 7749 addrlen = sizeof(peeraddr_in); 7750 7751 if ((s_data = accept(s_listen, 7752 (struct sockaddr *)&peeraddr_in, 7753 &addrlen)) == INVALID_SOCKET) { 7754 /* Let's just punt. The remote will be given some information */ 7755 close(s_listen); 7756 7757 exit(1); 7758 } 7759 7760 #ifdef KLUDGE_SOCKET_OPTIONS 7761 /* this is for those systems which *INCORRECTLY* fail to pass */ 7762 /* attributes across an accept() call. Including this goes against */ 7763 /* my better judgement :( raj 11/95 */ 7764 7765 kludge_socket_options(s_data); 7766 7767 #endif /* KLUDGE_SOCKET_OPTIONS */ 7768 7769 #ifdef WIN32 7770 /* this is used so the timer thread can close the socket out from */ 7771 /* under us, which to date is the easiest/cleanest/least */ 7772 /* Windows-specific way I can find to force the winsock calls to */ 7773 /* return WSAEINTR with the test is over. anything that will run on */ 7774 /* 95 and NT and is closer to what netperf expects from Unix signals */ 7775 /* and such would be appreciated raj 1/96 */ 7776 win_kludge_socket = s_data; 7777 #endif /* WIN32 */ 7778 7779 if (debug) { 7780 fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n"); 7781 fflush(where); 7782 } 7783 7784 /* Now it's time to start receiving data on the connection. We will */ 7785 /* first grab the apropriate counters and then start grabbing. */ 7786 7787 cpu_start(tcp_rr_request->measure_cpu); 7788 7789 /* The loop will exit when we hit the end of the test time, or when */ 7790 /* we have exchanged the requested number of transactions. */ 7791 7792 if (tcp_rr_request->test_length > 0) { 7793 times_up = 0; 7794 trans_remaining = 0; 7795 start_timer(tcp_rr_request->test_length + PAD_TIME); 7796 } 7797 else { 7798 times_up = 1; 7799 trans_remaining = tcp_rr_request->test_length * -1; 7800 } 7801 7802 trans_received = 0; 7803 7804 while ((!times_up) || (trans_remaining > 0)) { 7805 temp_message_ptr = recv_ring->buffer_ptr; 7806 request_bytes_remaining = tcp_rr_request->request_size; 7807 while(request_bytes_remaining > 0) { 7808 if((request_bytes_recvd=recv(s_data, 7809 temp_message_ptr, 7810 request_bytes_remaining, 7811 0)) == SOCKET_ERROR) { 7812 if (SOCKET_EINTR(request_bytes_recvd)) 7813 { 7814 timed_out = 1; 7815 break; 7816 } 7817 7818 netperf_response.content.serv_errno = errno; 7819 send_response(); 7820 exit(1); 7821 } 7822 else if( request_bytes_recvd == 0 ) { 7823 if (debug) { 7824 fprintf(where,"zero is my hero\n"); 7825 fflush(where); 7826 } 7827 sock_closed = 1; 7828 break; 7829 } 7830 else { 7831 request_bytes_remaining -= request_bytes_recvd; 7832 temp_message_ptr += request_bytes_recvd; 7833 } 7834 } 7835 7836 recv_ring = recv_ring->next; 7837 7838 if ((timed_out) || (sock_closed)) { 7839 /* we hit the end of the test based on time - or the socket 7840 closed on us along the way. bail out of here now... */ 7841 if (debug) { 7842 fprintf(where,"yo5\n"); 7843 fflush(where); 7844 } 7845 break; 7846 } 7847 7848 /* Now, send the response to the remote */ 7849 if((bytes_sent=send(s_data, 7850 send_ring->buffer_ptr, 7851 tcp_rr_request->response_size, 7852 0)) == SOCKET_ERROR) { 7853 if (SOCKET_EINTR(bytes_sent)) { 7854 /* the test timer has popped */ 7855 timed_out = 1; 7856 fprintf(where,"yo6\n"); 7857 fflush(where); 7858 break; 7859 } 7860 netperf_response.content.serv_errno = 992; 7861 send_response(); 7862 exit(1); 7863 } 7864 7865 send_ring = send_ring->next; 7866 7867 trans_received++; 7868 if (trans_remaining) { 7869 trans_remaining--; 7870 } 7871 } 7872 7873 7874 /* The loop now exits due to timeout or transaction count being */ 7875 /* reached */ 7876 7877 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time); 7878 7879 stop_timer(); 7880 7881 if (timed_out) { 7882 /* we ended the test by time, which was at least 2 seconds */ 7883 /* longer than we wanted to run. so, we want to subtract */ 7884 /* PAD_TIME from the elapsed_time. */ 7885 elapsed_time -= PAD_TIME; 7886 } 7887 7888 /* send the results to the sender */ 7889 7890 if (debug) { 7891 fprintf(where, 7892 "recv_tcp_rr: got %d transactions\n", 7893 trans_received); 7894 fflush(where); 7895 } 7896 7897 tcp_rr_results->bytes_received = (trans_received * 7898 (tcp_rr_request->request_size + 7899 tcp_rr_request->response_size)); 7900 tcp_rr_results->trans_received = trans_received; 7901 tcp_rr_results->elapsed_time = elapsed_time; 7902 tcp_rr_results->cpu_method = cpu_method; 7903 tcp_rr_results->num_cpus = lib_num_loc_cpus; 7904 if (tcp_rr_request->measure_cpu) { 7905 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 7906 } 7907 7908 if (debug) { 7909 fprintf(where, 7910 "recv_tcp_rr: test complete, sending results.\n"); 7911 fflush(where); 7912 } 7913 7914 /* we are now done with the sockets */ 7915 close(s_data); 7916 close(s_listen); 7917 7918 send_response(); 7919 7920 } 7921 7922 7923 void 7925 loc_cpu_rate() 7926 { 7927 #if defined(USE_LOOPER) 7928 float dummy; 7929 #endif 7930 7931 /* a rather simple little test - it merely calibrates the local cpu */ 7932 /* and prints the results. There are no headers to allow someone to */ 7933 /* find a rate and use it in other tests automagically by setting a */ 7934 /* variable equal to the output of this test. We ignore any rates */ 7935 /* that may have been specified. In fact, we ignore all of the */ 7936 /* command line args! */ 7937 7938 fprintf(where, 7939 "%g", 7940 calibrate_local_cpu(0.0)); 7941 7942 if (verbosity > 1) 7943 fprintf(where, 7944 "\nThere %s %d local %s\n", 7945 (lib_num_loc_cpus > 1) ? "are" : "is", 7946 lib_num_loc_cpus, 7947 (lib_num_loc_cpus > 1) ? "cpus" : "cpu"); 7948 7949 /* we need the cpu_start, cpu_stop in the looper case to kill the */ 7950 /* child proceses raj 4/95 */ 7951 7952 #ifdef USE_LOOPER 7953 cpu_start(1); 7954 cpu_stop(1,&dummy); 7955 #endif /* USE_LOOPER */ 7956 7957 } 7958 7959 void 7960 rem_cpu_rate() 7961 { 7962 /* this test is much like the local variant, except that it works for */ 7963 /* the remote system, so in this case, we do pay attention to the */ 7964 /* value of the '-H' command line argument. */ 7965 7966 fprintf(where, 7967 "%g", 7968 calibrate_remote_cpu()); 7969 7970 if (verbosity > 1) 7971 fprintf(where, 7972 "\nThere %s %d remote %s\n", 7973 (lib_num_rem_cpus > 1) ? "are" : "is", 7974 lib_num_rem_cpus, 7975 (lib_num_rem_cpus > 1) ? "cpus" : "cpu"); 7976 7977 } 7978 7979 7981 /* this test is intended to test the performance of establishing a 7982 connection, exchanging a request/response pair, and repeating. it 7983 is expected that this would be a good starting-point for 7984 comparision of T/TCP with classic TCP for transactional workloads. 7985 it will also look (can look) much like the communication pattern 7986 of http for www access. */ 7987 7988 void 7989 send_tcp_conn_rr(char remote_host[]) 7990 { 7991 7992 char *tput_title = "\ 7993 Local /Remote\n\ 7994 Socket Size Request Resp. Elapsed Trans.\n\ 7995 Send Recv Size Size Time Rate \n\ 7996 bytes Bytes bytes bytes secs. per sec \n\n"; 7997 7998 char *tput_fmt_0 = 7999 "%7.2f\n"; 8000 8001 char *tput_fmt_1_line_1 = "\ 8002 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 8003 char *tput_fmt_1_line_2 = "\ 8004 %-6d %-6d\n"; 8005 8006 char *cpu_title = "\ 8007 Local /Remote\n\ 8008 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 8009 Send Recv Size Size Time Rate local remote local remote\n\ 8010 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 8011 8012 char *cpu_fmt_0 = 8013 "%6.3f\n"; 8014 8015 char *cpu_fmt_1_line_1 = "\ 8016 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 8017 8018 char *cpu_fmt_1_line_2 = "\ 8019 %-6d %-6d\n"; 8020 8021 char *ksink_fmt = "\n\ 8022 Alignment Offset\n\ 8023 Local Remote Local Remote\n\ 8024 Send Recv Send Recv\n\ 8025 %5d %5d %5d %5d\n"; 8026 8027 8028 int timed_out = 0; 8029 float elapsed_time; 8030 8031 int len; 8032 struct ring_elt *send_ring; 8033 struct ring_elt *recv_ring; 8034 char *temp_message_ptr; 8035 int nummessages; 8036 SOCKET send_socket; 8037 int trans_remaining; 8038 double bytes_xferd; 8039 int rsp_bytes_left; 8040 int rsp_bytes_recvd; 8041 8042 float local_cpu_utilization; 8043 float local_service_demand; 8044 float remote_cpu_utilization; 8045 float remote_service_demand; 8046 double thruput; 8047 8048 struct addrinfo *local_res; 8049 struct addrinfo *remote_res; 8050 8051 int myport; 8052 int ret; 8053 8054 struct tcp_conn_rr_request_struct *tcp_conn_rr_request; 8055 struct tcp_conn_rr_response_struct *tcp_conn_rr_response; 8056 struct tcp_conn_rr_results_struct *tcp_conn_rr_result; 8057 8058 tcp_conn_rr_request = 8059 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data; 8060 tcp_conn_rr_response = 8061 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data; 8062 tcp_conn_rr_result = 8063 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data; 8064 8065 8066 #ifdef WANT_HISTOGRAM 8067 if (verbosity > 1) { 8068 time_hist = HIST_new(); 8069 } 8070 #endif /* WANT_HISTOGRAM */ 8071 8072 /* since we are now disconnected from the code that established the */ 8073 /* control socket, and since we want to be able to use different */ 8074 /* protocols and such, we are passed the name of the remote host and */ 8075 /* must turn that into the test specific addressing information. */ 8076 8077 complete_addrinfos(&remote_res, 8078 &local_res, 8079 remote_host, 8080 SOCK_STREAM, 8081 IPPROTO_TCP, 8082 0); 8083 8084 if ( print_headers ) { 8085 print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res); 8086 } 8087 8088 /* initialize a few counters */ 8089 8090 nummessages = 0; 8091 bytes_xferd = 0.0; 8092 times_up = 0; 8093 8094 /* set-up the data buffers with the requested alignment and offset */ 8095 if (send_width == 0) send_width = 1; 8096 if (recv_width == 0) recv_width = 1; 8097 8098 send_ring = allocate_buffer_ring(send_width, 8099 req_size, 8100 local_send_align, 8101 local_send_offset); 8102 8103 recv_ring = allocate_buffer_ring(recv_width, 8104 rsp_size, 8105 local_recv_align, 8106 local_recv_offset); 8107 8108 8109 if (debug) { 8110 fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n"); 8111 } 8112 8113 /* If the user has requested cpu utilization measurements, we must */ 8114 /* calibrate the cpu(s). We will perform this task within the tests */ 8115 /* themselves. If the user has specified the cpu rate, then */ 8116 /* calibrate_local_cpu will return rather quickly as it will have */ 8117 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 8118 /* all the "normal" calibration stuff and return the rate back.*/ 8119 8120 if (local_cpu_usage) { 8121 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 8122 } 8123 8124 if (!no_control) { 8125 8126 /* Tell the remote end to do a listen. The server alters the 8127 socket paramters on the other side at this point, hence the 8128 reason for all the values being passed in the setup message. If 8129 the user did not specify any of the parameters, they will be 8130 passed as 0, which will indicate to the remote that no changes 8131 beyond the system's default should be used. Alignment is the 8132 exception, it will default to 8, which will be no alignment 8133 alterations. */ 8134 8135 netperf_request.content.request_type = DO_TCP_CRR; 8136 tcp_conn_rr_request->recv_buf_size = rsr_size_req; 8137 tcp_conn_rr_request->send_buf_size = rss_size_req; 8138 tcp_conn_rr_request->recv_alignment = remote_recv_align; 8139 tcp_conn_rr_request->recv_offset = remote_recv_offset; 8140 tcp_conn_rr_request->send_alignment = remote_send_align; 8141 tcp_conn_rr_request->send_offset = remote_send_offset; 8142 tcp_conn_rr_request->request_size = req_size; 8143 tcp_conn_rr_request->response_size = rsp_size; 8144 tcp_conn_rr_request->no_delay = rem_nodelay; 8145 tcp_conn_rr_request->measure_cpu = remote_cpu_usage; 8146 tcp_conn_rr_request->cpu_rate = remote_cpu_rate; 8147 tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid; 8148 tcp_conn_rr_request->so_sndavoid = rem_sndavoid; 8149 if (test_time) { 8150 tcp_conn_rr_request->test_length = test_time; 8151 } 8152 else { 8153 tcp_conn_rr_request->test_length = test_trans * -1; 8154 } 8155 tcp_conn_rr_request->port = atoi(remote_data_port); 8156 tcp_conn_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 8157 8158 if (debug > 1) { 8159 fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n"); 8160 } 8161 8162 send_request(); 8163 8164 /* The response from the remote will contain all of the relevant 8165 socket parameters for this test type. We will put them back 8166 into the variables here so they can be displayed if desired. 8167 The remote will have calibrated CPU if necessary, and will have 8168 done all the needed set-up we will have calibrated the cpu 8169 locally before sending the request, and will grab the counter 8170 value right after the connect returns. The remote will grab the 8171 counter right after the accept call. This saves the hassle of 8172 extra messages being sent for the TCP tests. */ 8173 8174 recv_response(); 8175 8176 if (!netperf_response.content.serv_errno) { 8177 rsr_size = tcp_conn_rr_response->recv_buf_size; 8178 rss_size = tcp_conn_rr_response->send_buf_size; 8179 rem_nodelay = tcp_conn_rr_response->no_delay; 8180 remote_cpu_usage = tcp_conn_rr_response->measure_cpu; 8181 remote_cpu_rate = tcp_conn_rr_response->cpu_rate; 8182 /* make sure that port numbers are in network order */ 8183 set_port_number(remote_res, 8184 (unsigned short)tcp_conn_rr_response->data_port_number); 8185 8186 if (debug) { 8187 fprintf(where,"remote listen done.\n"); 8188 fprintf(where,"remote port is %u\n",get_port_number(remote_res)); 8189 fflush(where); 8190 } 8191 } 8192 else { 8193 Set_errno(netperf_response.content.serv_errno); 8194 fprintf(where, 8195 "netperf: remote error %d", 8196 netperf_response.content.serv_errno); 8197 perror(""); 8198 fflush(where); 8199 exit(1); 8200 } 8201 } 8202 #ifdef WANT_DEMO 8203 DEMO_RR_SETUP(100) 8204 #endif 8205 8206 /* pick a nice random spot between client_port_min and */ 8207 /* client_port_max for our initial port number */ 8208 srand(getpid()); 8209 if (client_port_max - client_port_min) { 8210 myport = client_port_min + 8211 (rand() % (client_port_max - client_port_min)); 8212 } 8213 else { 8214 myport = client_port_min; 8215 } 8216 /* there will be a ++ before the first call to bind, so subtract one */ 8217 myport--; 8218 /* Set-up the test end conditions. For a request/response test, they */ 8219 /* can be either time or transaction based. */ 8220 8221 if (test_time) { 8222 /* The user wanted to end the test after a period of time. */ 8223 times_up = 0; 8224 trans_remaining = 0; 8225 start_timer(test_time); 8226 } 8227 else { 8228 /* The tester wanted to send a number of bytes. */ 8229 trans_remaining = test_bytes; 8230 times_up = 1; 8231 } 8232 8233 /* The cpu_start routine will grab the current time and possibly */ 8234 /* value of the idle counter for later use in measuring cpu */ 8235 /* utilization and/or service demand and thruput. */ 8236 8237 8238 cpu_start(local_cpu_usage); 8239 8240 #ifdef WANT_DEMO 8241 if (demo_mode) { 8242 HIST_timestamp(demo_one_ptr); 8243 } 8244 #endif 8245 8246 /* We use an "OR" to control test execution. When the test is */ 8247 /* controlled by time, the byte count check will always return false. */ 8248 /* When the test is controlled by byte count, the time test will */ 8249 /* always return false. When the test is finished, the whole */ 8250 /* expression will go false and we will stop sending data. I think I */ 8251 /* just arbitrarily decrement trans_remaining for the timed test, but */ 8252 /* will not do that just yet... One other question is whether or not */ 8253 /* the send buffer and the receive buffer should be the same buffer. */ 8254 8255 while ((!times_up) || (trans_remaining > 0)) { 8256 8257 #ifdef WANT_HISTOGRAM 8258 if (verbosity > 1) { 8259 /* timestamp just before our call to create the socket, and then */ 8260 /* again just after the receive raj 3/95 */ 8261 HIST_timestamp(&time_one); 8262 } 8263 #endif /* WANT_HISTOGRAM */ 8264 8265 newport: 8266 /* pick a new port number */ 8267 myport++; 8268 8269 /* wrap the port number when we get to client_port_max. NOTE, some */ 8270 /* broken TCP's might treat the port number as a signed 16 bit */ 8271 /* quantity. we aren't interested in testing such broken */ 8272 /* implementations :) so we won't make sure that it is below 32767 */ 8273 /* raj 8/94 */ 8274 if (myport >= client_port_max) { 8275 myport = client_port_min; 8276 } 8277 8278 /* we do not want to use the port number that the server is */ 8279 /* sitting at - this would cause us to fail in a loopback test. we */ 8280 /* could just rely on the failure of the bind to get us past this, */ 8281 /* but I'm guessing that in this one case at least, it is much */ 8282 /* faster, given that we *know* that port number is already in use */ 8283 /* (or rather would be in a loopback test) */ 8284 8285 if (myport == get_port_number(remote_res)) myport++; 8286 8287 if (debug) { 8288 if ((nummessages % 100) == 0) { 8289 printf("port %d\n",myport); 8290 } 8291 } 8292 8293 /* set up the data socket */ 8294 set_port_number(local_res, (unsigned short)myport); 8295 send_socket = create_data_socket(local_res); 8296 8297 if (send_socket == INVALID_SOCKET) { 8298 perror("netperf: send_tcp_conn_rr: tcp stream data socket"); 8299 exit(1); 8300 } 8301 8302 8303 /* we used to call bind here, but that is now taken-care-of by the 8304 create_data_socket routine. */ 8305 8306 /* Connect up to the remote port on the data socket */ 8307 if ((ret = connect(send_socket, 8308 remote_res->ai_addr, 8309 remote_res->ai_addrlen)) == INVALID_SOCKET){ 8310 if (SOCKET_EINTR(ret)) 8311 { 8312 /* we hit the end of a */ 8313 /* timed test. */ 8314 timed_out = 1; 8315 break; 8316 } 8317 if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) { 8318 /* likely something our explicit bind() would have caught in 8319 the past, so go get another port, via create_data_socket. 8320 yes, this is a bit more overhead than before, but the 8321 condition should be rather rare. raj 2005-02-08 */ 8322 close(send_socket); 8323 goto newport; 8324 } 8325 perror("netperf: data socket connect failed"); 8326 printf("\tattempted to connect on socket %d to port %d", 8327 send_socket, 8328 get_port_number(remote_res)); 8329 printf(" from port %d \n",get_port_number(local_res)); 8330 exit(1); 8331 } 8332 8333 8334 /* send the request */ 8335 if((len=send(send_socket, 8336 send_ring->buffer_ptr, 8337 req_size, 8338 0)) != req_size) { 8339 if (SOCKET_EINTR(len)) 8340 { 8341 /* we hit the end of a */ 8342 /* timed test. */ 8343 timed_out = 1; 8344 break; 8345 } 8346 perror("send_tcp_conn_rr: data send error"); 8347 exit(1); 8348 } 8349 send_ring = send_ring->next; 8350 8351 /* receive the response */ 8352 rsp_bytes_left = rsp_size; 8353 temp_message_ptr = recv_ring->buffer_ptr; 8354 8355 8356 do { 8357 rsp_bytes_recvd = recv(send_socket, 8358 temp_message_ptr, 8359 rsp_bytes_left, 8360 0); 8361 if (rsp_bytes_recvd > 0) { 8362 rsp_bytes_left -= rsp_bytes_recvd; 8363 temp_message_ptr += rsp_bytes_recvd; 8364 } 8365 else { 8366 break; 8367 } 8368 } while (rsp_bytes_left); 8369 8370 8371 /* OK, we are out of the loop - now what? */ 8372 if (rsp_bytes_recvd < 0) { 8373 /* did the timer hit, or was there an error? */ 8374 if (SOCKET_EINTR(rsp_bytes_recvd)) 8375 { 8376 /* We hit the end of a timed test. */ 8377 timed_out = 1; 8378 break; 8379 } 8380 perror("send_tcp_conn_rr: data recv error"); 8381 exit(1); 8382 } 8383 8384 /* if this is a no_control test, we initiate connection close, 8385 otherwise the remote netserver does it to remain just like 8386 previous behaviour. raj 2007-27-08 */ 8387 if (!no_control) { 8388 shutdown(send_socket,SHUT_WR); 8389 } 8390 8391 /* we are expecting to get either a return of zero indicating 8392 connection close, or an error. */ 8393 rsp_bytes_recvd = recv(send_socket, 8394 temp_message_ptr, 8395 1, 8396 0); 8397 8398 /* our exit from the while loop should generally be when */ 8399 /* tmp_bytes_recvd is equal to zero, which implies the connection */ 8400 /* has been closed by the server side. By waiting until we get the */ 8401 /* zero return we can avoid race conditions that stick us with the */ 8402 /* TIME_WAIT connection and not the server. raj 8/96 */ 8403 8404 if (rsp_bytes_recvd == 0) { 8405 /* connection close, call close. we assume that the requisite */ 8406 /* number of bytes have been received */ 8407 recv_ring = recv_ring->next; 8408 8409 #ifdef WANT_HISTOGRAM 8410 if (verbosity > 1) { 8411 HIST_timestamp(&time_two); 8412 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 8413 } 8414 #endif /* WANT_HISTOGRAM */ 8415 8416 #ifdef WANT_DEMO 8417 DEMO_RR_INTERVAL(1) 8418 #endif 8419 8420 nummessages++; 8421 if (trans_remaining) { 8422 trans_remaining--; 8423 } 8424 8425 if (debug > 3) { 8426 fprintf(where, 8427 "Transaction %d completed on local port %d\n", 8428 nummessages, 8429 get_port_number(local_res)); 8430 fflush(where); 8431 } 8432 8433 close(send_socket); 8434 8435 } 8436 else { 8437 /* it was less than zero - an error occured */ 8438 if (SOCKET_EINTR(rsp_bytes_recvd)) 8439 { 8440 /* We hit the end of a timed test. */ 8441 timed_out = 1; 8442 break; 8443 } 8444 perror("send_tcp_conn_rr: data recv error"); 8445 exit(1); 8446 } 8447 8448 } 8449 8450 8451 /* this call will always give us the elapsed time for the test, and */ 8452 /* will also store-away the necessaries for cpu utilization */ 8453 8454 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 8455 /* how long did we really run? */ 8456 8457 if (!no_control) { 8458 /* Get the statistics from the remote end. The remote will have 8459 calculated service demand and all those interesting things. If 8460 it wasn't supposed to care, it will return obvious values. */ 8461 8462 recv_response(); 8463 if (!netperf_response.content.serv_errno) { 8464 if (debug) 8465 fprintf(where,"remote results obtained\n"); 8466 } 8467 else { 8468 Set_errno(netperf_response.content.serv_errno); 8469 fprintf(where, 8470 "netperf: remote error %d", 8471 netperf_response.content.serv_errno); 8472 perror(""); 8473 fflush(where); 8474 8475 exit(1); 8476 } 8477 } 8478 8479 /* We now calculate what our thruput was for the test. In the future, */ 8480 /* we may want to include a calculation of the thruput measured by */ 8481 /* the remote, but it should be the case that for a TCP stream test, */ 8482 /* that the two numbers should be *very* close... We calculate */ 8483 /* bytes_sent regardless of the way the test length was controlled. */ 8484 /* If it was time, we needed to, and if it was by bytes, the user may */ 8485 /* have specified a number of bytes that wasn't a multiple of the */ 8486 /* send_size, so we really didn't send what he asked for ;-) We use */ 8487 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 8488 /* 1024. A future enhancement *might* be to choose from a couple of */ 8489 /* unit selections. */ 8490 8491 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 8492 thruput = calc_thruput(bytes_xferd); 8493 8494 if (local_cpu_usage || remote_cpu_usage) { 8495 /* We must now do a little math for service demand and cpu */ 8496 /* utilization for the system(s) */ 8497 /* Of course, some of the information might be bogus because */ 8498 /* there was no idle counter in the kernel(s). We need to make */ 8499 /* a note of this for the user's benefit...*/ 8500 if (local_cpu_usage) { 8501 if (local_cpu_rate == 0.0) { 8502 fprintf(where, 8503 "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 8504 fprintf(where, 8505 "Local CPU usage numbers based on process information only!\n"); 8506 fflush(where); 8507 } 8508 local_cpu_utilization = calc_cpu_util(0.0); 8509 /* since calc_service demand is doing ms/Kunit we will */ 8510 /* multiply the number of transaction by 1024 to get */ 8511 /* "good" numbers */ 8512 local_service_demand = calc_service_demand((double) nummessages*1024, 8513 0.0, 8514 0.0, 8515 0); 8516 } 8517 else { 8518 local_cpu_utilization = (float) -1.0; 8519 local_service_demand = (float) -1.0; 8520 } 8521 8522 if (remote_cpu_usage) { 8523 if (remote_cpu_rate == 0.0) { 8524 fprintf(where, 8525 "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 8526 fprintf(where, 8527 "Remote CPU usage numbers based on process information only!\n"); 8528 fflush(where); 8529 } 8530 remote_cpu_utilization = tcp_conn_rr_result->cpu_util; 8531 /* since calc_service demand is doing ms/Kunit we will */ 8532 /* multiply the number of transaction by 1024 to get */ 8533 /* "good" numbers */ 8534 remote_service_demand = calc_service_demand((double) nummessages*1024, 8535 0.0, 8536 remote_cpu_utilization, 8537 tcp_conn_rr_result->num_cpus); 8538 } 8539 else { 8540 remote_cpu_utilization = (float) -1.0; 8541 remote_service_demand = (float) -1.0; 8542 } 8543 8544 /* We are now ready to print all the information. If the user */ 8545 /* has specified zero-level verbosity, we will just print the */ 8546 /* local service demand, or the remote service demand. If the */ 8547 /* user has requested verbosity level 1, he will get the basic */ 8548 /* "streamperf" numbers. If the user has specified a verbosity */ 8549 /* of greater than 1, we will display a veritable plethora of */ 8550 /* background information from outside of this block as it it */ 8551 /* not cpu_measurement specific... */ 8552 8553 switch (verbosity) { 8554 case 0: 8555 if (local_cpu_usage) { 8556 fprintf(where, 8557 cpu_fmt_0, 8558 local_service_demand); 8559 } 8560 else { 8561 fprintf(where, 8562 cpu_fmt_0, 8563 remote_service_demand); 8564 } 8565 break; 8566 case 1: 8567 case 2: 8568 8569 if (print_headers) { 8570 fprintf(where, 8571 cpu_title, 8572 local_cpu_method, 8573 remote_cpu_method); 8574 } 8575 8576 fprintf(where, 8577 cpu_fmt_1_line_1, /* the format string */ 8578 lss_size, /* local sendbuf size */ 8579 lsr_size, 8580 req_size, /* how large were the requests */ 8581 rsp_size, /* guess */ 8582 elapsed_time, /* how long was the test */ 8583 nummessages/elapsed_time, 8584 local_cpu_utilization, /* local cpu */ 8585 remote_cpu_utilization, /* remote cpu */ 8586 local_service_demand, /* local service demand */ 8587 remote_service_demand); /* remote service demand */ 8588 fprintf(where, 8589 cpu_fmt_1_line_2, 8590 rss_size, 8591 rsr_size); 8592 break; 8593 } 8594 } 8595 else { 8596 /* The tester did not wish to measure service demand. */ 8597 switch (verbosity) { 8598 case 0: 8599 fprintf(where, 8600 tput_fmt_0, 8601 nummessages/elapsed_time); 8602 break; 8603 case 1: 8604 case 2: 8605 if (print_headers) { 8606 fprintf(where,tput_title,format_units()); 8607 } 8608 8609 fprintf(where, 8610 tput_fmt_1_line_1, /* the format string */ 8611 lss_size, 8612 lsr_size, 8613 req_size, /* how large were the requests */ 8614 rsp_size, /* how large were the responses */ 8615 elapsed_time, /* how long did it take */ 8616 nummessages/elapsed_time); 8617 fprintf(where, 8618 tput_fmt_1_line_2, 8619 rss_size, /* remote recvbuf size */ 8620 rsr_size); 8621 8622 break; 8623 } 8624 } 8625 8626 /* it would be a good thing to include information about some of the */ 8627 /* other parameters that may have been set for this test, but at the */ 8628 /* moment, I do not wish to figure-out all the formatting, so I will */ 8629 /* just put this comment here to help remind me that it is something */ 8630 /* that should be done at a later time. */ 8631 8632 if (verbosity > 1) { 8633 /* The user wanted to know it all, so we will give it to him. */ 8634 /* This information will include as much as we can find about */ 8635 /* TCP statistics, the alignments of the sends and receives */ 8636 /* and all that sort of rot... */ 8637 8638 fprintf(where, 8639 ksink_fmt, 8640 local_send_align, 8641 remote_recv_offset, 8642 local_send_offset, 8643 remote_recv_offset); 8644 8645 #ifdef WANT_HISTOGRAM 8646 fprintf(where,"\nHistogram of request/response times\n"); 8647 fflush(where); 8648 HIST_report(time_hist); 8649 #endif /* WANT_HISTOGRAM */ 8650 8651 } 8652 8653 } 8654 8655 8656 void 8658 recv_tcp_conn_rr() 8659 { 8660 8661 char *message; 8662 struct addrinfo *local_res; 8663 char local_name[BUFSIZ]; 8664 char port_buffer[PORTBUFSIZE]; 8665 8666 struct sockaddr_storage myaddr_in, peeraddr_in; 8667 SOCKET s_listen,s_data; 8668 netperf_socklen_t addrlen; 8669 char *recv_message_ptr; 8670 char *send_message_ptr; 8671 char *temp_message_ptr; 8672 int trans_received; 8673 int trans_remaining; 8674 int bytes_sent; 8675 int request_bytes_recvd; 8676 int request_bytes_remaining; 8677 int timed_out = 0; 8678 float elapsed_time; 8679 8680 struct tcp_conn_rr_request_struct *tcp_conn_rr_request; 8681 struct tcp_conn_rr_response_struct *tcp_conn_rr_response; 8682 struct tcp_conn_rr_results_struct *tcp_conn_rr_results; 8683 8684 tcp_conn_rr_request = 8685 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data; 8686 tcp_conn_rr_response = 8687 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data; 8688 tcp_conn_rr_results = 8689 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data; 8690 8691 if (debug) { 8692 fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n"); 8693 fflush(where); 8694 } 8695 8696 /* We want to set-up the listen socket with all the desired */ 8697 /* parameters and then let the initiator know that all is ready. If */ 8698 /* socket size defaults are to be used, then the initiator will have */ 8699 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 8700 /* send-back what they are. If that information cannot be determined, */ 8701 /* then we send-back -1's for the sizes. If things go wrong for any */ 8702 /* reason, we will drop back ten yards and punt. */ 8703 8704 /* If anything goes wrong, we want the remote to know about it. It */ 8705 /* would be best if the error that the remote reports to the user is */ 8706 /* the actual error we encountered, rather than some bogus unexpected */ 8707 /* response type message. */ 8708 8709 if (debug) { 8710 fprintf(where,"recv_tcp_conn_rr: setting the response type...\n"); 8711 fflush(where); 8712 } 8713 8714 netperf_response.content.response_type = TCP_CRR_RESPONSE; 8715 8716 if (debug) { 8717 fprintf(where,"recv_tcp_conn_rr: the response type is set...\n"); 8718 fflush(where); 8719 } 8720 8721 /* set-up the data buffer with the requested alignment and offset */ 8722 message = (char *)malloc(DATABUFFERLEN); 8723 if (message == NULL) { 8724 printf("malloc(%d) failed!\n", DATABUFFERLEN); 8725 exit(1); 8726 } 8727 8728 /* We now alter the message_ptr variables to be at the desired */ 8729 /* alignments with the desired offsets. */ 8730 8731 if (debug) { 8732 fprintf(where, 8733 "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n", 8734 tcp_conn_rr_request->recv_alignment, 8735 tcp_conn_rr_request->recv_offset); 8736 fprintf(where, 8737 "recv_tcp_conn_rr: requested send alignment of %d offset %d\n", 8738 tcp_conn_rr_request->send_alignment, 8739 tcp_conn_rr_request->send_offset); 8740 fflush(where); 8741 } 8742 8743 recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset); 8744 8745 send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset); 8746 8747 if (debug) { 8748 fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n"); 8749 fflush(where); 8750 } 8751 8752 /* Grab a socket to listen on, and then listen on it. */ 8753 8754 if (debug) { 8755 fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n"); 8756 fflush(where); 8757 } 8758 8759 /* create_data_socket expects to find some things in the global */ 8760 /* variables, so set the globals based on the values in the request. */ 8761 /* once the socket has been created, we will set the response values */ 8762 /* based on the updated value of those globals. raj 7/94 */ 8763 lss_size_req = tcp_conn_rr_request->send_buf_size; 8764 lsr_size_req = tcp_conn_rr_request->recv_buf_size; 8765 loc_nodelay = tcp_conn_rr_request->no_delay; 8766 loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid; 8767 loc_sndavoid = tcp_conn_rr_request->so_sndavoid; 8768 8769 set_hostname_and_port(local_name, 8770 port_buffer, 8771 nf_to_af(tcp_conn_rr_request->ipfamily), 8772 tcp_conn_rr_request->port); 8773 8774 local_res = complete_addrinfo(local_name, 8775 local_name, 8776 port_buffer, 8777 nf_to_af(tcp_conn_rr_request->ipfamily), 8778 SOCK_STREAM, 8779 IPPROTO_TCP, 8780 0); 8781 8782 s_listen = create_data_socket(local_res); 8783 8784 if (s_listen == INVALID_SOCKET) { 8785 netperf_response.content.serv_errno = errno; 8786 send_response(); 8787 if (debug) { 8788 fprintf(where,"could not create data socket\n"); 8789 fflush(where); 8790 } 8791 exit(1); 8792 } 8793 8794 #ifdef WIN32 8795 /* The test timer can fire during operations on the listening socket, 8796 so to make the start_timer below work we have to move 8797 it to close s_listen while we are blocked on accept. */ 8798 win_kludge_socket2 = s_listen; 8799 #endif 8800 8801 8802 /* Now, let's set-up the socket to listen for connections */ 8803 if (listen(s_listen, 5) == SOCKET_ERROR) { 8804 netperf_response.content.serv_errno = errno; 8805 close(s_listen); 8806 send_response(); 8807 if (debug) { 8808 fprintf(where,"could not listen\n"); 8809 fflush(where); 8810 } 8811 exit(1); 8812 } 8813 8814 /* now get the port number assigned by the system */ 8815 addrlen = sizeof(myaddr_in); 8816 if (getsockname(s_listen, 8817 (struct sockaddr *)&myaddr_in, 8818 &addrlen) == SOCKET_ERROR){ 8819 netperf_response.content.serv_errno = errno; 8820 close(s_listen); 8821 send_response(); 8822 if (debug) { 8823 fprintf(where,"could not getsockname\n"); 8824 fflush(where); 8825 } 8826 exit(1); 8827 } 8828 8829 /* Now myaddr_in contains the port and the internet address this is */ 8830 /* returned to the sender also implicitly telling the sender that the */ 8831 /* socket buffer sizing has been done. */ 8832 8833 tcp_conn_rr_response->data_port_number = 8834 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 8835 if (debug) { 8836 fprintf(where,"telling the remote to call me at %d\n", 8837 tcp_conn_rr_response->data_port_number); 8838 fflush(where); 8839 } 8840 netperf_response.content.serv_errno = 0; 8841 8842 /* But wait, there's more. If the initiator wanted cpu measurements, */ 8843 /* then we must call the calibrate routine, which will return the max */ 8844 /* rate back to the initiator. If the CPU was not to be measured, or */ 8845 /* something went wrong with the calibration, we will return a 0.0 to */ 8846 /* the initiator. */ 8847 8848 tcp_conn_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 8849 if (tcp_conn_rr_request->measure_cpu) { 8850 tcp_conn_rr_response->measure_cpu = 1; 8851 tcp_conn_rr_response->cpu_rate = 8852 calibrate_local_cpu(tcp_conn_rr_request->cpu_rate); 8853 } 8854 8855 8856 8857 /* before we send the response back to the initiator, pull some of */ 8858 /* the socket parms from the globals */ 8859 tcp_conn_rr_response->send_buf_size = lss_size; 8860 tcp_conn_rr_response->recv_buf_size = lsr_size; 8861 tcp_conn_rr_response->no_delay = loc_nodelay; 8862 tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid; 8863 tcp_conn_rr_response->so_sndavoid = loc_sndavoid; 8864 8865 send_response(); 8866 8867 addrlen = sizeof(peeraddr_in); 8868 8869 /* Now it's time to start receiving data on the connection. We will */ 8870 /* first grab the apropriate counters and then start grabbing. */ 8871 8872 cpu_start(tcp_conn_rr_request->measure_cpu); 8873 8874 /* The loop will exit when the sender does a shutdown, which will */ 8875 /* return a length of zero */ 8876 8877 if (tcp_conn_rr_request->test_length > 0) { 8878 times_up = 0; 8879 trans_remaining = 0; 8880 start_timer(tcp_conn_rr_request->test_length + PAD_TIME); 8881 } 8882 else { 8883 times_up = 1; 8884 trans_remaining = tcp_conn_rr_request->test_length * -1; 8885 } 8886 8887 trans_received = 0; 8888 8889 while ((!times_up) || (trans_remaining > 0)) { 8890 8891 /* accept a connection from the remote */ 8892 #ifdef WIN32 8893 /* The test timer will probably fire during this accept, 8894 so to make the start_timer above work we have to move 8895 it to close s_listen while we are blocked on accept. */ 8896 win_kludge_socket = s_listen; 8897 #endif 8898 if ((s_data=accept(s_listen, 8899 (struct sockaddr *)&peeraddr_in, 8900 &addrlen)) == INVALID_SOCKET) { 8901 if (errno == EINTR) { 8902 /* the timer popped */ 8903 timed_out = 1; 8904 break; 8905 } 8906 fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno); 8907 fflush(where); 8908 close(s_listen); 8909 8910 exit(1); 8911 } 8912 8913 if (debug) { 8914 fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n"); 8915 fflush(where); 8916 } 8917 8918 #ifdef WIN32 8919 /* this is used so the timer thread can close the socket out from */ 8920 /* under us, which to date is the easiest/cleanest/least */ 8921 /* Windows-specific way I can find to force the winsock calls to */ 8922 /* return WSAEINTR with the test is over. anything that will run on */ 8923 /* 95 and NT and is closer to what netperf expects from Unix signals */ 8924 /* and such would be appreciated raj 1/96 */ 8925 win_kludge_socket = s_data; 8926 #endif /* WIN32 */ 8927 8928 #ifdef KLUDGE_SOCKET_OPTIONS 8929 /* this is for those systems which *INCORRECTLY* fail to pass */ 8930 /* attributes across an accept() call. Including this goes against */ 8931 /* my better judgement :( raj 11/95 */ 8932 8933 kludge_socket_options(s_data); 8934 8935 #endif /* KLUDGE_SOCKET_OPTIONS */ 8936 8937 temp_message_ptr = recv_message_ptr; 8938 request_bytes_remaining = tcp_conn_rr_request->request_size; 8939 8940 /* receive the request from the other side */ 8941 while (!times_up && (request_bytes_remaining > 0)) { 8942 if((request_bytes_recvd=recv(s_data, 8943 temp_message_ptr, 8944 request_bytes_remaining, 8945 0)) == SOCKET_ERROR) { 8946 if (SOCKET_EINTR(request_bytes_recvd)) 8947 { 8948 /* the timer popped */ 8949 timed_out = 1; 8950 break; 8951 } 8952 netperf_response.content.serv_errno = errno; 8953 send_response(); 8954 exit(1); 8955 } 8956 else { 8957 request_bytes_remaining -= request_bytes_recvd; 8958 temp_message_ptr += request_bytes_recvd; 8959 } 8960 } 8961 8962 if (timed_out) { 8963 /* we hit the end of the test based on time - lets */ 8964 /* bail out of here now... */ 8965 fprintf(where,"yo5\n"); 8966 fflush(where); 8967 break; 8968 } 8969 8970 /* Now, send the response to the remote */ 8971 if((bytes_sent=send(s_data, 8972 send_message_ptr, 8973 tcp_conn_rr_request->response_size, 8974 0)) == SOCKET_ERROR) { 8975 if (errno == EINTR) { 8976 /* the test timer has popped */ 8977 timed_out = 1; 8978 fprintf(where,"yo6\n"); 8979 fflush(where); 8980 break; 8981 } 8982 netperf_response.content.serv_errno = 99; 8983 send_response(); 8984 exit(1); 8985 } 8986 8987 trans_received++; 8988 if (trans_remaining) { 8989 trans_remaining--; 8990 } 8991 8992 if (debug) { 8993 fprintf(where, 8994 "recv_tcp_conn_rr: Transaction %d complete\n", 8995 trans_received); 8996 fflush(where); 8997 } 8998 8999 /* close the connection. the server will likely do a graceful */ 9000 /* close of the connection, insuring that all data has arrived at */ 9001 /* the client. for this it will call shutdown(), and then recv() and */ 9002 /* then close(). I'm reasonably confident that this is the */ 9003 /* appropriate sequence of calls - I would like to hear of */ 9004 /* examples in web servers to the contrary. raj 10/95*/ 9005 #ifdef TCP_CRR_SHUTDOWN 9006 shutdown(s_data,SHUT_WR); 9007 recv(s_data, 9008 recv_message_ptr, 9009 1, 9010 0); 9011 close(s_data); 9012 #else 9013 close(s_data); 9014 #endif /* TCP_CRR_SHUTDOWN */ 9015 9016 } 9017 9018 9019 /* The loop now exits due to timeout or transaction count being */ 9020 /* reached */ 9021 9022 cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time); 9023 9024 if (timed_out) { 9025 /* we ended the test by time, which was at least 2 seconds */ 9026 /* longer than we wanted to run. so, we want to subtract */ 9027 /* PAD_TIME from the elapsed_time. */ 9028 elapsed_time -= PAD_TIME; 9029 } 9030 /* send the results to the sender */ 9031 9032 if (debug) { 9033 fprintf(where, 9034 "recv_tcp_conn_rr: got %d transactions\n", 9035 trans_received); 9036 fflush(where); 9037 } 9038 9039 tcp_conn_rr_results->bytes_received = (trans_received * 9040 (tcp_conn_rr_request->request_size + 9041 tcp_conn_rr_request->response_size)); 9042 tcp_conn_rr_results->trans_received = trans_received; 9043 tcp_conn_rr_results->elapsed_time = elapsed_time; 9044 if (tcp_conn_rr_request->measure_cpu) { 9045 tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time); 9046 } 9047 9048 if (debug) { 9049 fprintf(where, 9050 "recv_tcp_conn_rr: test complete, sending results.\n"); 9051 fflush(where); 9052 } 9053 9054 send_response(); 9055 9056 } 9057 9058 9060 #ifdef DO_1644 9061 9062 /* this test is intended to test the performance of establishing a */ 9063 /* connection, exchanging a request/response pair, and repeating. it */ 9064 /* is expected that this would be a good starting-point for */ 9065 /* comparision of T/TCP with classic TCP for transactional workloads. */ 9066 /* it will also look (can look) much like the communication pattern */ 9067 /* of http for www access. */ 9068 9069 int 9070 send_tcp_tran_rr(char remote_host[]) 9071 { 9072 9073 char *tput_title = "\ 9074 Local /Remote\n\ 9075 Socket Size Request Resp. Elapsed Trans.\n\ 9076 Send Recv Size Size Time Rate \n\ 9077 bytes Bytes bytes bytes secs. per sec \n\n"; 9078 9079 char *tput_fmt_0 = 9080 "%7.2f\n"; 9081 9082 char *tput_fmt_1_line_1 = "\ 9083 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 9084 char *tput_fmt_1_line_2 = "\ 9085 %-6d %-6d\n"; 9086 9087 char *cpu_title = "\ 9088 Local /Remote\n\ 9089 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 9090 Send Recv Size Size Time Rate local remote local remote\n\ 9091 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 9092 9093 char *cpu_fmt_0 = 9094 "%6.3f\n"; 9095 9096 char *cpu_fmt_1_line_1 = "\ 9097 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 9098 9099 char *cpu_fmt_1_line_2 = "\ 9100 %-6d %-6d\n"; 9101 9102 char *ksink_fmt = "\n\ 9103 Alignment Offset\n\ 9104 Local Remote Local Remote\n\ 9105 Send Recv Send Recv\n\ 9106 %5d %5d %5d %5d\n"; 9107 9108 9109 int one = 1; 9110 int timed_out = 0; 9111 float elapsed_time; 9112 9113 int len; 9114 struct ring_elt *send_ring; 9115 struct ring_elt *recv_ring; 9116 char *temp_message_ptr; 9117 int nummessages; 9118 SOCKET send_socket; 9119 int trans_remaining; 9120 double bytes_xferd; 9121 int sock_opt_len = sizeof(int); 9122 int rsp_bytes_left; 9123 int rsp_bytes_recvd; 9124 9125 float local_cpu_utilization; 9126 float local_service_demand; 9127 float remote_cpu_utilization; 9128 float remote_service_demand; 9129 double thruput; 9130 9131 struct hostent *hp; 9132 struct sockaddr_in server; 9133 struct sockaddr_in *myaddr; 9134 unsigned int addr; 9135 int myport; 9136 9137 struct tcp_tran_rr_request_struct *tcp_tran_rr_request; 9138 struct tcp_tran_rr_response_struct *tcp_tran_rr_response; 9139 struct tcp_tran_rr_results_struct *tcp_tran_rr_result; 9140 9141 tcp_tran_rr_request = 9142 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data; 9143 tcp_tran_rr_response = 9144 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data; 9145 tcp_tran_rr_result = 9146 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data; 9147 9148 9149 #ifdef WANT_HISTOGRAM 9150 if (verbosity > 1) { 9151 time_hist = HIST_new(); 9152 } 9153 #endif /* WANT_HISTOGRAM */ 9154 9155 /* since we are now disconnected from the code that established the */ 9156 /* control socket, and since we want to be able to use different */ 9157 /* protocols and such, we are passed the name of the remote host and */ 9158 /* must turn that into the test specific addressing information. */ 9159 9160 myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage)); 9161 if (myaddr == NULL) { 9162 printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage)); 9163 exit(1); 9164 } 9165 9166 bzero((char *)&server, 9167 sizeof(server)); 9168 bzero((char *)myaddr, 9169 sizeof(struct sockaddr_storage)); 9170 myaddr->sin_family = AF_INET; 9171 9172 complete_addrinfos(&remote_res, 9173 &local_res, 9174 remote_host, 9175 SOCK_STREAM, 9176 IPPROTO_TCP, 9177 0); 9178 9179 if ( print_headers ) { 9180 print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res); 9181 } 9182 9183 /* initialize a few counters */ 9184 9185 nummessages = 0; 9186 bytes_xferd = 0.0; 9187 times_up = 0; 9188 9189 /* set-up the data buffers with the requested alignment and offset */ 9190 if (send_width == 0) send_width = 1; 9191 if (recv_width == 0) recv_width = 1; 9192 9193 send_ring = allocate_buffer_ring(send_width, 9194 req_size, 9195 local_send_align, 9196 local_send_offset); 9197 9198 recv_ring = allocate_buffer_ring(recv_width, 9199 rsp_size, 9200 local_recv_align, 9201 local_recv_offset); 9202 9203 9204 if (debug) { 9205 fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n"); 9206 } 9207 9208 /* If the user has requested cpu utilization measurements, we must */ 9209 /* calibrate the cpu(s). We will perform this task within the tests */ 9210 /* themselves. If the user has specified the cpu rate, then */ 9211 /* calibrate_local_cpu will return rather quickly as it will have */ 9212 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 9213 /* all the "normal" calibration stuff and return the rate back.*/ 9214 9215 if (local_cpu_usage) { 9216 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 9217 } 9218 9219 /* Tell the remote end to do a listen. The server alters the socket */ 9220 /* paramters on the other side at this point, hence the reason for */ 9221 /* all the values being passed in the setup message. If the user did */ 9222 /* not specify any of the parameters, they will be passed as 0, which */ 9223 /* will indicate to the remote that no changes beyond the system's */ 9224 /* default should be used. Alignment is the exception, it will */ 9225 /* default to 8, which will be no alignment alterations. */ 9226 9227 netperf_request.content.request_type = DO_TCP_TRR; 9228 tcp_tran_rr_request->recv_buf_size = rsr_size_req; 9229 tcp_tran_rr_request->send_buf_size = rss_size_req; 9230 tcp_tran_rr_request->recv_alignment = remote_recv_align; 9231 tcp_tran_rr_request->recv_offset = remote_recv_offset; 9232 tcp_tran_rr_request->send_alignment = remote_send_align; 9233 tcp_tran_rr_request->send_offset = remote_send_offset; 9234 tcp_tran_rr_request->request_size = req_size; 9235 tcp_tran_rr_request->response_size = rsp_size; 9236 tcp_tran_rr_request->no_delay = rem_nodelay; 9237 tcp_tran_rr_request->measure_cpu = remote_cpu_usage; 9238 tcp_tran_rr_request->cpu_rate = remote_cpu_rate; 9239 tcp_tran_rr_request->so_rcvavoid = rem_rcvavoid; 9240 tcp_tran_rr_request->so_sndavoid = rem_sndavoid; 9241 if (test_time) { 9242 tcp_tran_rr_request->test_length = test_time; 9243 } 9244 else { 9245 tcp_tran_rr_request->test_length = test_trans * -1; 9246 } 9247 tcp_tran_rr_request->port = atoi(remote_data_port); 9248 tcp_tran_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 9249 9250 if (debug > 1) { 9251 fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n"); 9252 } 9253 9254 send_request(); 9255 9256 /* The response from the remote will contain all of the relevant */ 9257 /* socket parameters for this test type. We will put them back into */ 9258 /* the variables here so they can be displayed if desired. The */ 9259 /* remote will have calibrated CPU if necessary, and will have done */ 9260 /* all the needed set-up we will have calibrated the cpu locally */ 9261 /* before sending the request, and will grab the counter value right */ 9262 /* after the connect returns. The remote will grab the counter right */ 9263 /* after the accept call. This saves the hassle of extra messages */ 9264 /* being sent for the TCP tests. */ 9265 9266 recv_response(); 9267 9268 if (!netperf_response.content.serv_errno) { 9269 rsr_size = tcp_tran_rr_response->recv_buf_size; 9270 rss_size = tcp_tran_rr_response->send_buf_size; 9271 rem_nodelay = tcp_tran_rr_response->no_delay; 9272 remote_cpu_usage= tcp_tran_rr_response->measure_cpu; 9273 remote_cpu_rate = tcp_tran_rr_response->cpu_rate; 9274 /* make sure that port numbers are in network order */ 9275 server.sin_port = tcp_tran_rr_response->data_port_number; 9276 server.sin_port = htons(server.sin_port); 9277 if (debug) { 9278 fprintf(where,"remote listen done.\n"); 9279 fprintf(where,"remote port is %d\n",ntohs(server.sin_port)); 9280 fflush(where); 9281 } 9282 } 9283 else { 9284 Set_errno(netperf_response.content.serv_errno); 9285 fprintf(where, 9286 "netperf: remote error %d", 9287 netperf_response.content.serv_errno); 9288 perror(""); 9289 fflush(where); 9290 exit(1); 9291 } 9292 9293 /* pick a nice random spot between client_port_min and */ 9294 /* client_port_max for our initial port number. if they are the */ 9295 /* same, then just set to _min */ 9296 if (client_port_max - client_port_min) { 9297 srand(getpid()); 9298 myport = client_port_min + 9299 (rand() % (client_port_max - client_port_min)); 9300 } 9301 else { 9302 myport = client_port_min; 9303 } 9304 9305 /* there will be a ++ before the first call to bind, so subtract one */ 9306 myport--; 9307 myaddr->sin_port = htons((unsigned short)myport); 9308 9309 /* Set-up the test end conditions. For a request/response test, they */ 9310 /* can be either time or transaction based. */ 9311 9312 if (test_time) { 9313 /* The user wanted to end the test after a period of time. */ 9314 times_up = 0; 9315 trans_remaining = 0; 9316 start_timer(test_time); 9317 } 9318 else { 9319 /* The tester wanted to send a number of bytes. */ 9320 trans_remaining = test_bytes; 9321 times_up = 1; 9322 } 9323 9324 /* The cpu_start routine will grab the current time and possibly */ 9325 /* value of the idle counter for later use in measuring cpu */ 9326 /* utilization and/or service demand and thruput. */ 9327 9328 cpu_start(local_cpu_usage); 9329 9330 /* We use an "OR" to control test execution. When the test is */ 9331 /* controlled by time, the byte count check will always return false. */ 9332 /* When the test is controlled by byte count, the time test will */ 9333 /* always return false. When the test is finished, the whole */ 9334 /* expression will go false and we will stop sending data. I think I */ 9335 /* just arbitrarily decrement trans_remaining for the timed test, but */ 9336 /* will not do that just yet... One other question is whether or not */ 9337 /* the send buffer and the receive buffer should be the same buffer. */ 9338 9339 while ((!times_up) || (trans_remaining > 0)) { 9340 9341 #ifdef WANT_HISTOGRAM 9342 if (verbosity > 1) { 9343 /* timestamp just before our call to create the socket, and then */ 9344 /* again just after the receive raj 3/95 */ 9345 HIST_timestamp(&time_one); 9346 } 9347 #endif /* WANT_HISTOGRAM */ 9348 9349 /* set up the data socket - is this really necessary or can I just */ 9350 /* re-use the same socket and move this cal out of the while loop. */ 9351 /* it does introcudea *boatload* of system calls. I guess that it */ 9352 /* all depends on "reality of programming." keeping it this way is */ 9353 /* a bit more conservative I imagine - raj 3/95 */ 9354 send_socket = create_data_socket(local_res); 9355 9356 if (send_socket == INVALID_SOCKET) { 9357 perror("netperf: send_tcp_tran_rr: tcp stream data socket"); 9358 exit(1); 9359 } 9360 9361 /* we set SO_REUSEADDR on the premis that no unreserved port */ 9362 /* number on the local system is going to be already connected to */ 9363 /* the remote netserver's port number. One thing that I might */ 9364 /* try later is to have the remote actually allocate a couple of */ 9365 /* port numbers and cycle through those as well. depends on if we */ 9366 /* can get through all the unreserved port numbers in less than */ 9367 /* the length of the TIME_WAIT state raj 8/94 */ 9368 one = 1; 9369 if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR, 9370 (char *)&one, sock_opt_len) == SOCKET_ERROR) { 9371 perror("netperf: send_tcp_tran_rr: so_reuseaddr"); 9372 exit(1); 9373 } 9374 9375 newport: 9376 /* pick a new port number */ 9377 myport = ntohs(myaddr->sin_port); 9378 myport++; 9379 9380 /* we do not want to use the port number that the server is */ 9381 /* sitting at - this would cause us to fail in a loopback test. we */ 9382 /* could just rely on the failure of the bind to get us past this, */ 9383 /* but I'm guessing that in this one case at least, it is much */ 9384 /* faster, given that we *know* that port number is already in use */ 9385 /* (or rather would be in a loopback test) */ 9386 9387 if (myport == ntohs(server.sin_port)) myport++; 9388 9389 /* wrap the port number when we get to 65535. NOTE, some broken */ 9390 /* TCP's might treat the port number as a signed 16 bit quantity. */ 9391 /* we aren't interested in testing such broken implementations :) */ 9392 /* raj 8/94 */ 9393 if (myport >= client_port_max) { 9394 myport = client_port_min; 9395 } 9396 myaddr->sin_port = htons((unsigned short)myport); 9397 9398 if (debug) { 9399 if ((nummessages % 100) == 0) { 9400 printf("port %d\n",myport); 9401 } 9402 } 9403 9404 /* we want to bind our socket to a particular port number. */ 9405 if (bind(send_socket, 9406 (struct sockaddr *)myaddr, 9407 sizeof(struct sockaddr_storage)) == SOCKET_ERROR) { 9408 /* if the bind failed, someone else must have that port number */ 9409 /* - perhaps in the listen state. since we can't use it, skip to */ 9410 /* the next port number. we may have to do this again later, but */ 9411 /* that's just too bad :) */ 9412 if (debug > 1) { 9413 fprintf(where, 9414 "send_tcp_tran_rr: tried to bind to port %d errno %d\n", 9415 ntohs(myaddr->sin_port), 9416 errno); 9417 fflush(where); 9418 } 9419 /* yes, goto's are supposed to be evil, but they do have their */ 9420 /* uses from time to time. the real world doesn't always have */ 9421 /* to code to ge tthe A in CS 101 :) raj 3/95 */ 9422 goto newport; 9423 } 9424 9425 /* Connect up to the remote port on the data socket. Since this is */ 9426 /* a test for RFC_1644-style transactional TCP, we can use the */ 9427 /* sendto() call instead of calling connect and then send() */ 9428 9429 /* send the request */ 9430 if((len=sendto(send_socket, 9431 send_ring->buffer_ptr, 9432 req_size, 9433 MSG_EOF, 9434 (struct sockaddr *)&server, 9435 sizeof(server))) != req_size) { 9436 if (SOCKET_EINTR(len)) 9437 { 9438 /* we hit the end of a */ 9439 /* timed test. */ 9440 timed_out = 1; 9441 break; 9442 } 9443 perror("send_tcp_tran_rr: data send error"); 9444 exit(1); 9445 } 9446 send_ring = send_ring->next; 9447 9448 /* receive the response */ 9449 rsp_bytes_left = rsp_size; 9450 temp_message_ptr = recv_ring->buffer_ptr; 9451 while(rsp_bytes_left > 0) { 9452 if((rsp_bytes_recvd=recv(send_socket, 9453 temp_message_ptr, 9454 rsp_bytes_left, 9455 0)) == SOCKET_ERROR) { 9456 if (SOCKET_EINTR(rsp_bytes_recvd)) 9457 { 9458 /* We hit the end of a timed test. */ 9459 timed_out = 1; 9460 break; 9461 } 9462 perror("send_tcp_tran_rr: data recv error"); 9463 exit(1); 9464 } 9465 rsp_bytes_left -= rsp_bytes_recvd; 9466 temp_message_ptr += rsp_bytes_recvd; 9467 } 9468 recv_ring = recv_ring->next; 9469 9470 if (timed_out) { 9471 /* we may have been in a nested while loop - we need */ 9472 /* another call to break. */ 9473 break; 9474 } 9475 9476 close(send_socket); 9477 9478 #ifdef WANT_HISTOGRAM 9479 if (verbosity > 1) { 9480 HIST_timestamp(&time_two); 9481 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 9482 } 9483 #endif /* WANT_HISTOGRAM */ 9484 9485 nummessages++; 9486 if (trans_remaining) { 9487 trans_remaining--; 9488 } 9489 9490 if (debug > 3) { 9491 fprintf(where, 9492 "Transaction %d completed on local port %d\n", 9493 nummessages, 9494 ntohs(myaddr->sin_port)); 9495 fflush(where); 9496 } 9497 9498 9499 } 9500 9501 /* this call will always give us the elapsed time for the test, and */ 9502 /* will also store-away the necessaries for cpu utilization */ 9503 9504 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 9505 /* how long did we really run? */ 9506 9507 /* Get the statistics from the remote end. The remote will have */ 9508 /* calculated service demand and all those interesting things. If it */ 9509 /* wasn't supposed to care, it will return obvious values. */ 9510 9511 recv_response(); 9512 if (!netperf_response.content.serv_errno) { 9513 if (debug) 9514 fprintf(where,"remote results obtained\n"); 9515 } 9516 else { 9517 Set_errno(netperf_response.content.serv_errno); 9518 fprintf(where, 9519 "netperf: remote error %d", 9520 netperf_response.content.serv_errno); 9521 perror(""); 9522 fflush(where); 9523 exit(1); 9524 } 9525 9526 /* We now calculate what our thruput was for the test. In the future, */ 9527 /* we may want to include a calculation of the thruput measured by */ 9528 /* the remote, but it should be the case that for a TCP stream test, */ 9529 /* that the two numbers should be *very* close... We calculate */ 9530 /* bytes_sent regardless of the way the test length was controlled. */ 9531 /* If it was time, we needed to, and if it was by bytes, the user may */ 9532 /* have specified a number of bytes that wasn't a multiple of the */ 9533 /* send_size, so we really didn't send what he asked for ;-) We use */ 9534 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 9535 /* 1024. A future enhancement *might* be to choose from a couple of */ 9536 /* unit selections. */ 9537 9538 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 9539 thruput = calc_thruput(bytes_xferd); 9540 9541 if (local_cpu_usage || remote_cpu_usage) { 9542 /* We must now do a little math for service demand and cpu */ 9543 /* utilization for the system(s) */ 9544 /* Of course, some of the information might be bogus because */ 9545 /* there was no idle counter in the kernel(s). We need to make */ 9546 /* a note of this for the user's benefit...*/ 9547 if (local_cpu_usage) { 9548 if (local_cpu_rate == 0.0) { 9549 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 9550 fprintf(where,"Local CPU usage numbers based on process information only!\n"); 9551 fflush(where); 9552 } 9553 local_cpu_utilization = calc_cpu_util(0.0); 9554 /* since calc_service demand is doing ms/Kunit we will */ 9555 /* multiply the number of transaction by 1024 to get */ 9556 /* "good" numbers */ 9557 local_service_demand = calc_service_demand((double) nummessages*1024, 9558 0.0, 9559 0.0, 9560 0); 9561 } 9562 else { 9563 local_cpu_utilization = (float) -1.0; 9564 local_service_demand = (float) -1.0; 9565 } 9566 9567 if (remote_cpu_usage) { 9568 if (remote_cpu_rate == 0.0) { 9569 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 9570 fprintf(where,"Remote CPU usage numbers based on process information only!\n"); 9571 fflush(where); 9572 } 9573 remote_cpu_utilization = tcp_tran_rr_result->cpu_util; 9574 /* since calc_service demand is doing ms/Kunit we will */ 9575 /* multiply the number of transaction by 1024 to get */ 9576 /* "good" numbers */ 9577 remote_service_demand = calc_service_demand((double) nummessages*1024, 9578 0.0, 9579 remote_cpu_utilization, 9580 tcp_tran_rr_result->num_cpus); 9581 } 9582 else { 9583 remote_cpu_utilization = (float) -1.0; 9584 remote_service_demand = (float) -1.0; 9585 } 9586 9587 /* We are now ready to print all the information. If the user */ 9588 /* has specified zero-level verbosity, we will just print the */ 9589 /* local service demand, or the remote service demand. If the */ 9590 /* user has requested verbosity level 1, he will get the basic */ 9591 /* "streamperf" numbers. If the user has specified a verbosity */ 9592 /* of greater than 1, we will display a veritable plethora of */ 9593 /* background information from outside of this block as it it */ 9594 /* not cpu_measurement specific... */ 9595 9596 switch (verbosity) { 9597 case 0: 9598 if (local_cpu_usage) { 9599 fprintf(where, 9600 cpu_fmt_0, 9601 local_service_demand); 9602 } 9603 else { 9604 fprintf(where, 9605 cpu_fmt_0, 9606 remote_service_demand); 9607 } 9608 break; 9609 case 1: 9610 case 2: 9611 9612 if (print_headers) { 9613 fprintf(where, 9614 cpu_title, 9615 local_cpu_method, 9616 remote_cpu_method); 9617 } 9618 9619 fprintf(where, 9620 cpu_fmt_1_line_1, /* the format string */ 9621 lss_size, /* local sendbuf size */ 9622 lsr_size, 9623 req_size, /* how large were the requests */ 9624 rsp_size, /* guess */ 9625 elapsed_time, /* how long was the test */ 9626 nummessages/elapsed_time, 9627 local_cpu_utilization, /* local cpu */ 9628 remote_cpu_utilization, /* remote cpu */ 9629 local_service_demand, /* local service demand */ 9630 remote_service_demand); /* remote service demand */ 9631 fprintf(where, 9632 cpu_fmt_1_line_2, 9633 rss_size, 9634 rsr_size); 9635 break; 9636 } 9637 } 9638 else { 9639 /* The tester did not wish to measure service demand. */ 9640 switch (verbosity) { 9641 case 0: 9642 fprintf(where, 9643 tput_fmt_0, 9644 nummessages/elapsed_time); 9645 break; 9646 case 1: 9647 case 2: 9648 if (print_headers) { 9649 fprintf(where,tput_title,format_units()); 9650 } 9651 9652 fprintf(where, 9653 tput_fmt_1_line_1, /* the format string */ 9654 lss_size, 9655 lsr_size, 9656 req_size, /* how large were the requests */ 9657 rsp_size, /* how large were the responses */ 9658 elapsed_time, /* how long did it take */ 9659 nummessages/elapsed_time); 9660 fprintf(where, 9661 tput_fmt_1_line_2, 9662 rss_size, /* remote recvbuf size */ 9663 rsr_size); 9664 9665 break; 9666 } 9667 } 9668 9669 /* it would be a good thing to include information about some of the */ 9670 /* other parameters that may have been set for this test, but at the */ 9671 /* moment, I do not wish to figure-out all the formatting, so I will */ 9672 /* just put this comment here to help remind me that it is something */ 9673 /* that should be done at a later time. */ 9674 9675 if (verbosity > 1) { 9676 /* The user wanted to know it all, so we will give it to him. */ 9677 /* This information will include as much as we can find about */ 9678 /* TCP statistics, the alignments of the sends and receives */ 9679 /* and all that sort of rot... */ 9680 9681 fprintf(where, 9682 ksink_fmt, 9683 local_send_align, 9684 remote_recv_offset, 9685 local_send_offset, 9686 remote_recv_offset); 9687 9688 #ifdef WANT_HISTOGRAM 9689 fprintf(where,"\nHistogram of request/response times\n"); 9690 fflush(where); 9691 HIST_report(time_hist); 9692 #endif /* WANT_HISTOGRAM */ 9693 9694 } 9695 9696 } 9697 9698 9699 int 9701 recv_tcp_tran_rr() 9702 { 9703 9704 char *message; 9705 struct sockaddr_in myaddr_in, 9706 peeraddr_in; 9707 SOCKET s_listen,s_data; 9708 netperf_socklen_t addrlen; 9709 int NoPush = 1; 9710 9711 char *recv_message_ptr; 9712 char *send_message_ptr; 9713 char *temp_message_ptr; 9714 int trans_received; 9715 int trans_remaining; 9716 int bytes_sent; 9717 int request_bytes_recvd; 9718 int request_bytes_remaining; 9719 int timed_out = 0; 9720 float elapsed_time; 9721 9722 struct tcp_tran_rr_request_struct *tcp_tran_rr_request; 9723 struct tcp_tran_rr_response_struct *tcp_tran_rr_response; 9724 struct tcp_tran_rr_results_struct *tcp_tran_rr_results; 9725 9726 tcp_tran_rr_request = 9727 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data; 9728 tcp_tran_rr_response = 9729 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data; 9730 tcp_tran_rr_results = 9731 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data; 9732 9733 if (debug) { 9734 fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n"); 9735 fflush(where); 9736 } 9737 9738 /* We want to set-up the listen socket with all the desired */ 9739 /* parameters and then let the initiator know that all is ready. If */ 9740 /* socket size defaults are to be used, then the initiator will have */ 9741 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 9742 /* send-back what they are. If that information cannot be determined, */ 9743 /* then we send-back -1's for the sizes. If things go wrong for any */ 9744 /* reason, we will drop back ten yards and punt. */ 9745 9746 /* If anything goes wrong, we want the remote to know about it. It */ 9747 /* would be best if the error that the remote reports to the user is */ 9748 /* the actual error we encountered, rather than some bogus unexpected */ 9749 /* response type message. */ 9750 9751 if (debug) { 9752 fprintf(where,"recv_tcp_tran_rr: setting the response type...\n"); 9753 fflush(where); 9754 } 9755 9756 netperf_response.content.response_type = TCP_TRR_RESPONSE; 9757 9758 if (debug) { 9759 fprintf(where,"recv_tcp_tran_rr: the response type is set...\n"); 9760 fflush(where); 9761 } 9762 9763 /* set-up the data buffer with the requested alignment and offset */ 9764 message = (char *)malloc(DATABUFFERLEN); 9765 if (message == NULL) { 9766 printf("malloc(%d) failed!\n", DATABUFFERLEN); 9767 exit(1); 9768 } 9769 9770 /* We now alter the message_ptr variables to be at the desired */ 9771 /* alignments with the desired offsets. */ 9772 9773 if (debug) { 9774 fprintf(where, 9775 "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n", 9776 tcp_tran_rr_request->recv_alignment, 9777 tcp_tran_rr_request->recv_offset); 9778 fprintf(where, 9779 "recv_tcp_tran_rr: requested send alignment of %d offset %d\n", 9780 tcp_tran_rr_request->send_alignment, 9781 tcp_tran_rr_request->send_offset); 9782 fflush(where); 9783 } 9784 9785 recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset); 9786 9787 send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset); 9788 9789 if (debug) { 9790 fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n"); 9791 fflush(where); 9792 } 9793 9794 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */ 9795 /* can put in OUR values !-) At some point, we may want to nail this */ 9796 /* socket to a particular network-level address, but for now, */ 9797 /* INADDR_ANY should be just fine. */ 9798 9799 bzero((char *)&myaddr_in, 9800 sizeof(myaddr_in)); 9801 myaddr_in.sin_family = AF_INET; 9802 myaddr_in.sin_addr.s_addr = INADDR_ANY; 9803 myaddr_in.sin_port = htons((unsigned short)tcp_tran_rr_request->port); 9804 9805 /* Grab a socket to listen on, and then listen on it. */ 9806 9807 if (debug) { 9808 fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n"); 9809 fflush(where); 9810 } 9811 9812 /* create_data_socket expects to find some things in the global */ 9813 /* variables, so set the globals based on the values in the request. */ 9814 /* once the socket has been created, we will set the response values */ 9815 /* based on the updated value of those globals. raj 7/94 */ 9816 lss_size_req = tcp_tran_rr_request->send_buf_size; 9817 lsr_size_req = tcp_tran_rr_request->recv_buf_size; 9818 loc_nodelay = tcp_tran_rr_request->no_delay; 9819 loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid; 9820 loc_sndavoid = tcp_tran_rr_request->so_sndavoid; 9821 9822 set_hostname_and_port(local_name, 9823 port_buffer, 9824 nf_to_af(tcp_tran_rr_request->ipfamily), 9825 tcp_tran_rr_request->port); 9826 9827 local_res = complete_addrinfo(local_name, 9828 local_name, 9829 port_buffer, 9830 nf_to_af(tcp_tran_rr_request->ipfamily), 9831 SOCK_STREAM, 9832 IPPROTO_TCP, 9833 0); 9834 9835 s_listen = create_data_socket(local_res); 9836 9837 if (s_listen == INVALID_SOCKET) { 9838 netperf_response.content.serv_errno = errno; 9839 send_response(); 9840 if (debug) { 9841 fprintf(where,"could not create data socket\n"); 9842 fflush(where); 9843 } 9844 exit(1); 9845 } 9846 9847 #ifdef WIN32 9848 /* The test timer can fire during operations on the listening socket, 9849 so to make the start_timer below work we have to move 9850 it to close s_listen while we are blocked on accept. */ 9851 win_kludge_socket2 = s_listen; 9852 #endif 9853 9854 9855 /* Let's get an address assigned to this socket so we can tell the */ 9856 /* initiator how to reach the data socket. There may be a desire to */ 9857 /* nail this socket to a specific IP address in a multi-homed, */ 9858 /* multi-connection situation, but for now, we'll ignore the issue */ 9859 /* and concentrate on single connection testing. */ 9860 9861 if (bind(s_listen, 9862 (struct sockaddr *)&myaddr_in, 9863 sizeof(myaddr_in)) == SOCKET_ERROR) { 9864 netperf_response.content.serv_errno = errno; 9865 close(s_listen); 9866 send_response(); 9867 if (debug) { 9868 fprintf(where,"could not bind\n"); 9869 fflush(where); 9870 } 9871 exit(1); 9872 } 9873 9874 /* we want to disable the implicit PUSH on all sends. at some point, */ 9875 /* this might want to be a parm to the test raj 3/95 */ 9876 if (setsockopt(s_listen, 9877 IPPROTO_TCP, 9878 TCP_NOPUSH, 9879 (const char *)&NoPush, 9880 sizeof(int)) == SOCKET_ERROR) { 9881 fprintf(where, 9882 "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n", 9883 errno); 9884 fflush(where); 9885 netperf_response.content.serv_errno = errno; 9886 close(s_listen); 9887 send_response(); 9888 } 9889 9890 /* Now, let's set-up the socket to listen for connections */ 9891 if (listen(s_listen, 5) == SOCKET_ERROR) { 9892 netperf_response.content.serv_errno = errno; 9893 close(s_listen); 9894 send_response(); 9895 if (debug) { 9896 fprintf(where,"could not listen\n"); 9897 fflush(where); 9898 } 9899 exit(1); 9900 } 9901 9902 /* now get the port number assigned by the system */ 9903 addrlen = sizeof(myaddr_in); 9904 if (getsockname(s_listen, 9905 (struct sockaddr *)&myaddr_in, 9906 &addrlen) == SOCKET_ERROR){ 9907 netperf_response.content.serv_errno = errno; 9908 close(s_listen); 9909 send_response(); 9910 if (debug) { 9911 fprintf(where,"could not geetsockname\n"); 9912 fflush(where); 9913 } 9914 exit(1); 9915 } 9916 9917 /* Now myaddr_in contains the port and the internet address this is */ 9918 /* returned to the sender also implicitly telling the sender that the */ 9919 /* socket buffer sizing has been done. */ 9920 9921 tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 9922 if (debug) { 9923 fprintf(where,"telling the remote to call me at %d\n", 9924 tcp_tran_rr_response->data_port_number); 9925 fflush(where); 9926 } 9927 netperf_response.content.serv_errno = 0; 9928 9929 /* But wait, there's more. If the initiator wanted cpu measurements, */ 9930 /* then we must call the calibrate routine, which will return the max */ 9931 /* rate back to the initiator. If the CPU was not to be measured, or */ 9932 /* something went wrong with the calibration, we will return a 0.0 to */ 9933 /* the initiator. */ 9934 9935 tcp_tran_rr_response->cpu_rate = 0.0; /* assume no cpu */ 9936 if (tcp_tran_rr_request->measure_cpu) { 9937 tcp_tran_rr_response->measure_cpu = 1; 9938 tcp_tran_rr_response->cpu_rate = 9939 calibrate_local_cpu(tcp_tran_rr_request->cpu_rate); 9940 } 9941 9942 9943 9944 /* before we send the response back to the initiator, pull some of */ 9945 /* the socket parms from the globals */ 9946 tcp_tran_rr_response->send_buf_size = lss_size; 9947 tcp_tran_rr_response->recv_buf_size = lsr_size; 9948 tcp_tran_rr_response->no_delay = loc_nodelay; 9949 tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid; 9950 tcp_tran_rr_response->so_sndavoid = loc_sndavoid; 9951 9952 send_response(); 9953 9954 addrlen = sizeof(peeraddr_in); 9955 9956 /* Now it's time to start receiving data on the connection. We will */ 9957 /* first grab the apropriate counters and then start grabbing. */ 9958 9959 cpu_start(tcp_tran_rr_request->measure_cpu); 9960 9961 /* The loop will exit when the sender does a shutdown, which will */ 9962 /* return a length of zero */ 9963 9964 if (tcp_tran_rr_request->test_length > 0) { 9965 times_up = 0; 9966 trans_remaining = 0; 9967 start_timer(tcp_tran_rr_request->test_length + PAD_TIME); 9968 } 9969 else { 9970 times_up = 1; 9971 trans_remaining = tcp_tran_rr_request->test_length * -1; 9972 } 9973 9974 trans_received = 0; 9975 9976 while ((!times_up) || (trans_remaining > 0)) { 9977 9978 /* accept a connection from the remote */ 9979 if ((s_data=accept(s_listen, 9980 (struct sockaddr *)&peeraddr_in, 9981 &addrlen)) == INVALID_SOCKET) { 9982 if (errno == EINTR) { 9983 /* the timer popped */ 9984 timed_out = 1; 9985 break; 9986 } 9987 fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno); 9988 fflush(where); 9989 close(s_listen); 9990 9991 exit(1); 9992 } 9993 9994 if (debug) { 9995 fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n"); 9996 fflush(where); 9997 } 9998 9999 #ifdef WIN32 10000 /* this is used so the timer thread can close the socket out from */ 10001 /* under us, which to date is the easiest/cleanest/least */ 10002 /* Windows-specific way I can find to force the winsock calls to */ 10003 /* return WSAEINTR with the test is over. anything that will run on */ 10004 /* 95 and NT and is closer to what netperf expects from Unix signals */ 10005 /* and such would be appreciated raj 1/96 */ 10006 win_kludge_socket = s_data; 10007 #endif /* WIN32 */ 10008 10009 #ifdef KLUDGE_SOCKET_OPTIONS 10010 /* this is for those systems which *INCORRECTLY* fail to pass */ 10011 /* attributes across an accept() call. Including this goes against */ 10012 /* my better judgement :( raj 11/95 */ 10013 10014 kludge_socket_options(s_data); 10015 10016 #endif /* KLUDGE_SOCKET_OPTIONS */ 10017 10018 temp_message_ptr = recv_message_ptr; 10019 request_bytes_remaining = tcp_tran_rr_request->request_size; 10020 10021 /* receive the request from the other side. we can just receive */ 10022 /* until we get zero bytes, but that would be a slight structure */ 10023 /* change in the code, with minimal perfomance effects. If */ 10024 /* however, I has variable-length messages, I would want to do */ 10025 /* this to avoid needing "double reads" - one for the message */ 10026 /* length, and one for the rest of the message raj 3/95 */ 10027 while(request_bytes_remaining > 0) { 10028 if((request_bytes_recvd=recv(s_data, 10029 temp_message_ptr, 10030 request_bytes_remaining, 10031 0)) == SOCKET_ERROR) { 10032 if ( SOCKET_EINTR(request_bytes_recvd) ) 10033 { 10034 /* the timer popped */ 10035 timed_out = 1; 10036 break; 10037 } 10038 netperf_response.content.serv_errno = errno; 10039 send_response(); 10040 exit(1); 10041 } 10042 else { 10043 request_bytes_remaining -= request_bytes_recvd; 10044 temp_message_ptr += request_bytes_recvd; 10045 } 10046 } 10047 10048 if (timed_out) { 10049 /* we hit the end of the test based on time - lets */ 10050 /* bail out of here now... */ 10051 fprintf(where,"yo5\n"); 10052 fflush(where); 10053 break; 10054 } 10055 10056 /* Now, send the response to the remote we can use sendto here to */ 10057 /* help remind people that this is an rfc 1644 style of test */ 10058 if((bytes_sent=sendto(s_data, 10059 send_message_ptr, 10060 tcp_tran_rr_request->response_size, 10061 MSG_EOF, 10062 (struct sockaddr *)&peeraddr_in, 10063 sizeof(struct sockaddr_storage))) == SOCKET_ERROR) { 10064 if (SOCKET_EINTR(bytes_sent)) { 10065 /* the test timer has popped */ 10066 timed_out = 1; 10067 fprintf(where,"yo6\n"); 10068 fflush(where); 10069 break; 10070 } 10071 netperf_response.content.serv_errno = 99; 10072 send_response(); 10073 exit(1); 10074 } 10075 10076 trans_received++; 10077 if (trans_remaining) { 10078 trans_remaining--; 10079 } 10080 10081 if (debug) { 10082 fprintf(where, 10083 "recv_tcp_tran_rr: Transaction %d complete\n", 10084 trans_received); 10085 fflush(where); 10086 } 10087 10088 /* close the connection. since we have disable PUSH on sends, the */ 10089 /* FIN should be tacked-onto our last send instead of being */ 10090 /* standalone */ 10091 close(s_data); 10092 10093 } 10094 10095 10096 /* The loop now exits due to timeout or transaction count being */ 10097 /* reached */ 10098 10099 cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time); 10100 10101 if (timed_out) { 10102 /* we ended the test by time, which was at least 2 seconds */ 10103 /* longer than we wanted to run. so, we want to subtract */ 10104 /* PAD_TIME from the elapsed_time. */ 10105 elapsed_time -= PAD_TIME; 10106 } 10107 /* send the results to the sender */ 10108 10109 if (debug) { 10110 fprintf(where, 10111 "recv_tcp_tran_rr: got %d transactions\n", 10112 trans_received); 10113 fflush(where); 10114 } 10115 10116 tcp_tran_rr_results->bytes_received = (trans_received * 10117 (tcp_tran_rr_request->request_size + 10118 tcp_tran_rr_request->response_size)); 10119 tcp_tran_rr_results->trans_received = trans_received; 10120 tcp_tran_rr_results->elapsed_time = elapsed_time; 10121 if (tcp_tran_rr_request->measure_cpu) { 10122 tcp_tran_rr_results->cpu_util = calc_cpu_util(elapsed_time); 10123 } 10124 10125 if (debug) { 10126 fprintf(where, 10127 "recv_tcp_tran_rr: test complete, sending results.\n"); 10128 fflush(where); 10129 } 10130 10131 send_response(); 10132 10133 } 10134 #endif /* DO_1644 */ 10135 10136 #ifdef DO_NBRR 10138 /* this routine implements the sending (netperf) side of the TCP_RR */ 10139 /* test using POSIX-style non-blocking sockets. */ 10140 10141 void 10142 send_tcp_nbrr(char remote_host[]) 10143 { 10144 10145 char *tput_title = "\ 10146 Local /Remote\n\ 10147 Socket Size Request Resp. Elapsed Trans.\n\ 10148 Send Recv Size Size Time Rate \n\ 10149 bytes Bytes bytes bytes secs. per sec \n\n"; 10150 10151 char *tput_fmt_0 = 10152 "%7.2f\n"; 10153 10154 char *tput_fmt_1_line_1 = "\ 10155 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 10156 char *tput_fmt_1_line_2 = "\ 10157 %-6d %-6d\n"; 10158 10159 char *cpu_title = "\ 10160 Local /Remote\n\ 10161 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 10162 Send Recv Size Size Time Rate local remote local remote\n\ 10163 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 10164 10165 char *cpu_fmt_0 = 10166 "%6.3f %c\n"; 10167 10168 char *cpu_fmt_1_line_1 = "\ 10169 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 10170 10171 char *cpu_fmt_1_line_2 = "\ 10172 %-6d %-6d\n"; 10173 10174 char *ksink_fmt = "\ 10175 Alignment Offset\n\ 10176 Local Remote Local Remote\n\ 10177 Send Recv Send Recv\n\ 10178 %5d %5d %5d %5d\n"; 10179 10180 10181 int timed_out = 0; 10182 float elapsed_time; 10183 10184 int len; 10185 char *temp_message_ptr; 10186 int nummessages; 10187 SOCKET send_socket; 10188 int trans_remaining; 10189 double bytes_xferd; 10190 10191 struct ring_elt *send_ring; 10192 struct ring_elt *recv_ring; 10193 10194 int rsp_bytes_left; 10195 int rsp_bytes_recvd; 10196 10197 float local_cpu_utilization; 10198 float local_service_demand; 10199 float remote_cpu_utilization; 10200 float remote_service_demand; 10201 double thruput; 10202 10203 struct hostent *hp; 10204 struct sockaddr_storage server; 10205 unsigned int addr; 10206 10207 struct tcp_rr_request_struct *tcp_rr_request; 10208 struct tcp_rr_response_struct *tcp_rr_response; 10209 struct tcp_rr_results_struct *tcp_rr_result; 10210 10211 struct addrinfo *remote_res; 10212 struct addrinfo *local_res; 10213 10214 tcp_rr_request = 10215 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 10216 tcp_rr_response= 10217 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 10218 tcp_rr_result = 10219 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 10220 10221 #ifdef WANT_HISTOGRAM 10222 if (verbosity > 1) { 10223 time_hist = HIST_new(); 10224 } 10225 #endif /* WANT_HISTOGRAM */ 10226 10227 /* since we are now disconnected from the code that established the */ 10228 /* control socket, and since we want to be able to use different */ 10229 /* protocols and such, we are passed the name of the remote host and */ 10230 /* must turn that into the test specific addressing information. */ 10231 10232 bzero((char *)&server, 10233 sizeof(server)); 10234 10235 complete_addrinfos(&remote_res, 10236 &local_res, 10237 remote_host, 10238 SOCK_STREAM, 10239 IPPROTO_TCP, 10240 0); 10241 10242 if ( print_headers ) { 10243 print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res); 10244 } 10245 10246 /* initialize a few counters */ 10247 10248 send_ring = NULL; 10249 recv_ring = NULL; 10250 confidence_iteration = 1; 10251 init_stat(); 10252 10253 /* we have a great-big while loop which controls the number of times */ 10254 /* we run a particular test. this is for the calculation of a */ 10255 /* confidence interval (I really should have stayed awake during */ 10256 /* probstats :). If the user did not request confidence measurement */ 10257 /* (no confidence is the default) then we will only go though the */ 10258 /* loop once. the confidence stuff originates from the folks at IBM */ 10259 10260 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 10261 (confidence_iteration <= iteration_min)) { 10262 10263 /* initialize a few counters. we have to remember that we might be */ 10264 /* going through the loop more than once. */ 10265 10266 nummessages = 0; 10267 bytes_xferd = 0.0; 10268 times_up = 0; 10269 timed_out = 0; 10270 trans_remaining = 0; 10271 10272 /* set-up the data buffers with the requested alignment and offset. */ 10273 /* since this is a request/response test, default the send_width and */ 10274 /* recv_width to 1 and not two raj 7/94 */ 10275 10276 if (send_width == 0) send_width = 1; 10277 if (recv_width == 0) recv_width = 1; 10278 10279 if (send_ring == NULL) { 10280 send_ring = allocate_buffer_ring(send_width, 10281 req_size, 10282 local_send_align, 10283 local_send_offset); 10284 } 10285 10286 if (recv_ring == NULL) { 10287 recv_ring = allocate_buffer_ring(recv_width, 10288 rsp_size, 10289 local_recv_align, 10290 local_recv_offset); 10291 } 10292 10293 /*set up the data socket */ 10294 send_socket = create_data_socket(local_res); 10295 10296 if (send_socket == INVALID_SOCKET){ 10297 perror("netperf: send_tcp_nbrr: tcp stream data socket"); 10298 exit(1); 10299 } 10300 10301 if (debug) { 10302 fprintf(where,"send_tcp_nbrr: send_socket obtained...\n"); 10303 } 10304 10305 /* If the user has requested cpu utilization measurements, we must */ 10306 /* calibrate the cpu(s). We will perform this task within the tests */ 10307 /* themselves. If the user has specified the cpu rate, then */ 10308 /* calibrate_local_cpu will return rather quickly as it will have */ 10309 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 10310 /* all the "normal" calibration stuff and return the rate back.*/ 10311 10312 if (local_cpu_usage) { 10313 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 10314 } 10315 10316 /* Tell the remote end to do a listen. The server alters the socket */ 10317 /* paramters on the other side at this point, hence the reason for */ 10318 /* all the values being passed in the setup message. If the user did */ 10319 /* not specify any of the parameters, they will be passed as 0, which */ 10320 /* will indicate to the remote that no changes beyond the system's */ 10321 /* default should be used. Alignment is the exception, it will */ 10322 /* default to 8, which will be no alignment alterations. */ 10323 10324 netperf_request.content.request_type = DO_TCP_NBRR; 10325 tcp_rr_request->recv_buf_size = rsr_size_req; 10326 tcp_rr_request->send_buf_size = rss_size_req; 10327 tcp_rr_request->recv_alignment = remote_recv_align; 10328 tcp_rr_request->recv_offset = remote_recv_offset; 10329 tcp_rr_request->send_alignment = remote_send_align; 10330 tcp_rr_request->send_offset = remote_send_offset; 10331 tcp_rr_request->request_size = req_size; 10332 tcp_rr_request->response_size = rsp_size; 10333 tcp_rr_request->no_delay = rem_nodelay; 10334 tcp_rr_request->measure_cpu = remote_cpu_usage; 10335 tcp_rr_request->cpu_rate = remote_cpu_rate; 10336 tcp_rr_request->so_rcvavoid = rem_rcvavoid; 10337 tcp_rr_request->so_sndavoid = rem_sndavoid; 10338 if (test_time) { 10339 tcp_rr_request->test_length = test_time; 10340 } 10341 else { 10342 tcp_rr_request->test_length = test_trans * -1; 10343 } 10344 10345 if (debug > 1) { 10346 fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n"); 10347 } 10348 10349 send_request(); 10350 10351 /* The response from the remote will contain all of the relevant */ 10352 /* socket parameters for this test type. We will put them back into */ 10353 /* the variables here so they can be displayed if desired. The */ 10354 /* remote will have calibrated CPU if necessary, and will have done */ 10355 /* all the needed set-up we will have calibrated the cpu locally */ 10356 /* before sending the request, and will grab the counter value right*/ 10357 /* after the connect returns. The remote will grab the counter right*/ 10358 /* after the accept call. This saves the hassle of extra messages */ 10359 /* being sent for the TCP tests. */ 10360 10361 recv_response(); 10362 10363 if (!netperf_response.content.serv_errno) { 10364 if (debug) 10365 fprintf(where,"remote listen done.\n"); 10366 rsr_size = tcp_rr_response->recv_buf_size; 10367 rss_size = tcp_rr_response->send_buf_size; 10368 rem_nodelay = tcp_rr_response->no_delay; 10369 remote_cpu_usage = tcp_rr_response->measure_cpu; 10370 remote_cpu_rate = tcp_rr_response->cpu_rate; 10371 /* make sure that port numbers are in network order */ 10372 server.sin_port = (unsigned short)tcp_rr_response->data_port_number; 10373 server.sin_port = htons(server.sin_port); 10374 } 10375 else { 10376 Set_errno(netperf_response.content.serv_errno); 10377 fprintf(where, 10378 "netperf: remote error %d", 10379 netperf_response.content.serv_errno); 10380 perror(""); 10381 fflush(where); 10382 exit(1); 10383 } 10384 10385 /*Connect up to the remote port on the data socket */ 10386 if (connect(send_socket, 10387 remote_res->ai_addr, 10388 remote_res->ai_addrlen) == INVALID_SOCKET){ 10389 perror("netperf: data socket connect failed"); 10390 10391 exit(1); 10392 } 10393 10394 /* now that we are connected, mark the socket as non-blocking */ 10395 if (!set_nonblock(send_socket)) { 10396 perror("netperf: set_nonblock"); 10397 exit(1); 10398 } 10399 10400 /* Data Socket set-up is finished. If there were problems, either the */ 10401 /* connect would have failed, or the previous response would have */ 10402 /* indicated a problem. I failed to see the value of the extra */ 10403 /* message after the accept on the remote. If it failed, we'll see it */ 10404 /* here. If it didn't, we might as well start pumping data. */ 10405 10406 /* Set-up the test end conditions. For a request/response test, they */ 10407 /* can be either time or transaction based. */ 10408 10409 if (test_time) { 10410 /* The user wanted to end the test after a period of time. */ 10411 times_up = 0; 10412 trans_remaining = 0; 10413 start_timer(test_time); 10414 } 10415 else { 10416 /* The tester wanted to send a number of bytes. */ 10417 trans_remaining = test_bytes; 10418 times_up = 1; 10419 } 10420 10421 /* The cpu_start routine will grab the current time and possibly */ 10422 /* value of the idle counter for later use in measuring cpu */ 10423 /* utilization and/or service demand and thruput. */ 10424 10425 cpu_start(local_cpu_usage); 10426 10427 #ifdef WANT_INTERVALS 10428 INTERVALS_INIT(); 10429 #endif /* WANT_INTERVALS */ 10430 10431 /* We use an "OR" to control test execution. When the test is */ 10432 /* controlled by time, the byte count check will always return false. */ 10433 /* When the test is controlled by byte count, the time test will */ 10434 /* always return false. When the test is finished, the whole */ 10435 /* expression will go false and we will stop sending data. I think I */ 10436 /* just arbitrarily decrement trans_remaining for the timed test, but */ 10437 /* will not do that just yet... One other question is whether or not */ 10438 /* the send buffer and the receive buffer should be the same buffer. */ 10439 10440 while ((!times_up) || (trans_remaining > 0)) { 10441 /* send the request. we assume that if we use a blocking socket, */ 10442 /* the request will be sent at one shot. */ 10443 10444 #ifdef WANT_HISTOGRAM 10445 if (verbosity > 1) { 10446 /* timestamp just before our call to send, and then again just */ 10447 /* after the receive raj 8/94 */ 10448 HIST_timestamp(&time_one); 10449 } 10450 #endif /* WANT_HISTOGRAM */ 10451 10452 /* even though this is a non-blocking socket, we will assume for */ 10453 /* the time being that we will be able to send an entire request */ 10454 /* without getting an EAGAIN */ 10455 if((len=send(send_socket, 10456 send_ring->buffer_ptr, 10457 req_size, 10458 0)) != req_size) { 10459 if (SOCKET_EINTR(len)) { 10460 /* we hit the end of a */ 10461 /* timed test. */ 10462 timed_out = 1; 10463 break; 10464 } 10465 perror("send_tcp_nbrr: data send error"); 10466 exit(1); 10467 } 10468 send_ring = send_ring->next; 10469 10470 /* receive the response. since we are using non-blocking I/O, we */ 10471 /* will "spin" on the recvs */ 10472 rsp_bytes_left = rsp_size; 10473 temp_message_ptr = recv_ring->buffer_ptr; 10474 while(rsp_bytes_left > 0) { 10475 if((rsp_bytes_recvd=recv(send_socket, 10476 temp_message_ptr, 10477 rsp_bytes_left, 10478 0)) == SOCKET_ERROR) { 10479 if (SOCKET_EINTR(rsp_bytes_recvd)) 10480 { 10481 /* We hit the end of a timed test. */ 10482 timed_out = 1; 10483 break; 10484 } 10485 #ifndef WIN32 // But what does WinNT indicate in this situation... 10486 else if (errno == EAGAIN) { 10487 Set_errno(0); 10488 continue; 10489 } 10490 #endif 10491 else { 10492 perror("send_tcp_nbrr: data recv error"); 10493 exit(1); 10494 } 10495 } 10496 rsp_bytes_left -= rsp_bytes_recvd; 10497 temp_message_ptr += rsp_bytes_recvd; 10498 } 10499 recv_ring = recv_ring->next; 10500 10501 if (timed_out) { 10502 /* we may have been in a nested while loop - we need */ 10503 /* another call to break. */ 10504 break; 10505 } 10506 10507 #ifdef WANT_HISTOGRAM 10508 if (verbosity > 1) { 10509 HIST_timestamp(&time_two); 10510 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 10511 } 10512 #endif /* WANT_HISTOGRAM */ 10513 #ifdef WANT_INTERVALS 10514 INTERVALS_WAIT(); 10515 #endif /* WANT_INTERVALS */ 10516 10517 nummessages++; 10518 if (trans_remaining) { 10519 trans_remaining--; 10520 } 10521 10522 if (debug > 3) { 10523 if ((nummessages % 100) == 0) { 10524 fprintf(where, 10525 "Transaction %d completed\n", 10526 nummessages); 10527 fflush(where); 10528 } 10529 } 10530 } 10531 10532 /* At this point we used to call shutdown on the data socket to be */ 10533 /* sure all the data was delivered, but this was not germane in a */ 10534 /* request/response test, and it was causing the tests to "hang" when */ 10535 /* they were being controlled by time. So, I have replaced this */ 10536 /* shutdown call with a call to close that can be found later in the */ 10537 /* procedure. */ 10538 10539 /* this call will always give us the elapsed time for the test, and */ 10540 /* will also store-away the necessaries for cpu utilization */ 10541 10542 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 10543 /* measured? how long */ 10544 /* did we really run? */ 10545 10546 /* Get the statistics from the remote end. The remote will have */ 10547 /* calculated service demand and all those interesting things. If it */ 10548 /* wasn't supposed to care, it will return obvious values. */ 10549 10550 recv_response(); 10551 if (!netperf_response.content.serv_errno) { 10552 if (debug) 10553 fprintf(where,"remote results obtained\n"); 10554 } 10555 else { 10556 Set_errno(netperf_response.content.serv_errno); 10557 fprintf(where, 10558 "netperf: remote error %d", 10559 netperf_response.content.serv_errno); 10560 perror(""); 10561 fflush(where); 10562 10563 exit(1); 10564 } 10565 10566 /* We now calculate what our thruput was for the test. */ 10567 10568 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 10569 thruput = nummessages/elapsed_time; 10570 10571 if (local_cpu_usage || remote_cpu_usage) { 10572 /* We must now do a little math for service demand and cpu */ 10573 /* utilization for the system(s) */ 10574 /* Of course, some of the information might be bogus because */ 10575 /* there was no idle counter in the kernel(s). We need to make */ 10576 /* a note of this for the user's benefit...*/ 10577 if (local_cpu_usage) { 10578 local_cpu_utilization = calc_cpu_util(0.0); 10579 /* since calc_service demand is doing ms/Kunit we will */ 10580 /* multiply the number of transaction by 1024 to get */ 10581 /* "good" numbers */ 10582 local_service_demand = calc_service_demand((double) nummessages*1024, 10583 0.0, 10584 0.0, 10585 0); 10586 } 10587 else { 10588 local_cpu_utilization = (float) -1.0; 10589 local_service_demand = (float) -1.0; 10590 } 10591 10592 if (remote_cpu_usage) { 10593 remote_cpu_utilization = tcp_rr_result->cpu_util; 10594 /* since calc_service demand is doing ms/Kunit we will */ 10595 /* multiply the number of transaction by 1024 to get */ 10596 /* "good" numbers */ 10597 remote_service_demand = calc_service_demand((double) nummessages*1024, 10598 0.0, 10599 remote_cpu_utilization, 10600 tcp_rr_result->num_cpus); 10601 } 10602 else { 10603 remote_cpu_utilization = (float) -1.0; 10604 remote_service_demand = (float) -1.0; 10605 } 10606 10607 } 10608 else { 10609 /* we were not measuring cpu, for the confidence stuff, we */ 10610 /* should make it -1.0 */ 10611 local_cpu_utilization = (float) -1.0; 10612 local_service_demand = (float) -1.0; 10613 remote_cpu_utilization = (float) -1.0; 10614 remote_service_demand = (float) -1.0; 10615 } 10616 10617 /* at this point, we want to calculate the confidence information. */ 10618 /* if debugging is on, calculate_confidence will print-out the */ 10619 /* parameters we pass it */ 10620 10621 calculate_confidence(confidence_iteration, 10622 elapsed_time, 10623 thruput, 10624 local_cpu_utilization, 10625 remote_cpu_utilization, 10626 local_service_demand, 10627 remote_service_demand); 10628 10629 10630 confidence_iteration++; 10631 10632 /* we are now done with the socket, so close it */ 10633 close(send_socket); 10634 10635 } 10636 10637 retrieve_confident_values(&elapsed_time, 10638 &thruput, 10639 &local_cpu_utilization, 10640 &remote_cpu_utilization, 10641 &local_service_demand, 10642 &remote_service_demand); 10643 10644 /* We are now ready to print all the information. If the user */ 10645 /* has specified zero-level verbosity, we will just print the */ 10646 /* local service demand, or the remote service demand. If the */ 10647 /* user has requested verbosity level 1, he will get the basic */ 10648 /* "streamperf" numbers. If the user has specified a verbosity */ 10649 /* of greater than 1, we will display a veritable plethora of */ 10650 /* background information from outside of this block as it it */ 10651 /* not cpu_measurement specific... */ 10652 10653 if (confidence < 0) { 10654 /* we did not hit confidence, but were we asked to look for it? */ 10655 if (iteration_max > 1) { 10656 display_confidence(); 10657 } 10658 } 10659 10660 if (local_cpu_usage || remote_cpu_usage) { 10661 local_cpu_method = format_cpu_method(cpu_method); 10662 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method); 10663 10664 switch (verbosity) { 10665 case 0: 10666 if (local_cpu_usage) { 10667 fprintf(where, 10668 cpu_fmt_0, 10669 local_service_demand, 10670 local_cpu_method); 10671 } 10672 else { 10673 fprintf(where, 10674 cpu_fmt_0, 10675 remote_service_demand, 10676 remote_cpu_method); 10677 } 10678 break; 10679 case 1: 10680 case 2: 10681 if (print_headers) { 10682 fprintf(where, 10683 cpu_title, 10684 local_cpu_method, 10685 remote_cpu_method); 10686 } 10687 10688 fprintf(where, 10689 cpu_fmt_1_line_1, /* the format string */ 10690 lss_size, /* local sendbuf size */ 10691 lsr_size, 10692 req_size, /* how large were the requests */ 10693 rsp_size, /* guess */ 10694 elapsed_time, /* how long was the test */ 10695 thruput, 10696 local_cpu_utilization, /* local cpu */ 10697 remote_cpu_utilization, /* remote cpu */ 10698 local_service_demand, /* local service demand */ 10699 remote_service_demand); /* remote service demand */ 10700 fprintf(where, 10701 cpu_fmt_1_line_2, 10702 rss_size, 10703 rsr_size); 10704 break; 10705 } 10706 } 10707 else { 10708 /* The tester did not wish to measure service demand. */ 10709 10710 switch (verbosity) { 10711 case 0: 10712 fprintf(where, 10713 tput_fmt_0, 10714 thruput); 10715 break; 10716 case 1: 10717 case 2: 10718 if (print_headers) { 10719 fprintf(where,tput_title,format_units()); 10720 } 10721 10722 fprintf(where, 10723 tput_fmt_1_line_1, /* the format string */ 10724 lss_size, 10725 lsr_size, 10726 req_size, /* how large were the requests */ 10727 rsp_size, /* how large were the responses */ 10728 elapsed_time, /* how long did it take */ 10729 thruput); 10730 fprintf(where, 10731 tput_fmt_1_line_2, 10732 rss_size, /* remote recvbuf size */ 10733 rsr_size); 10734 10735 break; 10736 } 10737 } 10738 10739 /* it would be a good thing to include information about some of the */ 10740 /* other parameters that may have been set for this test, but at the */ 10741 /* moment, I do not wish to figure-out all the formatting, so I will */ 10742 /* just put this comment here to help remind me that it is something */ 10743 /* that should be done at a later time. */ 10744 10745 /* how to handle the verbose information in the presence of */ 10746 /* confidence intervals is yet to be determined... raj 11/94 */ 10747 if (verbosity > 1) { 10748 /* The user wanted to know it all, so we will give it to him. */ 10749 /* This information will include as much as we can find about */ 10750 /* TCP statistics, the alignments of the sends and receives */ 10751 /* and all that sort of rot... */ 10752 10753 fprintf(where, 10754 ksink_fmt, 10755 local_send_align, 10756 remote_recv_offset, 10757 local_send_offset, 10758 remote_recv_offset); 10759 10760 #ifdef WANT_HISTOGRAM 10761 fprintf(where,"\nHistogram of request/response times\n"); 10762 fflush(where); 10763 HIST_report(time_hist); 10764 #endif /* WANT_HISTOGRAM */ 10765 10766 } 10767 10768 } 10769 10770 /* this routine implements the receive (netserver) side of a TCP_RR */ 10772 /* test */ 10773 void 10774 recv_tcp_nbrr() 10775 { 10776 10777 struct ring_elt *send_ring; 10778 struct ring_elt *recv_ring; 10779 10780 struct sockaddr_in myaddr_in, 10781 peeraddr_in; 10782 SOCKET s_listen,s_data; 10783 netperf_socklen_t addrlen; 10784 char *temp_message_ptr; 10785 int trans_received; 10786 int trans_remaining; 10787 int bytes_sent; 10788 int request_bytes_recvd; 10789 int request_bytes_remaining; 10790 int timed_out = 0; 10791 float elapsed_time; 10792 10793 struct addrinfo *local_res; 10794 char local_name[BUFSIZ]; 10795 char port_buffer[PORTBUFSIZE]; 10796 10797 struct tcp_rr_request_struct *tcp_rr_request; 10798 struct tcp_rr_response_struct *tcp_rr_response; 10799 struct tcp_rr_results_struct *tcp_rr_results; 10800 10801 tcp_rr_request = 10802 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data; 10803 tcp_rr_response = 10804 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data; 10805 tcp_rr_results = 10806 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data; 10807 10808 if (debug) { 10809 fprintf(where,"netserver: recv_tcp_nbrr: entered...\n"); 10810 fflush(where); 10811 } 10812 10813 /* We want to set-up the listen socket with all the desired */ 10814 /* parameters and then let the initiator know that all is ready. If */ 10815 /* socket size defaults are to be used, then the initiator will have */ 10816 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 10817 /* send-back what they are. If that information cannot be determined, */ 10818 /* then we send-back -1's for the sizes. If things go wrong for any */ 10819 /* reason, we will drop back ten yards and punt. */ 10820 10821 /* If anything goes wrong, we want the remote to know about it. It */ 10822 /* would be best if the error that the remote reports to the user is */ 10823 /* the actual error we encountered, rather than some bogus unexpected */ 10824 /* response type message. */ 10825 10826 if (debug) { 10827 fprintf(where,"recv_tcp_nbrr: setting the response type...\n"); 10828 fflush(where); 10829 } 10830 10831 netperf_response.content.response_type = TCP_RR_RESPONSE; 10832 10833 if (debug) { 10834 fprintf(where,"recv_tcp_nbrr: the response type is set...\n"); 10835 fflush(where); 10836 } 10837 10838 /* allocate the recv and send rings with the requested alignments */ 10839 /* and offsets. raj 7/94 */ 10840 if (debug) { 10841 fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n", 10842 tcp_rr_request->recv_alignment, 10843 tcp_rr_request->recv_offset); 10844 fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n", 10845 tcp_rr_request->send_alignment, 10846 tcp_rr_request->send_offset); 10847 fflush(where); 10848 } 10849 10850 /* at some point, these need to come to us from the remote system */ 10851 if (send_width == 0) send_width = 1; 10852 if (recv_width == 0) recv_width = 1; 10853 10854 send_ring = allocate_buffer_ring(send_width, 10855 tcp_rr_request->response_size, 10856 tcp_rr_request->send_alignment, 10857 tcp_rr_request->send_offset); 10858 10859 recv_ring = allocate_buffer_ring(recv_width, 10860 tcp_rr_request->request_size, 10861 tcp_rr_request->recv_alignment, 10862 tcp_rr_request->recv_offset); 10863 10864 10865 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */ 10866 /* can put in OUR values !-) At some point, we may want to nail this */ 10867 /* socket to a particular network-level address, but for now, */ 10868 /* INADDR_ANY should be just fine. */ 10869 10870 bzero((char *)&myaddr_in, 10871 sizeof(myaddr_in)); 10872 myaddr_in.sin_family = AF_INET; 10873 myaddr_in.sin_addr.s_addr = INADDR_ANY; 10874 myaddr_in.sin_port = htons((unsigned short)tcp_rr_request->port); 10875 10876 /* Grab a socket to listen on, and then listen on it. */ 10877 10878 if (debug) { 10879 fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n"); 10880 fflush(where); 10881 } 10882 10883 /* create_data_socket expects to find some things in the global */ 10884 /* variables, so set the globals based on the values in the request. */ 10885 /* once the socket has been created, we will set the response values */ 10886 /* based on the updated value of those globals. raj 7/94 */ 10887 lss_size_req = tcp_rr_request->send_buf_size; 10888 lsr_size_req = tcp_rr_request->recv_buf_size; 10889 loc_nodelay = tcp_rr_request->no_delay; 10890 loc_rcvavoid = tcp_rr_request->so_rcvavoid; 10891 loc_sndavoid = tcp_rr_request->so_sndavoid; 10892 10893 set_hostname_and_port(local_name, 10894 port_buffer, 10895 nf_to_af(tcp_rr_request->ipfamily), 10896 tcp_rr_request->port); 10897 10898 local_res = complete_addrinfo(local_name, 10899 local_name, 10900 port_buffer, 10901 nf_to_af(tcp_rr_request->ipfamily), 10902 SOCK_STREAM, 10903 IPPROTO_TCP, 10904 0); 10905 10906 s_listen = create_data_socket(local_res); 10907 10908 if (s_listen == INVALID_SOCKET) { 10909 netperf_response.content.serv_errno = errno; 10910 send_response(); 10911 10912 exit(1); 10913 } 10914 10915 /* Let's get an address assigned to this socket so we can tell the */ 10916 /* initiator how to reach the data socket. There may be a desire to */ 10917 /* nail this socket to a specific IP address in a multi-homed, */ 10918 /* multi-connection situation, but for now, we'll ignore the issue */ 10919 /* and concentrate on single connection testing. */ 10920 10921 if (bind(s_listen, 10922 (struct sockaddr *)&myaddr_in, 10923 sizeof(myaddr_in)) == SOCKET_ERROR) { 10924 netperf_response.content.serv_errno = errno; 10925 close(s_listen); 10926 send_response(); 10927 10928 exit(1); 10929 } 10930 10931 /* Now, let's set-up the socket to listen for connections */ 10932 if (listen(s_listen, 5) == SOCKET_ERROR) { 10933 netperf_response.content.serv_errno = errno; 10934 close(s_listen); 10935 send_response(); 10936 10937 exit(1); 10938 } 10939 10940 10941 /* now get the port number assigned by the system */ 10942 addrlen = sizeof(myaddr_in); 10943 if (getsockname(s_listen, 10944 (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){ 10945 netperf_response.content.serv_errno = errno; 10946 close(s_listen); 10947 send_response(); 10948 10949 exit(1); 10950 } 10951 10952 /* Now myaddr_in contains the port and the internet address this is */ 10953 /* returned to the sender also implicitly telling the sender that the */ 10954 /* socket buffer sizing has been done. */ 10955 10956 tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 10957 netperf_response.content.serv_errno = 0; 10958 10959 /* But wait, there's more. If the initiator wanted cpu measurements, */ 10960 /* then we must call the calibrate routine, which will return the max */ 10961 /* rate back to the initiator. If the CPU was not to be measured, or */ 10962 /* something went wrong with the calibration, we will return a 0.0 to */ 10963 /* the initiator. */ 10964 10965 tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */ 10966 tcp_rr_response->measure_cpu = 0; 10967 10968 if (tcp_rr_request->measure_cpu) { 10969 tcp_rr_response->measure_cpu = 1; 10970 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate); 10971 } 10972 10973 10974 /* before we send the response back to the initiator, pull some of */ 10975 /* the socket parms from the globals */ 10976 tcp_rr_response->send_buf_size = lss_size; 10977 tcp_rr_response->recv_buf_size = lsr_size; 10978 tcp_rr_response->no_delay = loc_nodelay; 10979 tcp_rr_response->so_rcvavoid = loc_rcvavoid; 10980 tcp_rr_response->so_sndavoid = loc_sndavoid; 10981 tcp_rr_response->test_length = tcp_rr_request->test_length; 10982 send_response(); 10983 10984 addrlen = sizeof(peeraddr_in); 10985 10986 if ((s_data = accept(s_listen, 10987 (struct sockaddr *)&peeraddr_in, 10988 &addrlen)) == INVALID_SOCKET) { 10989 /* Let's just punt. The remote will be given some information */ 10990 close(s_listen); 10991 exit(1); 10992 } 10993 10994 if (debug) { 10995 fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n"); 10996 fflush(where); 10997 } 10998 10999 #ifdef KLUDGE_SOCKET_OPTIONS 11000 /* this is for those systems which *INCORRECTLY* fail to pass */ 11001 /* attributes across an accept() call. Including this goes against */ 11002 /* my better judgement :( raj 11/95 */ 11003 11004 kludge_socket_options(s_data); 11005 11006 #endif /* KLUDGE_SOCKET_OPTIONS */ 11007 11008 /* now that we are connected, mark the socket as non-blocking */ 11009 if (!set_nonblock(s_data)) { 11010 close(s_data); 11011 exit(1); 11012 } 11013 11014 11015 /* Now it's time to start receiving data on the connection. We will */ 11016 /* first grab the apropriate counters and then start grabbing. */ 11017 11018 cpu_start(tcp_rr_request->measure_cpu); 11019 11020 #ifdef WIN32 11021 /* this is used so the timer thread can close the socket out from */ 11022 /* under us, which to date is the easiest/cleanest/least */ 11023 /* Windows-specific way I can find to force the winsock calls to */ 11024 /* return WSAEINTR with the test is over. anything that will run on */ 11025 /* 95 and NT and is closer to what netperf expects from Unix signals */ 11026 /* and such would be appreciated raj 1/96 */ 11027 win_kludge_socket = s_data; 11028 #endif /* WIN32 */ 11029 11030 /* The loop will exit when the sender does a shutdown, which will */ 11031 /* return a length of zero */ 11032 11033 if (tcp_rr_request->test_length > 0) { 11034 times_up = 0; 11035 trans_remaining = 0; 11036 start_timer(tcp_rr_request->test_length + PAD_TIME); 11037 } 11038 else { 11039 times_up = 1; 11040 trans_remaining = tcp_rr_request->test_length * -1; 11041 } 11042 11043 trans_received = 0; 11044 11045 while ((!times_up) || (trans_remaining > 0)) { 11046 temp_message_ptr = recv_ring->buffer_ptr; 11047 request_bytes_remaining = tcp_rr_request->request_size; 11048 while(request_bytes_remaining > 0) { 11049 if((request_bytes_recvd=recv(s_data, 11050 temp_message_ptr, 11051 request_bytes_remaining, 11052 0)) == SOCKET_ERROR) { 11053 if ( SOCKET_EINTR(request_bytes_recvd)) 11054 { 11055 /* the timer popped */ 11056 timed_out = 1; 11057 break; 11058 } 11059 #ifndef WIN32 // But what does WinNT indicate in this situation... 11060 else if (errno == EAGAIN) { 11061 Set_errno(0); 11062 if (times_up) { 11063 timed_out = 1; 11064 break; 11065 } 11066 continue; 11067 } 11068 #endif 11069 else { 11070 netperf_response.content.serv_errno = errno; 11071 send_response(); 11072 exit(1); 11073 } 11074 } 11075 else { 11076 request_bytes_remaining -= request_bytes_recvd; 11077 temp_message_ptr += request_bytes_recvd; 11078 } 11079 } 11080 11081 recv_ring = recv_ring->next; 11082 11083 if (timed_out) { 11084 /* we hit the end of the test based on time - lets */ 11085 /* bail out of here now... */ 11086 fprintf(where,"yo5\n"); 11087 fflush(where); 11088 break; 11089 } 11090 11091 /* Now, send the response to the remote */ 11092 if((bytes_sent=send(s_data, 11093 send_ring->buffer_ptr, 11094 tcp_rr_request->response_size, 11095 0)) == SOCKET_ERROR) { 11096 if (SOCKET_EINTR(bytes_sent)) { 11097 /* the test timer has popped */ 11098 timed_out = 1; 11099 fprintf(where,"yo6\n"); 11100 fflush(where); 11101 break; 11102 } 11103 netperf_response.content.serv_errno = 992; 11104 send_response(); 11105 exit(1); 11106 } 11107 11108 send_ring = send_ring->next; 11109 11110 trans_received++; 11111 if (trans_remaining) { 11112 trans_remaining--; 11113 } 11114 } 11115 11116 11117 /* The loop now exits due to timeout or transaction count being */ 11118 /* reached */ 11119 11120 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time); 11121 11122 stop_timer(); 11123 11124 if (timed_out) { 11125 /* we ended the test by time, which was at least 2 seconds */ 11126 /* longer than we wanted to run. so, we want to subtract */ 11127 /* PAD_TIME from the elapsed_time. */ 11128 elapsed_time -= PAD_TIME; 11129 } 11130 11131 /* send the results to the sender */ 11132 11133 if (debug) { 11134 fprintf(where, 11135 "recv_tcp_nbrr: got %d transactions\n", 11136 trans_received); 11137 fflush(where); 11138 } 11139 11140 tcp_rr_results->bytes_received = (trans_received * 11141 (tcp_rr_request->request_size + 11142 tcp_rr_request->response_size)); 11143 tcp_rr_results->trans_received = trans_received; 11144 tcp_rr_results->elapsed_time = elapsed_time; 11145 tcp_rr_results->cpu_method = cpu_method; 11146 tcp_rr_results->num_cpus = lib_num_loc_cpus; 11147 if (tcp_rr_request->measure_cpu) { 11148 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 11149 } 11150 11151 if (debug) { 11152 fprintf(where, 11153 "recv_tcp_nbrr: test complete, sending results.\n"); 11154 fflush(where); 11155 } 11156 11157 /* we are done with the socket, free it */ 11158 close(s_data); 11159 11160 send_response(); 11161 11162 } 11163 11164 #endif /* DO_NBRR */ 11165 11166 11168 /* this test is intended to test the performance of establishing a */ 11169 /* connection, and then closing it again. this test is of somewhat */ 11170 /* arcane interest since no packets are exchanged between the */ 11171 /* user-space processes, but it will show the raw overhead of */ 11172 /* establishing a TCP connection. that service demand could then be */ 11173 /* compared with the sum of the service demands of a TCP_CRR and */ 11174 /* TCP_RR test - presumeably, they would all relate */ 11175 11176 void 11177 send_tcp_cc(char remote_host[]) 11178 { 11179 11180 char *tput_title = "\ 11181 Local /Remote\n\ 11182 Socket Size Request Resp. Elapsed Trans.\n\ 11183 Send Recv Size Size Time Rate \n\ 11184 bytes Bytes bytes bytes secs. per sec \n\n"; 11185 11186 char *tput_fmt_0 = 11187 "%7.2f\n"; 11188 11189 char *tput_fmt_1_line_1 = "\ 11190 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 11191 char *tput_fmt_1_line_2 = "\ 11192 %-6d %-6d\n"; 11193 11194 char *cpu_title = "\ 11195 Local /Remote\n\ 11196 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 11197 Send Recv Size Size Time Rate local remote local remote\n\ 11198 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n"; 11199 11200 char *cpu_fmt_0 = 11201 "%6.3f\n"; 11202 11203 char *cpu_fmt_1_line_1 = "\ 11204 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 11205 11206 char *cpu_fmt_1_line_2 = "\ 11207 %-6d %-6d\n"; 11208 11209 char *ksink_fmt = "\n\ 11210 Alignment Offset\n\ 11211 Local Remote Local Remote\n\ 11212 Send Recv Send Recv\n\ 11213 %5d %5d %5d %5d\n"; 11214 11215 11216 int timed_out = 0; 11217 float elapsed_time; 11218 11219 char temp_message_ptr[1]; 11220 int nummessages; 11221 SOCKET send_socket; 11222 int trans_remaining; 11223 double bytes_xferd; 11224 int rsp_bytes_left = 1; 11225 int rsp_bytes_recvd; 11226 11227 float local_cpu_utilization; 11228 float local_service_demand; 11229 float remote_cpu_utilization; 11230 float remote_service_demand; 11231 double thruput; 11232 11233 struct addrinfo *local_res; 11234 struct addrinfo *remote_res; 11235 11236 int myport; 11237 int ret; 11238 11239 struct tcp_cc_request_struct *tcp_cc_request; 11240 struct tcp_cc_response_struct *tcp_cc_response; 11241 struct tcp_cc_results_struct *tcp_cc_result; 11242 11243 tcp_cc_request = 11244 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data; 11245 tcp_cc_response = 11246 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data; 11247 tcp_cc_result = 11248 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data; 11249 11250 11251 #ifdef WANT_HISTOGRAM 11252 if (verbosity > 1) { 11253 time_hist = HIST_new(); 11254 } 11255 #endif /* WANT_HISTOGRAM */ 11256 11257 /* since we are now disconnected from the code that established the */ 11258 /* control socket, and since we want to be able to use different */ 11259 /* protocols and such, we are passed the name of the remote host and */ 11260 /* must turn that into the test specific addressing information. */ 11261 11262 complete_addrinfos(&remote_res, 11263 &local_res, 11264 remote_host, 11265 SOCK_STREAM, 11266 IPPROTO_TCP, 11267 0); 11268 11269 if ( print_headers ) { 11270 print_top_test_header("TCP Connect/Close TEST",local_res,remote_res); 11271 } 11272 11273 /* initialize a few counters */ 11274 11275 nummessages = 0; 11276 bytes_xferd = 0.0; 11277 times_up = 0; 11278 11279 /* since there are no data buffers in this test, we need no send or */ 11280 /* recv rings */ 11281 11282 if (debug) { 11283 fprintf(where,"send_tcp_cc: send_socket obtained...\n"); 11284 } 11285 11286 /* If the user has requested cpu utilization measurements, we must */ 11287 /* calibrate the cpu(s). We will perform this task within the tests */ 11288 /* themselves. If the user has specified the cpu rate, then */ 11289 /* calibrate_local_cpu will return rather quickly as it will have */ 11290 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 11291 /* all the "normal" calibration stuff and return the rate back.*/ 11292 11293 if (local_cpu_usage) { 11294 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 11295 } 11296 11297 /* Tell the remote end to do a listen. The server alters the socket */ 11298 /* paramters on the other side at this point, hence the reason for */ 11299 /* all the values being passed in the setup message. If the user did */ 11300 /* not specify any of the parameters, they will be passed as 0, which */ 11301 /* will indicate to the remote that no changes beyond the system's */ 11302 /* default should be used. Alignment is the exception, it will */ 11303 /* default to 8, which will be no alignment alterations. */ 11304 11305 netperf_request.content.request_type = DO_TCP_CC; 11306 tcp_cc_request->recv_buf_size = rsr_size_req; 11307 tcp_cc_request->send_buf_size = rss_size_req; 11308 tcp_cc_request->recv_alignment = remote_recv_align; 11309 tcp_cc_request->recv_offset = remote_recv_offset; 11310 tcp_cc_request->send_alignment = remote_send_align; 11311 tcp_cc_request->send_offset = remote_send_offset; 11312 tcp_cc_request->request_size = req_size; 11313 tcp_cc_request->response_size = rsp_size; 11314 tcp_cc_request->no_delay = rem_nodelay; 11315 tcp_cc_request->measure_cpu = remote_cpu_usage; 11316 tcp_cc_request->cpu_rate = remote_cpu_rate; 11317 tcp_cc_request->so_rcvavoid = rem_rcvavoid; 11318 tcp_cc_request->so_sndavoid = rem_sndavoid; 11319 if (test_time) { 11320 tcp_cc_request->test_length = test_time; 11321 } 11322 else { 11323 tcp_cc_request->test_length = test_trans * -1; 11324 } 11325 tcp_cc_request->port = atoi(remote_data_port); 11326 tcp_cc_request->ipfamily = af_to_nf(remote_res->ai_family); 11327 11328 if (debug > 1) { 11329 fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n"); 11330 } 11331 11332 send_request(); 11333 11334 /* The response from the remote will contain all of the relevant */ 11335 /* socket parameters for this test type. We will put them back into */ 11336 /* the variables here so they can be displayed if desired. The */ 11337 /* remote will have calibrated CPU if necessary, and will have done */ 11338 /* all the needed set-up we will have calibrated the cpu locally */ 11339 /* before sending the request, and will grab the counter value right */ 11340 /* after the connect returns. The remote will grab the counter right */ 11341 /* after the accept call. This saves the hassle of extra messages */ 11342 /* being sent for the TCP tests. */ 11343 11344 recv_response(); 11345 11346 if (!netperf_response.content.serv_errno) { 11347 rsr_size = tcp_cc_response->recv_buf_size; 11348 rss_size = tcp_cc_response->send_buf_size; 11349 rem_nodelay = tcp_cc_response->no_delay; 11350 remote_cpu_usage= tcp_cc_response->measure_cpu; 11351 remote_cpu_rate = tcp_cc_response->cpu_rate; 11352 /* make sure that port numbers are in network order */ 11353 set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number); 11354 11355 if (debug) { 11356 fprintf(where,"remote listen done.\n"); 11357 fprintf(where,"remote port is %d\n",get_port_number(remote_res)); 11358 fflush(where); 11359 } 11360 } 11361 else { 11362 Set_errno(netperf_response.content.serv_errno); 11363 fprintf(where, 11364 "netperf: remote error %d", 11365 netperf_response.content.serv_errno); 11366 perror(""); 11367 fflush(where); 11368 exit(1); 11369 } 11370 11371 #ifdef WANT_DEMO 11372 DEMO_RR_SETUP(100) 11373 #endif 11374 11375 /* pick a nice random spot between client_port_min and */ 11376 /* client_port_max for our initial port number */ 11377 srand(getpid()); 11378 if (client_port_max - client_port_min) { 11379 myport = client_port_min + 11380 (rand() % (client_port_max - client_port_min)); 11381 } 11382 else { 11383 myport = client_port_min; 11384 } 11385 /* there will be a ++ before the first call to bind, so subtract one */ 11386 myport--; 11387 11388 /* Set-up the test end conditions. For a request/response test, they */ 11389 /* can be either time or transaction based. */ 11390 11391 if (test_time) { 11392 /* The user wanted to end the test after a period of time. */ 11393 times_up = 0; 11394 trans_remaining = 0; 11395 start_timer(test_time); 11396 } 11397 else { 11398 /* The tester wanted to send a number of bytes. */ 11399 trans_remaining = test_bytes; 11400 times_up = 1; 11401 } 11402 11403 /* The cpu_start routine will grab the current time and possibly */ 11404 /* value of the idle counter for later use in measuring cpu */ 11405 /* utilization and/or service demand and thruput. */ 11406 11407 cpu_start(local_cpu_usage); 11408 11409 #ifdef WANT_DEMO 11410 if (demo_mode) { 11411 HIST_timestamp(demo_one_ptr); 11412 } 11413 #endif 11414 11415 /* We use an "OR" to control test execution. When the test is */ 11416 /* controlled by time, the byte count check will always return false. */ 11417 /* When the test is controlled by byte count, the time test will */ 11418 /* always return false. When the test is finished, the whole */ 11419 /* expression will go false and we will stop sending data. I think I */ 11420 /* just arbitrarily decrement trans_remaining for the timed test, but */ 11421 /* will not do that just yet... One other question is whether or not */ 11422 /* the send buffer and the receive buffer should be the same buffer. */ 11423 11424 while ((!times_up) || (trans_remaining > 0)) { 11425 11426 #ifdef WANT_HISTOGRAM 11427 if (verbosity > 1) { 11428 /* timestamp just before our call to create the socket, and then */ 11429 /* again just after the receive raj 3/95 */ 11430 HIST_timestamp(&time_one); 11431 } 11432 #endif /* WANT_HISTOGRAM */ 11433 11434 /* set up the data socket */ 11435 /* newport: is this label really required any longer? */ 11436 /* pick a new port number */ 11437 myport++; 11438 11439 /* wrap the port number when we get to client_port_max. NOTE, some */ 11440 /* broken TCP's might treat the port number as a signed 16 bit */ 11441 /* quantity. we aren't interested in testing such broken */ 11442 /* implementations :) so we won't make sure that it is below 32767 */ 11443 /* raj 8/94 */ 11444 if (myport >= client_port_max) { 11445 myport = client_port_min; 11446 } 11447 11448 /* we do not want to use the port number that the server is */ 11449 /* sitting at - this would cause us to fail in a loopback test. we */ 11450 /* could just rely on the failure of the bind to get us past this, */ 11451 /* but I'm guessing that in this one case at least, it is much */ 11452 /* faster, given that we *know* that port number is already in use */ 11453 /* (or rather would be in a loopback test) */ 11454 11455 if (myport == get_port_number(remote_res)) myport++; 11456 11457 if (debug) { 11458 if ((nummessages % 100) == 0) { 11459 printf("port %d\n",myport); 11460 } 11461 } 11462 set_port_number(local_res, (unsigned short)myport); 11463 send_socket = create_data_socket(local_res); 11464 11465 if (send_socket == INVALID_SOCKET) { 11466 perror("netperf: send_tcp_cc: tcp stream data socket"); 11467 exit(1); 11468 } 11469 11470 /* we used to have a call to bind() here, but that is being 11471 taken care of by create_data_socket(). raj 2005-02-08 */ 11472 11473 /* Connect up to the remote port on the data socket */ 11474 if ((ret = connect(send_socket, 11475 remote_res->ai_addr, 11476 remote_res->ai_addrlen)) == INVALID_SOCKET){ 11477 if (SOCKET_EINTR(ret)) 11478 { 11479 /* we hit the end of a */ 11480 /* timed test. */ 11481 timed_out = 1; 11482 break; 11483 } 11484 perror("netperf: data socket connect failed"); 11485 printf("\tattempted to connect on socket %d to port %d", 11486 send_socket, 11487 get_port_number(remote_res)); 11488 printf(" from port %u \n",get_port_number(local_res)); 11489 exit(1); 11490 } 11491 11492 /* we hang in a recv() to get the remote's close indication */ 11493 11494 rsp_bytes_recvd=recv(send_socket, 11495 temp_message_ptr, 11496 rsp_bytes_left, 11497 0); 11498 11499 11500 if (rsp_bytes_recvd == 0) { 11501 /* connection close, call close. we assume that the requisite */ 11502 /* number of bytes have been received */ 11503 11504 #ifdef WANT_HISTOGRAM 11505 if (verbosity > 1) { 11506 HIST_timestamp(&time_two); 11507 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 11508 } 11509 #endif /* WANT_HISTOGRAM */ 11510 11511 #ifdef WANT_DEMO 11512 DEMO_RR_INTERVAL(1) 11513 #endif 11514 11515 nummessages++; 11516 if (trans_remaining) { 11517 trans_remaining--; 11518 } 11519 11520 if (debug > 3) { 11521 fprintf(where, 11522 "Transaction %d completed on local port %u\n", 11523 nummessages, 11524 get_port_number(local_res)); 11525 fflush(where); 11526 } 11527 11528 close(send_socket); 11529 11530 } 11531 else { 11532 /* it was less than zero - an error occured */ 11533 if (SOCKET_EINTR(rsp_bytes_recvd)) 11534 { 11535 /* We hit the end of a timed test. */ 11536 timed_out = 1; 11537 break; 11538 } 11539 perror("send_tcp_cc: data recv error"); 11540 exit(1); 11541 } 11542 11543 } 11544 11545 11546 /* this call will always give us the elapsed time for the test, and */ 11547 /* will also store-away the necessaries for cpu utilization */ 11548 11549 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */ 11550 /* how long did we really run? */ 11551 11552 /* Get the statistics from the remote end. The remote will have */ 11553 /* calculated service demand and all those interesting things. If it */ 11554 /* wasn't supposed to care, it will return obvious values. */ 11555 11556 recv_response(); 11557 if (!netperf_response.content.serv_errno) { 11558 if (debug) 11559 fprintf(where,"remote results obtained\n"); 11560 } 11561 else { 11562 Set_errno(netperf_response.content.serv_errno); 11563 fprintf(where, 11564 "netperf: remote error %d", 11565 netperf_response.content.serv_errno); 11566 perror(""); 11567 fflush(where); 11568 11569 exit(1); 11570 } 11571 11572 /* We now calculate what our thruput was for the test. In the future, */ 11573 /* we may want to include a calculation of the thruput measured by */ 11574 /* the remote, but it should be the case that for a TCP stream test, */ 11575 /* that the two numbers should be *very* close... We calculate */ 11576 /* bytes_sent regardless of the way the test length was controlled. */ 11577 /* If it was time, we needed to, and if it was by bytes, the user may */ 11578 /* have specified a number of bytes that wasn't a multiple of the */ 11579 /* send_size, so we really didn't send what he asked for ;-) We use */ 11580 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */ 11581 /* 1024. A future enhancement *might* be to choose from a couple of */ 11582 /* unit selections. */ 11583 11584 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 11585 thruput = calc_thruput(bytes_xferd); 11586 11587 if (local_cpu_usage || remote_cpu_usage) { 11588 /* We must now do a little math for service demand and cpu */ 11589 /* utilization for the system(s) */ 11590 /* Of course, some of the information might be bogus because */ 11591 /* there was no idle counter in the kernel(s). We need to make */ 11592 /* a note of this for the user's benefit...*/ 11593 if (local_cpu_usage) { 11594 if (local_cpu_rate == 0.0) { 11595 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n"); 11596 fprintf(where,"Local CPU usage numbers based on process information only!\n"); 11597 fflush(where); 11598 } 11599 local_cpu_utilization = calc_cpu_util(0.0); 11600 /* since calc_service demand is doing ms/Kunit we will */ 11601 /* multiply the number of transaction by 1024 to get */ 11602 /* "good" numbers */ 11603 local_service_demand = calc_service_demand((double) nummessages*1024, 11604 0.0, 11605 0.0, 11606 0); 11607 } 11608 else { 11609 local_cpu_utilization = (float) -1.0; 11610 local_service_demand = (float) -1.0; 11611 } 11612 11613 if (remote_cpu_usage) { 11614 if (remote_cpu_rate == 0.0) { 11615 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n"); 11616 fprintf(where,"Remote CPU usage numbers based on process information only!\n"); 11617 fflush(where); 11618 } 11619 remote_cpu_utilization = tcp_cc_result->cpu_util; 11620 /* since calc_service demand is doing ms/Kunit we will */ 11621 /* multiply the number of transaction by 1024 to get */ 11622 /* "good" numbers */ 11623 remote_service_demand = calc_service_demand((double) nummessages*1024, 11624 0.0, 11625 remote_cpu_utilization, 11626 tcp_cc_result->num_cpus); 11627 } 11628 else { 11629 remote_cpu_utilization = (float) -1.0; 11630 remote_service_demand = (float) -1.0; 11631 } 11632 11633 /* We are now ready to print all the information. If the user */ 11634 /* has specified zero-level verbosity, we will just print the */ 11635 /* local service demand, or the remote service demand. If the */ 11636 /* user has requested verbosity level 1, he will get the basic */ 11637 /* "streamperf" numbers. If the user has specified a verbosity */ 11638 /* of greater than 1, we will display a veritable plethora of */ 11639 /* background information from outside of this block as it it */ 11640 /* not cpu_measurement specific... */ 11641 11642 switch (verbosity) { 11643 case 0: 11644 if (local_cpu_usage) { 11645 fprintf(where, 11646 cpu_fmt_0, 11647 local_service_demand); 11648 } 11649 else { 11650 fprintf(where, 11651 cpu_fmt_0, 11652 remote_service_demand); 11653 } 11654 break; 11655 case 1: 11656 case 2: 11657 11658 if (print_headers) { 11659 fprintf(where, 11660 cpu_title, 11661 local_cpu_method, 11662 remote_cpu_method); 11663 } 11664 11665 fprintf(where, 11666 cpu_fmt_1_line_1, /* the format string */ 11667 lss_size, /* local sendbuf size */ 11668 lsr_size, 11669 req_size, /* how large were the requests */ 11670 rsp_size, /* guess */ 11671 elapsed_time, /* how long was the test */ 11672 nummessages/elapsed_time, 11673 local_cpu_utilization, /* local cpu */ 11674 remote_cpu_utilization, /* remote cpu */ 11675 local_service_demand, /* local service demand */ 11676 remote_service_demand); /* remote service demand */ 11677 fprintf(where, 11678 cpu_fmt_1_line_2, 11679 rss_size, 11680 rsr_size); 11681 break; 11682 } 11683 } 11684 else { 11685 /* The tester did not wish to measure service demand. */ 11686 switch (verbosity) { 11687 case 0: 11688 fprintf(where, 11689 tput_fmt_0, 11690 nummessages/elapsed_time); 11691 break; 11692 case 1: 11693 case 2: 11694 if (print_headers) { 11695 fprintf(where,tput_title,format_units()); 11696 } 11697 11698 fprintf(where, 11699 tput_fmt_1_line_1, /* the format string */ 11700 lss_size, 11701 lsr_size, 11702 req_size, /* how large were the requests */ 11703 rsp_size, /* how large were the responses */ 11704 elapsed_time, /* how long did it take */ 11705 nummessages/elapsed_time); 11706 fprintf(where, 11707 tput_fmt_1_line_2, 11708 rss_size, /* remote recvbuf size */ 11709 rsr_size); 11710 11711 break; 11712 } 11713 } 11714 11715 /* it would be a good thing to include information about some of the */ 11716 /* other parameters that may have been set for this test, but at the */ 11717 /* moment, I do not wish to figure-out all the formatting, so I will */ 11718 /* just put this comment here to help remind me that it is something */ 11719 /* that should be done at a later time. */ 11720 11721 if (verbosity > 1) { 11722 /* The user wanted to know it all, so we will give it to him. */ 11723 /* This information will include as much as we can find about */ 11724 /* TCP statistics, the alignments of the sends and receives */ 11725 /* and all that sort of rot... */ 11726 11727 fprintf(where, 11728 ksink_fmt, 11729 local_send_align, 11730 remote_recv_offset, 11731 local_send_offset, 11732 remote_recv_offset); 11733 11734 #ifdef WANT_HISTOGRAM 11735 fprintf(where,"\nHistogram of request/response times\n"); 11736 fflush(where); 11737 HIST_report(time_hist); 11738 #endif /* WANT_HISTOGRAM */ 11739 11740 } 11741 11742 } 11743 11744 11745 void 11747 recv_tcp_cc() 11748 { 11749 11750 char *message; 11751 11752 struct addrinfo *local_res; 11753 char local_name[BUFSIZ]; 11754 char port_buffer[PORTBUFSIZE]; 11755 11756 struct sockaddr_storage myaddr_in, peeraddr_in; 11757 SOCKET s_listen,s_data; 11758 netperf_socklen_t addrlen; 11759 char *recv_message_ptr; 11760 char *send_message_ptr; 11761 int trans_received; 11762 int trans_remaining; 11763 int timed_out = 0; 11764 float elapsed_time; 11765 11766 struct tcp_cc_request_struct *tcp_cc_request; 11767 struct tcp_cc_response_struct *tcp_cc_response; 11768 struct tcp_cc_results_struct *tcp_cc_results; 11769 11770 tcp_cc_request = 11771 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data; 11772 tcp_cc_response = 11773 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data; 11774 tcp_cc_results = 11775 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data; 11776 11777 if (debug) { 11778 fprintf(where,"netserver: recv_tcp_cc: entered...\n"); 11779 fflush(where); 11780 } 11781 11782 /* We want to set-up the listen socket with all the desired */ 11783 /* parameters and then let the initiator know that all is ready. If */ 11784 /* socket size defaults are to be used, then the initiator will have */ 11785 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 11786 /* send-back what they are. If that information cannot be determined, */ 11787 /* then we send-back -1's for the sizes. If things go wrong for any */ 11788 /* reason, we will drop back ten yards and punt. */ 11789 11790 /* If anything goes wrong, we want the remote to know about it. It */ 11791 /* would be best if the error that the remote reports to the user is */ 11792 /* the actual error we encountered, rather than some bogus unexpected */ 11793 /* response type message. */ 11794 11795 if (debug) { 11796 fprintf(where,"recv_tcp_cc: setting the response type...\n"); 11797 fflush(where); 11798 } 11799 11800 netperf_response.content.response_type = TCP_CC_RESPONSE; 11801 11802 if (debug) { 11803 fprintf(where,"recv_tcp_cc: the response type is set...\n"); 11804 fflush(where); 11805 } 11806 11807 /* set-up the data buffer with the requested alignment and offset */ 11808 message = (char *)malloc(DATABUFFERLEN); 11809 if (message == NULL) { 11810 printf("malloc(%d) failed!\n", DATABUFFERLEN); 11811 exit(1); 11812 } 11813 11814 /* We now alter the message_ptr variables to be at the desired */ 11815 /* alignments with the desired offsets. */ 11816 11817 if (debug) { 11818 fprintf(where, 11819 "recv_tcp_cc: requested recv alignment of %d offset %d\n", 11820 tcp_cc_request->recv_alignment, 11821 tcp_cc_request->recv_offset); 11822 fprintf(where, 11823 "recv_tcp_cc: requested send alignment of %d offset %d\n", 11824 tcp_cc_request->send_alignment, 11825 tcp_cc_request->send_offset); 11826 fflush(where); 11827 } 11828 11829 recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset); 11830 11831 send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset); 11832 11833 if (debug) { 11834 fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n"); 11835 fflush(where); 11836 } 11837 11838 /* Grab a socket to listen on, and then listen on it. */ 11839 11840 if (debug) { 11841 fprintf(where,"recv_tcp_cc: grabbing a socket...\n"); 11842 fflush(where); 11843 } 11844 11845 /* create_data_socket expects to find some things in the global */ 11846 /* variables, so set the globals based on the values in the request. */ 11847 /* once the socket has been created, we will set the response values */ 11848 /* based on the updated value of those globals. raj 7/94 */ 11849 lss_size_req = tcp_cc_request->send_buf_size; 11850 lsr_size_req = tcp_cc_request->recv_buf_size; 11851 loc_nodelay = tcp_cc_request->no_delay; 11852 loc_rcvavoid = tcp_cc_request->so_rcvavoid; 11853 loc_sndavoid = tcp_cc_request->so_sndavoid; 11854 11855 set_hostname_and_port(local_name, 11856 port_buffer, 11857 nf_to_af(tcp_cc_request->ipfamily), 11858 tcp_cc_request->port); 11859 11860 local_res = complete_addrinfo(local_name, 11861 local_name, 11862 port_buffer, 11863 nf_to_af(tcp_cc_request->ipfamily), 11864 SOCK_STREAM, 11865 IPPROTO_TCP, 11866 0); 11867 11868 s_listen = create_data_socket(local_res); 11869 11870 if (s_listen == INVALID_SOCKET) { 11871 netperf_response.content.serv_errno = errno; 11872 send_response(); 11873 if (debug) { 11874 fprintf(where,"could not create data socket\n"); 11875 fflush(where); 11876 } 11877 exit(1); 11878 } 11879 11880 #ifdef WIN32 11881 /* The test timer can fire during operations on the listening socket, 11882 so to make the start_timer below work we have to move 11883 it to close s_listen while we are blocked on accept. */ 11884 win_kludge_socket2 = s_listen; 11885 #endif 11886 11887 11888 /* Now, let's set-up the socket to listen for connections */ 11889 if (listen(s_listen, 5) == SOCKET_ERROR) { 11890 netperf_response.content.serv_errno = errno; 11891 close(s_listen); 11892 send_response(); 11893 if (debug) { 11894 fprintf(where,"could not listen\n"); 11895 fflush(where); 11896 } 11897 exit(1); 11898 } 11899 11900 /* now get the port number assigned by the system */ 11901 addrlen = sizeof(myaddr_in); 11902 if (getsockname(s_listen, 11903 (struct sockaddr *)&myaddr_in, 11904 &addrlen) == SOCKET_ERROR){ 11905 netperf_response.content.serv_errno = errno; 11906 close(s_listen); 11907 send_response(); 11908 if (debug) { 11909 fprintf(where,"could not geetsockname\n"); 11910 fflush(where); 11911 } 11912 exit(1); 11913 } 11914 11915 /* Now myaddr_in contains the port and the internet address this is */ 11916 /* returned to the sender also implicitly telling the sender that the */ 11917 /* socket buffer sizing has been done. */ 11918 11919 tcp_cc_response->data_port_number = 11920 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port); 11921 if (debug) { 11922 fprintf(where,"telling the remote to call me at %d\n", 11923 tcp_cc_response->data_port_number); 11924 fflush(where); 11925 } 11926 netperf_response.content.serv_errno = 0; 11927 11928 /* But wait, there's more. If the initiator wanted cpu measurements, */ 11929 /* then we must call the calibrate routine, which will return the max */ 11930 /* rate back to the initiator. If the CPU was not to be measured, or */ 11931 /* something went wrong with the calibration, we will return a 0.0 to */ 11932 /* the initiator. */ 11933 11934 tcp_cc_response->cpu_rate = (float)0.0; /* assume no cpu */ 11935 if (tcp_cc_request->measure_cpu) { 11936 tcp_cc_response->measure_cpu = 1; 11937 tcp_cc_response->cpu_rate = 11938 calibrate_local_cpu(tcp_cc_request->cpu_rate); 11939 } 11940 11941 11942 11943 /* before we send the response back to the initiator, pull some of */ 11944 /* the socket parms from the globals */ 11945 tcp_cc_response->send_buf_size = lss_size; 11946 tcp_cc_response->recv_buf_size = lsr_size; 11947 tcp_cc_response->no_delay = loc_nodelay; 11948 tcp_cc_response->so_rcvavoid = loc_rcvavoid; 11949 tcp_cc_response->so_sndavoid = loc_sndavoid; 11950 11951 send_response(); 11952 11953 addrlen = sizeof(peeraddr_in); 11954 11955 /* Now it's time to start receiving data on the connection. We will */ 11956 /* first grab the apropriate counters and then start grabbing. */ 11957 11958 cpu_start(tcp_cc_request->measure_cpu); 11959 11960 /* The loop will exit when the sender does a shutdown, which will */ 11961 /* return a length of zero */ 11962 11963 if (tcp_cc_request->test_length > 0) { 11964 times_up = 0; 11965 trans_remaining = 0; 11966 start_timer(tcp_cc_request->test_length + PAD_TIME); 11967 } 11968 else { 11969 times_up = 1; 11970 trans_remaining = tcp_cc_request->test_length * -1; 11971 } 11972 11973 trans_received = 0; 11974 11975 while ((!times_up) || (trans_remaining > 0)) { 11976 #ifdef WIN32 11977 /* The test timer will probably fire during this accept, 11978 so to make the start_timer above work we have to move 11979 it to close s_listen while we are blocked on accept. */ 11980 win_kludge_socket = s_listen; 11981 #endif 11982 /* accept a connection from the remote */ 11983 if ((s_data=accept(s_listen, 11984 (struct sockaddr *)&peeraddr_in, 11985 &addrlen)) == INVALID_SOCKET) { 11986 if (errno == EINTR) { 11987 /* the timer popped */ 11988 timed_out = 1; 11989 break; 11990 } 11991 fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno); 11992 fflush(where); 11993 close(s_listen); 11994 11995 exit(1); 11996 } 11997 11998 #ifdef KLUDGE_SOCKET_OPTIONS 11999 /* this is for those systems which *INCORRECTLY* fail to pass */ 12000 /* attributes across an accept() call. Including this goes against */ 12001 /* my better judgement :( raj 11/95 */ 12002 12003 kludge_socket_options(s_data); 12004 12005 #endif /* KLUDGE_SOCKET_OPTIONS */ 12006 12007 #ifdef WIN32 12008 /* this is used so the timer thread can close the socket out from */ 12009 /* under us, which to date is the easiest/cleanest/least */ 12010 /* Windows-specific way I can find to force the winsock calls to */ 12011 /* return WSAEINTR with the test is over. anything that will run on */ 12012 /* 95 and NT and is closer to what netperf expects from Unix signals */ 12013 /* and such would be appreciated raj 1/96 */ 12014 win_kludge_socket = s_data; 12015 #endif /* WIN32 */ 12016 12017 if (debug) { 12018 fprintf(where,"recv_tcp_cc: accepted data connection.\n"); 12019 fflush(where); 12020 } 12021 12022 12023 /* close the connection. the server will likely do a graceful */ 12024 /* close of the connection, insuring that all data has arrived at */ 12025 /* the client. for this it will call shutdown(), and then recv() and */ 12026 /* then close(). I'm reasonably confident that this is the */ 12027 /* appropriate sequence of calls - I would like to hear of */ 12028 /* examples in web servers to the contrary. raj 10/95*/ 12029 close(s_data); 12030 12031 trans_received++; 12032 if (trans_remaining) { 12033 trans_remaining--; 12034 } 12035 12036 if (debug) { 12037 fprintf(where, 12038 "recv_tcp_cc: Transaction %d complete\n", 12039 trans_received); 12040 fflush(where); 12041 } 12042 12043 } 12044 12045 12046 /* The loop now exits due to timeout or transaction count being */ 12047 /* reached */ 12048 12049 cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time); 12050 12051 if (timed_out) { 12052 /* we ended the test by time, which was at least 2 seconds */ 12053 /* longer than we wanted to run. so, we want to subtract */ 12054 /* PAD_TIME from the elapsed_time. */ 12055 elapsed_time -= PAD_TIME; 12056 } 12057 /* send the results to the sender */ 12058 12059 if (debug) { 12060 fprintf(where, 12061 "recv_tcp_cc: got %d transactions\n", 12062 trans_received); 12063 fflush(where); 12064 } 12065 12066 tcp_cc_results->bytes_received = (trans_received * 12067 (tcp_cc_request->request_size + 12068 tcp_cc_request->response_size)); 12069 tcp_cc_results->trans_received = trans_received; 12070 tcp_cc_results->elapsed_time = elapsed_time; 12071 if (tcp_cc_request->measure_cpu) { 12072 tcp_cc_results->cpu_util = calc_cpu_util(elapsed_time); 12073 } 12074 12075 if (debug) { 12076 fprintf(where, 12077 "recv_tcp_cc: test complete, sending results.\n"); 12078 fflush(where); 12079 } 12080 12081 send_response(); 12082 12083 } 12084 12085 void 12087 print_sockets_usage() 12088 { 12089 12090 fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout); 12091 exit(1); 12092 12093 } 12094 12095 void 12096 scan_sockets_args(int argc, char *argv[]) 12097 12098 { 12099 12100 #define SOCKETS_ARGS "b:CDnNhH:L:m:M:p:P:r:s:S:T:Vw:W:z46" 12101 12102 extern char *optarg; /* pointer to option string */ 12103 12104 int c; 12105 12106 char 12107 arg1[BUFSIZ], /* argument holders */ 12108 arg2[BUFSIZ]; 12109 12110 if (debug) { 12111 int i; 12112 printf("%s called with the following argument vector\n", 12113 __func__); 12114 for (i = 0; i< argc; i++) { 12115 printf("%s ",argv[i]); 12116 } 12117 printf("\n"); 12118 } 12119 12120 strncpy(local_data_port,"0",sizeof(local_data_port)); 12121 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 12122 12123 /* Go through all the command line arguments and break them */ 12124 /* out. For those options that take two parms, specifying only */ 12125 /* the first will set both to that value. Specifying only the */ 12126 /* second will leave the first untouched. To change only the */ 12127 /* first, use the form "first," (see the routine break_args.. */ 12128 12129 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) { 12130 switch (c) { 12131 case '?': 12132 case '4': 12133 remote_data_family = AF_INET; 12134 local_data_family = AF_INET; 12135 break; 12136 case '6': 12137 #if defined(AF_INET6) 12138 remote_data_family = AF_INET6; 12139 local_data_family = AF_INET6; 12140 #else 12141 fprintf(stderr, 12142 "This netperf was not compiled on an IPv6 capable host!\n"); 12143 fflush(stderr); 12144 exit(-1); 12145 #endif 12146 break; 12147 case 'h': 12148 print_sockets_usage(); 12149 exit(1); 12150 case 'b': 12151 #ifdef WANT_FIRST_BURST 12152 first_burst_size = atoi(optarg); 12153 #else /* WANT_FIRST_BURST */ 12154 printf("Initial request burst functionality not compiled-in!\n"); 12155 #endif /* WANT_FIRST_BURST */ 12156 break; 12157 case 'C': 12158 #ifdef TCP_CORK 12159 /* set TCP_CORK */ 12160 loc_tcpcork = 1; 12161 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */ 12162 #else 12163 printf("WARNING: TCP_CORK not available on this platform!\n"); 12164 #endif /* TCP_CORK */ 12165 break; 12166 case 'D': 12167 /* set the TCP nodelay flag */ 12168 loc_nodelay = 1; 12169 rem_nodelay = 1; 12170 break; 12171 case 'H': 12172 break_args_explicit(optarg,arg1,arg2); 12173 if (arg1[0]) { 12174 /* make sure we leave room for the NULL termination boys and 12175 girls. raj 2005-02-82 */ 12176 remote_data_address = malloc(strlen(arg1)+1); 12177 strncpy(remote_data_address,arg1,strlen(arg1)); 12178 } 12179 if (arg2[0]) 12180 remote_data_family = parse_address_family(arg2); 12181 break; 12182 case 'L': 12183 break_args_explicit(optarg,arg1,arg2); 12184 if (arg1[0]) { 12185 /* make sure we leave room for the NULL termination boys and 12186 girls. raj 2005-02-82 */ 12187 local_data_address = malloc(strlen(arg1)+1); 12188 strncpy(local_data_address,arg1,strlen(arg1)); 12189 } 12190 if (arg2[0]) 12191 local_data_family = parse_address_family(arg2); 12192 break; 12193 case 's': 12194 /* set local socket sizes */ 12195 break_args(optarg,arg1,arg2); 12196 if (arg1[0]) 12197 lss_size_req = convert(arg1); 12198 if (arg2[0]) 12199 lsr_size_req = convert(arg2); 12200 break; 12201 case 'S': 12202 /* set remote socket sizes */ 12203 break_args(optarg,arg1,arg2); 12204 if (arg1[0]) 12205 rss_size_req = convert(arg1); 12206 if (arg2[0]) 12207 rsr_size_req = convert(arg2); 12208 break; 12209 case 'r': 12210 /* set the request/response sizes */ 12211 break_args(optarg,arg1,arg2); 12212 if (arg1[0]) 12213 req_size = convert(arg1); 12214 if (arg2[0]) 12215 rsp_size = convert(arg2); 12216 break; 12217 case 'm': 12218 /* set the send size */ 12219 send_size = convert(optarg); 12220 break; 12221 case 'M': 12222 /* set the recv size */ 12223 recv_size = convert(optarg); 12224 break; 12225 case 'n': 12226 /* set the local socket type*/ 12227 local_connected = 1; 12228 break; 12229 case 'N': 12230 /* set the remote socket type*/ 12231 remote_connected = 1; 12232 break; 12233 case 'p': 12234 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */ 12235 /* tests. */ 12236 break_args(optarg,arg1,arg2); 12237 if (arg1[0]) 12238 client_port_min = atoi(arg1); 12239 if (arg2[0]) 12240 client_port_max = atoi(arg2); 12241 break; 12242 case 'P': 12243 /* set the local and remote data port numbers for the tests to 12244 allow them to run through those blankety blank end-to-end 12245 breaking firewalls. raj 2004-06-15 */ 12246 break_args(optarg,arg1,arg2); 12247 if (arg1[0]) 12248 strncpy(local_data_port,arg1,sizeof(local_data_port)); 12249 if (arg2[0]) 12250 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 12251 break; 12252 case 't': 12253 /* set the test name */ 12254 strcpy(test_name,optarg); 12255 break; 12256 case 'W': 12257 /* set the "width" of the user space data */ 12258 /* buffer. This will be the number of */ 12259 /* send_size buffers malloc'd in the */ 12260 /* *_STREAM test. It may be enhanced to set */ 12261 /* both send and receive "widths" but for now */ 12262 /* it is just the sending *_STREAM. */ 12263 send_width = convert(optarg); 12264 break; 12265 case 'V' : 12266 /* we want to do copy avoidance and will set */ 12267 /* it for everything, everywhere, if we really */ 12268 /* can. of course, we don't know anything */ 12269 /* about the remote... */ 12270 #ifdef SO_SND_COPYAVOID 12271 loc_sndavoid = 1; 12272 #else 12273 loc_sndavoid = 0; 12274 printf("Local send copy avoidance not available.\n"); 12275 #endif 12276 #ifdef SO_RCV_COPYAVOID 12277 loc_rcvavoid = 1; 12278 #else 12279 loc_rcvavoid = 0; 12280 printf("Local recv copy avoidance not available.\n"); 12281 #endif 12282 rem_sndavoid = 1; 12283 rem_rcvavoid = 1; 12284 break; 12285 }; 12286 } 12287 12288 #if defined(WANT_FIRST_BURST) 12289 #if defined(WANT_HISTOGRAM) 12290 /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user 12291 indeed wants a non-zero first burst size, and we would emit a 12292 histogram, then we should emit a warning that the two are not 12293 compatible. raj 2006-01-31 */ 12294 if ((first_burst_size > 0) && (verbosity >= 2)) { 12295 fprintf(stderr, 12296 "WARNING! Histograms and first bursts are incompatible!\n"); 12297 fflush(stderr); 12298 } 12299 #endif 12300 #endif 12301 12302 /* we do not want to make remote_data_address non-NULL because if 12303 the user has not specified a remote adata address, we want to 12304 take it from the hostname in the -H global option. raj 12305 2005-02-08 */ 12306 12307 /* so, if there is to be no control connection, we want to have some 12308 different settings for a few things */ 12309 12310 if (no_control) { 12311 12312 if (strcmp(remote_data_port,"0") == 0) { 12313 /* we need to select either the discard port, echo port or 12314 chargen port dedepending on the test name. raj 2007-02-08 */ 12315 if (strstr(test_name,"STREAM") || 12316 strstr(test_name,"SENDFILE")) { 12317 strncpy(remote_data_port,"discard",sizeof(remote_data_port)); 12318 } 12319 else if (strstr(test_name,"RR")) { 12320 strncpy(remote_data_port,"echo",sizeof(remote_data_port)); 12321 } 12322 else if (strstr(test_name,"MAERTS")) { 12323 strncpy(remote_data_port,"chargen",sizeof(remote_data_port)); 12324 } 12325 else { 12326 printf("No default port known for the %s test, please set one yourself\n",test_name); 12327 exit(-1); 12328 } 12329 } 12330 remote_data_port[sizeof(remote_data_port) - 1] = '\0'; 12331 12332 /* I go back and forth on whether these should become -1 or if 12333 they should become 0 for a no_control test. what do you think? 12334 raj 2006-02-08 */ 12335 12336 rem_rcvavoid = -1; 12337 rem_sndavoid = -1; 12338 rss_size_req = -1; 12339 rsr_size_req = -1; 12340 rem_nodelay = -1; 12341 12342 if (strstr(test_name,"STREAM") || 12343 strstr(test_name,"SENDFILE")) { 12344 recv_size = -1; 12345 } 12346 else if (strstr(test_name,"RR")) { 12347 /* I am however _certain_ that for a no control RR test the 12348 response size must equal the request size since 99 times out 12349 of ten we will be speaking to the echo service somewhere */ 12350 rsp_size = req_size; 12351 } 12352 else if (strstr(test_name,"MAERTS")) { 12353 send_size = -1; 12354 } 12355 else { 12356 printf("No default port known for the %s test, please set one yourself\n",test_name); 12357 exit(-1); 12358 } 12359 } 12360 } 12361