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