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