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 */