1#ifndef lint 2char nettest_sdp[]="\ 3@(#)nettest_sdp.c (c) Copyright 2007-2012 Hewlett-Packard Co. Version 2.6.0"; 4#else 5#define DIRTY 6#define WANT_HISTOGRAM 7#define WANT_INTERVALS 8#endif /* lint */ 9 10/****************************************************************/ 11/* */ 12/* nettest_sdp.c */ 13/* */ 14/* */ 15/* scan_sdp_args() get the sdp command line args */ 16/* */ 17/* the actual test routines... */ 18/* */ 19/* send_sdp_stream() perform a sdp stream test */ 20/* recv_sdp_stream() */ 21/* send_sdp_rr() perform a sdp request/response */ 22/* recv_sdp_rr() */ 23/* */ 24/* relies on create_data_socket in nettest_bsd.c */ 25/****************************************************************/ 26 27#if HAVE_CONFIG_H 28# include <config.h> 29#endif 30 31#if defined(WANT_SDP) 32 33#include <sys/types.h> 34#include <fcntl.h> 35#include <errno.h> 36#include <signal.h> 37#include <stdio.h> 38#include <string.h> 39#include <time.h> 40#ifdef NOSTDLIBH 41#include <malloc.h> 42#else /* NOSTDLIBH */ 43#include <stdlib.h> 44#endif /* NOSTDLIBH */ 45 46#if !defined(__VMS) 47#include <sys/ipc.h> 48#endif /* !defined(__VMS) */ 49#include <unistd.h> 50#include <sys/types.h> 51#include <sys/socket.h> 52#include <netinet/in.h> 53#include <netinet/tcp.h> 54#include <arpa/inet.h> 55#include <netdb.h> 56 57/* would seem that not all sdp.h files define a MSG_EOF, but that 58 MSG_EOF can be the same as MSG_FIN so lets work with that 59 assumption. initial find by Jon Pedersen. raj 2006-02-01 */ 60#ifndef MSG_EOF 61#ifdef MSG_FIN 62#define MSG_EOF MSG_FIN 63#else 64#error Must have either MSG_EOF or MSG_FIN defined 65#endif 66#endif 67 68#include "netlib.h" 69#include "netsh.h" 70/* get some of the functions from nettest_bsd.c */ 71#include "nettest_bsd.h" 72#include "nettest_sdp.h" 73 74#ifdef WANT_HISTOGRAM 75#ifdef __sgi 76#include <sys/time.h> 77#endif /* __sgi */ 78#include "hist.h" 79#endif /* WANT_HISTOGRAM */ 80 81#ifdef WANT_FIRST_BURST 82extern int first_burst_size; 83#endif /* WANT_FIRST_BURST */ 84 85 86 87/* these variables are specific to SDP tests. declare */ 88/* them static to make them global only to this file. */ 89 90static int 91 msg_count = 0, /* number of messages to transmit on association */ 92 non_block = 0, /* default to blocking sockets */ 93 num_associations = 1; /* number of associations on the endpoint */ 94 95static int confidence_iteration; 96static char local_cpu_method; 97static char remote_cpu_method; 98 99#ifdef WANT_HISTOGRAM 100static struct timeval time_one; 101static struct timeval time_two; 102static HIST time_hist; 103#endif /* WANT_HISTOGRAM */ 104 105 106char sdp_usage[] = "\n\ 107Usage: netperf [global options] -- [test options] \n\ 108\n\ 109SDP Sockets Test Options:\n\ 110 -b number Send number requests at the start of _RR tests\n\ 111 -D [L][,R] Set SDP_NODELAY locally and/or remotely\n\ 112 -h Display this text\n\ 113 -H name,fam Use name (or IP) and family as target of data connection\n\ 114 -L name,fam Use name (or IP) and family as source of data connextion\n\ 115 -m bytes Set the size of each sent message\n\ 116 -M bytes Set the size of each received messages\n\ 117 -P local[,remote] Set the local/remote port for the data socket\n\ 118 -r req,[rsp] Set request/response sizes (_RR tests)\n\ 119 -s send[,recv] Set local socket send/recv buffer sizes\n\ 120 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 121 -V Enable copy avoidance if supported\n\ 122 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 123 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 124\n\ 125For those options taking two parms, at least one must be specified;\n\ 126specifying one value without a comma will set both parms to that\n\ 127value, specifying a value with a leading comma will set just the second\n\ 128parm, a value with a trailing comma will set just the first. To set\n\ 129each parm to unique values, specify both and separate them with a\n\ 130comma.\n"; 131 132 133 /* This routine is intended to retrieve interesting aspects of sdp */ 134 /* for the data connection. at first, it attempts to retrieve the */ 135 /* maximum segment size. later, it might be modified to retrieve */ 136 /* other information, but it must be information that can be */ 137 /* retrieved quickly as it is called during the timing of the test. */ 138 /* for that reason, a second routine may be created that can be */ 139 /* called outside of the timing loop */ 140static 141void 142get_sdp_info(int socket, int * mss) 143{ 144 145#ifdef TCP_MAXSEG 146 netperf_socklen_t sock_opt_len; 147 148 sock_opt_len = sizeof(netperf_socklen_t); 149 if (getsockopt(socket, 150 getprotobyname("tcp")->p_proto, 151 TCP_MAXSEG, 152 (char *)mss, 153 &sock_opt_len) == SOCKET_ERROR) { 154 fprintf(where, 155 "netperf: get_sdp_info: getsockopt TCP_MAXSEG: errno %d\n", 156 errno); 157 fflush(where); 158 *mss = -1; 159 } 160#else 161 *mss = -1; 162#endif /* TCP_MAXSEG */ 163 164} 165 166void 167send_sdp_stream(char remote_host[]) 168{ 169 170 char *tput_title = "\ 171Recv Send Send \n\ 172Socket Socket Message Elapsed \n\ 173Size Size Size Time Throughput \n\ 174bytes bytes bytes secs. %s/sec \n\n"; 175 176 char *tput_fmt_0 = 177 "%7.2f %s\n"; 178 179 char *tput_fmt_1 = 180 "%6d %6d %6d %-6.2f %7.2f %s\n"; 181 182 char *cpu_title = "\ 183Recv Send Send Utilization Service Demand\n\ 184Socket Socket Message Elapsed Send Recv Send Recv\n\ 185Size Size Size Time Throughput local remote local remote\n\ 186bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 187 188 char *cpu_fmt_0 = 189 "%6.3f %c %s\n"; 190 191 char *cpu_fmt_1 = 192 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 193 194 char *ksink_fmt = "\n\ 195Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 196Local Remote Local Remote Xfered Per Per\n\ 197Send Recv Send Recv Send (avg) Recv (avg)\n\ 198%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 199 200 char *ksink_fmt2 = "\n\ 201Maximum\n\ 202Segment\n\ 203Size (bytes)\n\ 204%6d\n"; 205 206 207 float elapsed_time; 208 209 /* what we want is to have a buffer space that is at least one */ 210 /* send-size greater than our send window. this will insure that we */ 211 /* are never trying to re-use a buffer that may still be in the hands */ 212 /* of the transport. This buffer will be malloc'd after we have found */ 213 /* the size of the local senc socket buffer. We will want to deal */ 214 /* with alignment and offset concerns as well. */ 215 216 struct ring_elt *send_ring; 217 218 int len; 219 unsigned int nummessages = 0; 220 SOCKET send_socket; 221 int bytes_remaining; 222 int sdp_mss = -1; /* possibly uninitialized on printf far below */ 223 224 /* with links like fddi, one can send > 32 bits worth of bytes */ 225 /* during a test... ;-) at some point, this should probably become a */ 226 /* 64bit integral type, but those are not entirely common yet */ 227 228 unsigned long long local_bytes_sent = 0; 229 double bytes_sent = 0.0; 230 231 float local_cpu_utilization; 232 float local_service_demand; 233 float remote_cpu_utilization; 234 float remote_service_demand; 235 236 double thruput; 237 238 struct addrinfo *remote_res; 239 struct addrinfo *local_res; 240 241 struct sdp_stream_request_struct *sdp_stream_request; 242 struct sdp_stream_response_struct *sdp_stream_response; 243 struct sdp_stream_results_struct *sdp_stream_result; 244 245 sdp_stream_request = 246 (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data; 247 sdp_stream_response = 248 (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data; 249 sdp_stream_result = 250 (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data; 251 252#ifdef WANT_HISTOGRAM 253 if (verbosity > 1) { 254 time_hist = HIST_new(); 255 } 256#endif /* WANT_HISTOGRAM */ 257 /* since we are now disconnected from the code that established the */ 258 /* control socket, and since we want to be able to use different */ 259 /* protocols and such, we are passed the name of the remote host and */ 260 /* must turn that into the test specific addressing information. */ 261 262 /* complete_addrinfos will either succede or exit the process */ 263 complete_addrinfos(&remote_res, 264 &local_res, 265 remote_host, 266 SOCK_STREAM, 267 IPPROTO_TCP, 268 0); 269 270 if ( print_headers ) { 271 print_top_test_header("SDP STREAM TEST",local_res,remote_res); 272 } 273 274 send_ring = NULL; 275 confidence_iteration = 1; 276 init_stat(); 277 278 /* we have a great-big while loop which controls the number of times */ 279 /* we run a particular test. this is for the calculation of a */ 280 /* confidence interval (I really should have stayed awake during */ 281 /* probstats :). If the user did not request confidence measurement */ 282 /* (no confidence is the default) then we will only go though the */ 283 /* loop once. the confidence stuff originates from the folks at IBM */ 284 285 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 286 (confidence_iteration <= iteration_min)) { 287 288 /* initialize a few counters. we have to remember that we might be */ 289 /* going through the loop more than once. */ 290 291 nummessages = 0; 292 bytes_sent = 0.0; 293 times_up = 0; 294 295 /*set up the data socket */ 296 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 297 local_res->ai_family = AF_INET_SDP; 298 local_res->ai_protocol = 0; 299 send_socket = create_data_socket(local_res); 300 301 if (send_socket == INVALID_SOCKET){ 302 perror("netperf: send_sdp_stream: sdp stream data socket"); 303 exit(1); 304 } 305 306 if (debug) { 307 fprintf(where,"send_sdp_stream: send_socket obtained...\n"); 308 } 309 310 /* at this point, we have either retrieved the socket buffer sizes, */ 311 /* or have tried to set them, so now, we may want to set the send */ 312 /* size based on that (because the user either did not use a -m */ 313 /* option, or used one with an argument of 0). If the socket buffer */ 314 /* size is not available, we will set the send size to 4KB - no */ 315 /* particular reason, just arbitrary... */ 316 if (send_size == 0) { 317 if (lss_size > 0) { 318 send_size = lss_size; 319 } 320 else { 321 send_size = 4096; 322 } 323 } 324 325 /* set-up the data buffer ring with the requested alignment and offset. */ 326 /* note also that we have allocated a quantity */ 327 /* of memory that is at least one send-size greater than our socket */ 328 /* buffer size. We want to be sure that there are at least two */ 329 /* buffers allocated - this can be a bit of a problem when the */ 330 /* send_size is bigger than the socket size, so we must check... the */ 331 /* user may have wanted to explicitly set the "width" of our send */ 332 /* buffers, we should respect that wish... */ 333 if (send_width == 0) { 334 send_width = (lss_size/send_size) + 1; 335 if (send_width == 1) send_width++; 336 } 337 338 if (send_ring == NULL) { 339 /* only allocate the send ring once. this is a networking test, */ 340 /* not a memory allocation test. this way, we do not need a */ 341 /* deallocate_buffer_ring() routine, and I don't feel like */ 342 /* writing one anyway :) raj 11/94 */ 343 send_ring = allocate_buffer_ring(send_width, 344 send_size, 345 local_send_align, 346 local_send_offset); 347 } 348 349 /* If the user has requested cpu utilization measurements, we must */ 350 /* calibrate the cpu(s). We will perform this task within the tests */ 351 /* themselves. If the user has specified the cpu rate, then */ 352 /* calibrate_local_cpu will return rather quickly as it will have */ 353 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 354 /* all the "normal" calibration stuff and return the rate back. */ 355 356 if (local_cpu_usage) { 357 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 358 } 359 360 if (!no_control) { 361 /* Tell the remote end to do a listen. The server alters the 362 socket paramters on the other side at this point, hence the 363 reason for all the values being passed in the setup 364 message. If the user did not specify any of the parameters, 365 they will be passed as 0, which will indicate to the remote 366 that no changes beyond the system's default should be 367 used. Alignment is the exception, it will default to 1, which 368 will be no alignment alterations. */ 369 370 netperf_request.content.request_type = DO_SDP_STREAM; 371 sdp_stream_request->send_buf_size = rss_size_req; 372 sdp_stream_request->recv_buf_size = rsr_size_req; 373 sdp_stream_request->receive_size = recv_size; 374 sdp_stream_request->no_delay = rem_nodelay; 375 sdp_stream_request->recv_alignment = remote_recv_align; 376 sdp_stream_request->recv_offset = remote_recv_offset; 377 sdp_stream_request->measure_cpu = remote_cpu_usage; 378 sdp_stream_request->cpu_rate = remote_cpu_rate; 379 if (test_time) { 380 sdp_stream_request->test_length = test_time; 381 } 382 else { 383 sdp_stream_request->test_length = test_bytes; 384 } 385 sdp_stream_request->so_rcvavoid = rem_rcvavoid; 386 sdp_stream_request->so_sndavoid = rem_sndavoid; 387#ifdef DIRTY 388 sdp_stream_request->dirty_count = rem_dirty_count; 389 sdp_stream_request->clean_count = rem_clean_count; 390#endif /* DIRTY */ 391 sdp_stream_request->port = atoi(remote_data_port); 392 sdp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 393 if (debug > 1) { 394 fprintf(where, 395 "netperf: send_sdp_stream: requesting SDP stream test\n"); 396 } 397 398 send_request(); 399 400 /* The response from the remote will contain all of the relevant 401 socket parameters for this test type. We will put them back 402 into the variables here so they can be displayed if desired. 403 The remote will have calibrated CPU if necessary, and will 404 have done all the needed set-up we will have calibrated the 405 cpu locally before sending the request, and will grab the 406 counter value right after the connect returns. The remote 407 will grab the counter right after the accept call. This saves 408 the hassle of extra messages being sent for the SDP 409 tests. */ 410 411 recv_response(); 412 413 if (!netperf_response.content.serv_errno) { 414 if (debug) 415 fprintf(where,"remote listen done.\n"); 416 rsr_size = sdp_stream_response->recv_buf_size; 417 rss_size = sdp_stream_response->send_buf_size; 418 rem_nodelay = sdp_stream_response->no_delay; 419 remote_cpu_usage= sdp_stream_response->measure_cpu; 420 remote_cpu_rate = sdp_stream_response->cpu_rate; 421 422 /* we have to make sure that the server port number is in 423 network order */ 424 set_port_number(remote_res, 425 (short)sdp_stream_response->data_port_number); 426 427 rem_rcvavoid = sdp_stream_response->so_rcvavoid; 428 rem_sndavoid = sdp_stream_response->so_sndavoid; 429 } 430 else { 431 Set_errno(netperf_response.content.serv_errno); 432 fprintf(where, 433 "netperf: remote error %d", 434 netperf_response.content.serv_errno); 435 perror(""); 436 fflush(where); 437 438 exit(1); 439 } 440 } 441 442#ifdef WANT_DEMO 443 DEMO_STREAM_SETUP(lss_size,rsr_size) 444#endif 445 446 /*Connect up to the remote port on the data socket */ 447 if (connect(send_socket, 448 remote_res->ai_addr, 449 remote_res->ai_addrlen) == INVALID_SOCKET){ 450 perror("netperf: send_sdp_stream: data socket connect failed"); 451 exit(1); 452 } 453 454 /* Data Socket set-up is finished. If there were problems, either */ 455 /* the connect would have failed, or the previous response would */ 456 /* have indicated a problem. I failed to see the value of the */ 457 /* extra message after the accept on the remote. If it failed, */ 458 /* we'll see it here. If it didn't, we might as well start pumping */ 459 /* data. */ 460 461 /* Set-up the test end conditions. For a stream test, they can be */ 462 /* either time or byte-count based. */ 463 464 if (test_time) { 465 /* The user wanted to end the test after a period of time. */ 466 times_up = 0; 467 bytes_remaining = 0; 468 /* in previous revisions, we had the same code repeated throught */ 469 /* all the test suites. this was unnecessary, and meant more */ 470 /* work for me when I wanted to switch to POSIX signals, so I */ 471 /* have abstracted this out into a routine in netlib.c. if you */ 472 /* are experiencing signal problems, you might want to look */ 473 /* there. raj 11/94 */ 474 start_timer(test_time); 475 } 476 else { 477 /* The tester wanted to send a number of bytes. */ 478 bytes_remaining = test_bytes; 479 times_up = 1; 480 } 481 482 /* The cpu_start routine will grab the current time and possibly */ 483 /* value of the idle counter for later use in measuring cpu */ 484 /* utilization and/or service demand and thruput. */ 485 486 cpu_start(local_cpu_usage); 487 488 /* we only start the interval timer if we are using the 489 timer-timed intervals rather than the sit and spin ones. raj 490 2006-02-06 */ 491#if defined(WANT_INTERVALS) 492 INTERVALS_INIT(); 493#endif /* WANT_INTERVALS */ 494 495 /* before we start, initialize a few variables */ 496 497#ifdef WANT_DEMO 498 if (demo_mode) { 499 HIST_timestamp(demo_one_ptr); 500 } 501#endif 502 503 504 /* We use an "OR" to control test execution. When the test is */ 505 /* controlled by time, the byte count check will always return false. */ 506 /* When the test is controlled by byte count, the time test will */ 507 /* always return false. When the test is finished, the whole */ 508 /* expression will go false and we will stop sending data. */ 509 510 while ((!times_up) || (bytes_remaining > 0)) { 511 512#ifdef DIRTY 513 access_buffer(send_ring->buffer_ptr, 514 send_size, 515 loc_dirty_count, 516 loc_clean_count); 517#endif /* DIRTY */ 518 519#ifdef WANT_HISTOGRAM 520 if (verbosity > 1) { 521 /* timestamp just before we go into send and then again just 522 after we come out raj 8/94 */ 523 /* but lets only do this if there is going to be a histogram 524 displayed */ 525 HIST_timestamp(&time_one); 526 } 527#endif /* WANT_HISTOGRAM */ 528 529 if((len=send(send_socket, 530 send_ring->buffer_ptr, 531 send_size, 532 0)) != send_size) { 533 if ((len >=0) || SOCKET_EINTR(len)) { 534 /* the test was interrupted, must be the end of test */ 535 break; 536 } 537 perror("netperf: data send error"); 538 printf("len was %d\n",len); 539 exit(1); 540 } 541 542 local_bytes_sent += send_size; 543 544#ifdef WANT_HISTOGRAM 545 if (verbosity > 1) { 546 /* timestamp the exit from the send call and update the histogram */ 547 HIST_timestamp(&time_two); 548 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 549 } 550#endif /* WANT_HISTOGRAM */ 551 552#ifdef WANT_DEMO 553 DEMO_STREAM_INTERVAL(send_size) 554#endif 555 556#if defined(WANT_INTERVALS) 557 INTERVALS_WAIT(); 558#endif /* WANT_INTERVALS */ 559 560 /* now we want to move our pointer to the next position in the */ 561 /* data buffer...we may also want to wrap back to the "beginning" */ 562 /* of the bufferspace, so we will mod the number of messages sent */ 563 /* by the send width, and use that to calculate the offset to add */ 564 /* to the base pointer. */ 565 nummessages++; 566 send_ring = send_ring->next; 567 if (bytes_remaining) { 568 bytes_remaining -= send_size; 569 } 570 } 571 572 /* The test is over. Flush the buffers to the remote end. We do a */ 573 /* graceful release to insure that all data has been taken by the */ 574 /* remote. */ 575 576 /* but first, if the verbosity is greater than 1, find-out what */ 577 /* the SDP maximum segment_size was (if possible) */ 578 if (verbosity > 1) { 579 sdp_mss = -1; 580 get_sdp_info(send_socket,&sdp_mss); 581 } 582 583 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) { 584 perror("netperf: cannot shutdown sdp stream socket"); 585 exit(1); 586 } 587 588 /* hang a recv() off the socket to block until the remote has */ 589 /* brought all the data up into the application. it will do a */ 590 /* shutdown to cause a FIN to be sent our way. We will assume that */ 591 /* any exit from the recv() call is good... raj 4/93 */ 592 593 recv(send_socket, send_ring->buffer_ptr, send_size, 0); 594 595 /* this call will always give us the elapsed time for the test, and */ 596 /* will also store-away the necessaries for cpu utilization */ 597 598 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 599 /* measured and how */ 600 /* long did we really */ 601 /* run? */ 602 603 /* we are finished with the socket, so close it to prevent hitting */ 604 /* the limit on maximum open files. */ 605 606 close(send_socket); 607 608 if (!no_control) { 609 /* Get the statistics from the remote end. The remote will have 610 calculated service demand and all those interesting 611 things. If it wasn't supposed to care, it will return obvious 612 values. */ 613 614 recv_response(); 615 if (!netperf_response.content.serv_errno) { 616 if (debug) 617 fprintf(where,"remote results obtained\n"); 618 } 619 else { 620 Set_errno(netperf_response.content.serv_errno); 621 fprintf(where, 622 "netperf: remote error %d", 623 netperf_response.content.serv_errno); 624 perror(""); 625 fflush(where); 626 627 exit(1); 628 } 629 630 /* We now calculate what our thruput was for the test. In the 631 future, we may want to include a calculation of the thruput 632 measured by the remote, but it should be the case that for a 633 SDP stream test, that the two numbers should be *very* 634 close... We calculate bytes_sent regardless of the way the 635 test length was controlled. If it was time, we needed to, 636 and if it was by bytes, the user may have specified a number 637 of bytes that wasn't a multiple of the send_size, so we 638 really didn't send what he asked for ;-) */ 639 640 bytes_sent = ntohd(sdp_stream_result->bytes_received); 641 } 642 else { 643 bytes_sent = (double)local_bytes_sent; 644 } 645 646 thruput = calc_thruput(bytes_sent); 647 648 if (local_cpu_usage || remote_cpu_usage) { 649 /* We must now do a little math for service demand and cpu */ 650 /* utilization for the system(s) */ 651 /* Of course, some of the information might be bogus because */ 652 /* there was no idle counter in the kernel(s). We need to make */ 653 /* a note of this for the user's benefit...*/ 654 if (local_cpu_usage) { 655 656 local_cpu_utilization = calc_cpu_util(0.0); 657 local_service_demand = calc_service_demand(bytes_sent, 658 0.0, 659 0.0, 660 0); 661 } 662 else { 663 local_cpu_utilization = (float) -1.0; 664 local_service_demand = (float) -1.0; 665 } 666 667 if (remote_cpu_usage) { 668 669 remote_cpu_utilization = sdp_stream_result->cpu_util; 670 remote_service_demand = calc_service_demand(bytes_sent, 671 0.0, 672 remote_cpu_utilization, 673 sdp_stream_result->num_cpus); 674 } 675 else { 676 remote_cpu_utilization = (float) -1.0; 677 remote_service_demand = (float) -1.0; 678 } 679 } 680 else { 681 /* we were not measuring cpu, for the confidence stuff, we */ 682 /* should make it -1.0 */ 683 local_cpu_utilization = (float) -1.0; 684 local_service_demand = (float) -1.0; 685 remote_cpu_utilization = (float) -1.0; 686 remote_service_demand = (float) -1.0; 687 } 688 689 /* at this point, we want to calculate the confidence information. */ 690 /* if debugging is on, calculate_confidence will print-out the */ 691 /* parameters we pass it */ 692 693 calculate_confidence(confidence_iteration, 694 elapsed_time, 695 thruput, 696 local_cpu_utilization, 697 remote_cpu_utilization, 698 local_service_demand, 699 remote_service_demand); 700 701 702 confidence_iteration++; 703 } 704 705 /* at this point, we have finished making all the runs that we */ 706 /* will be making. so, we should extract what the calcuated values */ 707 /* are for all the confidence stuff. we could make the values */ 708 /* global, but that seemed a little messy, and it did not seem worth */ 709 /* all the mucking with header files. so, we create a routine much */ 710 /* like calcualte_confidence, which just returns the mean values. */ 711 /* raj 11/94 */ 712 713 retrieve_confident_values(&elapsed_time, 714 &thruput, 715 &local_cpu_utilization, 716 &remote_cpu_utilization, 717 &local_service_demand, 718 &remote_service_demand); 719 720 /* We are now ready to print all the information. If the user */ 721 /* has specified zero-level verbosity, we will just print the */ 722 /* local service demand, or the remote service demand. If the */ 723 /* user has requested verbosity level 1, he will get the basic */ 724 /* "streamperf" numbers. If the user has specified a verbosity */ 725 /* of greater than 1, we will display a veritable plethora of */ 726 /* background information from outside of this block as it it */ 727 /* not cpu_measurement specific... */ 728 729 if (confidence < 0) { 730 /* we did not hit confidence, but were we asked to look for it? */ 731 if (iteration_max > 1) { 732 display_confidence(); 733 } 734 } 735 736 if (local_cpu_usage || remote_cpu_usage) { 737 local_cpu_method = format_cpu_method(cpu_method); 738 remote_cpu_method = format_cpu_method(sdp_stream_result->cpu_method); 739 740 switch (verbosity) { 741 case 0: 742 if (local_cpu_usage) { 743 fprintf(where, 744 cpu_fmt_0, 745 local_service_demand, 746 local_cpu_method, 747 ((print_headers) || 748 (result_brand == NULL)) ? "" : result_brand); 749 } 750 else { 751 fprintf(where, 752 cpu_fmt_0, 753 remote_service_demand, 754 remote_cpu_method, 755 ((print_headers) || 756 (result_brand == NULL)) ? "" : result_brand); 757 } 758 break; 759 case 1: 760 case 2: 761 if (print_headers) { 762 fprintf(where, 763 cpu_title, 764 format_units(), 765 local_cpu_method, 766 remote_cpu_method); 767 } 768 769 fprintf(where, 770 cpu_fmt_1, /* the format string */ 771 rsr_size, /* remote recvbuf size */ 772 lss_size, /* local sendbuf size */ 773 send_size, /* how large were the sends */ 774 elapsed_time, /* how long was the test */ 775 thruput, /* what was the xfer rate */ 776 local_cpu_utilization, /* local cpu */ 777 remote_cpu_utilization, /* remote cpu */ 778 local_service_demand, /* local service demand */ 779 remote_service_demand, /* remote service demand */ 780 ((print_headers) || 781 (result_brand == NULL)) ? "" : result_brand); 782 break; 783 } 784 } 785 else { 786 /* The tester did not wish to measure service demand. */ 787 788 switch (verbosity) { 789 case 0: 790 fprintf(where, 791 tput_fmt_0, 792 thruput, 793 ((print_headers) || 794 (result_brand == NULL)) ? "" : result_brand); 795 break; 796 case 1: 797 case 2: 798 if (print_headers) { 799 fprintf(where,tput_title,format_units()); 800 } 801 fprintf(where, 802 tput_fmt_1, /* the format string */ 803 rsr_size, /* remote recvbuf size */ 804 lss_size, /* local sendbuf size */ 805 send_size, /* how large were the sends */ 806 elapsed_time, /* how long did it take */ 807 thruput, /* how fast did it go */ 808 ((print_headers) || 809 (result_brand == NULL)) ? "" : result_brand); 810 break; 811 } 812 } 813 814 /* it would be a good thing to include information about some of the */ 815 /* other parameters that may have been set for this test, but at the */ 816 /* moment, I do not wish to figure-out all the formatting, so I will */ 817 /* just put this comment here to help remind me that it is something */ 818 /* that should be done at a later time. */ 819 820 if (verbosity > 1) { 821 /* The user wanted to know it all, so we will give it to him. */ 822 /* This information will include as much as we can find about */ 823 /* SDP statistics, the alignments of the sends and receives */ 824 /* and all that sort of rot... */ 825 826 /* this stuff needs to be worked-out in the presence of confidence */ 827 /* intervals and multiple iterations of the test... raj 11/94 */ 828 829 fprintf(where, 830 ksink_fmt, 831 "Bytes", 832 "Bytes", 833 "Bytes", 834 local_send_align, 835 remote_recv_align, 836 local_send_offset, 837 remote_recv_offset, 838 bytes_sent, 839 bytes_sent / (double)nummessages, 840 nummessages, 841 bytes_sent / (double)sdp_stream_result->recv_calls, 842 sdp_stream_result->recv_calls); 843 fprintf(where, 844 ksink_fmt2, 845 sdp_mss); 846 fflush(where); 847#ifdef WANT_HISTOGRAM 848 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 849 fflush(where); 850 HIST_report(time_hist); 851#endif /* WANT_HISTOGRAM */ 852 } 853 854} 855 856 857 858/* This routine implements the netperf-side SDP unidirectional data 859 transfer test (a.k.a. stream) for the sockets interface where the 860 data flow is from the netserver to the netperf. It receives its 861 parameters via global variables from the shell and writes its 862 output to the standard output. */ 863 864 865void 866send_sdp_maerts(char remote_host[]) 867{ 868 869 char *tput_title = "\ 870Recv Send Send \n\ 871Socket Socket Message Elapsed \n\ 872Size Size Size Time Throughput \n\ 873bytes bytes bytes secs. %s/sec \n\n"; 874 875 char *tput_fmt_0 = 876 "%7.2f %s\n"; 877 878 char *tput_fmt_1 = 879 "%6d %6d %6d %-6.2f %7.2f \n %s"; 880 881 char *cpu_title = "\ 882Recv Send Send Utilization Service Demand\n\ 883Socket Socket Message Elapsed Send Recv Send Recv\n\ 884Size Size Size Time Throughput local remote local remote\n\ 885bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 886 887 char *cpu_fmt_0 = 888 "%6.3f %c %s\n"; 889 890 char *cpu_fmt_1 = 891 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 892 893 char *ksink_fmt = "\n\ 894Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\ 895Local Remote Local Remote Xfered Per Per\n\ 896Recv Send Recv Send Recv (avg) Send (avg)\n\ 897%5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 898 899 char *ksink_fmt2 = "\n\ 900Maximum\n\ 901Segment\n\ 902Size (bytes)\n\ 903%6d\n"; 904 905 906 float elapsed_time; 907 908 /* what we want is to have a buffer space that is at least one */ 909 /* recv-size greater than our recv window. this will insure that we */ 910 /* are never trying to re-use a buffer that may still be in the hands */ 911 /* of the transport. This buffer will be malloc'd after we have found */ 912 /* the size of the local senc socket buffer. We will want to deal */ 913 /* with alignment and offset concerns as well. */ 914 915 struct ring_elt *recv_ring; 916 917 int len; 918 unsigned int nummessages = 0; 919 SOCKET recv_socket; 920 int bytes_remaining; 921 int sdp_mss = -1; /* possibly uninitialized on printf far below */ 922 923 /* with links like fddi, one can recv > 32 bits worth of bytes */ 924 /* during a test... ;-) at some point, this should probably become a */ 925 /* 64bit integral type, but those are not entirely common yet */ 926 double bytes_sent = 0.0; 927 unsigned long long local_bytes_recvd = 0; 928 929 float local_cpu_utilization; 930 float local_service_demand; 931 float remote_cpu_utilization; 932 float remote_service_demand; 933 934 double thruput; 935 936 struct addrinfo *remote_res; 937 struct addrinfo *local_res; 938 939 struct sdp_maerts_request_struct *sdp_maerts_request; 940 struct sdp_maerts_response_struct *sdp_maerts_response; 941 struct sdp_maerts_results_struct *sdp_maerts_result; 942 943 sdp_maerts_request = 944 (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data; 945 sdp_maerts_response = 946 (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data; 947 sdp_maerts_result = 948 (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data; 949 950#ifdef WANT_HISTOGRAM 951 if (verbosity > 1) { 952 time_hist = HIST_new(); 953 } 954#endif /* WANT_HISTOGRAM */ 955 /* since we are now disconnected from the code that established the */ 956 /* control socket, and since we want to be able to use different */ 957 /* protocols and such, we are passed the name of the remote host and */ 958 /* must turn that into the test specific addressing information. */ 959 960 complete_addrinfos(&remote_res, 961 &local_res, 962 remote_host, 963 SOCK_STREAM, 964 IPPROTO_TCP, 965 0); 966 967 if ( print_headers ) { 968 print_top_test_header("SDP MAERTS TEST",local_res,remote_res); 969 } 970 971 recv_ring = NULL; 972 confidence_iteration = 1; 973 init_stat(); 974 975 /* we have a great-big while loop which controls the number of times */ 976 /* we run a particular test. this is for the calculation of a */ 977 /* confidence interval (I really should have stayed awake during */ 978 /* probstats :). If the user did not request confidence measurement */ 979 /* (no confidence is the default) then we will only go though the */ 980 /* loop once. the confidence stuff originates from the folks at IBM */ 981 982 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 983 (confidence_iteration <= iteration_min)) { 984 985 /* initialize a few counters. we have to remember that we might be */ 986 /* going through the loop more than once. */ 987 988 nummessages = 0; 989 bytes_sent = 0.0; 990 times_up = 0; 991 992 /*set up the data socket */ 993 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 994 local_res->ai_family = AF_INET_SDP; 995 local_res->ai_protocol = 0; 996 recv_socket = create_data_socket(local_res); 997 998 if (recv_socket == INVALID_SOCKET){ 999 perror("netperf: send_sdp_maerts: sdp stream data socket"); 1000 exit(1); 1001 } 1002 1003 if (debug) { 1004 fprintf(where,"send_sdp_maerts: recv_socket obtained...\n"); 1005 } 1006 1007 /* at this point, we have either retrieved the socket buffer sizes, */ 1008 /* or have tried to set them, so now, we may want to set the recv */ 1009 /* size based on that (because the user either did not use a -m */ 1010 /* option, or used one with an argument of 0). If the socket buffer */ 1011 /* size is not available, we will set the recv size to 4KB - no */ 1012 /* particular reason, just arbitrary... */ 1013 if (recv_size == 0) { 1014 if (lsr_size > 0) { 1015 recv_size = lsr_size; 1016 } 1017 else { 1018 recv_size = 4096; 1019 } 1020 } 1021 1022 /* set-up the data buffer ring with the requested alignment and offset. */ 1023 /* note also that we have allocated a quantity */ 1024 /* of memory that is at least one recv-size greater than our socket */ 1025 /* buffer size. We want to be sure that there are at least two */ 1026 /* buffers allocated - this can be a bit of a problem when the */ 1027 /* recv_size is bigger than the socket size, so we must check... the */ 1028 /* user may have wanted to explicitly set the "width" of our recv */ 1029 /* buffers, we should respect that wish... */ 1030 if (recv_width == 0) { 1031 recv_width = (lsr_size/recv_size) + 1; 1032 if (recv_width == 1) recv_width++; 1033 } 1034 1035 if (recv_ring == NULL) { 1036 /* only allocate the recv ring once. this is a networking test, */ 1037 /* not a memory allocation test. this way, we do not need a */ 1038 /* deallocate_buffer_ring() routine, and I don't feel like */ 1039 /* writing one anyway :) raj 11/94 */ 1040 recv_ring = allocate_buffer_ring(recv_width, 1041 recv_size, 1042 local_recv_align, 1043 local_recv_offset); 1044 } 1045 1046 /* If the user has requested cpu utilization measurements, we must */ 1047 /* calibrate the cpu(s). We will perform this task within the tests */ 1048 /* themselves. If the user has specified the cpu rate, then */ 1049 /* calibrate_local_cpu will return rather quickly as it will have */ 1050 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 1051 /* all the "normal" calibration stuff and return the rate back. */ 1052 1053 if (local_cpu_usage) { 1054 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 1055 } 1056 1057 if (!no_control) { 1058 /* Tell the remote end to do a listen. The server alters the 1059 socket paramters on the other side at this point, hence the 1060 reason for all the values being passed in the setup 1061 message. If the user did not specify any of the parameters, 1062 they will be passed as 0, which will indicate to the remote 1063 that no changes beyond the system's default should be 1064 used. Alignment is the exception, it will default to 1, which 1065 will be no alignment alterations. */ 1066 1067 netperf_request.content.request_type = DO_SDP_MAERTS; 1068 sdp_maerts_request->send_buf_size = rss_size_req; 1069 sdp_maerts_request->recv_buf_size = rsr_size_req; 1070 sdp_maerts_request->send_size = send_size; 1071 sdp_maerts_request->no_delay = rem_nodelay; 1072 sdp_maerts_request->send_alignment = remote_send_align; 1073 sdp_maerts_request->send_offset = remote_send_offset; 1074 sdp_maerts_request->measure_cpu = remote_cpu_usage; 1075 sdp_maerts_request->cpu_rate = remote_cpu_rate; 1076 if (test_time) { 1077 sdp_maerts_request->test_length = test_time; 1078 } 1079 else { 1080 sdp_maerts_request->test_length = test_bytes; 1081 } 1082 sdp_maerts_request->so_rcvavoid = rem_rcvavoid; 1083 sdp_maerts_request->so_sndavoid = rem_sndavoid; 1084#ifdef DIRTY 1085 sdp_maerts_request->dirty_count = rem_dirty_count; 1086 sdp_maerts_request->clean_count = rem_clean_count; 1087#endif /* DIRTY */ 1088 sdp_maerts_request->port = atoi(remote_data_port); 1089 sdp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family); 1090 if (debug > 1) { 1091 fprintf(where, 1092 "netperf: send_sdp_maerts: requesting SDP maerts test\n"); 1093 } 1094 1095 send_request(); 1096 1097 /* The response from the remote will contain all of the relevant 1098 socket parameters for this test type. We will put them back 1099 into the variables here so they can be displayed if desired. 1100 The remote will have calibrated CPU if necessary, and will 1101 have done all the needed set-up we will have calibrated the 1102 cpu locally before sending the request, and will grab the 1103 counter value right after the connect returns. The remote 1104 will grab the counter right after the accept call. This saves 1105 the hassle of extra messages being sent for the SDP 1106 tests. */ 1107 1108 recv_response(); 1109 1110 if (!netperf_response.content.serv_errno) { 1111 if (debug) 1112 fprintf(where,"remote listen done.\n"); 1113 rsr_size = sdp_maerts_response->recv_buf_size; 1114 rss_size = sdp_maerts_response->send_buf_size; 1115 rem_nodelay = sdp_maerts_response->no_delay; 1116 remote_cpu_usage= sdp_maerts_response->measure_cpu; 1117 remote_cpu_rate = sdp_maerts_response->cpu_rate; 1118 send_size = sdp_maerts_response->send_size; 1119 1120 /* we have to make sure that the server port number is in 1121 network order */ 1122 set_port_number(remote_res, 1123 (short)sdp_maerts_response->data_port_number); 1124 rem_rcvavoid = sdp_maerts_response->so_rcvavoid; 1125 rem_sndavoid = sdp_maerts_response->so_sndavoid; 1126 } 1127 else { 1128 Set_errno(netperf_response.content.serv_errno); 1129 fprintf(where, 1130 "netperf: remote error %d", 1131 netperf_response.content.serv_errno); 1132 perror(""); 1133 fflush(where); 1134 1135 exit(1); 1136 } 1137 } 1138 1139#ifdef WANT_DEMO 1140 DEMO_STREAM_SETUP(lsr_size,rss_size) 1141#endif 1142 1143 /*Connect up to the remote port on the data socket */ 1144 if (connect(recv_socket, 1145 remote_res->ai_addr, 1146 remote_res->ai_addrlen) == INVALID_SOCKET){ 1147 perror("netperf: send_sdp_maerts: data socket connect failed"); 1148 exit(1); 1149 } 1150 1151 /* Data Socket set-up is finished. If there were problems, either */ 1152 /* the connect would have failed, or the previous response would */ 1153 /* have indicated a problem. I failed to see the value of the */ 1154 /* extra message after the accept on the remote. If it failed, */ 1155 /* we'll see it here. If it didn't, we might as well start pumping */ 1156 /* data. */ 1157 1158 /* Set-up the test end conditions. For a maerts test, they can be */ 1159 /* either time or byte-count based. */ 1160 1161 if (test_time) { 1162 /* The user wanted to end the test after a period of time. */ 1163 times_up = 0; 1164 bytes_remaining = 0; 1165 /* in previous revisions, we had the same code repeated throught */ 1166 /* all the test suites. this was unnecessary, and meant more */ 1167 /* work for me when I wanted to switch to POSIX signals, so I */ 1168 /* have abstracted this out into a routine in netlib.c. if you */ 1169 /* are experiencing signal problems, you might want to look */ 1170 /* there. raj 11/94 */ 1171 if (!no_control) { 1172 /* this is a netperf to netserver test, netserver will close 1173 to tell us the test is over, so use PAD_TIME to avoid 1174 causing the netserver fits. */ 1175 start_timer(test_time + PAD_TIME); 1176 } 1177 else { 1178 /* this is a netperf to data source test, no PAD_TIME */ 1179 start_timer(test_time); 1180 } 1181 } 1182 else { 1183 /* The tester wanted to recv a number of bytes. we don't do that 1184 in a SDP_MAERTS test. sorry. raj 2002-06-21 */ 1185 printf("netperf: send_sdp_maerts: test must be timed\n"); 1186 exit(1); 1187 } 1188 1189 /* The cpu_start routine will grab the current time and possibly */ 1190 /* value of the idle counter for later use in measuring cpu */ 1191 /* utilization and/or service demand and thruput. */ 1192 1193 cpu_start(local_cpu_usage); 1194 1195#ifdef WANT_INTERVALS 1196 INTERVALS_INIT(); 1197#endif /* WANT_INTERVALS */ 1198 1199 /* before we start, initialize a few variables */ 1200 1201#ifdef WANT_DEMO 1202 if (demo_mode) { 1203 HIST_timestamp(demo_one_ptr); 1204 } 1205#endif 1206 1207 /* the test will continue until we either get a zero-byte recv() 1208 on the socket or our failsafe timer expires. most of the time 1209 we trust that we get a zero-byte recieve from the socket. raj 1210 2002-06-21 */ 1211 1212#ifdef WANT_HISTOGRAM 1213 if (verbosity > 1) { 1214 /* timestamp just before we go into recv and then again just 1215 after we come out raj 8/94 */ 1216 /* but only if we are actually going to display a histogram. raj 1217 2006-02-07 */ 1218 HIST_timestamp(&time_one); 1219 } 1220#endif /* WANT_HISTOGRAM */ 1221 1222 while ((!times_up) && (len=recv(recv_socket, 1223 recv_ring->buffer_ptr, 1224 recv_size, 1225 0)) > 0 ) { 1226 1227#ifdef WANT_HISTOGRAM 1228 if (verbosity > 1) { 1229 /* timestamp the exit from the recv call and update the histogram */ 1230 HIST_timestamp(&time_two); 1231 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 1232 } 1233#endif /* WANT_HISTOGRAM */ 1234 1235#ifdef DIRTY 1236 access_buffer(recv_ring->buffer_ptr, 1237 recv_size, 1238 loc_dirty_count, 1239 loc_clean_count); 1240#endif /* DIRTY */ 1241 1242#ifdef WANT_DEMO 1243 DEMO_STREAM_INTERVAL(len); 1244#endif 1245 1246#ifdef WANT_INTERVALS 1247 INTERVALS_WAIT(); 1248#endif /* WANT_INTERVALS */ 1249 1250 /* now we want to move our pointer to the next position in the */ 1251 /* data buffer...we may also want to wrap back to the "beginning" */ 1252 /* of the bufferspace, so we will mod the number of messages sent */ 1253 /* by the recv width, and use that to calculate the offset to add */ 1254 /* to the base pointer. */ 1255 nummessages++; 1256 recv_ring = recv_ring->next; 1257 if (bytes_remaining) { 1258 bytes_remaining -= len; 1259 } 1260 1261 local_bytes_recvd += len; 1262 1263#ifdef WANT_HISTOGRAM 1264 if (verbosity > 1) { 1265 /* make sure we timestamp just before we go into recv */ 1266 /* raj 2004-06-15 */ 1267 HIST_timestamp(&time_one); 1268 } 1269#endif /* WANT_HISTOGRAM */ 1270 1271 } 1272 1273 /* an EINTR is to be expected when this is a no_control test */ 1274 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) { 1275 perror("send_sdp_maerts: data recv error"); 1276 printf("len was %d\n",len); 1277 exit(1); 1278 } 1279 1280 /* if we get here, it must mean we had a recv return of 0 before 1281 the watchdog timer expired, or the watchdog timer expired and 1282 this was a no_control test */ 1283 1284 /* The test is over. Flush the buffers to the remote end. We do a 1285 graceful release to tell the remote we have all the data. */ 1286 1287 /* but first, if the verbosity is greater than 1, find-out what */ 1288 /* the SDP maximum segment_size was (if possible) */ 1289 if (verbosity > 1) { 1290 sdp_mss = -1; 1291 get_sdp_info(recv_socket,&sdp_mss); 1292 } 1293 1294 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) { 1295 perror("netperf: cannot shutdown sdp maerts socket"); 1296 exit(1); 1297 } 1298 1299 stop_timer(); 1300 1301 /* this call will always give us the local elapsed time for the 1302 test, and will also store-away the necessaries for cpu 1303 utilization */ 1304 1305 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 1306 /* measured and how */ 1307 /* long did we really */ 1308 /* run? */ 1309 1310 /* we are finished with the socket, so close it to prevent hitting */ 1311 /* the limit on maximum open files. */ 1312 1313 close(recv_socket); 1314 1315 if (!no_control) { 1316 /* Get the statistics from the remote end. The remote will have 1317 calculated service demand and all those interesting 1318 things. If it wasn't supposed to care, it will return obvious 1319 values. */ 1320 1321 recv_response(); 1322 if (!netperf_response.content.serv_errno) { 1323 if (debug) 1324 fprintf(where,"remote results obtained\n"); 1325 } 1326 else { 1327 Set_errno(netperf_response.content.serv_errno); 1328 fprintf(where, 1329 "netperf: remote error %d", 1330 netperf_response.content.serv_errno); 1331 perror(""); 1332 fflush(where); 1333 1334 exit(1); 1335 } 1336 1337 /* We now calculate what our thruput was for the test. In the 1338 future, we may want to include a calculation of the thruput 1339 measured by the remote, but it should be the case that for a 1340 SDP maerts test, that the two numbers should be *very* 1341 close... We calculate bytes_sent regardless of the way the 1342 test length was controlled. If it was time, we needed to, 1343 and if it was by bytes, the user may have specified a number 1344 of bytes that wasn't a multiple of the recv_size, so we 1345 really didn't recv what he asked for ;-) */ 1346 1347 bytes_sent = ntohd(sdp_maerts_result->bytes_sent); 1348 } 1349 else { 1350 bytes_sent = (double)local_bytes_recvd; 1351 } 1352 1353 1354 thruput = calc_thruput(bytes_sent); 1355 1356 if (local_cpu_usage || remote_cpu_usage) { 1357 /* We must now do a little math for service demand and cpu */ 1358 /* utilization for the system(s) */ 1359 /* Of course, some of the information might be bogus because */ 1360 /* there was no idle counter in the kernel(s). We need to make */ 1361 /* a note of this for the user's benefit...*/ 1362 if (local_cpu_usage) { 1363 1364 local_cpu_utilization = calc_cpu_util(0.0); 1365 local_service_demand = calc_service_demand(bytes_sent, 1366 0.0, 1367 0.0, 1368 0); 1369 } 1370 else { 1371 local_cpu_utilization = (float) -1.0; 1372 local_service_demand = (float) -1.0; 1373 } 1374 1375 if (remote_cpu_usage) { 1376 1377 remote_cpu_utilization = sdp_maerts_result->cpu_util; 1378 remote_service_demand = calc_service_demand(bytes_sent, 1379 0.0, 1380 remote_cpu_utilization, 1381 sdp_maerts_result->num_cpus); 1382 } 1383 else { 1384 remote_cpu_utilization = (float) -1.0; 1385 remote_service_demand = (float) -1.0; 1386 } 1387 } 1388 else { 1389 /* we were not measuring cpu, for the confidence stuff, we */ 1390 /* should make it -1.0 */ 1391 local_cpu_utilization = (float) -1.0; 1392 local_service_demand = (float) -1.0; 1393 remote_cpu_utilization = (float) -1.0; 1394 remote_service_demand = (float) -1.0; 1395 } 1396 1397 /* at this point, we want to calculate the confidence information. */ 1398 /* if debugging is on, calculate_confidence will print-out the */ 1399 /* parameters we pass it */ 1400 1401 calculate_confidence(confidence_iteration, 1402 elapsed_time, 1403 thruput, 1404 local_cpu_utilization, 1405 remote_cpu_utilization, 1406 local_service_demand, 1407 remote_service_demand); 1408 1409 1410 confidence_iteration++; 1411 } 1412 1413 /* at this point, we have finished making all the runs that we */ 1414 /* will be making. so, we should extract what the calcuated values */ 1415 /* are for all the confidence stuff. we could make the values */ 1416 /* global, but that seemed a little messy, and it did not seem worth */ 1417 /* all the mucking with header files. so, we create a routine much */ 1418 /* like calcualte_confidence, which just returns the mean values. */ 1419 /* raj 11/94 */ 1420 1421 retrieve_confident_values(&elapsed_time, 1422 &thruput, 1423 &local_cpu_utilization, 1424 &remote_cpu_utilization, 1425 &local_service_demand, 1426 &remote_service_demand); 1427 1428 /* We are now ready to print all the information. If the user */ 1429 /* has specified zero-level verbosity, we will just print the */ 1430 /* local service demand, or the remote service demand. If the */ 1431 /* user has requested verbosity level 1, he will get the basic */ 1432 /* "streamperf" numbers. If the user has specified a verbosity */ 1433 /* of greater than 1, we will display a veritable plethora of */ 1434 /* background information from outside of this block as it it */ 1435 /* not cpu_measurement specific... */ 1436 1437 if (confidence < 0) { 1438 /* we did not hit confidence, but were we asked to look for it? */ 1439 if (iteration_max > 1) { 1440 display_confidence(); 1441 } 1442 } 1443 1444 if (local_cpu_usage || remote_cpu_usage) { 1445 local_cpu_method = format_cpu_method(cpu_method); 1446 remote_cpu_method = format_cpu_method(sdp_maerts_result->cpu_method); 1447 1448 switch (verbosity) { 1449 case 0: 1450 if (local_cpu_usage) { 1451 fprintf(where, 1452 cpu_fmt_0, 1453 local_service_demand, 1454 local_cpu_method, 1455 ((print_headers) || 1456 (result_brand == NULL)) ? "" : result_brand); 1457 } 1458 else { 1459 fprintf(where, 1460 cpu_fmt_0, 1461 remote_service_demand, 1462 remote_cpu_method, 1463 ((print_headers) || 1464 (result_brand == NULL)) ? "" : result_brand); 1465 } 1466 break; 1467 case 1: 1468 case 2: 1469 if (print_headers) { 1470 fprintf(where, 1471 cpu_title, 1472 format_units(), 1473 local_cpu_method, 1474 remote_cpu_method); 1475 } 1476 1477 fprintf(where, 1478 cpu_fmt_1, /* the format string */ 1479 rsr_size, /* remote recvbuf size */ 1480 lss_size, /* local sendbuf size */ 1481 send_size, /* how large were the recvs */ 1482 elapsed_time, /* how long was the test */ 1483 thruput, /* what was the xfer rate */ 1484 local_cpu_utilization, /* local cpu */ 1485 remote_cpu_utilization, /* remote cpu */ 1486 local_service_demand, /* local service demand */ 1487 remote_service_demand, /* remote service demand */ 1488 ((print_headers) || 1489 (result_brand == NULL)) ? "" : result_brand); 1490 break; 1491 } 1492 } 1493 else { 1494 /* The tester did not wish to measure service demand. */ 1495 1496 switch (verbosity) { 1497 case 0: 1498 fprintf(where, 1499 tput_fmt_0, 1500 thruput, 1501 ((print_headers) || 1502 (result_brand == NULL)) ? "" : result_brand); 1503 break; 1504 case 1: 1505 case 2: 1506 if (print_headers) { 1507 fprintf(where,tput_title,format_units()); 1508 } 1509 fprintf(where, 1510 tput_fmt_1, /* the format string */ 1511 lsr_size, /* local recvbuf size */ 1512 rss_size, /* remot sendbuf size */ 1513 send_size, /* how large were the recvs */ 1514 elapsed_time, /* how long did it take */ 1515 thruput, /* how fast did it go */ 1516 ((print_headers) || 1517 (result_brand == NULL)) ? "" : result_brand); 1518 break; 1519 } 1520 } 1521 1522 /* it would be a good thing to include information about some of the */ 1523 /* other parameters that may have been set for this test, but at the */ 1524 /* moment, I do not wish to figure-out all the formatting, so I will */ 1525 /* just put this comment here to help remind me that it is something */ 1526 /* that should be done at a later time. */ 1527 1528 if (verbosity > 1) { 1529 /* The user wanted to know it all, so we will give it to him. */ 1530 /* This information will include as much as we can find about */ 1531 /* SDP statistics, the alignments of the sends and receives */ 1532 /* and all that sort of rot... */ 1533 1534 /* this stuff needs to be worked-out in the presence of confidence */ 1535 /* intervals and multiple iterations of the test... raj 11/94 */ 1536 1537 fprintf(where, 1538 ksink_fmt, 1539 "Bytes", 1540 "Bytes", 1541 "Bytes", 1542 local_recv_align, 1543 remote_recv_align, 1544 local_recv_offset, 1545 remote_recv_offset, 1546 bytes_sent, 1547 bytes_sent / (double)nummessages, 1548 nummessages, 1549 bytes_sent / (double)sdp_maerts_result->send_calls, 1550 sdp_maerts_result->send_calls); 1551 fprintf(where, 1552 ksink_fmt2, 1553 sdp_mss); 1554 fflush(where); 1555#ifdef WANT_HISTOGRAM 1556 fprintf(where,"\n\nHistogram of time spent in recv() call.\n"); 1557 fflush(where); 1558 HIST_report(time_hist); 1559#endif /* WANT_HISTOGRAM */ 1560 } 1561 1562} 1563/* This is the server-side routine for the sdp stream test. It is */ 1564/* implemented as one routine. I could break things-out somewhat, but */ 1565/* didn't feel it was necessary. */ 1566 1567void 1568recv_sdp_stream() 1569{ 1570 1571 struct sockaddr_in myaddr_in, peeraddr_in; 1572 SOCKET s_listen,s_data; 1573 netperf_socklen_t addrlen; 1574 int len; 1575 unsigned int receive_calls; 1576 float elapsed_time; 1577 double bytes_received; 1578 1579 struct ring_elt *recv_ring; 1580 1581 struct addrinfo *local_res; 1582 char local_name[BUFSIZ]; 1583 char port_buffer[PORTBUFSIZE]; 1584 1585#ifdef DO_SELECT 1586 fd_set readfds; 1587 struct timeval timeout; 1588#endif /* DO_SELECT */ 1589 1590 struct sdp_stream_request_struct *sdp_stream_request; 1591 struct sdp_stream_response_struct *sdp_stream_response; 1592 struct sdp_stream_results_struct *sdp_stream_results; 1593 1594#ifdef DO_SELECT 1595 FD_ZERO(&readfds); 1596 timeout.tv_sec = 1; 1597 timeout.tv_usec = 0; 1598#endif /* DO_SELECT */ 1599 1600 sdp_stream_request = 1601 (struct sdp_stream_request_struct *)netperf_request.content.test_specific_data; 1602 sdp_stream_response = 1603 (struct sdp_stream_response_struct *)netperf_response.content.test_specific_data; 1604 sdp_stream_results = 1605 (struct sdp_stream_results_struct *)netperf_response.content.test_specific_data; 1606 1607 if (debug) { 1608 fprintf(where,"netserver: recv_sdp_stream: entered...\n"); 1609 fflush(where); 1610 } 1611 1612 /* We want to set-up the listen socket with all the desired */ 1613 /* parameters and then let the initiator know that all is ready. If */ 1614 /* socket size defaults are to be used, then the initiator will have */ 1615 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 1616 /* send-back what they are. If that information cannot be determined, */ 1617 /* then we send-back -1's for the sizes. If things go wrong for any */ 1618 /* reason, we will drop back ten yards and punt. */ 1619 1620 /* If anything goes wrong, we want the remote to know about it. It */ 1621 /* would be best if the error that the remote reports to the user is */ 1622 /* the actual error we encountered, rather than some bogus unexpected */ 1623 /* response type message. */ 1624 1625 if (debug) { 1626 fprintf(where,"recv_sdp_stream: setting the response type...\n"); 1627 fflush(where); 1628 } 1629 1630 netperf_response.content.response_type = SDP_STREAM_RESPONSE; 1631 1632 if (debug) { 1633 fprintf(where,"recv_sdp_stream: the response type is set...\n"); 1634 fflush(where); 1635 } 1636 1637 /* We now alter the message_ptr variable to be at the desired */ 1638 /* alignment with the desired offset. */ 1639 1640 if (debug) { 1641 fprintf(where,"recv_sdp_stream: requested alignment of %d\n", 1642 sdp_stream_request->recv_alignment); 1643 fflush(where); 1644 } 1645 1646 /* create_data_socket expects to find some things in the global */ 1647 /* variables, so set the globals based on the values in the request. */ 1648 /* once the socket has been created, we will set the response values */ 1649 /* based on the updated value of those globals. raj 7/94 */ 1650 lss_size_req = sdp_stream_request->send_buf_size; 1651 lsr_size_req = sdp_stream_request->recv_buf_size; 1652 loc_nodelay = sdp_stream_request->no_delay; 1653 loc_rcvavoid = sdp_stream_request->so_rcvavoid; 1654 loc_sndavoid = sdp_stream_request->so_sndavoid; 1655 1656 set_hostname_and_port(local_name, 1657 port_buffer, 1658 nf_to_af(sdp_stream_request->ipfamily), 1659 sdp_stream_request->port); 1660 1661 local_res = complete_addrinfo(local_name, 1662 local_name, 1663 port_buffer, 1664 nf_to_af(sdp_stream_request->ipfamily), 1665 SOCK_STREAM, 1666 IPPROTO_TCP, 1667 0); 1668 1669 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 1670 local_res->ai_family = AF_INET_SDP; 1671 local_res->ai_protocol = 0; 1672 s_listen = create_data_socket(local_res); 1673 1674 if (s_listen == INVALID_SOCKET) { 1675 netperf_response.content.serv_errno = errno; 1676 send_response(); 1677 exit(1); 1678 } 1679 1680#ifdef WIN32 1681 /* The test timer can fire during operations on the listening socket, 1682 so to make the start_timer below work we have to move 1683 it to close s_listen while we are blocked on accept. */ 1684 win_kludge_socket2 = s_listen; 1685#endif 1686 1687 /* what sort of sizes did we end-up with? */ 1688 if (sdp_stream_request->receive_size == 0) { 1689 if (lsr_size > 0) { 1690 recv_size = lsr_size; 1691 } 1692 else { 1693 recv_size = 4096; 1694 } 1695 } 1696 else { 1697 recv_size = sdp_stream_request->receive_size; 1698 } 1699 1700 /* we want to set-up our recv_ring in a manner analagous to what we */ 1701 /* do on the sending side. this is more for the sake of symmetry */ 1702 /* than for the needs of say copy avoidance, but it might also be */ 1703 /* more realistic - this way one could conceivably go with a */ 1704 /* double-buffering scheme when taking the data an putting it into */ 1705 /* the filesystem or something like that. raj 7/94 */ 1706 1707 if (recv_width == 0) { 1708 recv_width = (lsr_size/recv_size) + 1; 1709 if (recv_width == 1) recv_width++; 1710 } 1711 1712 recv_ring = allocate_buffer_ring(recv_width, 1713 recv_size, 1714 sdp_stream_request->recv_alignment, 1715 sdp_stream_request->recv_offset); 1716 1717 if (debug) { 1718 fprintf(where,"recv_sdp_stream: receive alignment and offset set...\n"); 1719 fflush(where); 1720 } 1721 1722 /* Now, let's set-up the socket to listen for connections */ 1723 if (listen(s_listen, 5) == SOCKET_ERROR) { 1724 netperf_response.content.serv_errno = errno; 1725 close(s_listen); 1726 send_response(); 1727 1728 exit(1); 1729 } 1730 1731 1732 /* now get the port number assigned by the system */ 1733 addrlen = sizeof(myaddr_in); 1734 if (getsockname(s_listen, 1735 (struct sockaddr *)&myaddr_in, 1736 &addrlen) == SOCKET_ERROR){ 1737 netperf_response.content.serv_errno = errno; 1738 close(s_listen); 1739 send_response(); 1740 1741 exit(1); 1742 } 1743 1744 /* Now myaddr_in contains the port and the internet address this is */ 1745 /* returned to the sender also implicitly telling the sender that the */ 1746 /* socket buffer sizing has been done. */ 1747 1748 sdp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 1749 netperf_response.content.serv_errno = 0; 1750 1751 /* But wait, there's more. If the initiator wanted cpu measurements, */ 1752 /* then we must call the calibrate routine, which will return the max */ 1753 /* rate back to the initiator. If the CPU was not to be measured, or */ 1754 /* something went wrong with the calibration, we will return a -1 to */ 1755 /* the initiator. */ 1756 1757 sdp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 1758 if (sdp_stream_request->measure_cpu) { 1759 sdp_stream_response->measure_cpu = 1; 1760 sdp_stream_response->cpu_rate = 1761 calibrate_local_cpu(sdp_stream_request->cpu_rate); 1762 } 1763 else { 1764 sdp_stream_response->measure_cpu = 0; 1765 } 1766 1767 /* before we send the response back to the initiator, pull some of */ 1768 /* the socket parms from the globals */ 1769 sdp_stream_response->send_buf_size = lss_size; 1770 sdp_stream_response->recv_buf_size = lsr_size; 1771 sdp_stream_response->no_delay = loc_nodelay; 1772 sdp_stream_response->so_rcvavoid = loc_rcvavoid; 1773 sdp_stream_response->so_sndavoid = loc_sndavoid; 1774 sdp_stream_response->receive_size = recv_size; 1775 1776 send_response(); 1777 1778 addrlen = sizeof(peeraddr_in); 1779 1780 if ((s_data=accept(s_listen, 1781 (struct sockaddr *)&peeraddr_in, 1782 &addrlen)) == INVALID_SOCKET) { 1783 /* Let's just punt. The remote will be given some information */ 1784 close(s_listen); 1785 exit(1); 1786 } 1787 1788#ifdef KLUDGE_SOCKET_OPTIONS 1789 /* this is for those systems which *INCORRECTLY* fail to pass */ 1790 /* attributes across an accept() call. Including this goes against */ 1791 /* my better judgement :( raj 11/95 */ 1792 1793 kludge_socket_options(s_data); 1794 1795#endif /* KLUDGE_SOCKET_OPTIONS */ 1796 1797 /* Now it's time to start receiving data on the connection. We will */ 1798 /* first grab the apropriate counters and then start grabbing. */ 1799 1800 cpu_start(sdp_stream_request->measure_cpu); 1801 1802 /* The loop will exit when the sender does a shutdown, which will */ 1803 /* return a length of zero */ 1804 1805 /* there used to be an #ifdef DIRTY call to access_buffer() here, 1806 but we have switched from accessing the buffer before the recv() 1807 call to accessing the buffer after the recv() call. The 1808 accessing before was, IIRC, related to having dirty data when 1809 doing page-flipping copy avoidance. */ 1810 1811 bytes_received = 0; 1812 receive_calls = 0; 1813 1814 while ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0) { 1815 if (len == SOCKET_ERROR ) 1816 { 1817 netperf_response.content.serv_errno = errno; 1818 send_response(); 1819 exit(1); 1820 } 1821 bytes_received += len; 1822 receive_calls++; 1823 1824#ifdef DIRTY 1825 /* we access the buffer after the recv() call now, rather than before */ 1826 access_buffer(recv_ring->buffer_ptr, 1827 recv_size, 1828 sdp_stream_request->dirty_count, 1829 sdp_stream_request->clean_count); 1830#endif /* DIRTY */ 1831 1832 1833 /* move to the next buffer in the recv_ring */ 1834 recv_ring = recv_ring->next; 1835 1836#ifdef PAUSE 1837 sleep(1); 1838#endif /* PAUSE */ 1839 1840#ifdef DO_SELECT 1841 FD_SET(s_data,&readfds); 1842 select(s_data+1,&readfds,NULL,NULL,&timeout); 1843#endif /* DO_SELECT */ 1844 1845 } 1846 1847 /* perform a shutdown to signal the sender that */ 1848 /* we have received all the data sent. raj 4/93 */ 1849 1850 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) { 1851 netperf_response.content.serv_errno = errno; 1852 send_response(); 1853 exit(1); 1854 } 1855 1856 cpu_stop(sdp_stream_request->measure_cpu,&elapsed_time); 1857 1858 /* send the results to the sender */ 1859 1860 if (debug) { 1861 fprintf(where, 1862 "recv_sdp_stream: got %g bytes\n", 1863 bytes_received); 1864 fprintf(where, 1865 "recv_sdp_stream: got %d recvs\n", 1866 receive_calls); 1867 fflush(where); 1868 } 1869 1870 sdp_stream_results->bytes_received = htond(bytes_received); 1871 sdp_stream_results->elapsed_time = elapsed_time; 1872 sdp_stream_results->recv_calls = receive_calls; 1873 1874 sdp_stream_results->cpu_method = cpu_method; 1875 sdp_stream_results->num_cpus = lib_num_loc_cpus; 1876 1877 if (sdp_stream_request->measure_cpu) { 1878 sdp_stream_results->cpu_util = calc_cpu_util(0.0); 1879 }; 1880 1881 if (debug) { 1882 fprintf(where, 1883 "recv_sdp_stream: test complete, sending results.\n"); 1884 fprintf(where, 1885 " bytes_received %g receive_calls %d\n", 1886 bytes_received, 1887 receive_calls); 1888 fprintf(where, 1889 " len %d\n", 1890 len); 1891 fflush(where); 1892 } 1893 1894 send_response(); 1895 1896 /* we are now done with the sockets */ 1897 close(s_data); 1898 close(s_listen); 1899 1900 } 1901 1902/* This is the server-side routine for the sdp maerts test. It is 1903 implemented as one routine. I could break things-out somewhat, but 1904 didn't feel it was necessary. */ 1905 1906void 1907recv_sdp_maerts() 1908{ 1909 1910 struct sockaddr_in myaddr_in, peeraddr_in; 1911 struct addrinfo *local_res; 1912 char local_name[BUFSIZ]; 1913 char port_buffer[PORTBUFSIZE]; 1914 1915 SOCKET s_listen,s_data; 1916 netperf_socklen_t addrlen; 1917 int len; 1918 unsigned int send_calls; 1919 float elapsed_time; 1920 double bytes_sent = 0.0 ; 1921 1922 struct ring_elt *send_ring; 1923 1924 struct sdp_maerts_request_struct *sdp_maerts_request; 1925 struct sdp_maerts_response_struct *sdp_maerts_response; 1926 struct sdp_maerts_results_struct *sdp_maerts_results; 1927 1928 sdp_maerts_request = 1929 (struct sdp_maerts_request_struct *)netperf_request.content.test_specific_data; 1930 sdp_maerts_response = 1931 (struct sdp_maerts_response_struct *)netperf_response.content.test_specific_data; 1932 sdp_maerts_results = 1933 (struct sdp_maerts_results_struct *)netperf_response.content.test_specific_data; 1934 1935 if (debug) { 1936 fprintf(where,"netserver: recv_sdp_maerts: entered...\n"); 1937 fflush(where); 1938 } 1939 1940 /* We want to set-up the listen socket with all the desired 1941 parameters and then let the initiator know that all is ready. If 1942 socket size defaults are to be used, then the initiator will have 1943 sent us 0's. If the socket sizes cannot be changed, then we will 1944 send-back what they are. If that information cannot be 1945 determined, then we send-back -1's for the sizes. If things go 1946 wrong for any reason, we will drop back ten yards and punt. */ 1947 1948 /* If anything goes wrong, we want the remote to know about it. It 1949 would be best if the error that the remote reports to the user is 1950 the actual error we encountered, rather than some bogus 1951 unexpected response type message. */ 1952 1953 if (debug) { 1954 fprintf(where,"recv_sdp_maerts: setting the response type...\n"); 1955 fflush(where); 1956 } 1957 1958 netperf_response.content.response_type = SDP_MAERTS_RESPONSE; 1959 1960 if (debug) { 1961 fprintf(where,"recv_sdp_maerts: the response type is set...\n"); 1962 fflush(where); 1963 } 1964 1965 /* We now alter the message_ptr variable to be at the desired */ 1966 /* alignment with the desired offset. */ 1967 1968 if (debug) { 1969 fprintf(where,"recv_sdp_maerts: requested alignment of %d\n", 1970 sdp_maerts_request->send_alignment); 1971 fflush(where); 1972 } 1973 1974 /* Grab a socket to listen on, and then listen on it. */ 1975 1976 if (debug) { 1977 fprintf(where,"recv_sdp_maerts: grabbing a socket...\n"); 1978 fflush(where); 1979 } 1980 1981 /* create_data_socket expects to find some things in the global */ 1982 /* variables, so set the globals based on the values in the request. */ 1983 /* once the socket has been created, we will set the response values */ 1984 /* based on the updated value of those globals. raj 7/94 */ 1985 lss_size_req = sdp_maerts_request->send_buf_size; 1986 lsr_size_req = sdp_maerts_request->recv_buf_size; 1987 loc_nodelay = sdp_maerts_request->no_delay; 1988 loc_rcvavoid = sdp_maerts_request->so_rcvavoid; 1989 loc_sndavoid = sdp_maerts_request->so_sndavoid; 1990 1991 set_hostname_and_port(local_name, 1992 port_buffer, 1993 nf_to_af(sdp_maerts_request->ipfamily), 1994 sdp_maerts_request->port); 1995 1996 local_res = complete_addrinfo(local_name, 1997 local_name, 1998 port_buffer, 1999 nf_to_af(sdp_maerts_request->ipfamily), 2000 SOCK_STREAM, 2001 IPPROTO_TCP, 2002 0); 2003 2004 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 2005 local_res->ai_family = AF_INET_SDP; 2006 local_res->ai_protocol = 0; 2007 s_listen = create_data_socket(local_res); 2008 2009 if (s_listen == INVALID_SOCKET) { 2010 netperf_response.content.serv_errno = errno; 2011 send_response(); 2012 exit(1); 2013 } 2014 2015#ifdef WIN32 2016 /* The test timer can fire during operations on the listening socket, 2017 so to make the start_timer below work we have to move 2018 it to close s_listen while we are blocked on accept. */ 2019 win_kludge_socket2 = s_listen; 2020#endif 2021 2022 2023 /* what sort of sizes did we end-up with? */ 2024 if (sdp_maerts_request->send_size == 0) { 2025 if (lss_size > 0) { 2026 send_size = lss_size; 2027 } 2028 else { 2029 send_size = 4096; 2030 } 2031 } 2032 else { 2033 send_size = sdp_maerts_request->send_size; 2034 } 2035 2036 /* we want to set-up our recv_ring in a manner analagous to what we */ 2037 /* do on the recving side. this is more for the sake of symmetry */ 2038 /* than for the needs of say copy avoidance, but it might also be */ 2039 /* more realistic - this way one could conceivably go with a */ 2040 /* double-buffering scheme when taking the data an putting it into */ 2041 /* the filesystem or something like that. raj 7/94 */ 2042 2043 if (send_width == 0) { 2044 send_width = (lsr_size/send_size) + 1; 2045 if (send_width == 1) send_width++; 2046 } 2047 2048 send_ring = allocate_buffer_ring(send_width, 2049 send_size, 2050 sdp_maerts_request->send_alignment, 2051 sdp_maerts_request->send_offset); 2052 2053 if (debug) { 2054 fprintf(where,"recv_sdp_maerts: receive alignment and offset set...\n"); 2055 fflush(where); 2056 } 2057 2058 /* Now, let's set-up the socket to listen for connections */ 2059 if (listen(s_listen, 5) == SOCKET_ERROR) { 2060 netperf_response.content.serv_errno = errno; 2061 close(s_listen); 2062 send_response(); 2063 2064 exit(1); 2065 } 2066 2067 2068 /* now get the port number assigned by the system */ 2069 addrlen = sizeof(myaddr_in); 2070 if (getsockname(s_listen, 2071 (struct sockaddr *)&myaddr_in, 2072 &addrlen) == SOCKET_ERROR){ 2073 netperf_response.content.serv_errno = errno; 2074 close(s_listen); 2075 send_response(); 2076 2077 exit(1); 2078 } 2079 2080 /* Now myaddr_in contains the port and the internet address this is */ 2081 /* returned to the sender also implicitly telling the sender that the */ 2082 /* socket buffer sizing has been done. */ 2083 2084 sdp_maerts_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 2085 netperf_response.content.serv_errno = 0; 2086 2087 /* But wait, there's more. If the initiator wanted cpu measurements, */ 2088 /* then we must call the calibrate routine, which will return the max */ 2089 /* rate back to the initiator. If the CPU was not to be measured, or */ 2090 /* something went wrong with the calibration, we will return a -1 to */ 2091 /* the initiator. */ 2092 2093 sdp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */ 2094 if (sdp_maerts_request->measure_cpu) { 2095 sdp_maerts_response->measure_cpu = 1; 2096 sdp_maerts_response->cpu_rate = 2097 calibrate_local_cpu(sdp_maerts_request->cpu_rate); 2098 } 2099 else { 2100 sdp_maerts_response->measure_cpu = 0; 2101 } 2102 2103 /* before we send the response back to the initiator, pull some of */ 2104 /* the socket parms from the globals */ 2105 sdp_maerts_response->send_buf_size = lss_size; 2106 sdp_maerts_response->recv_buf_size = lsr_size; 2107 sdp_maerts_response->no_delay = loc_nodelay; 2108 sdp_maerts_response->so_rcvavoid = loc_rcvavoid; 2109 sdp_maerts_response->so_sndavoid = loc_sndavoid; 2110 sdp_maerts_response->send_size = send_size; 2111 2112 send_response(); 2113 2114 addrlen = sizeof(peeraddr_in); 2115 2116 /* we will start the timer before the accept() to be somewhat 2117 analagous to the starting of the timer before the connect() call 2118 in the SDP_STREAM test. raj 2002-06-21 */ 2119 2120 start_timer(sdp_maerts_request->test_length); 2121 2122 /* Now it's time to start receiving data on the connection. We will 2123 first grab the apropriate counters and then start grabbing. */ 2124 2125 cpu_start(sdp_maerts_request->measure_cpu); 2126 2127 2128 if ((s_data=accept(s_listen, 2129 (struct sockaddr *)&peeraddr_in, 2130 &addrlen)) == INVALID_SOCKET) { 2131 /* Let's just punt. The remote will be given some information */ 2132 close(s_listen); 2133 exit(1); 2134 } 2135 2136#ifdef KLUDGE_SOCKET_OPTIONS 2137 2138 /* this is for those systems which *INCORRECTLY* fail to pass 2139 attributes across an accept() call. Including this goes against 2140 my better judgement :( raj 11/95 */ 2141 2142 kludge_socket_options(s_data); 2143 2144#endif /* KLUDGE_SOCKET_OPTIONS */ 2145 2146 /* The loop will exit when the sender does a shutdown, which will */ 2147 /* return a length of zero */ 2148 2149 bytes_sent = 0.0; 2150 send_calls = 0; 2151 2152 len = 0; /* nt-lint; len is not initialized (printf far below) if 2153 times_up initially true.*/ 2154 times_up = 0; /* must remember to initialize this little beauty */ 2155 while (!times_up) { 2156 2157#ifdef DIRTY 2158 /* we want to dirty some number of consecutive integers in the buffer */ 2159 /* we are about to send. we may also want to bring some number of */ 2160 /* them cleanly into the cache. The clean ones will follow any dirty */ 2161 /* ones into the cache. */ 2162 2163 access_buffer(send_ring->buffer_ptr, 2164 send_size, 2165 sdp_maerts_request->dirty_count, 2166 sdp_maerts_request->clean_count); 2167 2168#endif /* DIRTY */ 2169 2170 if((len=send(s_data, 2171 send_ring->buffer_ptr, 2172 send_size, 2173 0)) != send_size) { 2174 if ((len >=0) || SOCKET_EINTR(len)) { 2175 /* the test was interrupted, must be the end of test */ 2176 break; 2177 } 2178 netperf_response.content.serv_errno = errno; 2179 send_response(); 2180 exit(1); 2181 } 2182 2183 bytes_sent += len; 2184 send_calls++; 2185 2186 /* more to the next buffer in the send_ring */ 2187 send_ring = send_ring->next; 2188 2189 } 2190 2191 /* perform a shutdown to signal the sender that */ 2192 /* we have received all the data sent. raj 4/93 */ 2193 2194 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) { 2195 netperf_response.content.serv_errno = errno; 2196 send_response(); 2197 exit(1); 2198 } 2199 2200 /* hang a recv() off the socket to block until the remote has 2201 brought all the data up into the application. it will do a 2202 shutdown to cause a FIN to be sent our way. We will assume that 2203 any exit from the recv() call is good... raj 4/93 */ 2204 2205 recv(s_data, send_ring->buffer_ptr, send_size, 0); 2206 2207 2208 cpu_stop(sdp_maerts_request->measure_cpu,&elapsed_time); 2209 2210 /* send the results to the sender */ 2211 2212 if (debug) { 2213 fprintf(where, 2214 "recv_sdp_maerts: got %g bytes\n", 2215 bytes_sent); 2216 fprintf(where, 2217 "recv_sdp_maerts: got %d sends\n", 2218 send_calls); 2219 fflush(where); 2220 } 2221 2222 sdp_maerts_results->bytes_sent = htond(bytes_sent); 2223 sdp_maerts_results->elapsed_time = elapsed_time; 2224 sdp_maerts_results->send_calls = send_calls; 2225 2226 if (sdp_maerts_request->measure_cpu) { 2227 sdp_maerts_results->cpu_util = calc_cpu_util(0.0); 2228 }; 2229 2230 if (debug) { 2231 fprintf(where, 2232 "recv_sdp_maerts: test complete, sending results.\n"); 2233 fprintf(where, 2234 " bytes_sent %g send_calls %d\n", 2235 bytes_sent, 2236 send_calls); 2237 fprintf(where, 2238 " len %d\n", 2239 len); 2240 fflush(where); 2241 } 2242 2243 sdp_maerts_results->cpu_method = cpu_method; 2244 sdp_maerts_results->num_cpus = lib_num_loc_cpus; 2245 send_response(); 2246 2247 /* we are now done with the sockets */ 2248 close(s_data); 2249 close(s_listen); 2250 2251 } 2252 2253 2254 /* this routine implements the sending (netperf) side of the SDP_RR */ 2255 /* test. */ 2256 2257void 2258send_sdp_rr(char remote_host[]) 2259{ 2260 2261 char *tput_title = "\ 2262Local /Remote\n\ 2263Socket Size Request Resp. Elapsed Trans.\n\ 2264Send Recv Size Size Time Rate \n\ 2265bytes Bytes bytes bytes secs. per sec \n\n"; 2266 2267 char *tput_fmt_0 = 2268 "%7.2f %s\n"; 2269 2270 char *tput_fmt_1_line_1 = "\ 2271%-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n"; 2272 char *tput_fmt_1_line_2 = "\ 2273%-6d %-6d\n"; 2274 2275 char *cpu_title = "\ 2276Local /Remote\n\ 2277Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 2278Send Recv Size Size Time Rate local remote local remote\n\ 2279bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 2280 2281 char *cpu_fmt_0 = 2282 "%6.3f %c %s\n"; 2283 2284 char *cpu_fmt_1_line_1 = "\ 2285%-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n"; 2286 2287 char *cpu_fmt_1_line_2 = "\ 2288%-6d %-6d\n"; 2289 2290 char *ksink_fmt = "\ 2291Alignment Offset\n\ 2292Local Remote Local Remote\n\ 2293Send Recv Send Recv\n\ 2294%5d %5d %5d %5d\n"; 2295 2296 2297 int timed_out = 0; 2298 float elapsed_time; 2299 2300 int len; 2301 char *temp_message_ptr; 2302 int nummessages; 2303 SOCKET send_socket; 2304 int trans_remaining; 2305 double bytes_xferd; 2306 2307 struct ring_elt *send_ring; 2308 struct ring_elt *recv_ring; 2309 2310 int rsp_bytes_left; 2311 int rsp_bytes_recvd; 2312 2313 float local_cpu_utilization; 2314 float local_service_demand; 2315 float remote_cpu_utilization; 2316 float remote_service_demand; 2317 double thruput; 2318 2319 struct addrinfo *local_res; 2320 struct addrinfo *remote_res; 2321 2322 struct sdp_rr_request_struct *sdp_rr_request; 2323 struct sdp_rr_response_struct *sdp_rr_response; 2324 struct sdp_rr_results_struct *sdp_rr_result; 2325 2326#ifdef WANT_FIRST_BURST 2327#define REQUEST_CWND_INITIAL 2 2328 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both 2329 Unix and the state of New Jersey - both were simple an unspoiled. 2330 then it was realized that some stacks are quite picky about 2331 initial congestion windows and a non-trivial initial burst of 2332 requests would not be individual segments even with TCP_NODELAY 2333 set. so, we have to start tracking a poor-man's congestion window 2334 up here in window space because we want to try to make something 2335 happen that frankly, we cannot guarantee with the specification 2336 of SDP. ain't that grand?-) raj 2006-01-30 */ 2337 int requests_outstanding = 0; 2338 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having 2339 three requests 2340 outstanding at the 2341 beginning of the test 2342 is ok with SDP stacks 2343 of interest. the first 2344 two will come from our 2345 first_burst loop, and 2346 the third from our 2347 regularly scheduled 2348 send */ 2349#endif 2350 2351 sdp_rr_request = 2352 (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data; 2353 sdp_rr_response= 2354 (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data; 2355 sdp_rr_result = 2356 (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data; 2357 2358#ifdef WANT_HISTOGRAM 2359 if (verbosity > 1) { 2360 time_hist = HIST_new(); 2361 } 2362#endif /* WANT_HISTOGRAM */ 2363 2364 /* since we are now disconnected from the code that established the */ 2365 /* control socket, and since we want to be able to use different */ 2366 /* protocols and such, we are passed the name of the remote host and */ 2367 /* must turn that into the test specific addressing information. */ 2368 2369 complete_addrinfos(&remote_res, 2370 &local_res, 2371 remote_host, 2372 SOCK_STREAM, 2373 IPPROTO_TCP, 2374 0); 2375 2376 if ( print_headers ) { 2377 print_top_test_header("SDP REQUEST/RESPONSE TEST",local_res,remote_res); 2378 } 2379 2380 /* initialize a few counters */ 2381 2382 send_ring = NULL; 2383 recv_ring = NULL; 2384 confidence_iteration = 1; 2385 init_stat(); 2386 2387 /* we have a great-big while loop which controls the number of times */ 2388 /* we run a particular test. this is for the calculation of a */ 2389 /* confidence interval (I really should have stayed awake during */ 2390 /* probstats :). If the user did not request confidence measurement */ 2391 /* (no confidence is the default) then we will only go though the */ 2392 /* loop once. the confidence stuff originates from the folks at IBM */ 2393 2394 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 2395 (confidence_iteration <= iteration_min)) { 2396 2397 /* initialize a few counters. we have to remember that we might be */ 2398 /* going through the loop more than once. */ 2399 2400 nummessages = 0; 2401 bytes_xferd = 0.0; 2402 times_up = 0; 2403 timed_out = 0; 2404 trans_remaining = 0; 2405 2406#ifdef WANT_FIRST_BURST 2407 /* we have to remember to reset the number of transactions 2408 outstanding and the "congestion window for each new 2409 iteration. raj 2006-01-31 */ 2410 requests_outstanding = 0; 2411 request_cwnd = REQUEST_CWND_INITIAL; 2412#endif 2413 2414 2415 /* set-up the data buffers with the requested alignment and offset. */ 2416 /* since this is a request/response test, default the send_width and */ 2417 /* recv_width to 1 and not two raj 7/94 */ 2418 2419 if (send_width == 0) send_width = 1; 2420 if (recv_width == 0) recv_width = 1; 2421 2422 if (send_ring == NULL) { 2423 send_ring = allocate_buffer_ring(send_width, 2424 req_size, 2425 local_send_align, 2426 local_send_offset); 2427 } 2428 2429 if (recv_ring == NULL) { 2430 recv_ring = allocate_buffer_ring(recv_width, 2431 rsp_size, 2432 local_recv_align, 2433 local_recv_offset); 2434 } 2435 2436 /*set up the data socket */ 2437 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 2438 local_res->ai_family = AF_INET_SDP; 2439 local_res->ai_protocol = 0; 2440 send_socket = create_data_socket(local_res); 2441 2442 if (send_socket == INVALID_SOCKET){ 2443 perror("netperf: send_sdp_rr: sdp stream data socket"); 2444 exit(1); 2445 } 2446 2447 if (debug) { 2448 fprintf(where,"send_sdp_rr: send_socket obtained...\n"); 2449 } 2450 2451 /* If the user has requested cpu utilization measurements, we must */ 2452 /* calibrate the cpu(s). We will perform this task within the tests */ 2453 /* themselves. If the user has specified the cpu rate, then */ 2454 /* calibrate_local_cpu will return rather quickly as it will have */ 2455 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 2456 /* all the "normal" calibration stuff and return the rate back.*/ 2457 2458 if (local_cpu_usage) { 2459 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 2460 } 2461 2462 if (!no_control) { 2463 /* Tell the remote end to do a listen. The server alters the 2464 socket paramters on the other side at this point, hence the 2465 reason for all the values being passed in the setup 2466 message. If the user did not specify any of the parameters, 2467 they will be passed as 0, which will indicate to the remote 2468 that no changes beyond the system's default should be 2469 used. Alignment is the exception, it will default to 8, which 2470 will be no alignment alterations. */ 2471 2472 netperf_request.content.request_type = DO_SDP_RR; 2473 sdp_rr_request->recv_buf_size = rsr_size_req; 2474 sdp_rr_request->send_buf_size = rss_size_req; 2475 sdp_rr_request->recv_alignment = remote_recv_align; 2476 sdp_rr_request->recv_offset = remote_recv_offset; 2477 sdp_rr_request->send_alignment = remote_send_align; 2478 sdp_rr_request->send_offset = remote_send_offset; 2479 sdp_rr_request->request_size = req_size; 2480 sdp_rr_request->response_size = rsp_size; 2481 sdp_rr_request->no_delay = rem_nodelay; 2482 sdp_rr_request->measure_cpu = remote_cpu_usage; 2483 sdp_rr_request->cpu_rate = remote_cpu_rate; 2484 sdp_rr_request->so_rcvavoid = rem_rcvavoid; 2485 sdp_rr_request->so_sndavoid = rem_sndavoid; 2486 if (test_time) { 2487 sdp_rr_request->test_length = test_time; 2488 } 2489 else { 2490 sdp_rr_request->test_length = test_trans * -1; 2491 } 2492 sdp_rr_request->port = atoi(remote_data_port); 2493 sdp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 2494 2495 if (debug > 1) { 2496 fprintf(where,"netperf: send_sdp_rr: requesting SDP rr test\n"); 2497 } 2498 2499 send_request(); 2500 2501 /* The response from the remote will contain all of the relevant 2502 socket parameters for this test type. We will put them back 2503 into the variables here so they can be displayed if desired. 2504 The remote will have calibrated CPU if necessary, and will 2505 have done all the needed set-up we will have calibrated the 2506 cpu locally before sending the request, and will grab the 2507 counter value right after the connect returns. The remote 2508 will grab the counter right after the accept call. This saves 2509 the hassle of extra messages being sent for the SDP 2510 tests. */ 2511 2512 recv_response(); 2513 2514 if (!netperf_response.content.serv_errno) { 2515 if (debug) 2516 fprintf(where,"remote listen done.\n"); 2517 rsr_size = sdp_rr_response->recv_buf_size; 2518 rss_size = sdp_rr_response->send_buf_size; 2519 rem_nodelay = sdp_rr_response->no_delay; 2520 remote_cpu_usage = sdp_rr_response->measure_cpu; 2521 remote_cpu_rate = sdp_rr_response->cpu_rate; 2522 /* make sure that port numbers are in network order */ 2523 set_port_number(remote_res,(short)sdp_rr_response->data_port_number); 2524 } 2525 else { 2526 Set_errno(netperf_response.content.serv_errno); 2527 fprintf(where, 2528 "netperf: remote error %d", 2529 netperf_response.content.serv_errno); 2530 perror(""); 2531 fflush(where); 2532 2533 exit(1); 2534 } 2535 } 2536 2537#ifdef WANT_DEMO 2538 DEMO_RR_SETUP(1000) 2539#endif 2540 2541 /*Connect up to the remote port on the data socket */ 2542 if (connect(send_socket, 2543 remote_res->ai_addr, 2544 remote_res->ai_addrlen) == INVALID_SOCKET){ 2545 perror("netperf: data socket connect failed"); 2546 2547 exit(1); 2548 } 2549 2550 /* Data Socket set-up is finished. If there were problems, either the */ 2551 /* connect would have failed, or the previous response would have */ 2552 /* indicated a problem. I failed to see the value of the extra */ 2553 /* message after the accept on the remote. If it failed, we'll see it */ 2554 /* here. If it didn't, we might as well start pumping data. */ 2555 2556 /* Set-up the test end conditions. For a request/response test, they */ 2557 /* can be either time or transaction based. */ 2558 2559 if (test_time) { 2560 /* The user wanted to end the test after a period of time. */ 2561 times_up = 0; 2562 trans_remaining = 0; 2563 start_timer(test_time); 2564 } 2565 else { 2566 /* The tester wanted to send a number of bytes. */ 2567 trans_remaining = test_bytes; 2568 times_up = 1; 2569 } 2570 2571 /* The cpu_start routine will grab the current time and possibly */ 2572 /* value of the idle counter for later use in measuring cpu */ 2573 /* utilization and/or service demand and thruput. */ 2574 2575 cpu_start(local_cpu_usage); 2576 2577#ifdef WANT_INTERVALS 2578 INTERVALS_INIT(); 2579#endif /* WANT_INTERVALS */ 2580 2581 /* We use an "OR" to control test execution. When the test is */ 2582 /* controlled by time, the byte count check will always return false. */ 2583 /* When the test is controlled by byte count, the time test will */ 2584 /* always return false. When the test is finished, the whole */ 2585 /* expression will go false and we will stop sending data. I think I */ 2586 /* just arbitrarily decrement trans_remaining for the timed test, but */ 2587 /* will not do that just yet... One other question is whether or not */ 2588 /* the send buffer and the receive buffer should be the same buffer. */ 2589 2590#ifdef WANT_DEMO 2591 if (demo_mode) { 2592 HIST_timestamp(demo_one_ptr); 2593 } 2594#endif 2595 2596 while ((!times_up) || (trans_remaining > 0)) { 2597 /* send the request. we assume that if we use a blocking socket, */ 2598 /* the request will be sent at one shot. */ 2599 2600#ifdef WANT_FIRST_BURST 2601 /* we can inject no more than request_cwnd, which will grow with 2602 time, and no more than first_burst_size. we don't use <= to 2603 account for the "regularly scheduled" send call. of course 2604 that makes it more a "max_outstanding_ than a 2605 "first_burst_size" but for now we won't fix the names. also, 2606 I suspect the extra check against < first_burst_size is 2607 redundant since later I expect to make sure that request_cwnd 2608 can never get larger than first_burst_size, but just at the 2609 moment I'm feeling like a belt and suspenders kind of 2610 programmer. raj 2006-01-30 */ 2611 while ((first_burst_size > 0) && 2612 (requests_outstanding < request_cwnd) && 2613 (requests_outstanding < first_burst_size)) { 2614 if (debug) { 2615 fprintf(where, 2616 "injecting, req_outstndng %d req_cwnd %d burst %d\n", 2617 requests_outstanding, 2618 request_cwnd, 2619 first_burst_size); 2620 } 2621 if ((len = send(send_socket, 2622 send_ring->buffer_ptr, 2623 req_size, 2624 0)) != req_size) { 2625 /* we should never hit the end of the test in the first burst */ 2626 perror("send_sdp_rr: initial burst data send error"); 2627 exit(-1); 2628 } 2629 requests_outstanding += 1; 2630 } 2631 2632#endif /* WANT_FIRST_BURST */ 2633 2634#ifdef WANT_HISTOGRAM 2635 if (verbosity > 1) { 2636 /* timestamp just before our call to send, and then again just 2637 after the receive raj 8/94 */ 2638 /* but only if we are actually going to display one. raj 2639 2007-02-07 */ 2640 2641 HIST_timestamp(&time_one); 2642 } 2643#endif /* WANT_HISTOGRAM */ 2644 2645 if ((len = send(send_socket, 2646 send_ring->buffer_ptr, 2647 req_size, 2648 0)) != req_size) { 2649 if (SOCKET_EINTR(len) || (errno == 0)) { 2650 /* we hit the end of a */ 2651 /* timed test. */ 2652 timed_out = 1; 2653 break; 2654 } 2655 perror("send_sdp_rr: data send error"); 2656 exit(1); 2657 } 2658 send_ring = send_ring->next; 2659 2660#ifdef WANT_FIRST_BURST 2661 requests_outstanding += 1; 2662#endif 2663 2664 /* receive the response */ 2665 rsp_bytes_left = rsp_size; 2666 temp_message_ptr = recv_ring->buffer_ptr; 2667 while(rsp_bytes_left > 0) { 2668 if((rsp_bytes_recvd=recv(send_socket, 2669 temp_message_ptr, 2670 rsp_bytes_left, 2671 0)) == SOCKET_ERROR) { 2672 if ( SOCKET_EINTR(rsp_bytes_recvd) ) { 2673 /* We hit the end of a timed test. */ 2674 timed_out = 1; 2675 break; 2676 } 2677 perror("send_sdp_rr: data recv error"); 2678 exit(1); 2679 } 2680 rsp_bytes_left -= rsp_bytes_recvd; 2681 temp_message_ptr += rsp_bytes_recvd; 2682 } 2683 recv_ring = recv_ring->next; 2684 2685#ifdef WANT_FIRST_BURST 2686 /* so, since we've gotten a response back, update the 2687 bookkeeping accordingly. there is one less request 2688 outstanding and we can put one more out there than before. */ 2689 requests_outstanding -= 1; 2690 if (request_cwnd < first_burst_size) { 2691 request_cwnd += 1; 2692 if (debug) { 2693 fprintf(where, 2694 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n", 2695 request_cwnd, 2696 first_burst_size, 2697 requests_outstanding); 2698 } 2699 } 2700#endif 2701 if (timed_out) { 2702 /* we may have been in a nested while loop - we need */ 2703 /* another call to break. */ 2704 break; 2705 } 2706 2707#ifdef WANT_HISTOGRAM 2708 if (verbosity > 1) { 2709 HIST_timestamp(&time_two); 2710 HIST_add(time_hist,delta_micro(&time_one,&time_two)); 2711 } 2712#endif /* WANT_HISTOGRAM */ 2713 2714#ifdef WANT_DEMO 2715 DEMO_RR_INTERVAL(1); 2716#endif 2717 2718#ifdef WANT_INTERVALS 2719 INTERVALS_WAIT(); 2720#endif /* WANT_INTERVALS */ 2721 2722 nummessages++; 2723 if (trans_remaining) { 2724 trans_remaining--; 2725 } 2726 2727 if (debug > 3) { 2728 if ((nummessages % 100) == 0) { 2729 fprintf(where, 2730 "Transaction %d completed\n", 2731 nummessages); 2732 fflush(where); 2733 } 2734 } 2735 } 2736 2737 /* At this point we used to call shutdown on the data socket to be 2738 sure all the data was delivered, but this was not germane in a 2739 request/response test, and it was causing the tests to "hang" 2740 when they were being controlled by time. So, I have replaced 2741 this shutdown call with a call to close that can be found later 2742 in the procedure. */ 2743 2744 /* this call will always give us the elapsed time for the test, 2745 and will also store-away the necessaries for cpu utilization */ 2746 2747 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 2748 /* measured? how long */ 2749 /* did we really run? */ 2750 2751 if (!no_control) { 2752 /* Get the statistics from the remote end. The remote will have 2753 calculated CPU utilization. If it wasn't supposed to care, it 2754 will return obvious values. */ 2755 2756 recv_response(); 2757 if (!netperf_response.content.serv_errno) { 2758 if (debug) 2759 fprintf(where,"remote results obtained\n"); 2760 } 2761 else { 2762 Set_errno(netperf_response.content.serv_errno); 2763 fprintf(where,"netperf: remote error %d", 2764 netperf_response.content.serv_errno); 2765 perror(""); 2766 fflush(where); 2767 exit(1); 2768 } 2769 } 2770 2771 /* We now calculate what our throughput was for the test. */ 2772 2773 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 2774 thruput = nummessages/elapsed_time; 2775 2776 if (local_cpu_usage || remote_cpu_usage) { 2777 /* We must now do a little math for service demand and cpu 2778 utilization for the system(s) Of course, some of the 2779 information might be bogus because there was no idle counter in 2780 the kernel(s). We need to make a note of this for the user's 2781 benefit... */ 2782 if (local_cpu_usage) { 2783 local_cpu_utilization = calc_cpu_util(0.0); 2784 /* since calc_service demand is doing ms/Kunit we will 2785 multiply the number of transaction by 1024 to get "good" 2786 numbers */ 2787 local_service_demand = calc_service_demand((double) nummessages*1024, 2788 0.0, 2789 0.0, 2790 0); 2791 } 2792 else { 2793 local_cpu_utilization = (float) -1.0; 2794 local_service_demand = (float) -1.0; 2795 } 2796 2797 if (remote_cpu_usage) { 2798 remote_cpu_utilization = sdp_rr_result->cpu_util; 2799 /* since calc_service demand is doing ms/Kunit we will 2800 multiply the number of transaction by 1024 to get "good" 2801 numbers */ 2802 remote_service_demand = calc_service_demand((double) nummessages*1024, 2803 0.0, 2804 remote_cpu_utilization, 2805 sdp_rr_result->num_cpus); 2806 } 2807 else { 2808 remote_cpu_utilization = (float) -1.0; 2809 remote_service_demand = (float) -1.0; 2810 } 2811 2812 } 2813 else { 2814 /* we were not measuring cpu, for the confidence stuff, we */ 2815 /* should make it -1.0 */ 2816 local_cpu_utilization = (float) -1.0; 2817 local_service_demand = (float) -1.0; 2818 remote_cpu_utilization = (float) -1.0; 2819 remote_service_demand = (float) -1.0; 2820 } 2821 2822 /* at this point, we want to calculate the confidence information. 2823 if debugging is on, calculate_confidence will print-out the 2824 parameters we pass it */ 2825 2826 calculate_confidence(confidence_iteration, 2827 elapsed_time, 2828 thruput, 2829 local_cpu_utilization, 2830 remote_cpu_utilization, 2831 local_service_demand, 2832 remote_service_demand); 2833 2834 2835 confidence_iteration++; 2836 2837 /* we are now done with the socket, so close it */ 2838 close(send_socket); 2839 2840 } 2841 2842 retrieve_confident_values(&elapsed_time, 2843 &thruput, 2844 &local_cpu_utilization, 2845 &remote_cpu_utilization, 2846 &local_service_demand, 2847 &remote_service_demand); 2848 2849 /* We are now ready to print all the information. If the user has 2850 specified zero-level verbosity, we will just print the local 2851 service demand, or the remote service demand. If the user has 2852 requested verbosity level 1, he will get the basic "streamperf" 2853 numbers. If the user has specified a verbosity of greater than 1, 2854 we will display a veritable plethora of background information 2855 from outside of this block as it it not cpu_measurement 2856 specific... */ 2857 2858 if (confidence < 0) { 2859 /* we did not hit confidence, but were we asked to look for it? */ 2860 if (iteration_max > 1) { 2861 display_confidence(); 2862 } 2863 } 2864 2865 if (local_cpu_usage || remote_cpu_usage) { 2866 local_cpu_method = format_cpu_method(cpu_method); 2867 remote_cpu_method = format_cpu_method(sdp_rr_result->cpu_method); 2868 2869 switch (verbosity) { 2870 case 0: 2871 if (local_cpu_usage) { 2872 fprintf(where, 2873 cpu_fmt_0, 2874 local_service_demand, 2875 local_cpu_method, 2876 ((print_headers) || 2877 (result_brand == NULL)) ? "" : result_brand); 2878 } 2879 else { 2880 fprintf(where, 2881 cpu_fmt_0, 2882 remote_service_demand, 2883 remote_cpu_method, 2884 ((print_headers) || 2885 (result_brand == NULL)) ? "" : result_brand); 2886 } 2887 break; 2888 case 1: 2889 case 2: 2890 if (print_headers) { 2891 fprintf(where, 2892 cpu_title, 2893 local_cpu_method, 2894 remote_cpu_method); 2895 } 2896 2897 fprintf(where, 2898 cpu_fmt_1_line_1, /* the format string */ 2899 lss_size, /* local sendbuf size */ 2900 lsr_size, 2901 req_size, /* how large were the requests */ 2902 rsp_size, /* guess */ 2903 elapsed_time, /* how long was the test */ 2904 thruput, 2905 local_cpu_utilization, /* local cpu */ 2906 remote_cpu_utilization, /* remote cpu */ 2907 local_service_demand, /* local service demand */ 2908 remote_service_demand, /* remote service demand */ 2909 ((print_headers) || 2910 (result_brand == NULL)) ? "" : result_brand); 2911 fprintf(where, 2912 cpu_fmt_1_line_2, 2913 rss_size, 2914 rsr_size); 2915 break; 2916 } 2917 } 2918 else { 2919 /* The tester did not wish to measure service demand. */ 2920 2921 switch (verbosity) { 2922 case 0: 2923 fprintf(where, 2924 tput_fmt_0, 2925 thruput, 2926 ((print_headers) || 2927 (result_brand == NULL)) ? "" : result_brand); 2928 break; 2929 case 1: 2930 case 2: 2931 if (print_headers) { 2932 fprintf(where,tput_title,format_units()); 2933 } 2934 2935 fprintf(where, 2936 tput_fmt_1_line_1, /* the format string */ 2937 lss_size, 2938 lsr_size, 2939 req_size, /* how large were the requests */ 2940 rsp_size, /* how large were the responses */ 2941 elapsed_time, /* how long did it take */ 2942 thruput, 2943 ((print_headers) || 2944 (result_brand == NULL)) ? "" : result_brand); 2945 fprintf(where, 2946 tput_fmt_1_line_2, 2947 rss_size, /* remote recvbuf size */ 2948 rsr_size); 2949 2950 break; 2951 } 2952 } 2953 2954 /* it would be a good thing to include information about some of the */ 2955 /* other parameters that may have been set for this test, but at the */ 2956 /* moment, I do not wish to figure-out all the formatting, so I will */ 2957 /* just put this comment here to help remind me that it is something */ 2958 /* that should be done at a later time. */ 2959 2960 /* how to handle the verbose information in the presence of */ 2961 /* confidence intervals is yet to be determined... raj 11/94 */ 2962 if (verbosity > 1) { 2963 /* The user wanted to know it all, so we will give it to him. */ 2964 /* This information will include as much as we can find about */ 2965 /* SDP statistics, the alignments of the sends and receives */ 2966 /* and all that sort of rot... */ 2967 2968 fprintf(where, 2969 ksink_fmt, 2970 local_send_align, 2971 remote_recv_offset, 2972 local_send_offset, 2973 remote_recv_offset); 2974 2975#ifdef WANT_HISTOGRAM 2976 fprintf(where,"\nHistogram of request/response times\n"); 2977 fflush(where); 2978 HIST_report(time_hist); 2979#endif /* WANT_HISTOGRAM */ 2980 2981 } 2982 2983} 2984 /* this routine implements the receive (netserver) side of a SDP_RR */ 2985 /* test */ 2986void 2987recv_sdp_rr() 2988{ 2989 2990 struct ring_elt *send_ring; 2991 struct ring_elt *recv_ring; 2992 2993 struct addrinfo *local_res; 2994 char local_name[BUFSIZ]; 2995 char port_buffer[PORTBUFSIZE]; 2996 2997 struct sockaddr_in myaddr_in, 2998 peeraddr_in; 2999 SOCKET s_listen,s_data; 3000 netperf_socklen_t addrlen; 3001 char *temp_message_ptr; 3002 int trans_received; 3003 int trans_remaining; 3004 int bytes_sent; 3005 int request_bytes_recvd; 3006 int request_bytes_remaining; 3007 int timed_out = 0; 3008 int sock_closed = 0; 3009 float elapsed_time; 3010 3011 struct sdp_rr_request_struct *sdp_rr_request; 3012 struct sdp_rr_response_struct *sdp_rr_response; 3013 struct sdp_rr_results_struct *sdp_rr_results; 3014 3015 sdp_rr_request = 3016 (struct sdp_rr_request_struct *)netperf_request.content.test_specific_data; 3017 sdp_rr_response = 3018 (struct sdp_rr_response_struct *)netperf_response.content.test_specific_data; 3019 sdp_rr_results = 3020 (struct sdp_rr_results_struct *)netperf_response.content.test_specific_data; 3021 3022 if (debug) { 3023 fprintf(where,"netserver: recv_sdp_rr: entered...\n"); 3024 fflush(where); 3025 } 3026 3027 /* We want to set-up the listen socket with all the desired */ 3028 /* parameters and then let the initiator know that all is ready. If */ 3029 /* socket size defaults are to be used, then the initiator will have */ 3030 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 3031 /* send-back what they are. If that information cannot be determined, */ 3032 /* then we send-back -1's for the sizes. If things go wrong for any */ 3033 /* reason, we will drop back ten yards and punt. */ 3034 3035 /* If anything goes wrong, we want the remote to know about it. It */ 3036 /* would be best if the error that the remote reports to the user is */ 3037 /* the actual error we encountered, rather than some bogus unexpected */ 3038 /* response type message. */ 3039 3040 if (debug) { 3041 fprintf(where,"recv_sdp_rr: setting the response type...\n"); 3042 fflush(where); 3043 } 3044 3045 netperf_response.content.response_type = SDP_RR_RESPONSE; 3046 3047 if (debug) { 3048 fprintf(where,"recv_sdp_rr: the response type is set...\n"); 3049 fflush(where); 3050 } 3051 3052 /* allocate the recv and send rings with the requested alignments */ 3053 /* and offsets. raj 7/94 */ 3054 if (debug) { 3055 fprintf(where,"recv_sdp_rr: requested recv alignment of %d offset %d\n", 3056 sdp_rr_request->recv_alignment, 3057 sdp_rr_request->recv_offset); 3058 fprintf(where,"recv_sdp_rr: requested send alignment of %d offset %d\n", 3059 sdp_rr_request->send_alignment, 3060 sdp_rr_request->send_offset); 3061 fflush(where); 3062 } 3063 3064 /* at some point, these need to come to us from the remote system */ 3065 if (send_width == 0) send_width = 1; 3066 if (recv_width == 0) recv_width = 1; 3067 3068 send_ring = allocate_buffer_ring(send_width, 3069 sdp_rr_request->response_size, 3070 sdp_rr_request->send_alignment, 3071 sdp_rr_request->send_offset); 3072 3073 recv_ring = allocate_buffer_ring(recv_width, 3074 sdp_rr_request->request_size, 3075 sdp_rr_request->recv_alignment, 3076 sdp_rr_request->recv_offset); 3077 3078 3079 /* Grab a socket to listen on, and then listen on it. */ 3080 3081 if (debug) { 3082 fprintf(where,"recv_sdp_rr: grabbing a socket...\n"); 3083 fflush(where); 3084 } 3085 3086 /* create_data_socket expects to find some things in the global */ 3087 /* variables, so set the globals based on the values in the request. */ 3088 /* once the socket has been created, we will set the response values */ 3089 /* based on the updated value of those globals. raj 7/94 */ 3090 lss_size_req = sdp_rr_request->send_buf_size; 3091 lsr_size_req = sdp_rr_request->recv_buf_size; 3092 loc_nodelay = sdp_rr_request->no_delay; 3093 loc_rcvavoid = sdp_rr_request->so_rcvavoid; 3094 loc_sndavoid = sdp_rr_request->so_sndavoid; 3095 3096 set_hostname_and_port(local_name, 3097 port_buffer, 3098 nf_to_af(sdp_rr_request->ipfamily), 3099 sdp_rr_request->port); 3100 3101 local_res = complete_addrinfo(local_name, 3102 local_name, 3103 port_buffer, 3104 nf_to_af(sdp_rr_request->ipfamily), 3105 SOCK_STREAM, 3106 IPPROTO_TCP, 3107 0); 3108 3109 /* fake things out by changing local_res->ai_family to AF_INET_SDP */ 3110 local_res->ai_family = AF_INET_SDP; 3111 local_res->ai_protocol = 0; 3112 s_listen = create_data_socket(local_res); 3113 3114 if (s_listen == INVALID_SOCKET) { 3115 netperf_response.content.serv_errno = errno; 3116 send_response(); 3117 3118 exit(1); 3119 } 3120 3121 3122#ifdef WIN32 3123 /* The test timer can fire during operations on the listening socket, 3124 so to make the start_timer below work we have to move 3125 it to close s_listen while we are blocked on accept. */ 3126 win_kludge_socket2 = s_listen; 3127#endif 3128 3129 3130 /* Now, let's set-up the socket to listen for connections */ 3131 if (listen(s_listen, 5) == SOCKET_ERROR) { 3132 netperf_response.content.serv_errno = errno; 3133 close(s_listen); 3134 send_response(); 3135 3136 exit(1); 3137 } 3138 3139 3140 /* now get the port number assigned by the system */ 3141 addrlen = sizeof(myaddr_in); 3142 if (getsockname(s_listen, 3143 (struct sockaddr *)&myaddr_in, 3144 &addrlen) == SOCKET_ERROR) { 3145 netperf_response.content.serv_errno = errno; 3146 close(s_listen); 3147 send_response(); 3148 3149 exit(1); 3150 } 3151 3152 /* Now myaddr_in contains the port and the internet address this is */ 3153 /* returned to the sender also implicitly telling the sender that the */ 3154 /* socket buffer sizing has been done. */ 3155 3156 sdp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 3157 netperf_response.content.serv_errno = 0; 3158 3159 /* But wait, there's more. If the initiator wanted cpu measurements, */ 3160 /* then we must call the calibrate routine, which will return the max */ 3161 /* rate back to the initiator. If the CPU was not to be measured, or */ 3162 /* something went wrong with the calibration, we will return a 0.0 to */ 3163 /* the initiator. */ 3164 3165 sdp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 3166 sdp_rr_response->measure_cpu = 0; 3167 3168 if (sdp_rr_request->measure_cpu) { 3169 sdp_rr_response->measure_cpu = 1; 3170 sdp_rr_response->cpu_rate = calibrate_local_cpu(sdp_rr_request->cpu_rate); 3171 } 3172 3173 3174 /* before we send the response back to the initiator, pull some of */ 3175 /* the socket parms from the globals */ 3176 sdp_rr_response->send_buf_size = lss_size; 3177 sdp_rr_response->recv_buf_size = lsr_size; 3178 sdp_rr_response->no_delay = loc_nodelay; 3179 sdp_rr_response->so_rcvavoid = loc_rcvavoid; 3180 sdp_rr_response->so_sndavoid = loc_sndavoid; 3181 sdp_rr_response->test_length = sdp_rr_request->test_length; 3182 send_response(); 3183 3184 addrlen = sizeof(peeraddr_in); 3185 3186 if ((s_data = accept(s_listen, 3187 (struct sockaddr *)&peeraddr_in, 3188 &addrlen)) == INVALID_SOCKET) { 3189 /* Let's just punt. The remote will be given some information */ 3190 close(s_listen); 3191 3192 exit(1); 3193 } 3194 3195#ifdef KLUDGE_SOCKET_OPTIONS 3196 /* this is for those systems which *INCORRECTLY* fail to pass */ 3197 /* attributes across an accept() call. Including this goes against */ 3198 /* my better judgement :( raj 11/95 */ 3199 3200 kludge_socket_options(s_data); 3201 3202#endif /* KLUDGE_SOCKET_OPTIONS */ 3203 3204#ifdef WIN32 3205 /* this is used so the timer thread can close the socket out from */ 3206 /* under us, which to date is the easiest/cleanest/least */ 3207 /* Windows-specific way I can find to force the winsock calls to */ 3208 /* return WSAEINTR with the test is over. anything that will run on */ 3209 /* 95 and NT and is closer to what netperf expects from Unix signals */ 3210 /* and such would be appreciated raj 1/96 */ 3211 win_kludge_socket = s_data; 3212#endif /* WIN32 */ 3213 3214 if (debug) { 3215 fprintf(where,"recv_sdp_rr: accept completes on the data connection.\n"); 3216 fflush(where); 3217 } 3218 3219 /* Now it's time to start receiving data on the connection. We will */ 3220 /* first grab the apropriate counters and then start grabbing. */ 3221 3222 cpu_start(sdp_rr_request->measure_cpu); 3223 3224 /* The loop will exit when we hit the end of the test time, or when */ 3225 /* we have exchanged the requested number of transactions. */ 3226 3227 if (sdp_rr_request->test_length > 0) { 3228 times_up = 0; 3229 trans_remaining = 0; 3230 start_timer(sdp_rr_request->test_length + PAD_TIME); 3231 } 3232 else { 3233 times_up = 1; 3234 trans_remaining = sdp_rr_request->test_length * -1; 3235 } 3236 3237 trans_received = 0; 3238 3239 while ((!times_up) || (trans_remaining > 0)) { 3240 temp_message_ptr = recv_ring->buffer_ptr; 3241 request_bytes_remaining = sdp_rr_request->request_size; 3242 while(request_bytes_remaining > 0) { 3243 if((request_bytes_recvd=recv(s_data, 3244 temp_message_ptr, 3245 request_bytes_remaining, 3246 0)) == SOCKET_ERROR) { 3247 if (SOCKET_EINTR(request_bytes_recvd)) 3248 { 3249 timed_out = 1; 3250 break; 3251 } 3252 3253 netperf_response.content.serv_errno = errno; 3254 send_response(); 3255 exit(1); 3256 } 3257 else if( request_bytes_recvd == 0 ) { 3258 if (debug) { 3259 fprintf(where,"zero is my hero\n"); 3260 fflush(where); 3261 } 3262 sock_closed = 1; 3263 break; 3264 } 3265 else { 3266 request_bytes_remaining -= request_bytes_recvd; 3267 temp_message_ptr += request_bytes_recvd; 3268 } 3269 } 3270 3271 recv_ring = recv_ring->next; 3272 3273 if ((timed_out) || (sock_closed)) { 3274 /* we hit the end of the test based on time - or the socket 3275 closed on us along the way. bail out of here now... */ 3276 if (debug) { 3277 fprintf(where,"yo5\n"); 3278 fflush(where); 3279 } 3280 break; 3281 } 3282 3283 /* Now, send the response to the remote */ 3284 if((bytes_sent=send(s_data, 3285 send_ring->buffer_ptr, 3286 sdp_rr_request->response_size, 3287 0)) == SOCKET_ERROR) { 3288 if (SOCKET_EINTR(bytes_sent)) { 3289 /* the test timer has popped */ 3290 timed_out = 1; 3291 fprintf(where,"yo6\n"); 3292 fflush(where); 3293 break; 3294 } 3295 netperf_response.content.serv_errno = 992; 3296 send_response(); 3297 exit(1); 3298 } 3299 3300 send_ring = send_ring->next; 3301 3302 trans_received++; 3303 if (trans_remaining) { 3304 trans_remaining--; 3305 } 3306 } 3307 3308 3309 /* The loop now exits due to timeout or transaction count being */ 3310 /* reached */ 3311 3312 cpu_stop(sdp_rr_request->measure_cpu,&elapsed_time); 3313 3314 stop_timer(); 3315 3316 if (timed_out) { 3317 /* we ended the test by time, which was at least 2 seconds */ 3318 /* longer than we wanted to run. so, we want to subtract */ 3319 /* PAD_TIME from the elapsed_time. */ 3320 elapsed_time -= PAD_TIME; 3321 } 3322 3323 /* send the results to the sender */ 3324 3325 if (debug) { 3326 fprintf(where, 3327 "recv_sdp_rr: got %d transactions\n", 3328 trans_received); 3329 fflush(where); 3330 } 3331 3332 sdp_rr_results->bytes_received = (trans_received * 3333 (sdp_rr_request->request_size + 3334 sdp_rr_request->response_size)); 3335 sdp_rr_results->trans_received = trans_received; 3336 sdp_rr_results->elapsed_time = elapsed_time; 3337 sdp_rr_results->cpu_method = cpu_method; 3338 sdp_rr_results->num_cpus = lib_num_loc_cpus; 3339 if (sdp_rr_request->measure_cpu) { 3340 sdp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 3341 } 3342 3343 if (debug) { 3344 fprintf(where, 3345 "recv_sdp_rr: test complete, sending results.\n"); 3346 fflush(where); 3347 } 3348 3349 /* we are now done with the sockets */ 3350 close(s_data); 3351 close(s_listen); 3352 3353 send_response(); 3354 3355} 3356 3357 3358 3359void 3360print_sdp_usage() 3361{ 3362 3363 printf("%s",sdp_usage); 3364 exit(1); 3365 3366} 3367void 3368scan_sdp_args(argc, argv) 3369 int argc; 3370 char *argv[]; 3371 3372{ 3373 3374#define SOCKETS_ARGS "b:DhH:I:L:m:M:P:r:s:S:V46" 3375 3376 extern char *optarg; /* pointer to option string */ 3377 3378 int c; 3379 3380 char 3381 arg1[BUFSIZ], /* argument holders */ 3382 arg2[BUFSIZ]; 3383 3384 if (no_control) { 3385 fprintf(where, 3386 "The SDP tests do not know how to deal with no control tests\n"); 3387 exit(-1); 3388 } 3389 3390 strncpy(local_data_port,"0",sizeof(local_data_port)); 3391 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 3392 3393 /* Go through all the command line arguments and break them */ 3394 /* out. For those options that take two parms, specifying only */ 3395 /* the first will set both to that value. Specifying only the */ 3396 /* second will leave the first untouched. To change only the */ 3397 /* first, use the form "first," (see the routine break_args.. */ 3398 3399 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) { 3400 switch (c) { 3401 case '?': 3402 case '4': 3403 remote_data_family = AF_INET; 3404 local_data_family = AF_INET; 3405 break; 3406 case '6': 3407#if defined(AF_INET6) 3408 remote_data_family = AF_INET6; 3409 local_data_family = AF_INET6; 3410#else 3411 fprintf(stderr, 3412 "This netperf was not compiled on an IPv6 capable host!\n"); 3413 fflush(stderr); 3414 exit(-1); 3415#endif 3416 break; 3417 case 'h': 3418 print_sdp_usage(); 3419 exit(1); 3420 case 'b': 3421#ifdef WANT_FIRST_BURST 3422 first_burst_size = atoi(optarg); 3423#else /* WANT_FIRST_BURST */ 3424 printf("Initial request burst functionality not compiled-in!\n"); 3425#endif /* WANT_FIRST_BURST */ 3426 break; 3427 case 'D': 3428 /* set the nodelay flag */ 3429 loc_nodelay = 1; 3430 rem_nodelay = 1; 3431 break; 3432 case 'H': 3433 break_args_explicit(optarg,arg1,arg2); 3434 if (arg1[0]) { 3435 /* make sure we leave room for the NULL termination boys and 3436 girls. raj 2005-02-82 */ 3437 remote_data_address = malloc(strlen(arg1)+1); 3438 strncpy(remote_data_address,arg1,strlen(arg1)); 3439 } 3440 if (arg2[0]) 3441 remote_data_family = parse_address_family(arg2); 3442 break; 3443 case 'L': 3444 break_args_explicit(optarg,arg1,arg2); 3445 if (arg1[0]) { 3446 /* make sure we leave room for the NULL termination boys and 3447 girls. raj 2005-02-82 */ 3448 local_data_address = malloc(strlen(arg1)+1); 3449 strncpy(local_data_address,arg1,strlen(arg1)); 3450 } 3451 if (arg2[0]) 3452 local_data_family = parse_address_family(arg2); 3453 break; 3454 case 'P': 3455 /* set the local and remote data port numbers for the tests to 3456 allow them to run through those blankety blank end-to-end 3457 breaking firewalls. raj 2004-06-15 */ 3458 break_args(optarg,arg1,arg2); 3459 if (arg1[0]) 3460 strncpy(local_data_port,arg1,sizeof(local_data_port)); 3461 if (arg2[0]) 3462 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 3463 break; 3464 case 's': 3465 /* set local socket sizes */ 3466 break_args(optarg,arg1,arg2); 3467 if (arg1[0]) 3468 lss_size_req = convert(arg1); 3469 if (arg2[0]) 3470 lsr_size_req = convert(arg2); 3471 break; 3472 case 'S': 3473 /* set remote socket sizes */ 3474 break_args(optarg,arg1,arg2); 3475 if (arg1[0]) 3476 rss_size_req = convert(arg1); 3477 if (arg2[0]) 3478 rsr_size_req = convert(arg2); 3479 break; 3480 case 'r': 3481 /* set the request/response sizes */ 3482 break_args(optarg,arg1,arg2); 3483 if (arg1[0]) 3484 req_size = convert(arg1); 3485 if (arg2[0]) 3486 rsp_size = convert(arg2); 3487 break; 3488 case 'm': 3489 /* set size of the buffer for each sent message */ 3490 send_size = convert(optarg); 3491 break; 3492 case 'M': 3493 /* set the size of the buffer for each received message */ 3494 recv_size = convert(optarg); 3495 break; 3496 case 't': 3497 /* set the test name */ 3498 strcpy(test_name,optarg); 3499 break; 3500 case 'W': 3501 /* set the "width" of the user space data */ 3502 /* buffer. This will be the number of */ 3503 /* send_size buffers malloc'd in the */ 3504 /* *_STREAM test. It may be enhanced to set */ 3505 /* both send and receive "widths" but for now */ 3506 /* it is just the sending *_STREAM. */ 3507 send_width = convert(optarg); 3508 break; 3509 case 'V': 3510 /* we want to do copy avoidance and will set */ 3511 /* it for everything, everywhere, if we really */ 3512 /* can. of course, we don't know anything */ 3513 /* about the remote... */ 3514#ifdef SO_SND_COPYAVOID 3515 loc_sndavoid = 1; 3516#else 3517 loc_sndavoid = 0; 3518 printf("Local send copy avoidance not available.\n"); 3519#endif 3520#ifdef SO_RCV_COPYAVOID 3521 loc_rcvavoid = 1; 3522#else 3523 loc_rcvavoid = 0; 3524 printf("Local recv copy avoidance not available.\n"); 3525#endif 3526 rem_sndavoid = 1; 3527 rem_rcvavoid = 1; 3528 break; 3529 case 'N': 3530 /* this opton allows the user to set the number of 3531 * messages to send. This in effect modifies the test 3532 * time. If we know the message size, then the we can 3533 * express the test time as message_size * number_messages 3534 */ 3535 msg_count = convert (optarg); 3536 if (msg_count > 0) 3537 test_time = 0; 3538 break; 3539 case 'B': 3540 non_block = 1; 3541 break; 3542 case 'T': 3543 num_associations = atoi(optarg); 3544 if (num_associations <= 1) { 3545 printf("Number of SDP associations must be >= 1\n"); 3546 exit(1); 3547 } 3548 break; 3549 }; 3550 } 3551} 3552 3553#endif /* WANT_SDP */ 3554