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