1 #ifndef lint 2 char nettest_sctp[]="\ 3 @(#)nettest_sctp.c (c) Copyright 2005-2012 Hewlett-Packard Co. Version 2.6.0"; 4 #else 5 #define DIRTY 6 #define WANT_HISTOGRAM 7 #define WANT_INTERVALS 8 #endif /* lint */ 9 10 /****************************************************************/ 11 /* */ 12 /* nettest_sctp.c */ 13 /* */ 14 /* */ 15 /* scan_sctp_args() get the sctp command line args */ 16 /* */ 17 /* the actual test routines... */ 18 /* */ 19 /* send_sctp_stream() perform a sctp stream test */ 20 /* recv_sctp_stream() */ 21 /* send_sctp_rr() perform a sctp request/response */ 22 /* recv_sctp_rr() */ 23 /* send_sctp_stream_udp() perform a sctp request/response */ 24 /* recv_sctp_stream_upd() using UDP style API */ 25 /* send_sctp_rr_udp() perform a sctp request/response */ 26 /* recv_sctp_rr_upd() using UDP style API */ 27 /* */ 28 /* relies on create_data_socket in nettest_bsd.c */ 29 /****************************************************************/ 30 31 #if HAVE_CONFIG_H 32 # include <config.h> 33 #endif 34 35 #if defined(WANT_SCTP) 36 37 #include <sys/types.h> 38 #include <fcntl.h> 39 #include <errno.h> 40 #include <signal.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <time.h> 44 #ifdef NOSTDLIBH 45 #include <malloc.h> 46 #else /* NOSTDLIBH */ 47 #include <stdlib.h> 48 #endif /* NOSTDLIBH */ 49 50 #if !defined(__VMS) 51 #include <sys/ipc.h> 52 #endif /* !defined(__VMS) */ 53 #include <unistd.h> 54 #include <sys/types.h> 55 #include <sys/socket.h> 56 #include <netinet/in.h> 57 #include <netinet/tcp.h> 58 #include <netinet/sctp.h> 59 #include <arpa/inet.h> 60 #include <netdb.h> 61 62 /* would seem that not all sctp.h files define a MSG_EOF, but that 63 MSG_EOF can be the same as MSG_FIN so lets work with that 64 assumption. initial find by Jon Pedersen. raj 2006-02-01 */ 65 #ifndef MSG_EOF 66 #ifdef MSG_FIN 67 #define MSG_EOF MSG_FIN 68 #else 69 #error Must have either MSG_EOF or MSG_FIN defined 70 #endif 71 #endif 72 73 #include "netlib.h" 74 #include "netsh.h" 75 /* get some of the functions from nettest_bsd.c */ 76 #include "nettest_bsd.h" 77 #include "nettest_sctp.h" 78 79 #ifdef WANT_HISTOGRAM 80 #ifdef __sgi 81 #include <sys/time.h> 82 #endif /* __sgi */ 83 #include "hist.h" 84 #endif /* WANT_HISTOGRAM */ 85 86 #ifdef WANT_FIRST_BURST 87 extern int first_burst_size; 88 #endif /* WANT_FIRST_BURST */ 89 90 91 93 /* these variables are specific to SCTP tests. declare */ 94 /* them static to make them global only to this file. */ 95 96 static int 97 msg_count = 0, /* number of messages to transmit on association */ 98 non_block = 0, /* default to blocking sockets */ 99 num_associations = 1; /* number of associations on the endpoint */ 100 101 static int confidence_iteration; 102 static char local_cpu_method; 103 static char remote_cpu_method; 104 105 #ifdef WANT_HISTOGRAM 106 static HIST time_hist; 107 #endif /* WANT_HISTOGRAM */ 108 109 110 char sctp_usage[] = "\n\ 111 Usage: netperf [global options] -- [test options] \n\ 112 \n\ 113 SCTP Sockets Test Options:\n\ 114 -b number Send number requests at the start of _RR tests\n\ 115 -D [L][,R] Set SCTP_NODELAY locally and/or remotely\n\ 116 -h Display this text\n\ 117 -H name,fam Use name (or IP) and family as target of data connection\n\ 118 -L name,fam Use name (or IP) and family as source of data connextion\n\ 119 -m bytes Set the size of each sent message\n\ 120 -M bytes Set the size of each received messages\n\ 121 -P local[,remote] Set the local/remote port for the data socket\n\ 122 -r req,[rsp] Set request/response sizes (_RR tests)\n\ 123 -s send[,recv] Set local socket send/recv buffer sizes\n\ 124 -S send[,recv] Set remote socket send/recv buffer sizes\n\ 125 -V Enable copy avoidance if supported\n\ 126 -N number Specifies the number of messages to send (_STREAM tests)\n\ 127 -B run the test in non-blocking mode\n\ 128 -T number Number of associations to create (_MANY tests)\n\ 129 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\ 130 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\ 131 \n\ 132 For those options taking two parms, at least one must be specified;\n\ 133 specifying one value without a comma will set both parms to that\n\ 134 value, specifying a value with a leading comma will set just the second\n\ 135 parm, a value with a trailing comma will set just the first. To set\n\ 136 each parm to unique values, specify both and separate them with a\n\ 137 comma.\n"; 138 139 140 /* This routine is intended to retrieve interesting aspects of tcp */ 142 /* for the data connection. at first, it attempts to retrieve the */ 143 /* maximum segment size. later, it might be modified to retrieve */ 144 /* other information, but it must be information that can be */ 145 /* retrieved quickly as it is called during the timing of the test. */ 146 /* for that reason, a second routine may be created that can be */ 147 /* called outside of the timing loop */ 148 static 149 void 150 get_sctp_info( int socket, int *mss ) 151 { 152 153 socklen_t sock_opt_len; 154 155 if (sctp_opt_info(socket, 156 0, 157 SCTP_MAXSEG, 158 mss, 159 &sock_opt_len) < 0) { 160 lss_size = -1; 161 } 162 } 163 164 165 static 167 void 168 sctp_enable_events( int socket, int ev_mask ) 169 { 170 struct sctp_event_subscribe ev; 171 172 bzero(&ev, sizeof(ev)); 173 174 if (ev_mask & SCTP_SNDRCV_INFO_EV) 175 ev.sctp_data_io_event = 1; 176 177 if (ev_mask & SCTP_ASSOC_CHANGE_EV) 178 ev.sctp_association_event = 1; 179 180 if (ev_mask & SCTP_PEERADDR_CHANGE_EV) 181 ev.sctp_address_event = 1; 182 183 if (ev_mask & SCTP_SND_FAILED_EV) 184 ev.sctp_send_failure_event = 1; 185 186 if (ev_mask & SCTP_REMOTE_ERROR_EV) 187 ev.sctp_peer_error_event = 1; 188 189 if (ev_mask & SCTP_SHUTDOWN_EV) 190 ev.sctp_shutdown_event = 1; 191 192 if (ev_mask & SCTP_PD_EV) 193 ev.sctp_partial_delivery_event = 1; 194 195 if (ev_mask & SCTP_ADAPT_EV) 196 #ifdef HAVE_SCTP_ADAPTATION_LAYER_EVENT 197 ev.sctp_adaptation_layer_event = 1; 198 #else 199 ev.sctp_adaption_layer_event = 1; 200 #endif 201 202 if (setsockopt(socket, 203 IPPROTO_SCTP, 204 #ifdef SCTP_EVENTS 205 SCTP_EVENTS, 206 #else 207 SCTP_SET_EVENTS, 208 #endif 209 (const char*)&ev, 210 sizeof(ev)) != 0 ) { 211 fprintf(where, 212 "sctp_enable_event: could not set sctp events errno %d\n", 213 errno); 214 fflush(where); 215 exit(1); 216 } 217 } 218 219 221 static 222 sctp_disposition_t 223 sctp_process_event( int socket, void *buf ) 224 { 225 226 struct sctp_assoc_change *sac; 227 struct sctp_send_failed *ssf; 228 struct sctp_paddr_change *spc; 229 struct sctp_remote_error *sre; 230 union sctp_notification *snp; 231 232 snp = buf; 233 234 switch (snp->sn_header.sn_type) { 235 case SCTP_ASSOC_CHANGE: 236 if (debug) { 237 fprintf(where, "\tSCTP_ASSOC_CHANGE event, type:"); 238 fflush(where); 239 } 240 sac = &snp->sn_assoc_change; 241 switch (sac->sac_type) { 242 case SCTP_COMM_UP: 243 if (debug) { 244 fprintf(where, " SCTP_COMM_UP\n"); 245 fflush(where); 246 } 247 break; 248 case SCTP_RESTART: 249 if (debug) { 250 fprintf(where, " SCTP_RESTART\n"); 251 fflush(where); 252 } 253 break; 254 case SCTP_CANT_STR_ASSOC: 255 if (debug) { 256 fprintf(where, " SCTP_CANT_STR_ASSOC\n"); 257 fflush(where); 258 } 259 break; /* FIXME ignore above status changes */ 260 case SCTP_COMM_LOST: 261 if (debug) { 262 fprintf(where, " SCTP_COMM_LOST\n"); 263 fflush(where); 264 } 265 return SCTP_CLOSE; 266 case SCTP_SHUTDOWN_COMP: 267 if (debug) { 268 fprintf(where, " SCTP_SHUTDOWN_COMPLETE\n"); 269 fflush(where); 270 } 271 return SCTP_CLOSE; 272 break; 273 } 274 275 case SCTP_SEND_FAILED: 276 if (debug) { 277 fprintf(where, "\tSCTP_SEND_FAILED event\n"); 278 fflush(where); 279 } 280 ssf = &snp->sn_send_failed; 281 break; /* FIXME ??? ignore this for now */ 282 283 case SCTP_PEER_ADDR_CHANGE: 284 if (debug) { 285 fprintf(where, "\tSCTP_PEER_ADDR_CHANGE event\n"); 286 fflush(where); 287 } 288 spc = &snp->sn_paddr_change; 289 break; /* FIXME ??? ignore this for now */ 290 291 case SCTP_REMOTE_ERROR: 292 if (debug) { 293 fprintf(where, "\tSCTP_REMOTE_ERROR event\n"); 294 fflush(where); 295 } 296 sre = &snp->sn_remote_error; 297 break; /* FIXME ??? ignore this for now */ 298 case SCTP_SHUTDOWN_EVENT: 299 if (debug) { 300 fprintf(where, "\tSCTP_SHUTDOWN event\n"); 301 fflush(where); 302 } 303 return SCTP_CLOSE; 304 default: 305 fprintf(where, "unknown type: %hu\n", snp->sn_header.sn_type); 306 fflush(where); 307 break; 308 } 309 return SCTP_OK; 310 } 311 312 313 315 /* This routine implements the SCTP unidirectional data transfer test */ 316 /* (a.k.a. stream) for the sockets interface. It receives its */ 317 /* parameters via global variables from the shell and writes its */ 318 /* output to the standard output. */ 319 320 321 void 322 send_sctp_stream( char remote_host[] ) 323 { 324 325 char *tput_title = "\ 326 Recv Send Send \n\ 327 Socket Socket Message Elapsed \n\ 328 Size Size Size Time Throughput \n\ 329 bytes bytes bytes secs. %s/sec \n\n"; 330 331 char *tput_fmt_0 = 332 "%7.2f\n"; 333 334 char *tput_fmt_1 = 335 "%6d %6d %6d %-6.2f %7.2f \n"; 336 337 char *cpu_title = "\ 338 Recv Send Send Utilization Service Demand\n\ 339 Socket Socket Message Elapsed Send Recv Send Recv\n\ 340 Size Size Size Time Throughput local remote local remote\n\ 341 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 342 343 char *cpu_fmt_0 = 344 "%6.3f %c\n"; 345 346 char *cpu_fmt_1 = 347 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 348 349 char *ksink_fmt = "\n\ 350 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 351 Local Remote Local Remote Xfered Per Per\n\ 352 Send Recv Send Recv Send (avg) Recv (avg)\n\ 353 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 354 355 char *ksink_fmt2 = "\n\ 356 Maximum\n\ 357 Segment\n\ 358 Size (bytes)\n\ 359 %6d\n"; 360 361 362 float elapsed_time; 363 364 #ifdef WANT_INTERVALS 365 int interval_count; 366 sigset_t signal_set; 367 #endif 368 369 /* what we want is to have a buffer space that is at least one */ 370 /* send-size greater than our send window. this will insure that we */ 371 /* are never trying to re-use a buffer that may still be in the hands */ 372 /* of the transport. This buffer will be malloc'd after we have found */ 373 /* the size of the local senc socket buffer. We will want to deal */ 374 /* with alignment and offset concerns as well. */ 375 376 #ifdef DIRTY 377 int *message_int_ptr; 378 #endif 379 380 struct ring_elt *send_ring; 381 382 int len; 383 unsigned int nummessages = 0; 384 int send_socket; 385 int bytes_remaining; 386 int sctp_mss; 387 int timed_out; 388 389 /* with links like fddi, one can send > 32 bits worth of bytes */ 390 /* during a test... ;-) at some point, this should probably become a */ 391 /* 64bit integral type, but those are not entirely common yet */ 392 double bytes_sent = 0.0; 393 394 #ifdef DIRTY 395 int i; 396 #endif /* DIRTY */ 397 398 float local_cpu_utilization; 399 float local_service_demand; 400 float remote_cpu_utilization; 401 float remote_service_demand; 402 403 double thruput; 404 405 struct addrinfo *remote_res; 406 struct addrinfo *local_res; 407 408 struct sctp_stream_request_struct *sctp_stream_request; 409 struct sctp_stream_response_struct *sctp_stream_response; 410 struct sctp_stream_results_struct *sctp_stream_result; 411 412 sctp_stream_request = 413 (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data; 414 sctp_stream_response = 415 (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data; 416 sctp_stream_result = 417 (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data; 418 419 #ifdef WANT_HISTOGRAM 420 time_hist = HIST_new_n(1); 421 #endif /* WANT_HISTOGRAM */ 422 /* since we are now disconnected from the code that established the */ 423 /* control socket, and since we want to be able to use different */ 424 /* protocols and such, we are passed the name of the remote host and */ 425 /* must turn that into the test specific addressing information. */ 426 427 /* complete_addrinfos will either succede or exit the process */ 428 complete_addrinfos(&remote_res, 429 &local_res, 430 remote_host, 431 SOCK_STREAM, 432 IPPROTO_SCTP, 433 0); 434 435 if ( print_headers ) { 436 print_top_test_header("SCTP STREAM TEST", local_res, remote_res); 437 } 438 439 send_ring = NULL; 440 confidence_iteration = 1; 441 init_stat(); 442 443 /* we have a great-big while loop which controls the number of times */ 444 /* we run a particular test. this is for the calculation of a */ 445 /* confidence interval (I really should have stayed awake during */ 446 /* probstats :). If the user did not request confidence measurement */ 447 /* (no confidence is the default) then we will only go though the */ 448 /* loop once. the confidence stuff originates from the folks at IBM */ 449 450 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 451 (confidence_iteration <= iteration_min)) { 452 453 /* initialize a few counters. we have to remember that we might be */ 454 /* going through the loop more than once. */ 455 456 nummessages = 0; 457 bytes_sent = 0.0; 458 times_up = 0; 459 timed_out = 0; 460 461 /*set up the data socket */ 462 send_socket = create_data_socket(local_res); 463 464 if (send_socket == INVALID_SOCKET){ 465 perror("netperf: send_sctp_stream: sctp stream data socket"); 466 exit(1); 467 } 468 469 if (debug) { 470 fprintf(where,"send_sctp_stream: send_socket obtained...\n"); 471 } 472 473 /* at this point, we have either retrieved the socket buffer sizes, */ 474 /* or have tried to set them, so now, we may want to set the send */ 475 /* size based on that (because the user either did not use a -m */ 476 /* option, or used one with an argument of 0). If the socket buffer */ 477 /* size is not available, we will set the send size to 4KB - no */ 478 /* particular reason, just arbitrary... */ 479 if (send_size == 0) { 480 if (lss_size > 0) { 481 send_size = lss_size; 482 } 483 else { 484 send_size = 4096; 485 } 486 } 487 488 /* set-up the data buffer ring with the requested alignment and offset. */ 489 /* note also that we have allocated a quantity */ 490 /* of memory that is at least one send-size greater than our socket */ 491 /* buffer size. We want to be sure that there are at least two */ 492 /* buffers allocated - this can be a bit of a problem when the */ 493 /* send_size is bigger than the socket size, so we must check... the */ 494 /* user may have wanted to explicitly set the "width" of our send */ 495 /* buffers, we should respect that wish... */ 496 if (send_width == 0) { 497 send_width = (lss_size/send_size) + 1; 498 if (send_width == 1) send_width++; 499 } 500 501 if (send_ring == NULL) { 502 /* only allocate the send ring once. this is a networking test, */ 503 /* not a memory allocation test. this way, we do not need a */ 504 /* deallocate_buffer_ring() routine, and I don't feel like */ 505 /* writing one anyway :) raj 11/94 */ 506 send_ring = allocate_buffer_ring(send_width, 507 send_size, 508 local_send_align, 509 local_send_offset); 510 } 511 512 /* If the user has requested cpu utilization measurements, we must */ 513 /* calibrate the cpu(s). We will perform this task within the tests */ 514 /* themselves. If the user has specified the cpu rate, then */ 515 /* calibrate_local_cpu will return rather quickly as it will have */ 516 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 517 /* all the "normal" calibration stuff and return the rate back. */ 518 519 if (local_cpu_usage) { 520 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 521 } 522 523 /* Tell the remote end to do a listen. The server alters the socket */ 524 /* paramters on the other side at this point, hence the reason for */ 525 /* all the values being passed in the setup message. If the user did */ 526 /* not specify any of the parameters, they will be passed as 0, which */ 527 /* will indicate to the remote that no changes beyond the system's */ 528 /* default should be used. Alignment is the exception, it will */ 529 /* default to 1, which will be no alignment alterations. */ 530 531 netperf_request.content.request_type = DO_SCTP_STREAM; 532 sctp_stream_request->send_buf_size = rss_size_req; 533 sctp_stream_request->recv_buf_size = rsr_size_req; 534 sctp_stream_request->receive_size = recv_size; 535 sctp_stream_request->no_delay = rem_nodelay; 536 sctp_stream_request->recv_alignment = remote_recv_align; 537 sctp_stream_request->recv_offset = remote_recv_offset; 538 sctp_stream_request->measure_cpu = remote_cpu_usage; 539 sctp_stream_request->cpu_rate = remote_cpu_rate; 540 if (test_time) { 541 sctp_stream_request->test_length = test_time; 542 } 543 else { 544 if (msg_count) 545 test_bytes = send_size * msg_count; 546 547 sctp_stream_request->test_length = test_bytes; 548 } 549 sctp_stream_request->so_rcvavoid = rem_rcvavoid; 550 sctp_stream_request->so_sndavoid = rem_sndavoid; 551 #ifdef DIRTY 552 sctp_stream_request->dirty_count = rem_dirty_count; 553 sctp_stream_request->clean_count = rem_clean_count; 554 #endif /* DIRTY */ 555 sctp_stream_request->port = htonl(atoi(remote_data_port)); 556 sctp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 557 sctp_stream_request->non_blocking = non_block; 558 559 560 if (debug > 1) { 561 fprintf(where, 562 "netperf: send_sctp_stream: requesting sctp stream test\n"); 563 } 564 565 send_request(); 566 567 /* The response from the remote will contain all of the relevant */ 568 /* socket parameters for this test type. We will put them back into */ 569 /* the variables here so they can be displayed if desired. The */ 570 /* remote will have calibrated CPU if necessary, and will have done */ 571 /* all the needed set-up we will have calibrated the cpu locally */ 572 /* before sending the request, and will grab the counter value right*/ 573 /* after the connect returns. The remote will grab the counter right*/ 574 /* after the accept call. This saves the hassle of extra messages */ 575 /* being sent for the sctp tests. */ 576 577 recv_response(); 578 579 if (!netperf_response.content.serv_errno) { 580 if (debug) 581 fprintf(where,"remote listen done.\n"); 582 rsr_size = sctp_stream_response->recv_buf_size; 583 rss_size = sctp_stream_response->send_buf_size; 584 rem_nodelay = sctp_stream_response->no_delay; 585 remote_cpu_usage= sctp_stream_response->measure_cpu; 586 remote_cpu_rate = sctp_stream_response->cpu_rate; 587 588 /* we have to make sure that the server port number is in */ 589 /* network order */ 590 set_port_number(remote_res, (short)sctp_stream_response->data_port_number); 591 592 rem_rcvavoid = sctp_stream_response->so_rcvavoid; 593 rem_sndavoid = sctp_stream_response->so_sndavoid; 594 } 595 else { 596 Set_errno(netperf_response.content.serv_errno); 597 fprintf(where, 598 "netperf: remote error %d", 599 netperf_response.content.serv_errno); 600 perror(""); 601 fflush(where); 602 603 exit(1); 604 } 605 606 /*Connect up to the remote port on the data socket */ 607 if (connect(send_socket, 608 remote_res->ai_addr, 609 remote_res->ai_addrlen) == INVALID_SOCKET) { 610 perror("netperf: send_sctp_stream: data socket connect failed"); 611 exit(1); 612 } 613 614 sctp_enable_events(send_socket, SCTP_ASSOC_CHANGE_EV); 615 616 if (non_block) { 617 /* now that we are connected, mark the socket as non-blocking */ 618 if (!set_nonblock(send_socket)) { 619 perror("netperf: fcntl"); 620 exit(1); 621 } 622 } 623 624 /* Data Socket set-up is finished. If there were problems, either */ 625 /* the connect would have failed, or the previous response would */ 626 /* have indicated a problem. I failed to see the value of the */ 627 /* extra message after the accept on the remote. If it failed, */ 628 /* we'll see it here. If it didn't, we might as well start pumping */ 629 /* data. */ 630 631 /* Set-up the test end conditions. For a stream test, they can be */ 632 /* either time or byte-count based. */ 633 634 if (test_time) { 635 /* The user wanted to end the test after a period of time. */ 636 times_up = 0; 637 bytes_remaining = 0; 638 /* in previous revisions, we had the same code repeated throught */ 639 /* all the test suites. this was unnecessary, and meant more */ 640 /* work for me when I wanted to switch to POSIX signals, so I */ 641 /* have abstracted this out into a routine in netlib.c. if you */ 642 /* are experiencing signal problems, you might want to look */ 643 /* there. raj 11/94 */ 644 start_timer(test_time); 645 } 646 else { 647 /* The tester wanted to send a number of bytes. */ 648 bytes_remaining = test_bytes; 649 times_up = 1; 650 } 651 652 /* The cpu_start routine will grab the current time and possibly */ 653 /* value of the idle counter for later use in measuring cpu */ 654 /* utilization and/or service demand and thruput. */ 655 656 cpu_start(local_cpu_usage); 657 658 #ifdef WANT_INTERVALS 659 if ((interval_burst) || (demo_mode)) { 660 /* zero means that we never pause, so we never should need the */ 661 /* interval timer, unless we are in demo_mode */ 662 start_itimer(interval_wate); 663 } 664 interval_count = interval_burst; 665 /* get the signal set for the call to sigsuspend */ 666 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { 667 fprintf(where, 668 "send_sctp_stream: unable to get sigmask errno %d\n", 669 errno); 670 fflush(where); 671 exit(1); 672 } 673 #endif /* WANT_INTERVALS */ 674 675 #ifdef DIRTY 676 /* initialize the random number generator for putting dirty stuff */ 677 /* into the send buffer. raj */ 678 srand((int) getpid()); 679 #endif 680 681 /* before we start, initialize a few variables */ 682 683 /* We use an "OR" to control test execution. When the test is */ 684 /* controlled by time, the byte count check will always return false. */ 685 /* When the test is controlled by byte count, the time test will */ 686 /* always return false. When the test is finished, the whole */ 687 /* expression will go false and we will stop sending data. */ 688 689 while ((!times_up) || (bytes_remaining > 0)) { 690 691 #ifdef DIRTY 692 /* we want to dirty some number of consecutive integers in the buffer */ 693 /* we are about to send. we may also want to bring some number of */ 694 /* them cleanly into the cache. The clean ones will follow any dirty */ 695 /* ones into the cache. at some point, we might want to replace */ 696 /* the rand() call with something from a table to reduce our call */ 697 /* overhead during the test, but it is not a high priority item. */ 698 message_int_ptr = (int *)(send_ring->buffer_ptr); 699 for (i = 0; i < loc_dirty_count; i++) { 700 *message_int_ptr = rand(); 701 message_int_ptr++; 702 } 703 for (i = 0; i < loc_clean_count; i++) { 704 loc_dirty_count = *message_int_ptr; 705 message_int_ptr++; 706 } 707 #endif /* DIRTY */ 708 709 #ifdef WANT_HISTOGRAM 710 /* timestamp just before we go into send and then again just after */ 711 /* we come out raj 8/94 */ 712 HIST_timestamp_start(time_hist); 713 #endif /* WANT_HISTOGRAM */ 714 715 while ((len=sctp_sendmsg(send_socket, 716 send_ring->buffer_ptr, send_size, 717 NULL, 0, 718 0, 0, 0, 0, 0)) != send_size) { 719 if (non_block && errno == EAGAIN) 720 continue; 721 else if ((len >=0) || SOCKET_EINTR(len)) { 722 /* the test was interrupted, must be the end of test */ 723 timed_out = 1; 724 break; 725 } 726 perror("netperf: data send error"); 727 printf("len was %d\n",len); 728 exit(1); 729 } 730 731 if (timed_out) 732 break; /* we timed out durint sendmsg, done with test */ 733 734 #ifdef WANT_HISTOGRAM 735 /* timestamp the exit from the send call and update the histogram */ 736 HIST_timestamp_stop_add(time_hist); 737 #endif /* WANT_HISTOGRAM */ 738 739 #ifdef WANT_INTERVALS 740 if (demo_mode) { 741 units_this_tick += send_size; 742 } 743 /* in this case, the interval count is the count-down couter */ 744 /* to decide to sleep for a little bit */ 745 if ((interval_burst) && (--interval_count == 0)) { 746 /* call sigsuspend and wait for the interval timer to get us */ 747 /* out */ 748 if (debug > 1) { 749 fprintf(where,"about to suspend\n"); 750 fflush(where); 751 } 752 if (sigsuspend(&signal_set) == EFAULT) { 753 fprintf(where, 754 "send_sctp_stream: fault with sigsuspend.\n"); 755 fflush(where); 756 exit(1); 757 } 758 interval_count = interval_burst; 759 } 760 #endif /* WANT_INTERVALS */ 761 762 /* now we want to move our pointer to the next position in the */ 763 /* data buffer...we may also want to wrap back to the "beginning" */ 764 /* of the bufferspace, so we will mod the number of messages sent */ 765 /* by the send width, and use that to calculate the offset to add */ 766 /* to the base pointer. */ 767 nummessages++; 768 send_ring = send_ring->next; 769 if (bytes_remaining) { 770 bytes_remaining -= send_size; 771 } 772 } 773 774 /* The test is over. Flush the buffers to the remote end. We do a */ 775 /* graceful release to insure that all data has been taken by the */ 776 /* remote. */ 777 778 /* but first, if the verbosity is greater than 1, find-out what */ 779 /* the sctp maximum segment_size was (if possible) */ 780 if (verbosity > 1) { 781 sctp_mss = -1; 782 get_sctp_info(send_socket, &sctp_mss); 783 } 784 785 shutdown(send_socket, SHUT_WR); 786 787 /* The test server will signal to us when it wants to shutdown. 788 * In blocking mode, we can call recvmsg. In non-blocking 789 * mode, we need to select on the socket for reading. 790 * We'll assume that all returns are succefull 791 */ 792 if (non_block) { 793 fd_set readfds; 794 795 FD_ZERO(&readfds); 796 FD_SET(send_socket, &readfds); 797 select(send_socket+1, &readfds, NULL, NULL, NULL); 798 } else { 799 sctp_recvmsg(send_socket, send_ring->buffer_ptr, send_size, NULL, 800 0, NULL, 0); 801 } 802 803 /* this call will always give us the elapsed time for the test, and */ 804 /* will also store-away the necessaries for cpu utilization */ 805 806 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 807 /* measured and how */ 808 /* long did we really */ 809 /* run? */ 810 811 /* we are finished with the socket, so close it to prevent hitting */ 812 /* the limit on maximum open files. */ 813 close(send_socket); 814 815 /* Get the statistics from the remote end. The remote will have */ 816 /* calculated service demand and all those interesting things. If it */ 817 /* wasn't supposed to care, it will return obvious values. */ 818 819 recv_response(); 820 if (!netperf_response.content.serv_errno) { 821 if (debug) 822 fprintf(where,"remote results obtained\n"); 823 } 824 else { 825 Set_errno(netperf_response.content.serv_errno); 826 fprintf(where, 827 "netperf: remote error %d", 828 netperf_response.content.serv_errno); 829 perror(""); 830 fflush(where); 831 832 exit(1); 833 } 834 835 /* We now calculate what our thruput was for the test. In the future, */ 836 /* we may want to include a calculation of the thruput measured by */ 837 /* the remote, but it should be the case that for a sctp stream test, */ 838 /* that the two numbers should be *very* close... We calculate */ 839 /* bytes_sent regardless of the way the test length was controlled. */ 840 /* If it was time, we needed to, and if it was by bytes, the user may */ 841 /* have specified a number of bytes that wasn't a multiple of the */ 842 /* send_size, so we really didn't send what he asked for ;-) */ 843 844 bytes_sent = ntohd(sctp_stream_result->bytes_received); 845 846 thruput = (double) calc_thruput(bytes_sent); 847 848 if (local_cpu_usage || remote_cpu_usage) { 849 /* We must now do a little math for service demand and cpu */ 850 /* utilization for the system(s) */ 851 /* Of course, some of the information might be bogus because */ 852 /* there was no idle counter in the kernel(s). We need to make */ 853 /* a note of this for the user's benefit...*/ 854 if (local_cpu_usage) { 855 856 local_cpu_utilization = calc_cpu_util(0.0); 857 local_service_demand = calc_service_demand(bytes_sent, 858 0.0, 859 0.0, 860 0); 861 } 862 else { 863 local_cpu_utilization = (float) -1.0; 864 local_service_demand = (float) -1.0; 865 } 866 867 if (remote_cpu_usage) { 868 869 remote_cpu_utilization = sctp_stream_result->cpu_util; 870 remote_service_demand = calc_service_demand(bytes_sent, 871 0.0, 872 remote_cpu_utilization, 873 sctp_stream_result->num_cpus); 874 } 875 else { 876 remote_cpu_utilization = (float) -1.0; 877 remote_service_demand = (float) -1.0; 878 } 879 } 880 else { 881 /* we were not measuring cpu, for the confidence stuff, we */ 882 /* should make it -1.0 */ 883 local_cpu_utilization = (float) -1.0; 884 local_service_demand = (float) -1.0; 885 remote_cpu_utilization = (float) -1.0; 886 remote_service_demand = (float) -1.0; 887 } 888 889 /* at this point, we want to calculate the confidence information. */ 890 /* if debugging is on, calculate_confidence will print-out the */ 891 /* parameters we pass it */ 892 893 calculate_confidence(confidence_iteration, 894 elapsed_time, 895 thruput, 896 local_cpu_utilization, 897 remote_cpu_utilization, 898 local_service_demand, 899 remote_service_demand); 900 901 902 confidence_iteration++; 903 } 904 905 /* at this point, we have finished making all the runs that we */ 906 /* will be making. so, we should extract what the calcuated values */ 907 /* are for all the confidence stuff. we could make the values */ 908 /* global, but that seemed a little messy, and it did not seem worth */ 909 /* all the mucking with header files. so, we create a routine much */ 910 /* like calcualte_confidence, which just returns the mean values. */ 911 /* raj 11/94 */ 912 913 retrieve_confident_values(&elapsed_time, 914 &thruput, 915 &local_cpu_utilization, 916 &remote_cpu_utilization, 917 &local_service_demand, 918 &remote_service_demand); 919 920 /* We are now ready to print all the information. If the user */ 921 /* has specified zero-level verbosity, we will just print the */ 922 /* local service demand, or the remote service demand. If the */ 923 /* user has requested verbosity level 1, he will get the basic */ 924 /* "streamperf" numbers. If the user has specified a verbosity */ 925 /* of greater than 1, we will display a veritable plethora of */ 926 /* background information from outside of this block as it it */ 927 /* not cpu_measurement specific... */ 928 929 if (confidence < 0) { 930 /* we did not hit confidence, but were we asked to look for it? */ 931 if (iteration_max > 1) { 932 display_confidence(); 933 } 934 } 935 936 if (local_cpu_usage || remote_cpu_usage) { 937 local_cpu_method = format_cpu_method(cpu_method); 938 remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method); 939 940 switch (verbosity) { 941 case 0: 942 if (local_cpu_usage) { 943 fprintf(where, 944 cpu_fmt_0, 945 local_service_demand, 946 local_cpu_method); 947 } 948 else { 949 fprintf(where, 950 cpu_fmt_0, 951 remote_service_demand, 952 remote_cpu_method); 953 } 954 break; 955 case 1: 956 case 2: 957 if (print_headers) { 958 fprintf(where, 959 cpu_title, 960 format_units(), 961 local_cpu_method, 962 remote_cpu_method); 963 } 964 965 fprintf(where, 966 cpu_fmt_1, /* the format string */ 967 rsr_size, /* remote recvbuf size */ 968 lss_size, /* local sendbuf size */ 969 send_size, /* how large were the sends */ 970 elapsed_time, /* how long was the test */ 971 thruput, /* what was the xfer rate */ 972 local_cpu_utilization, /* local cpu */ 973 remote_cpu_utilization, /* remote cpu */ 974 local_service_demand, /* local service demand */ 975 remote_service_demand); /* remote service demand */ 976 break; 977 } 978 } 979 else { 980 /* The tester did not wish to measure service demand. */ 981 982 switch (verbosity) { 983 case 0: 984 fprintf(where, 985 tput_fmt_0, 986 thruput); 987 break; 988 case 1: 989 case 2: 990 if (print_headers) { 991 fprintf(where,tput_title,format_units()); 992 } 993 fprintf(where, 994 tput_fmt_1, /* the format string */ 995 rsr_size, /* remote recvbuf size */ 996 lss_size, /* local sendbuf size */ 997 send_size, /* how large were the sends */ 998 elapsed_time, /* how long did it take */ 999 thruput);/* how fast did it go */ 1000 break; 1001 } 1002 } 1003 1004 /* it would be a good thing to include information about some of the */ 1005 /* other parameters that may have been set for this test, but at the */ 1006 /* moment, I do not wish to figure-out all the formatting, so I will */ 1007 /* just put this comment here to help remind me that it is something */ 1008 /* that should be done at a later time. */ 1009 1010 if (verbosity > 1) { 1011 /* The user wanted to know it all, so we will give it to him. */ 1012 /* This information will include as much as we can find about */ 1013 /* sctp statistics, the alignments of the sends and receives */ 1014 /* and all that sort of rot... */ 1015 1016 /* this stuff needs to be worked-out in the presence of confidence */ 1017 /* intervals and multiple iterations of the test... raj 11/94 */ 1018 1019 fprintf(where, 1020 ksink_fmt, 1021 "Bytes", 1022 "Bytes", 1023 "Bytes", 1024 local_send_align, 1025 remote_recv_align, 1026 local_send_offset, 1027 remote_recv_offset, 1028 bytes_sent, 1029 bytes_sent / (double)nummessages, 1030 nummessages, 1031 bytes_sent / (double)sctp_stream_result->recv_calls, 1032 sctp_stream_result->recv_calls); 1033 fprintf(where, 1034 ksink_fmt2, 1035 sctp_mss); 1036 fflush(where); 1037 #ifdef WANT_HISTOGRAM 1038 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 1039 fflush(where); 1040 HIST_report(time_hist); 1041 #endif /* WANT_HISTOGRAM */ 1042 } 1043 1044 } 1045 1046 1047 1049 1050 /* This is the server-side routine for the sctp stream test. It is */ 1051 /* implemented as one routine. I could break things-out somewhat, but */ 1052 /* didn't feel it was necessary. */ 1053 1054 void 1055 recv_sctp_stream( void ) 1056 { 1057 1058 struct sockaddr_in myaddr_in; /* needed to get port number */ 1059 struct sockaddr_storage peeraddr; /* used in accept */ 1060 int s_listen,s_data; 1061 socklen_t addrlen; 1062 int len; 1063 unsigned int receive_calls; 1064 float elapsed_time; 1065 double bytes_received; 1066 1067 struct ring_elt *recv_ring; 1068 1069 struct addrinfo *local_res; 1070 char local_name[BUFSIZ]; 1071 char port_buffer[PORTBUFSIZE]; 1072 int msg_flags = 0; 1073 1074 #ifdef DIRTY 1075 int *message_int_ptr; 1076 int dirty_count; 1077 int clean_count; 1078 int i; 1079 #endif 1080 1081 #ifdef DO_SELECT 1082 fd_set readfds; 1083 struct timeval timeout; 1084 #endif /* DO_SELECT */ 1085 1086 struct sctp_stream_request_struct *sctp_stream_request; 1087 struct sctp_stream_response_struct *sctp_stream_response; 1088 struct sctp_stream_results_struct *sctp_stream_results; 1089 1090 #ifdef DO_SELECT 1091 FD_ZERO(&readfds); 1092 timeout.tv_sec = 1; 1093 timeout.tv_usec = 0; 1094 #endif /* DO_SELECT */ 1095 1096 sctp_stream_request = 1097 (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data; 1098 sctp_stream_response = 1099 (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data; 1100 sctp_stream_results = 1101 (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data; 1102 1103 if (debug) { 1104 fprintf(where,"netserver: recv_sctp_stream: entered...\n"); 1105 fflush(where); 1106 } 1107 1108 /* We want to set-up the listen socket with all the desired */ 1109 /* parameters and then let the initiator know that all is ready. If */ 1110 /* socket size defaults are to be used, then the initiator will have */ 1111 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 1112 /* send-back what they are. If that information cannot be determined, */ 1113 /* then we send-back -1's for the sizes. If things go wrong for any */ 1114 /* reason, we will drop back ten yards and punt. */ 1115 1116 /* If anything goes wrong, we want the remote to know about it. It */ 1117 /* would be best if the error that the remote reports to the user is */ 1118 /* the actual error we encountered, rather than some bogus unexpected */ 1119 /* response type message. */ 1120 1121 if (debug) { 1122 fprintf(where,"recv_sctp_stream: setting the response type...\n"); 1123 fflush(where); 1124 } 1125 1126 netperf_response.content.response_type = SCTP_STREAM_RESPONSE; 1127 1128 if (debug) { 1129 fprintf(where,"recv_sctp_stream: the response type is set...\n"); 1130 fflush(where); 1131 } 1132 1133 /* We now alter the message_ptr variable to be at the desired */ 1134 /* alignment with the desired offset. */ 1135 1136 if (debug) { 1137 fprintf(where,"recv_sctp_stream: requested alignment of %d\n", 1138 sctp_stream_request->recv_alignment); 1139 fflush(where); 1140 } 1141 1142 /* create_data_socket expects to find some things in the global */ 1143 /* variables, so set the globals based on the values in the request. */ 1144 /* once the socket has been created, we will set the response values */ 1145 /* based on the updated value of those globals. raj 7/94 */ 1146 lss_size_req = sctp_stream_request->send_buf_size; 1147 lsr_size_req = sctp_stream_request->recv_buf_size; 1148 loc_nodelay = sctp_stream_request->no_delay; 1149 loc_rcvavoid = sctp_stream_request->so_rcvavoid; 1150 loc_sndavoid = sctp_stream_request->so_sndavoid; 1151 non_block = sctp_stream_request->non_blocking; 1152 1153 set_hostname_and_port(local_name, 1154 port_buffer, 1155 nf_to_af(sctp_stream_request->ipfamily), 1156 sctp_stream_request->port); 1157 1158 local_res = complete_addrinfo(local_name, 1159 local_name, 1160 port_buffer, 1161 nf_to_af(sctp_stream_request->ipfamily), 1162 SOCK_STREAM, 1163 IPPROTO_SCTP, 1164 0); 1165 1166 s_listen = create_data_socket(local_res); 1167 1168 if (s_listen < 0) { 1169 netperf_response.content.serv_errno = errno; 1170 send_response(); 1171 exit(1); 1172 } 1173 1174 /* what sort of sizes did we end-up with? */ 1175 if (sctp_stream_request->receive_size == 0) { 1176 if (lsr_size > 0) { 1177 recv_size = lsr_size; 1178 } 1179 else { 1180 recv_size = 4096; 1181 } 1182 } 1183 else { 1184 recv_size = sctp_stream_request->receive_size; 1185 } 1186 1187 /* we want to set-up our recv_ring in a manner analagous to what we */ 1188 /* do on the sending side. this is more for the sake of symmetry */ 1189 /* than for the needs of say copy avoidance, but it might also be */ 1190 /* more realistic - this way one could conceivably go with a */ 1191 /* double-buffering scheme when taking the data an putting it into */ 1192 /* the filesystem or something like that. raj 7/94 */ 1193 1194 if (recv_width == 0) { 1195 recv_width = (lsr_size/recv_size) + 1; 1196 if (recv_width == 1) recv_width++; 1197 } 1198 1199 recv_ring = allocate_buffer_ring(recv_width, 1200 recv_size, 1201 sctp_stream_request->recv_alignment, 1202 sctp_stream_request->recv_offset); 1203 1204 if (debug) { 1205 fprintf(where,"recv_sctp_stream: set recv_size = %d, align = %d, offset = %d.\n", 1206 recv_size, sctp_stream_request->recv_alignment, 1207 sctp_stream_request->recv_offset); 1208 fflush(where); 1209 } 1210 1211 /* now get the port number assigned by the system */ 1212 addrlen = sizeof(myaddr_in); 1213 if (getsockname(s_listen, 1214 (struct sockaddr *)&myaddr_in, 1215 &addrlen) == -1){ 1216 netperf_response.content.serv_errno = errno; 1217 close(s_listen); 1218 send_response(); 1219 1220 exit(1); 1221 } 1222 1223 /* Now myaddr_in contains the port and the internet address this is */ 1224 /* returned to the sender also implicitly telling the sender that the */ 1225 /* socket buffer sizing has been done. */ 1226 1227 sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 1228 netperf_response.content.serv_errno = 0; 1229 1230 /* But wait, there's more. If the initiator wanted cpu measurements, */ 1231 /* then we must call the calibrate routine, which will return the max */ 1232 /* rate back to the initiator. If the CPU was not to be measured, or */ 1233 /* something went wrong with the calibration, we will return a -1 to */ 1234 /* the initiator. */ 1235 1236 sctp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 1237 if (sctp_stream_request->measure_cpu) { 1238 sctp_stream_response->measure_cpu = 1; 1239 sctp_stream_response->cpu_rate = 1240 calibrate_local_cpu(sctp_stream_request->cpu_rate); 1241 } 1242 else { 1243 sctp_stream_response->measure_cpu = 0; 1244 } 1245 1246 /* before we send the response back to the initiator, pull some of */ 1247 /* the socket parms from the globals */ 1248 sctp_stream_response->send_buf_size = lss_size; 1249 sctp_stream_response->recv_buf_size = lsr_size; 1250 sctp_stream_response->no_delay = loc_nodelay; 1251 sctp_stream_response->so_rcvavoid = loc_rcvavoid; 1252 sctp_stream_response->so_sndavoid = loc_sndavoid; 1253 sctp_stream_response->receive_size = recv_size; 1254 1255 /* Now, let's set-up the socket to listen for connections */ 1256 if (listen(s_listen, 5) == -1) { 1257 netperf_response.content.serv_errno = errno; 1258 close(s_listen); 1259 send_response(); 1260 1261 exit(1); 1262 } 1263 1264 send_response(); 1265 1266 addrlen = sizeof(peeraddr); 1267 1268 if ((s_data = accept(s_listen, 1269 (struct sockaddr *)&peeraddr, 1270 &addrlen)) == INVALID_SOCKET) { 1271 /* Let's just punt. The remote will be given some information */ 1272 close(s_listen); 1273 exit(1); 1274 } 1275 1276 sctp_enable_events(s_data, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV); 1277 1278 /* now that we are connected, mark the socket as non-blocking */ 1279 if (non_block) { 1280 fprintf(where, "setting socket as nonblocking\n"); 1281 fflush(where); 1282 if (!set_nonblock(s_data)) { 1283 close(s_data); 1284 exit(1); 1285 } 1286 } 1287 1288 #ifdef KLUDGE_SOCKET_OPTIONS 1289 /* this is for those systems which *INCORRECTLY* fail to pass */ 1290 /* attributes across an accept() call. Including this goes against */ 1291 /* my better judgement :( raj 11/95 */ 1292 1293 kludge_socket_options(s_data); 1294 1295 #endif /* KLUDGE_SOCKET_OPTIONS */ 1296 1297 /* Now it's time to start receiving data on the connection. We will */ 1298 /* first grab the apropriate counters and then start grabbing. */ 1299 1300 cpu_start(sctp_stream_request->measure_cpu); 1301 1302 /* The loop will exit when the sender does a shutdown, which will */ 1303 /* return a length of zero */ 1304 1305 #ifdef DIRTY 1306 /* we want to dirty some number of consecutive integers in the buffer */ 1307 /* we are about to recv. we may also want to bring some number of */ 1308 /* them cleanly into the cache. The clean ones will follow any dirty */ 1309 /* ones into the cache. */ 1310 1311 dirty_count = sctp_stream_request->dirty_count; 1312 clean_count = sctp_stream_request->clean_count; 1313 message_int_ptr = (int *)recv_ring->buffer_ptr; 1314 for (i = 0; i < dirty_count; i++) { 1315 *message_int_ptr = rand(); 1316 message_int_ptr++; 1317 } 1318 for (i = 0; i < clean_count; i++) { 1319 dirty_count = *message_int_ptr; 1320 message_int_ptr++; 1321 } 1322 #endif /* DIRTY */ 1323 1324 bytes_received = 0; 1325 receive_calls = 0; 1326 1327 while ((len = sctp_recvmsg(s_data, 1328 recv_ring->buffer_ptr, recv_size, 1329 NULL, 0, NULL, &msg_flags)) != 0) { 1330 if (len == SOCKET_ERROR) { 1331 if (non_block && errno == EAGAIN) { 1332 if (debug){ 1333 fprintf(where, 1334 "recv_sctp_stream: sctp_recvmsg timed out, trying again\n"); 1335 fflush(where); 1336 } 1337 Set_errno(0); 1338 continue; 1339 } 1340 if (debug) { 1341 fprintf(where, 1342 "recv_sctp_stream: sctp_recvmsg error %d, exiting", 1343 errno); 1344 fflush(where); 1345 } 1346 netperf_response.content.serv_errno = errno; 1347 send_response(); 1348 close(s_data); 1349 exit(1); 1350 } 1351 1352 if (msg_flags & MSG_NOTIFICATION) { 1353 msg_flags = 0; 1354 if (debug) { 1355 fprintf(where, 1356 "recv_sctp_stream: Got notification... processing\n"); 1357 fflush(where); 1358 } 1359 if (sctp_process_event(s_data, recv_ring->buffer_ptr) == SCTP_CLOSE) 1360 break; /* break out of the recvmsg loop */ 1361 1362 continue; 1363 } 1364 1365 bytes_received += len; 1366 receive_calls++; 1367 1368 /* more to the next buffer in the recv_ring */ 1369 recv_ring = recv_ring->next; 1370 1371 #ifdef PAUSE 1372 sleep(1); 1373 #endif /* PAUSE */ 1374 1375 #ifdef DIRTY 1376 message_int_ptr = (int *)(recv_ring->buffer_ptr); 1377 for (i = 0; i < dirty_count; i++) { 1378 *message_int_ptr = rand(); 1379 message_int_ptr++; 1380 } 1381 for (i = 0; i < clean_count; i++) { 1382 dirty_count = *message_int_ptr; 1383 message_int_ptr++; 1384 } 1385 #endif /* DIRTY */ 1386 1387 #ifdef DO_SELECT 1388 FD_SET(s_data,&readfds); 1389 select(s_data+1,&readfds,NULL,NULL,&timeout); 1390 #endif /* DO_SELECT */ 1391 1392 } 1393 1394 /* perform a shutdown to signal the sender that */ 1395 /* we have received all the data sent. raj 4/93 */ 1396 1397 if (close(s_data) == -1) { 1398 netperf_response.content.serv_errno = errno; 1399 send_response(); 1400 exit(1); 1401 } 1402 1403 cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time); 1404 1405 /* send the results to the sender */ 1406 1407 if (debug) { 1408 fprintf(where, 1409 "recv_sctp_stream: got %g bytes\n", 1410 bytes_received); 1411 fprintf(where, 1412 "recv_sctp_stream: got %d recvs\n", 1413 receive_calls); 1414 fflush(where); 1415 } 1416 1417 sctp_stream_results->bytes_received = htond(bytes_received); 1418 sctp_stream_results->elapsed_time = elapsed_time; 1419 sctp_stream_results->recv_calls = receive_calls; 1420 1421 if (sctp_stream_request->measure_cpu) { 1422 sctp_stream_results->cpu_util = calc_cpu_util(0.0); 1423 }; 1424 1425 if (debug) { 1426 fprintf(where, 1427 "recv_sctp_stream: test complete, sending results.\n"); 1428 fprintf(where, 1429 " bytes_received %g receive_calls %d\n", 1430 bytes_received, 1431 receive_calls); 1432 fprintf(where, 1433 " len %d\n", 1434 len); 1435 fflush(where); 1436 } 1437 1438 sctp_stream_results->cpu_method = cpu_method; 1439 sctp_stream_results->num_cpus = lib_num_loc_cpus; 1440 send_response(); 1441 1442 /* we are now done with the sockets */ 1443 close(s_listen); 1444 1445 } 1446 1447 1449 /* This routine implements the SCTP unidirectional data transfer test */ 1450 /* (a.k.a. stream) for the sockets interface. It receives its */ 1451 /* parameters via global variables from the shell and writes its */ 1452 /* output to the standard output. */ 1453 1454 1455 void 1456 send_sctp_stream_1toMany( char remote_host[] ) 1457 { 1458 1459 char *tput_title = "\ 1460 Recv Send Send \n\ 1461 Socket Socket Message Elapsed \n\ 1462 Size Size Size Time Throughput \n\ 1463 bytes bytes bytes secs. %s/sec \n\n"; 1464 1465 char *tput_fmt_0 = 1466 "%7.2f\n"; 1467 1468 char *tput_fmt_1 = 1469 "%6d %6d %6d %-6.2f %7.2f \n"; 1470 1471 char *cpu_title = "\ 1472 Recv Send Send Utilization Service Demand\n\ 1473 Socket Socket Message Elapsed Send Recv Send Recv\n\ 1474 Size Size Size Time Throughput local remote local remote\n\ 1475 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n"; 1476 1477 char *cpu_fmt_0 = 1478 "%6.3f %c\n"; 1479 1480 char *cpu_fmt_1 = 1481 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 1482 1483 char *ksink_fmt = "\n\ 1484 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\ 1485 Local Remote Local Remote Xfered Per Per\n\ 1486 Send Recv Send Recv Send (avg) Recv (avg)\n\ 1487 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n"; 1488 1489 char *ksink_fmt2 = "\n\ 1490 Maximum\n\ 1491 Segment\n\ 1492 Size (bytes)\n\ 1493 %6d\n"; 1494 1495 1496 float elapsed_time; 1497 1498 #ifdef WANT_INTERVALS 1499 int interval_count; 1500 sigset_t signal_set; 1501 #endif 1502 1503 /* what we want is to have a buffer space that is at least one */ 1504 /* send-size greater than our send window. this will insure that we */ 1505 /* are never trying to re-use a buffer that may still be in the hands */ 1506 /* of the transport. This buffer will be malloc'd after we have found */ 1507 /* the size of the local senc socket buffer. We will want to deal */ 1508 /* with alignment and offset concerns as well. */ 1509 1510 #ifdef DIRTY 1511 int *message_int_ptr; 1512 #endif 1513 1514 struct ring_elt *send_ring; 1515 1516 int len; 1517 unsigned int nummessages = 0; 1518 int *send_socket; 1519 int bytes_remaining; 1520 int sctp_mss; 1521 1522 /* with links like fddi, one can send > 32 bits worth of bytes */ 1523 /* during a test... ;-) at some point, this should probably become a */ 1524 /* 64bit integral type, but those are not entirely common yet */ 1525 double bytes_sent = 0.0; 1526 1527 #ifdef DIRTY 1528 int i; 1529 #endif /* DIRTY */ 1530 1531 float local_cpu_utilization; 1532 float local_service_demand; 1533 float remote_cpu_utilization; 1534 float remote_service_demand; 1535 1536 double thruput; 1537 1538 struct addrinfo *remote_res; 1539 struct addrinfo *local_res; 1540 1541 struct sctp_stream_request_struct *sctp_stream_request; 1542 struct sctp_stream_response_struct *sctp_stream_response; 1543 struct sctp_stream_results_struct *sctp_stream_result; 1544 1545 sctp_stream_request = 1546 (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data; 1547 sctp_stream_response = 1548 (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data; 1549 sctp_stream_result = 1550 (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data; 1551 1552 #ifdef WANT_HISTOGRAM 1553 time_hist = HIST_new_n(1); 1554 #endif /* WANT_HISTOGRAM */ 1555 1556 complete_addrinfos(&remote_res, 1557 &local_res, 1558 remote_host, 1559 SOCK_SEQPACKET, 1560 IPPROTO_SCTP, 1561 0); 1562 1563 if ( print_headers ) { 1564 print_top_test_header("SCTP 1-TO-MANY STREAM TEST",local_res,remote_res); 1565 } 1566 1567 send_ring = NULL; 1568 confidence_iteration = 1; 1569 init_stat(); 1570 1571 send_socket = malloc(sizeof (int) * num_associations); 1572 if (send_socket == NULL) { 1573 fprintf(where, "send_sctp_stream_1toMany: failed to allocation sockets!\n"); 1574 exit(1); 1575 } 1576 1577 /* we have a great-big while loop which controls the number of times */ 1578 /* we run a particular test. this is for the calculation of a */ 1579 /* confidence interval (I really should have stayed awake during */ 1580 /* probstats :). If the user did not request confidence measurement */ 1581 /* (no confidence is the default) then we will only go though the */ 1582 /* loop once. the confidence stuff originates from the folks at IBM */ 1583 1584 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 1585 (confidence_iteration <= iteration_min)) { 1586 1587 int j=0; 1588 int timed_out = 0; 1589 1590 1591 /* initialize a few counters. we have to remember that we might be */ 1592 /* going through the loop more than once. */ 1593 1594 nummessages = 0; 1595 bytes_sent = 0.0; 1596 times_up = 0; 1597 1598 /* at this point, we have either retrieved the socket buffer sizes, */ 1599 /* or have tried to set them, so now, we may want to set the send */ 1600 /* size based on that (because the user either did not use a -m */ 1601 /* option, or used one with an argument of 0). If the socket buffer */ 1602 /* size is not available, we will set the send size to 4KB - no */ 1603 /* particular reason, just arbitrary... */ 1604 if (send_size == 0) { 1605 if (lss_size > 0) { 1606 send_size = lss_size; 1607 } 1608 else { 1609 send_size = 4096; 1610 } 1611 } 1612 1613 /* set-up the data buffer ring with the requested alignment and offset. */ 1614 /* note also that we have allocated a quantity */ 1615 /* of memory that is at least one send-size greater than our socket */ 1616 /* buffer size. We want to be sure that there are at least two */ 1617 /* buffers allocated - this can be a bit of a problem when the */ 1618 /* send_size is bigger than the socket size, so we must check... the */ 1619 /* user may have wanted to explicitly set the "width" of our send */ 1620 /* buffers, we should respect that wish... */ 1621 if (send_width == 0) { 1622 send_width = (lss_size/send_size) + 1; 1623 if (send_width == 1) send_width++; 1624 } 1625 1626 if (send_ring == NULL) { 1627 /* only allocate the send ring once. this is a networking test, */ 1628 /* not a memory allocation test. this way, we do not need a */ 1629 /* deallocate_buffer_ring() routine, and I don't feel like */ 1630 /* writing one anyway :) raj 11/94 */ 1631 send_ring = allocate_buffer_ring(send_width, 1632 send_size, 1633 local_send_align, 1634 local_send_offset); 1635 } 1636 1637 /* If the user has requested cpu utilization measurements, we must */ 1638 /* calibrate the cpu(s). We will perform this task within the tests */ 1639 /* themselves. If the user has specified the cpu rate, then */ 1640 /* calibrate_local_cpu will return rather quickly as it will have */ 1641 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 1642 /* all the "normal" calibration stuff and return the rate back. */ 1643 1644 if (local_cpu_usage) { 1645 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 1646 } 1647 1648 /* Tell the remote end to do a listen. The server alters the socket */ 1649 /* paramters on the other side at this point, hence the reason for */ 1650 /* all the values being passed in the setup message. If the user did */ 1651 /* not specify any of the parameters, they will be passed as 0, which */ 1652 /* will indicate to the remote that no changes beyond the system's */ 1653 /* default should be used. Alignment is the exception, it will */ 1654 /* default to 1, which will be no alignment alterations. */ 1655 1656 netperf_request.content.request_type = DO_SCTP_STREAM_MANY; 1657 sctp_stream_request->send_buf_size = rss_size_req; 1658 sctp_stream_request->recv_buf_size = rsr_size_req; 1659 sctp_stream_request->receive_size = recv_size; 1660 sctp_stream_request->no_delay = rem_nodelay; 1661 sctp_stream_request->recv_alignment = remote_recv_align; 1662 sctp_stream_request->recv_offset = remote_recv_offset; 1663 sctp_stream_request->measure_cpu = remote_cpu_usage; 1664 sctp_stream_request->cpu_rate = remote_cpu_rate; 1665 if (test_time) { 1666 sctp_stream_request->test_length = test_time; 1667 } 1668 else { 1669 if (msg_count) 1670 test_bytes = send_size * msg_count; 1671 1672 sctp_stream_request->test_length = test_bytes*num_associations; 1673 } 1674 sctp_stream_request->so_rcvavoid = rem_rcvavoid; 1675 sctp_stream_request->so_sndavoid = rem_sndavoid; 1676 #ifdef DIRTY 1677 sctp_stream_request->dirty_count = rem_dirty_count; 1678 sctp_stream_request->clean_count = rem_clean_count; 1679 #endif /* DIRTY */ 1680 sctp_stream_request->port = (atoi(remote_data_port)); 1681 sctp_stream_request->ipfamily = af_to_nf(remote_res->ai_family); 1682 sctp_stream_request->non_blocking = non_block; 1683 1684 1685 if (debug > 1) { 1686 fprintf(where, 1687 "netperf: send_sctp_stream_1toMany: requesting sctp stream test\n"); 1688 } 1689 1690 send_request(); 1691 1692 /* The response from the remote will contain all of the relevant */ 1693 /* socket parameters for this test type. We will put them back into */ 1694 /* the variables here so they can be displayed if desired. The */ 1695 /* remote will have calibrated CPU if necessary, and will have done */ 1696 /* all the needed set-up we will have calibrated the cpu locally */ 1697 /* before sending the request, and will grab the counter value right*/ 1698 /* after the connect returns. The remote will grab the counter right*/ 1699 /* after the accept call. This saves the hassle of extra messages */ 1700 /* being sent for the sctp tests. */ 1701 1702 recv_response(); 1703 1704 if (!netperf_response.content.serv_errno) { 1705 if (debug) 1706 fprintf(where,"remote listen done.\n"); 1707 rsr_size = sctp_stream_response->recv_buf_size; 1708 rss_size = sctp_stream_response->send_buf_size; 1709 rem_nodelay = sctp_stream_response->no_delay; 1710 remote_cpu_usage= sctp_stream_response->measure_cpu; 1711 remote_cpu_rate = sctp_stream_response->cpu_rate; 1712 1713 /* we have to make sure that the server port number is in */ 1714 /* network order */ 1715 set_port_number(remote_res, (unsigned short)sctp_stream_response->data_port_number); 1716 rem_rcvavoid = sctp_stream_response->so_rcvavoid; 1717 rem_sndavoid = sctp_stream_response->so_sndavoid; 1718 } 1719 else { 1720 Set_errno(netperf_response.content.serv_errno); 1721 fprintf(where, 1722 "netperf: remote error %d", 1723 netperf_response.content.serv_errno); 1724 perror(""); 1725 fflush(where); 1726 1727 exit(1); 1728 } 1729 1730 /*set up the the array of data sockets and connect them to the server */ 1731 1732 for (j = 0; j < num_associations; j++) { 1733 send_socket[j] = create_data_socket(local_res); 1734 1735 if (send_socket[j] < 0){ 1736 perror("netperf: send_sctp_stream_1toMany: sctp stream data socket"); 1737 exit(1); 1738 } 1739 1740 if (debug) { 1741 fprintf(where,"send_sctp_stream_1toMany: send_socket obtained...\n"); 1742 } 1743 1744 /*Connect up to the remote port on the data socket */ 1745 if (connect(send_socket[j], 1746 remote_res->ai_addr, 1747 remote_res->ai_addrlen) == INVALID_SOCKET){ 1748 perror("netperf: send_sctp_stream_1toMany: data socket connect failed"); 1749 exit(1); 1750 } 1751 1752 /* Do it after connect is successfull, so that we don't see COMM_UP */ 1753 sctp_enable_events(send_socket[j], SCTP_ASSOC_CHANGE_EV); 1754 1755 if (non_block) { 1756 /* now that we are connected, mark the socket as non-blocking */ 1757 if (!set_nonblock(send_socket[j])) { 1758 perror("netperf: fcntl"); 1759 exit(1); 1760 } 1761 } 1762 } 1763 1764 /* Data Socket set-up is finished. If there were problems, either */ 1765 /* the connect would have failed, or the previous response would */ 1766 /* have indicated a problem. I failed to see the value of the */ 1767 /* extra message after the accept on the remote. If it failed, */ 1768 /* we'll see it here. If it didn't, we might as well start pumping */ 1769 /* data. */ 1770 1771 /* Set-up the test end conditions. For a stream test, they can be */ 1772 /* either time or byte-count based. */ 1773 1774 if (test_time) { 1775 /* The user wanted to end the test after a period of time. */ 1776 times_up = 0; 1777 bytes_remaining = 0; 1778 /* in previous revisions, we had the same code repeated throught */ 1779 /* all the test suites. this was unnecessary, and meant more */ 1780 /* work for me when I wanted to switch to POSIX signals, so I */ 1781 /* have abstracted this out into a routine in netlib.c. if you */ 1782 /* are experiencing signal problems, you might want to look */ 1783 /* there. raj 11/94 */ 1784 start_timer(test_time); 1785 } 1786 else { 1787 /* The tester wanted to send a number of bytes. */ 1788 bytes_remaining = test_bytes * num_associations; 1789 times_up = 1; 1790 } 1791 1792 /* The cpu_start routine will grab the current time and possibly */ 1793 /* value of the idle counter for later use in measuring cpu */ 1794 /* utilization and/or service demand and thruput. */ 1795 1796 cpu_start(local_cpu_usage); 1797 1798 #ifdef WANT_INTERVALS 1799 if ((interval_burst) || (demo_mode)) { 1800 /* zero means that we never pause, so we never should need the */ 1801 /* interval timer, unless we are in demo_mode */ 1802 start_itimer(interval_wate); 1803 } 1804 interval_count = interval_burst; 1805 /* get the signal set for the call to sigsuspend */ 1806 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { 1807 fprintf(where, 1808 "send_sctp_stream_1toMany: unable to get sigmask errno %d\n", 1809 errno); 1810 fflush(where); 1811 exit(1); 1812 } 1813 #endif /* WANT_INTERVALS */ 1814 1815 #ifdef DIRTY 1816 /* initialize the random number generator for putting dirty stuff */ 1817 /* into the send buffer. raj */ 1818 srand((int) getpid()); 1819 #endif 1820 1821 /* before we start, initialize a few variables */ 1822 1823 /* We use an "OR" to control test execution. When the test is */ 1824 /* controlled by time, the byte count check will always return false. */ 1825 /* When the test is controlled by byte count, the time test will */ 1826 /* always return false. When the test is finished, the whole */ 1827 /* expression will go false and we will stop sending data. */ 1828 1829 while ((!times_up) || (bytes_remaining > 0)) { 1830 1831 #ifdef DIRTY 1832 /* we want to dirty some number of consecutive integers in the buffer */ 1833 /* we are about to send. we may also want to bring some number of */ 1834 /* them cleanly into the cache. The clean ones will follow any dirty */ 1835 /* ones into the cache. at some point, we might want to replace */ 1836 /* the rand() call with something from a table to reduce our call */ 1837 /* overhead during the test, but it is not a high priority item. */ 1838 message_int_ptr = (int *)(send_ring->buffer_ptr); 1839 for (i = 0; i < loc_dirty_count; i++) { 1840 *message_int_ptr = rand(); 1841 message_int_ptr++; 1842 } 1843 for (i = 0; i < loc_clean_count; i++) { 1844 loc_dirty_count = *message_int_ptr; 1845 message_int_ptr++; 1846 } 1847 #endif /* DIRTY */ 1848 1849 #ifdef WANT_HISTOGRAM 1850 /* timestamp just before we go into send and then again just after */ 1851 /* we come out raj 8/94 */ 1852 HIST_timestamp_start(time_hist); 1853 #endif /* WANT_HISTOGRAM */ 1854 1855 for (j = 0; j < num_associations; j++) { 1856 1857 if((len=sctp_sendmsg(send_socket[j], 1858 send_ring->buffer_ptr, 1859 send_size, 1860 (struct sockaddr *)remote_res->ai_addr, 1861 remote_res->ai_addrlen, 1862 0, 0, 0, 0, 0)) != send_size) { 1863 if ((len >=0) || SOCKET_EINTR(len)) { 1864 /* the test was interrupted, must be the end of test */ 1865 timed_out = 1; 1866 break; 1867 } else if (non_block && errno == EAGAIN) { 1868 j--; /* send again on the same socket */ 1869 Set_errno(0); 1870 continue; 1871 } 1872 perror("netperf: data send error"); 1873 printf("len was %d\n",len); 1874 exit(1); 1875 } 1876 } 1877 1878 if (timed_out) 1879 break; /* test is over, try next iteration */ 1880 1881 #ifdef WANT_HISTOGRAM 1882 /* timestamp the exit from the send call and update the histogram */ 1883 HIST_timestamp_stop_add(time_hist); 1884 #endif /* WANT_HISTOGRAM */ 1885 1886 #ifdef WANT_INTERVALS 1887 if (demo_mode) { 1888 units_this_tick += send_size; 1889 } 1890 /* in this case, the interval count is the count-down couter */ 1891 /* to decide to sleep for a little bit */ 1892 if ((interval_burst) && (--interval_count == 0)) { 1893 /* call sigsuspend and wait for the interval timer to get us */ 1894 /* out */ 1895 if (debug > 1) { 1896 fprintf(where,"about to suspend\n"); 1897 fflush(where); 1898 } 1899 if (sigsuspend(&signal_set) == EFAULT) { 1900 fprintf(where, 1901 "send_sctp_stream_1toMany: fault with sigsuspend.\n"); 1902 fflush(where); 1903 exit(1); 1904 } 1905 interval_count = interval_burst; 1906 } 1907 #endif /* WANT_INTERVALS */ 1908 1909 /* now we want to move our pointer to the next position in the */ 1910 /* data buffer...we may also want to wrap back to the "beginning" */ 1911 /* of the bufferspace, so we will mod the number of messages sent */ 1912 /* by the send width, and use that to calculate the offset to add */ 1913 /* to the base pointer. */ 1914 nummessages++; 1915 send_ring = send_ring->next; 1916 if (bytes_remaining) { 1917 bytes_remaining -= send_size; 1918 } 1919 } 1920 1921 /* The test is over. Flush the buffers to the remote end. We do a */ 1922 /* graceful release to insure that all data has been taken by the */ 1923 /* remote. */ 1924 1925 /* but first, if the verbosity is greater than 1, find-out what */ 1926 /* the sctp maximum segment_size was (if possible) */ 1927 if (verbosity > 1) { 1928 sctp_mss = -1; 1929 get_sctp_info(send_socket[0], &sctp_mss); 1930 } 1931 1932 /* signal the server that we are all done writing, this will 1933 * initiate a shutdonw of one of the associations on the 1934 * server and trigger an event telling the server it's all done 1935 */ 1936 sctp_sendmsg(send_socket[0], NULL, 0, remote_res->ai_addr, 1937 remote_res->ai_addrlen, 0, MSG_EOF, 0, 0, 0); 1938 1939 1940 /* The test server will initiate closure of all associations 1941 * when it's done reading. We want a basic mechanism to catch this 1942 * and are using SCTP events for this. 1943 * In blocking mode, we can call recvmsg with the last socket we created. 1944 * In non-blocking mode, we need to select on the socket for reading. 1945 * We'll assume that all returns are succefull and signify 1946 * closure. 1947 * It is sufficient to do this on a single socket in the client. 1948 * We choose to do it on a socket other then the one that send MSG_EOF. 1949 * This means that anything comming in on that socket will be a shutdown. 1950 */ 1951 if (non_block) { 1952 fd_set readfds; 1953 1954 FD_ZERO(&readfds); 1955 FD_SET(send_socket[num_associations-1], &readfds); 1956 select(send_socket[num_associations-1]+1, &readfds, NULL, NULL, NULL); 1957 } else { 1958 sctp_recvmsg(send_socket[num_associations], send_ring->buffer_ptr, 1959 send_size, NULL, 0, NULL, 0); 1960 } 1961 1962 /* this call will always give us the elapsed time for the test, and */ 1963 /* will also store-away the necessaries for cpu utilization */ 1964 1965 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 1966 /* measured and how */ 1967 /* long did we really */ 1968 /* run? */ 1969 1970 /* we are finished with our sockets, so close them to prevent hitting */ 1971 /* the limit on maximum open files. */ 1972 for (j = 0; j < num_associations; j++) 1973 close(send_socket[j]); 1974 1975 /* Get the statistics from the remote end. The remote will have */ 1976 /* calculated service demand and all those interesting things. If it */ 1977 /* wasn't supposed to care, it will return obvious values. */ 1978 1979 recv_response(); 1980 if (!netperf_response.content.serv_errno) { 1981 if (debug) 1982 fprintf(where,"remote results obtained\n"); 1983 } 1984 else { 1985 Set_errno(netperf_response.content.serv_errno); 1986 fprintf(where, 1987 "netperf: remote error %d", 1988 netperf_response.content.serv_errno); 1989 perror(""); 1990 fflush(where); 1991 1992 exit(1); 1993 } 1994 1995 /* We now calculate what our thruput was for the test. In the future, */ 1996 /* we may want to include a calculation of the thruput measured by */ 1997 /* the remote, but it should be the case that for a sctp stream test, */ 1998 /* that the two numbers should be *very* close... We calculate */ 1999 /* bytes_sent regardless of the way the test length was controlled. */ 2000 /* If it was time, we needed to, and if it was by bytes, the user may */ 2001 /* have specified a number of bytes that wasn't a multiple of the */ 2002 /* send_size, so we really didn't send what he asked for ;-) */ 2003 2004 bytes_sent = ntohd(sctp_stream_result->bytes_received); 2005 2006 thruput = (double) calc_thruput(bytes_sent); 2007 2008 if (local_cpu_usage || remote_cpu_usage) { 2009 /* We must now do a little math for service demand and cpu */ 2010 /* utilization for the system(s) */ 2011 /* Of course, some of the information might be bogus because */ 2012 /* there was no idle counter in the kernel(s). We need to make */ 2013 /* a note of this for the user's benefit...*/ 2014 if (local_cpu_usage) { 2015 2016 local_cpu_utilization = calc_cpu_util(0.0); 2017 local_service_demand = calc_service_demand(bytes_sent, 2018 0.0, 2019 0.0, 2020 0); 2021 } 2022 else { 2023 local_cpu_utilization = (float) -1.0; 2024 local_service_demand = (float) -1.0; 2025 } 2026 2027 if (remote_cpu_usage) { 2028 2029 remote_cpu_utilization = sctp_stream_result->cpu_util; 2030 remote_service_demand = calc_service_demand(bytes_sent, 2031 0.0, 2032 remote_cpu_utilization, 2033 sctp_stream_result->num_cpus); 2034 } 2035 else { 2036 remote_cpu_utilization = (float) -1.0; 2037 remote_service_demand = (float) -1.0; 2038 } 2039 } 2040 else { 2041 /* we were not measuring cpu, for the confidence stuff, we */ 2042 /* should make it -1.0 */ 2043 local_cpu_utilization = (float) -1.0; 2044 local_service_demand = (float) -1.0; 2045 remote_cpu_utilization = (float) -1.0; 2046 remote_service_demand = (float) -1.0; 2047 } 2048 2049 /* at this point, we want to calculate the confidence information. */ 2050 /* if debugging is on, calculate_confidence will print-out the */ 2051 /* parameters we pass it */ 2052 2053 calculate_confidence(confidence_iteration, 2054 elapsed_time, 2055 thruput, 2056 local_cpu_utilization, 2057 remote_cpu_utilization, 2058 local_service_demand, 2059 remote_service_demand); 2060 2061 2062 confidence_iteration++; 2063 } 2064 2065 /* at this point, we have finished making all the runs that we */ 2066 /* will be making. so, we should extract what the calcuated values */ 2067 /* are for all the confidence stuff. we could make the values */ 2068 /* global, but that seemed a little messy, and it did not seem worth */ 2069 /* all the mucking with header files. so, we create a routine much */ 2070 /* like calcualte_confidence, which just returns the mean values. */ 2071 /* raj 11/94 */ 2072 2073 retrieve_confident_values(&elapsed_time, 2074 &thruput, 2075 &local_cpu_utilization, 2076 &remote_cpu_utilization, 2077 &local_service_demand, 2078 &remote_service_demand); 2079 2080 /* We are now ready to print all the information. If the user */ 2081 /* has specified zero-level verbosity, we will just print the */ 2082 /* local service demand, or the remote service demand. If the */ 2083 /* user has requested verbosity level 1, he will get the basic */ 2084 /* "streamperf" numbers. If the user has specified a verbosity */ 2085 /* of greater than 1, we will display a veritable plethora of */ 2086 /* background information from outside of this block as it it */ 2087 /* not cpu_measurement specific... */ 2088 2089 if (confidence < 0) { 2090 /* we did not hit confidence, but were we asked to look for it? */ 2091 if (iteration_max > 1) { 2092 display_confidence(); 2093 } 2094 } 2095 2096 if (local_cpu_usage || remote_cpu_usage) { 2097 local_cpu_method = format_cpu_method(cpu_method); 2098 remote_cpu_method = format_cpu_method(sctp_stream_result->cpu_method); 2099 2100 switch (verbosity) { 2101 case 0: 2102 if (local_cpu_usage) { 2103 fprintf(where, 2104 cpu_fmt_0, 2105 local_service_demand, 2106 local_cpu_method); 2107 } 2108 else { 2109 fprintf(where, 2110 cpu_fmt_0, 2111 remote_service_demand, 2112 remote_cpu_method); 2113 } 2114 break; 2115 case 1: 2116 case 2: 2117 if (print_headers) { 2118 fprintf(where, 2119 cpu_title, 2120 format_units(), 2121 local_cpu_method, 2122 remote_cpu_method); 2123 } 2124 2125 fprintf(where, 2126 cpu_fmt_1, /* the format string */ 2127 rsr_size, /* remote recvbuf size */ 2128 lss_size, /* local sendbuf size */ 2129 send_size, /* how large were the sends */ 2130 elapsed_time, /* how long was the test */ 2131 thruput, /* what was the xfer rate */ 2132 local_cpu_utilization, /* local cpu */ 2133 remote_cpu_utilization, /* remote cpu */ 2134 local_service_demand, /* local service demand */ 2135 remote_service_demand); /* remote service demand */ 2136 break; 2137 } 2138 } 2139 else { 2140 /* The tester did not wish to measure service demand. */ 2141 2142 switch (verbosity) { 2143 case 0: 2144 fprintf(where, 2145 tput_fmt_0, 2146 thruput); 2147 break; 2148 case 1: 2149 case 2: 2150 if (print_headers) { 2151 fprintf(where,tput_title,format_units()); 2152 } 2153 fprintf(where, 2154 tput_fmt_1, /* the format string */ 2155 rsr_size, /* remote recvbuf size */ 2156 lss_size, /* local sendbuf size */ 2157 send_size, /* how large were the sends */ 2158 elapsed_time, /* how long did it take */ 2159 thruput);/* how fast did it go */ 2160 break; 2161 } 2162 } 2163 2164 /* it would be a good thing to include information about some of the */ 2165 /* other parameters that may have been set for this test, but at the */ 2166 /* moment, I do not wish to figure-out all the formatting, so I will */ 2167 /* just put this comment here to help remind me that it is something */ 2168 /* that should be done at a later time. */ 2169 2170 if (verbosity > 1) { 2171 /* The user wanted to know it all, so we will give it to him. */ 2172 /* This information will include as much as we can find about */ 2173 /* sctp statistics, the alignments of the sends and receives */ 2174 /* and all that sort of rot... */ 2175 2176 /* this stuff needs to be worked-out in the presence of confidence */ 2177 /* intervals and multiple iterations of the test... raj 11/94 */ 2178 2179 fprintf(where, 2180 ksink_fmt, 2181 "Bytes", 2182 "Bytes", 2183 "Bytes", 2184 local_send_align, 2185 remote_recv_align, 2186 local_send_offset, 2187 remote_recv_offset, 2188 bytes_sent, 2189 bytes_sent / (double)nummessages, 2190 nummessages, 2191 bytes_sent / (double)sctp_stream_result->recv_calls, 2192 sctp_stream_result->recv_calls); 2193 fprintf(where, 2194 ksink_fmt2, 2195 sctp_mss); 2196 fflush(where); 2197 #ifdef WANT_HISTOGRAM 2198 fprintf(where,"\n\nHistogram of time spent in send() call.\n"); 2199 fflush(where); 2200 HIST_report(time_hist); 2201 #endif /* WANT_HISTOGRAM */ 2202 } 2203 2204 } 2205 2206 2207 2209 /* This is the server-side routine for the sctp stream test. It is */ 2210 /* implemented as one routine. I could break things-out somewhat, but */ 2211 /* didn't feel it was necessary. */ 2212 2213 void 2214 recv_sctp_stream_1toMany( void ) 2215 { 2216 2217 struct sockaddr_in myaddr_in; 2218 int s_recv; 2219 socklen_t addrlen; 2220 int len; 2221 unsigned int receive_calls; 2222 float elapsed_time; 2223 double bytes_received; 2224 int msg_flags = 0; 2225 2226 struct ring_elt *recv_ring; 2227 2228 struct addrinfo *local_res; 2229 char local_name[BUFSIZ]; 2230 char port_buffer[PORTBUFSIZE]; 2231 2232 #ifdef DIRTY 2233 int *message_int_ptr; 2234 int dirty_count; 2235 int clean_count; 2236 int i; 2237 #endif 2238 2239 #ifdef DO_SELECT 2240 fd_set readfds; 2241 struct timeval timeout; 2242 #endif 2243 2244 struct sctp_stream_request_struct *sctp_stream_request; 2245 struct sctp_stream_response_struct *sctp_stream_response; 2246 struct sctp_stream_results_struct *sctp_stream_results; 2247 2248 #ifdef DO_SELECT 2249 FD_ZERO(&readfds); 2250 timeout.tv_sec = 1; 2251 timeout.tv_usec = 0; 2252 #endif 2253 2254 sctp_stream_request = 2255 (struct sctp_stream_request_struct *)netperf_request.content.test_specific_data; 2256 sctp_stream_response = 2257 (struct sctp_stream_response_struct *)netperf_response.content.test_specific_data; 2258 sctp_stream_results = 2259 (struct sctp_stream_results_struct *)netperf_response.content.test_specific_data; 2260 2261 if (debug) { 2262 fprintf(where,"netserver: recv_sctp_stream: entered...\n"); 2263 fflush(where); 2264 } 2265 2266 /* We want to set-up the listen socket with all the desired */ 2267 /* parameters and then let the initiator know that all is ready. If */ 2268 /* socket size defaults are to be used, then the initiator will have */ 2269 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 2270 /* send-back what they are. If that information cannot be determined, */ 2271 /* then we send-back -1's for the sizes. If things go wrong for any */ 2272 /* reason, we will drop back ten yards and punt. */ 2273 2274 /* If anything goes wrong, we want the remote to know about it. It */ 2275 /* would be best if the error that the remote reports to the user is */ 2276 /* the actual error we encountered, rather than some bogus unexpected */ 2277 /* response type message. */ 2278 2279 if (debug) { 2280 fprintf(where,"recv_sctp_stream_1toMany: setting the response type...\n"); 2281 fflush(where); 2282 } 2283 2284 netperf_response.content.response_type = SCTP_STREAM_MANY_RESPONSE; 2285 2286 if (debug) { 2287 fprintf(where,"recv_sctp_stream_1toMany: the response type is set...\n"); 2288 fflush(where); 2289 } 2290 2291 /* We now alter the message_ptr variable to be at the desired */ 2292 /* alignment with the desired offset. */ 2293 2294 if (debug) { 2295 fprintf(where,"recv_sctp_stream_1toMany: requested alignment of %d\n", 2296 sctp_stream_request->recv_alignment); 2297 fflush(where); 2298 } 2299 2300 /* create_data_socket expects to find some things in the global */ 2301 /* variables, so set the globals based on the values in the request. */ 2302 /* once the socket has been created, we will set the response values */ 2303 /* based on the updated value of those globals. raj 7/94 */ 2304 lss_size_req = sctp_stream_request->send_buf_size; 2305 lsr_size_req = sctp_stream_request->recv_buf_size; 2306 loc_nodelay = sctp_stream_request->no_delay; 2307 loc_rcvavoid = sctp_stream_request->so_rcvavoid; 2308 loc_sndavoid = sctp_stream_request->so_sndavoid; 2309 non_block = sctp_stream_request->non_blocking; 2310 2311 set_hostname_and_port(local_name, 2312 port_buffer, 2313 nf_to_af(sctp_stream_request->ipfamily), 2314 sctp_stream_request->port); 2315 2316 local_res = complete_addrinfo(local_name, 2317 local_name, 2318 port_buffer, 2319 nf_to_af(sctp_stream_request->ipfamily), 2320 SOCK_SEQPACKET, 2321 IPPROTO_SCTP, 2322 0); 2323 2324 s_recv = create_data_socket(local_res); 2325 2326 if (s_recv < 0) { 2327 netperf_response.content.serv_errno = errno; 2328 send_response(); 2329 exit(1); 2330 } 2331 2332 /* what sort of sizes did we end-up with? */ 2333 if (sctp_stream_request->receive_size == 0) { 2334 if (lsr_size > 0) { 2335 recv_size = lsr_size; 2336 } 2337 else { 2338 recv_size = 4096; 2339 } 2340 } 2341 else { 2342 recv_size = sctp_stream_request->receive_size; 2343 } 2344 2345 /* we want to set-up our recv_ring in a manner analagous to what we */ 2346 /* do on the sending side. this is more for the sake of symmetry */ 2347 /* than for the needs of say copy avoidance, but it might also be */ 2348 /* more realistic - this way one could conceivably go with a */ 2349 /* double-buffering scheme when taking the data an putting it into */ 2350 /* the filesystem or something like that. raj 7/94 */ 2351 2352 if (recv_width == 0) { 2353 recv_width = (lsr_size/recv_size) + 1; 2354 if (recv_width == 1) recv_width++; 2355 } 2356 2357 recv_ring = allocate_buffer_ring(recv_width, 2358 recv_size, 2359 sctp_stream_request->recv_alignment, 2360 sctp_stream_request->recv_offset); 2361 2362 if (debug) { 2363 fprintf(where,"recv_sctp_stream: receive alignment and offset set...\n"); 2364 fflush(where); 2365 } 2366 2367 /* Now, let's set-up the socket to listen for connections */ 2368 if (listen(s_recv, 5) == -1) { 2369 netperf_response.content.serv_errno = errno; 2370 close(s_recv); 2371 send_response(); 2372 2373 exit(1); 2374 } 2375 2376 /* now get the port number assigned by the system */ 2377 addrlen = sizeof(myaddr_in); 2378 if (getsockname(s_recv, 2379 (struct sockaddr *)&myaddr_in, 2380 &addrlen) == -1){ 2381 netperf_response.content.serv_errno = errno; 2382 close(s_recv); 2383 send_response(); 2384 2385 exit(1); 2386 } 2387 2388 /* Now myaddr_in contains the port and the internet address this is */ 2389 /* returned to the sender also implicitly telling the sender that the */ 2390 /* socket buffer sizing has been done. */ 2391 2392 sctp_stream_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 2393 netperf_response.content.serv_errno = 0; 2394 2395 /* But wait, there's more. If the initiator wanted cpu measurements, */ 2396 /* then we must call the calibrate routine, which will return the max */ 2397 /* rate back to the initiator. If the CPU was not to be measured, or */ 2398 /* something went wrong with the calibration, we will return a -1 to */ 2399 /* the initiator. */ 2400 2401 sctp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */ 2402 if (sctp_stream_request->measure_cpu) { 2403 sctp_stream_response->measure_cpu = 1; 2404 sctp_stream_response->cpu_rate = 2405 calibrate_local_cpu(sctp_stream_request->cpu_rate); 2406 } 2407 else { 2408 sctp_stream_response->measure_cpu = 0; 2409 } 2410 2411 /* before we send the response back to the initiator, pull some of */ 2412 /* the socket parms from the globals */ 2413 sctp_stream_response->send_buf_size = lss_size; 2414 sctp_stream_response->recv_buf_size = lsr_size; 2415 sctp_stream_response->no_delay = loc_nodelay; 2416 sctp_stream_response->so_rcvavoid = loc_rcvavoid; 2417 sctp_stream_response->so_sndavoid = loc_sndavoid; 2418 sctp_stream_response->receive_size = recv_size; 2419 2420 send_response(); 2421 2422 2423 sctp_enable_events(s_recv, SCTP_ASSOC_CHANGE_EV | SCTP_SHUTDOWN_EV); 2424 2425 /* now that we are connected, mark the socket as non-blocking */ 2426 if (non_block) { 2427 if (!set_nonblock(s_recv)) { 2428 close(s_recv); 2429 exit(1); 2430 } 2431 } 2432 2433 2434 /* Now it's time to start receiving data on the connection. We will */ 2435 /* first grab the apropriate counters and then start grabbing. */ 2436 2437 cpu_start(sctp_stream_request->measure_cpu); 2438 2439 /* The loop will exit when the sender does a shutdown, which will */ 2440 /* return a length of zero */ 2441 2442 #ifdef DIRTY 2443 /* we want to dirty some number of consecutive integers in the buffer */ 2444 /* we are about to recv. we may also want to bring some number of */ 2445 /* them cleanly into the cache. The clean ones will follow any dirty */ 2446 /* ones into the cache. */ 2447 2448 dirty_count = sctp_stream_request->dirty_count; 2449 clean_count = sctp_stream_request->clean_count; 2450 message_int_ptr = (int *)recv_ring->buffer_ptr; 2451 for (i = 0; i < dirty_count; i++) { 2452 *message_int_ptr = rand(); 2453 message_int_ptr++; 2454 } 2455 for (i = 0; i < clean_count; i++) { 2456 dirty_count = *message_int_ptr; 2457 message_int_ptr++; 2458 } 2459 #endif /* DIRTY */ 2460 2461 bytes_received = 0; 2462 receive_calls = 0; 2463 2464 while ((len = sctp_recvmsg(s_recv, recv_ring->buffer_ptr, recv_size, 2465 NULL, 0, /* we don't care who it's from */ 2466 NULL, &msg_flags)) != 0) { 2467 if (len < 0) { 2468 if (non_block && errno == EAGAIN) { 2469 Set_errno(0); 2470 continue; 2471 } 2472 netperf_response.content.serv_errno = errno; 2473 send_response(); 2474 close(s_recv); 2475 exit(1); 2476 } 2477 2478 if (msg_flags & MSG_NOTIFICATION) { 2479 if (sctp_process_event(s_recv, recv_ring->buffer_ptr) == SCTP_CLOSE) 2480 break; 2481 2482 continue; 2483 } 2484 2485 bytes_received += len; 2486 receive_calls++; 2487 2488 /* more to the next buffer in the recv_ring */ 2489 recv_ring = recv_ring->next; 2490 2491 #ifdef PAUSE 2492 sleep(1); 2493 #endif /* PAUSE */ 2494 2495 #ifdef DIRTY 2496 message_int_ptr = (int *)(recv_ring->buffer_ptr); 2497 for (i = 0; i < dirty_count; i++) { 2498 *message_int_ptr = rand(); 2499 message_int_ptr++; 2500 } 2501 for (i = 0; i < clean_count; i++) { 2502 dirty_count = *message_int_ptr; 2503 message_int_ptr++; 2504 } 2505 #endif /* DIRTY */ 2506 2507 #ifdef DO_SELECT 2508 FD_SET(s_recv,&readfds); 2509 select(s_recv+1,&readfds,NULL,NULL,&timeout); 2510 #endif /* DO_SELECT */ 2511 2512 } 2513 2514 /* perform a shutdown to signal the sender. in this case, sctp 2515 * will close all associations on this socket 2516 */ 2517 if (close(s_recv) == -1) { 2518 netperf_response.content.serv_errno = errno; 2519 send_response(); 2520 exit(1); 2521 } 2522 2523 cpu_stop(sctp_stream_request->measure_cpu,&elapsed_time); 2524 2525 /* send the results to the sender */ 2526 2527 if (debug) { 2528 fprintf(where, 2529 "recv_sctp_stream: got %g bytes\n", 2530 bytes_received); 2531 fprintf(where, 2532 "recv_sctp_stream: got %d recvs\n", 2533 receive_calls); 2534 fflush(where); 2535 } 2536 2537 sctp_stream_results->bytes_received = htond(bytes_received); 2538 sctp_stream_results->elapsed_time = elapsed_time; 2539 sctp_stream_results->recv_calls = receive_calls; 2540 2541 if (sctp_stream_request->measure_cpu) { 2542 sctp_stream_results->cpu_util = calc_cpu_util(0.0); 2543 }; 2544 2545 if (debug) { 2546 fprintf(where, 2547 "recv_sctp_stream: test complete, sending results.\n"); 2548 fprintf(where, 2549 " bytes_received %g receive_calls %d\n", 2550 bytes_received, 2551 receive_calls); 2552 fprintf(where, 2553 " len %d\n", 2554 len); 2555 fflush(where); 2556 } 2557 2558 sctp_stream_results->cpu_method = cpu_method; 2559 sctp_stream_results->num_cpus = lib_num_loc_cpus; 2560 send_response(); 2561 } 2562 2563 2565 /* this routine implements the sending (netperf) side of the SCTP_RR */ 2566 /* test. */ 2567 2568 void 2569 send_sctp_rr( char remote_host[] ) 2570 { 2571 2572 char *tput_title = "\ 2573 Local /Remote\n\ 2574 Socket Size Request Resp. Elapsed Trans.\n\ 2575 Send Recv Size Size Time Rate \n\ 2576 bytes Bytes bytes bytes secs. per sec \n\n"; 2577 2578 char *tput_fmt_0 = 2579 "%7.2f\n"; 2580 2581 char *tput_fmt_1_line_1 = "\ 2582 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 2583 char *tput_fmt_1_line_2 = "\ 2584 %-6d %-6d\n"; 2585 2586 char *cpu_title = "\ 2587 Local /Remote\n\ 2588 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 2589 Send Recv Size Size Time Rate local remote local remote\n\ 2590 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 2591 2592 char *cpu_fmt_0 = 2593 "%6.3f %c\n"; 2594 2595 char *cpu_fmt_1_line_1 = "\ 2596 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 2597 2598 char *cpu_fmt_1_line_2 = "\ 2599 %-6d %-6d\n"; 2600 2601 char *ksink_fmt = "\ 2602 Alignment Offset\n\ 2603 Local Remote Local Remote\n\ 2604 Send Recv Send Recv\n\ 2605 %5d %5d %5d %5d\n"; 2606 2607 2608 int timed_out = 0; 2609 float elapsed_time; 2610 2611 int len; 2612 char *temp_message_ptr; 2613 int nummessages; 2614 int send_socket; 2615 int trans_remaining; 2616 int msg_flags = 0; 2617 double bytes_xferd; 2618 2619 struct ring_elt *send_ring; 2620 struct ring_elt *recv_ring; 2621 2622 int rsp_bytes_left; 2623 int rsp_bytes_recvd; 2624 2625 float local_cpu_utilization; 2626 float local_service_demand; 2627 float remote_cpu_utilization; 2628 float remote_service_demand; 2629 double thruput; 2630 2631 struct addrinfo *remote_res; 2632 struct addrinfo *local_res; 2633 2634 struct sctp_rr_request_struct *sctp_rr_request; 2635 struct sctp_rr_response_struct *sctp_rr_response; 2636 struct sctp_rr_results_struct *sctp_rr_result; 2637 2638 #ifdef WANT_INTERVALS 2639 int interval_count; 2640 sigset_t signal_set; 2641 #endif /* WANT_INTERVALS */ 2642 2643 sctp_rr_request = 2644 (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data; 2645 sctp_rr_response = 2646 (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data; 2647 sctp_rr_result = 2648 (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data; 2649 2650 #ifdef WANT_HISTOGRAM 2651 time_hist = HIST_new_n(1); 2652 #endif /* WANT_HISTOGRAM */ 2653 2654 /* since we are now disconnected from the code that established the */ 2655 /* control socket, and since we want to be able to use different */ 2656 /* protocols and such, we are passed the name of the remote host and */ 2657 /* must turn that into the test specific addressing information. */ 2658 2659 /* complete_addrinfos will either succede or exit the process */ 2660 complete_addrinfos(&remote_res, 2661 &local_res, 2662 remote_host, 2663 SOCK_STREAM, 2664 IPPROTO_SCTP, 2665 0); 2666 2667 if ( print_headers ) { 2668 print_top_test_header("SCTP REQUEST/RESPONSE TEST", local_res, remote_res); 2669 } 2670 2671 /* initialize a few counters */ 2672 2673 send_ring = NULL; 2674 recv_ring = NULL; 2675 confidence_iteration = 1; 2676 init_stat(); 2677 2678 /* we have a great-big while loop which controls the number of times */ 2679 /* we run a particular test. this is for the calculation of a */ 2680 /* confidence interval (I really should have stayed awake during */ 2681 /* probstats :). If the user did not request confidence measurement */ 2682 /* (no confidence is the default) then we will only go though the */ 2683 /* loop once. the confidence stuff originates from the folks at IBM */ 2684 2685 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 2686 (confidence_iteration <= iteration_min)) { 2687 2688 /* initialize a few counters. we have to remember that we might be */ 2689 /* going through the loop more than once. */ 2690 2691 nummessages = 0; 2692 bytes_xferd = 0.0; 2693 times_up = 0; 2694 timed_out = 0; 2695 trans_remaining = 0; 2696 2697 /* set-up the data buffers with the requested alignment and offset. */ 2698 /* since this is a request/response test, default the send_width and */ 2699 /* recv_width to 1 and not two raj 7/94 */ 2700 2701 if (send_width == 0) send_width = 1; 2702 if (recv_width == 0) recv_width = 1; 2703 2704 if (send_ring == NULL) { 2705 send_ring = allocate_buffer_ring(send_width, 2706 req_size, 2707 local_send_align, 2708 local_send_offset); 2709 } 2710 2711 if (recv_ring == NULL) { 2712 recv_ring = allocate_buffer_ring(recv_width, 2713 rsp_size, 2714 local_recv_align, 2715 local_recv_offset); 2716 } 2717 2718 /*set up the data socket */ 2719 send_socket = create_data_socket(local_res); 2720 2721 if (send_socket < 0){ 2722 perror("netperf: send_sctp_rr: sctp stream data socket"); 2723 exit(1); 2724 } 2725 2726 if (debug) { 2727 fprintf(where,"send_sctp_rr: send_socket obtained...\n"); 2728 } 2729 2730 /* If the user has requested cpu utilization measurements, we must */ 2731 /* calibrate the cpu(s). We will perform this task within the tests */ 2732 /* themselves. If the user has specified the cpu rate, then */ 2733 /* calibrate_local_cpu will return rather quickly as it will have */ 2734 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 2735 /* all the "normal" calibration stuff and return the rate back.*/ 2736 2737 if (local_cpu_usage) { 2738 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 2739 } 2740 2741 /* Tell the remote end to do a listen. The server alters the socket */ 2742 /* paramters on the other side at this point, hence the reason for */ 2743 /* all the values being passed in the setup message. If the user did */ 2744 /* not specify any of the parameters, they will be passed as 0, which */ 2745 /* will indicate to the remote that no changes beyond the system's */ 2746 /* default should be used. Alignment is the exception, it will */ 2747 /* default to 8, which will be no alignment alterations. */ 2748 2749 netperf_request.content.request_type = DO_SCTP_RR; 2750 sctp_rr_request->recv_buf_size = rsr_size_req; 2751 sctp_rr_request->send_buf_size = rss_size_req; 2752 sctp_rr_request->recv_alignment = remote_recv_align; 2753 sctp_rr_request->recv_offset = remote_recv_offset; 2754 sctp_rr_request->send_alignment = remote_send_align; 2755 sctp_rr_request->send_offset = remote_send_offset; 2756 sctp_rr_request->request_size = req_size; 2757 sctp_rr_request->response_size = rsp_size; 2758 sctp_rr_request->no_delay = rem_nodelay; 2759 sctp_rr_request->measure_cpu = remote_cpu_usage; 2760 sctp_rr_request->cpu_rate = remote_cpu_rate; 2761 sctp_rr_request->so_rcvavoid = rem_rcvavoid; 2762 sctp_rr_request->so_sndavoid = rem_sndavoid; 2763 if (test_time) { 2764 sctp_rr_request->test_length = test_time; 2765 } 2766 else { 2767 sctp_rr_request->test_length = test_trans * -1; 2768 } 2769 sctp_rr_request->non_blocking = non_block; 2770 sctp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 2771 2772 if (debug > 1) { 2773 fprintf(where,"netperf: send_sctp_rr: requesting SCTP rr test\n"); 2774 } 2775 2776 send_request(); 2777 2778 /* The response from the remote will contain all of the relevant */ 2779 /* socket parameters for this test type. We will put them back into */ 2780 /* the variables here so they can be displayed if desired. The */ 2781 /* remote will have calibrated CPU if necessary, and will have done */ 2782 /* all the needed set-up we will have calibrated the cpu locally */ 2783 /* before sending the request, and will grab the counter value right*/ 2784 /* after the connect returns. The remote will grab the counter right*/ 2785 /* after the accept call. This saves the hassle of extra messages */ 2786 /* being sent for the sctp tests. */ 2787 2788 recv_response(); 2789 2790 if (!netperf_response.content.serv_errno) { 2791 if (debug) 2792 fprintf(where,"remote listen done.\n"); 2793 rsr_size = sctp_rr_response->recv_buf_size; 2794 rss_size = sctp_rr_response->send_buf_size; 2795 rem_nodelay = sctp_rr_response->no_delay; 2796 remote_cpu_usage = sctp_rr_response->measure_cpu; 2797 remote_cpu_rate = sctp_rr_response->cpu_rate; 2798 /* make sure that port numbers are in network order */ 2799 set_port_number(remote_res, 2800 (unsigned short)sctp_rr_response->data_port_number); 2801 } 2802 else { 2803 Set_errno(netperf_response.content.serv_errno); 2804 fprintf(where, 2805 "netperf: remote error %d", 2806 netperf_response.content.serv_errno); 2807 perror(""); 2808 fflush(where); 2809 2810 exit(1); 2811 } 2812 2813 /*Connect up to the remote port on the data socket */ 2814 if (connect(send_socket, 2815 remote_res->ai_addr, 2816 remote_res->ai_addrlen) <0){ 2817 perror("netperf: send_sctp_rr data socket connect failed"); 2818 exit(1); 2819 } 2820 2821 /* don't need events for 1-to-1 API with request-response tests */ 2822 sctp_enable_events(send_socket, 0); 2823 2824 /* set non-blocking if needed */ 2825 if (non_block) { 2826 if (!set_nonblock(send_socket)) { 2827 close(send_socket); 2828 exit(1); 2829 } 2830 } 2831 2832 /* Data Socket set-up is finished. If there were problems, either the */ 2833 /* connect would have failed, or the previous response would have */ 2834 /* indicated a problem. I failed to see the value of the extra */ 2835 /* message after the accept on the remote. If it failed, we'll see it */ 2836 /* here. If it didn't, we might as well start pumping data. */ 2837 2838 /* Set-up the test end conditions. For a request/response test, they */ 2839 /* can be either time or transaction based. */ 2840 2841 if (test_time) { 2842 /* The user wanted to end the test after a period of time. */ 2843 times_up = 0; 2844 trans_remaining = 0; 2845 start_timer(test_time); 2846 } 2847 else { 2848 /* The tester wanted to send a number of bytes. */ 2849 trans_remaining = test_bytes; 2850 times_up = 1; 2851 } 2852 2853 /* The cpu_start routine will grab the current time and possibly */ 2854 /* value of the idle counter for later use in measuring cpu */ 2855 /* utilization and/or service demand and thruput. */ 2856 2857 cpu_start(local_cpu_usage); 2858 2859 #ifdef WANT_INTERVALS 2860 if ((interval_burst) || (demo_mode)) { 2861 /* zero means that we never pause, so we never should need the */ 2862 /* interval timer, unless we are in demo_mode */ 2863 start_itimer(interval_wate); 2864 } 2865 interval_count = interval_burst; 2866 /* get the signal set for the call to sigsuspend */ 2867 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { 2868 fprintf(where, 2869 "send_sctp_rr: unable to get sigmask errno %d\n", 2870 errno); 2871 fflush(where); 2872 exit(1); 2873 } 2874 #endif /* WANT_INTERVALS */ 2875 2876 /* We use an "OR" to control test execution. When the test is */ 2877 /* controlled by time, the byte count check will always return false. */ 2878 /* When the test is controlled by byte count, the time test will */ 2879 /* always return false. When the test is finished, the whole */ 2880 /* expression will go false and we will stop sending data. I think I */ 2881 /* just arbitrarily decrement trans_remaining for the timed test, but */ 2882 /* will not do that just yet... One other question is whether or not */ 2883 /* the send buffer and the receive buffer should be the same buffer. */ 2884 2885 #ifdef WANT_FIRST_BURST 2886 { 2887 int i; 2888 for (i = 0; i < first_burst_size; i++) { 2889 if((len=sctp_sendmsg(send_socket, 2890 send_ring->buffer_ptr, req_size, 2891 NULL, 0, /* don't need addrs with 1-to-1 */ 2892 0, 0, 0, 0, 0)) != req_size) { 2893 /* we should never hit the end of the test in the first burst */ 2894 perror("send_sctp_rr: initial burst data send error"); 2895 exit(1); 2896 } 2897 } 2898 } 2899 #endif /* WANT_FIRST_BURST */ 2900 2901 while ((!times_up) || (trans_remaining > 0)) { 2902 /* send the request. we assume that if we use a blocking socket, */ 2903 /* the request will be sent at one shot. */ 2904 2905 #ifdef WANT_HISTOGRAM 2906 /* timestamp just before our call to send, and then again just */ 2907 /* after the receive raj 8/94 */ 2908 HIST_timestamp_start(time_hist); 2909 #endif /* WANT_HISTOGRAM */ 2910 2911 while ((len=sctp_sendmsg(send_socket, 2912 send_ring->buffer_ptr, req_size, 2913 NULL, 0, /* don't need addrs with 1-to-1 */ 2914 0, 0, 0, 0, 0)) != req_size) { 2915 if (non_block && errno == EAGAIN) { 2916 /* try sending again */ 2917 continue; 2918 } else if (SOCKET_EINTR(len) || (errno == 0)) { 2919 /* we hit the end of a */ 2920 /* timed test. */ 2921 timed_out = 1; 2922 break; 2923 } 2924 perror("send_sctp_rr: data send error"); 2925 exit(1); 2926 } 2927 2928 if (timed_out) { 2929 /* we timed out while sending. break out another level */ 2930 break; 2931 } 2932 send_ring = send_ring->next; 2933 2934 /* receive the response */ 2935 rsp_bytes_left = rsp_size; 2936 temp_message_ptr = recv_ring->buffer_ptr; 2937 do { 2938 msg_flags = 0; 2939 if ((rsp_bytes_recvd=sctp_recvmsg(send_socket, 2940 temp_message_ptr, rsp_bytes_left, 2941 NULL, 0, 2942 NULL, &msg_flags)) < 0) { 2943 if (errno == EINTR) { 2944 /* We hit the end of a timed test. */ 2945 timed_out = 1; 2946 break; 2947 } else if (non_block && errno == EAGAIN) { 2948 continue; 2949 } 2950 perror("send_sctp_rr: data recv error"); 2951 exit(1); 2952 } 2953 rsp_bytes_left -= rsp_bytes_recvd; 2954 temp_message_ptr += rsp_bytes_recvd; 2955 } while (!(msg_flags & MSG_EOR)); 2956 2957 recv_ring = recv_ring->next; 2958 2959 if (timed_out) { 2960 /* we may have been in a nested while loop - we need */ 2961 /* another call to break. */ 2962 break; 2963 } 2964 2965 #ifdef WANT_HISTOGRAM 2966 HIST_timestamp_stop_add(time_hist); 2967 #endif /* WANT_HISTOGRAM */ 2968 #ifdef WANT_INTERVALS 2969 if (demo_mode) { 2970 units_this_tick += 1; 2971 } 2972 /* in this case, the interval count is the count-down couter */ 2973 /* to decide to sleep for a little bit */ 2974 if ((interval_burst) && (--interval_count == 0)) { 2975 /* call sigsuspend and wait for the interval timer to get us */ 2976 /* out */ 2977 if (debug > 1) { 2978 fprintf(where,"about to suspend\n"); 2979 fflush(where); 2980 } 2981 if (sigsuspend(&signal_set) == EFAULT) { 2982 fprintf(where, 2983 "send_sctp_rr: fault with signal set!\n"); 2984 fflush(where); 2985 exit(1); 2986 } 2987 interval_count = interval_burst; 2988 } 2989 #endif /* WANT_INTERVALS */ 2990 2991 nummessages++; 2992 if (trans_remaining) { 2993 trans_remaining--; 2994 } 2995 2996 if (debug > 3) { 2997 if ((nummessages % 100) == 0) { 2998 fprintf(where, 2999 "Transaction %d completed\n", 3000 nummessages); 3001 fflush(where); 3002 } 3003 } 3004 } 3005 3006 /* At this point we used to call shutdown on the data socket to be */ 3007 /* sure all the data was delivered, but this was not germane in a */ 3008 /* request/response test, and it was causing the tests to "hang" when */ 3009 /* they were being controlled by time. So, I have replaced this */ 3010 /* shutdown call with a call to close that can be found later in the */ 3011 /* procedure. */ 3012 3013 /* this call will always give us the elapsed time for the test, and */ 3014 /* will also store-away the necessaries for cpu utilization */ 3015 3016 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 3017 /* measured? how long */ 3018 /* did we really run? */ 3019 3020 /* Get the statistics from the remote end. The remote will have */ 3021 /* calculated CPU utilization. If it wasn't supposed to care, it */ 3022 /* will return obvious values. */ 3023 3024 recv_response(); 3025 if (!netperf_response.content.serv_errno) { 3026 if (debug) 3027 fprintf(where,"remote results obtained\n"); 3028 } 3029 else { 3030 Set_errno(netperf_response.content.serv_errno); 3031 fprintf(where,"netperf: remote error %d", 3032 netperf_response.content.serv_errno); 3033 perror(""); 3034 fflush(where); 3035 exit(1); 3036 } 3037 3038 /* We now calculate what our throughput was for the test. */ 3039 3040 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 3041 thruput = nummessages/elapsed_time; 3042 3043 if (local_cpu_usage || remote_cpu_usage) { 3044 /* We must now do a little math for service demand and cpu */ 3045 /* utilization for the system(s) */ 3046 /* Of course, some of the information might be bogus because */ 3047 /* there was no idle counter in the kernel(s). We need to make */ 3048 /* a note of this for the user's benefit...*/ 3049 if (local_cpu_usage) { 3050 local_cpu_utilization = calc_cpu_util(0.0); 3051 /* since calc_service demand is doing ms/Kunit we will */ 3052 /* multiply the number of transaction by 1024 to get */ 3053 /* "good" numbers */ 3054 local_service_demand = calc_service_demand((double) nummessages*1024, 3055 0.0, 3056 0.0, 3057 0); 3058 } 3059 else { 3060 local_cpu_utilization = (float) -1.0; 3061 local_service_demand = (float) -1.0; 3062 } 3063 3064 if (remote_cpu_usage) { 3065 remote_cpu_utilization = sctp_rr_result->cpu_util; 3066 /* since calc_service demand is doing ms/Kunit we will */ 3067 /* multiply the number of transaction by 1024 to get */ 3068 /* "good" numbers */ 3069 remote_service_demand = calc_service_demand((double) nummessages*1024, 3070 0.0, 3071 remote_cpu_utilization, 3072 sctp_rr_result->num_cpus); 3073 } 3074 else { 3075 remote_cpu_utilization = (float) -1.0; 3076 remote_service_demand = (float) -1.0; 3077 } 3078 3079 } 3080 else { 3081 /* we were not measuring cpu, for the confidence stuff, we */ 3082 /* should make it -1.0 */ 3083 local_cpu_utilization = (float) -1.0; 3084 local_service_demand = (float) -1.0; 3085 remote_cpu_utilization = (float) -1.0; 3086 remote_service_demand = (float) -1.0; 3087 } 3088 3089 /* at this point, we want to calculate the confidence information. */ 3090 /* if debugging is on, calculate_confidence will print-out the */ 3091 /* parameters we pass it */ 3092 3093 calculate_confidence(confidence_iteration, 3094 elapsed_time, 3095 thruput, 3096 local_cpu_utilization, 3097 remote_cpu_utilization, 3098 local_service_demand, 3099 remote_service_demand); 3100 3101 3102 confidence_iteration++; 3103 3104 /* we are now done with the socket, so close it */ 3105 close(send_socket); 3106 3107 } 3108 3109 retrieve_confident_values(&elapsed_time, 3110 &thruput, 3111 &local_cpu_utilization, 3112 &remote_cpu_utilization, 3113 &local_service_demand, 3114 &remote_service_demand); 3115 3116 /* We are now ready to print all the information. If the user */ 3117 /* has specified zero-level verbosity, we will just print the */ 3118 /* local service demand, or the remote service demand. If the */ 3119 /* user has requested verbosity level 1, he will get the basic */ 3120 /* "streamperf" numbers. If the user has specified a verbosity */ 3121 /* of greater than 1, we will display a veritable plethora of */ 3122 /* background information from outside of this block as it it */ 3123 /* not cpu_measurement specific... */ 3124 3125 if (confidence < 0) { 3126 /* we did not hit confidence, but were we asked to look for it? */ 3127 if (iteration_max > 1) { 3128 display_confidence(); 3129 } 3130 } 3131 3132 if (local_cpu_usage || remote_cpu_usage) { 3133 local_cpu_method = format_cpu_method(cpu_method); 3134 remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method); 3135 3136 switch (verbosity) { 3137 case 0: 3138 if (local_cpu_usage) { 3139 fprintf(where, 3140 cpu_fmt_0, 3141 local_service_demand, 3142 local_cpu_method); 3143 } 3144 else { 3145 fprintf(where, 3146 cpu_fmt_0, 3147 remote_service_demand, 3148 remote_cpu_method); 3149 } 3150 break; 3151 case 1: 3152 case 2: 3153 if (print_headers) { 3154 fprintf(where, 3155 cpu_title, 3156 local_cpu_method, 3157 remote_cpu_method); 3158 } 3159 3160 fprintf(where, 3161 cpu_fmt_1_line_1, /* the format string */ 3162 lss_size, /* local sendbuf size */ 3163 lsr_size, 3164 req_size, /* how large were the requests */ 3165 rsp_size, /* guess */ 3166 elapsed_time, /* how long was the test */ 3167 thruput, 3168 local_cpu_utilization, /* local cpu */ 3169 remote_cpu_utilization, /* remote cpu */ 3170 local_service_demand, /* local service demand */ 3171 remote_service_demand); /* remote service demand */ 3172 fprintf(where, 3173 cpu_fmt_1_line_2, 3174 rss_size, 3175 rsr_size); 3176 break; 3177 } 3178 } 3179 else { 3180 /* The tester did not wish to measure service demand. */ 3181 3182 switch (verbosity) { 3183 case 0: 3184 fprintf(where, 3185 tput_fmt_0, 3186 thruput); 3187 break; 3188 case 1: 3189 case 2: 3190 if (print_headers) { 3191 fprintf(where,tput_title,format_units()); 3192 } 3193 3194 fprintf(where, 3195 tput_fmt_1_line_1, /* the format string */ 3196 lss_size, 3197 lsr_size, 3198 req_size, /* how large were the requests */ 3199 rsp_size, /* how large were the responses */ 3200 elapsed_time, /* how long did it take */ 3201 thruput); 3202 fprintf(where, 3203 tput_fmt_1_line_2, 3204 rss_size, /* remote recvbuf size */ 3205 rsr_size); 3206 3207 break; 3208 } 3209 } 3210 3211 /* it would be a good thing to include information about some of the */ 3212 /* other parameters that may have been set for this test, but at the */ 3213 /* moment, I do not wish to figure-out all the formatting, so I will */ 3214 /* just put this comment here to help remind me that it is something */ 3215 /* that should be done at a later time. */ 3216 3217 /* how to handle the verbose information in the presence of */ 3218 /* confidence intervals is yet to be determined... raj 11/94 */ 3219 if (verbosity > 1) { 3220 /* The user wanted to know it all, so we will give it to him. */ 3221 /* This information will include as much as we can find about */ 3222 /* TCP statistics, the alignments of the sends and receives */ 3223 /* and all that sort of rot... */ 3224 3225 fprintf(where, 3226 ksink_fmt, 3227 local_send_align, 3228 remote_recv_offset, 3229 local_send_offset, 3230 remote_recv_offset); 3231 3232 #ifdef WANT_HISTOGRAM 3233 fprintf(where,"\nHistogram of request/response times\n"); 3234 fflush(where); 3235 HIST_report(time_hist); 3236 #endif /* WANT_HISTOGRAM */ 3237 3238 } 3239 3240 } 3241 3242 3243 /* this routine implements the receive (netserver) side of a TCP_RR */ 3245 /* test */ 3246 void 3247 recv_sctp_rr( void ) 3248 { 3249 3250 struct ring_elt *send_ring; 3251 struct ring_elt *recv_ring; 3252 3253 struct addrinfo *local_res; 3254 char local_name[BUFSIZ]; 3255 char port_buffer[PORTBUFSIZE]; 3256 3257 struct sockaddr_in myaddr_in, peeraddr_in; 3258 int s_listen, s_data; 3259 socklen_t addrlen; 3260 char *temp_message_ptr; 3261 int trans_received; 3262 int trans_remaining; 3263 int bytes_sent; 3264 int request_bytes_recvd; 3265 int request_bytes_remaining; 3266 int timed_out = 0; 3267 float elapsed_time; 3268 3269 struct sctp_rr_request_struct *sctp_rr_request; 3270 struct sctp_rr_response_struct *sctp_rr_response; 3271 struct sctp_rr_results_struct *sctp_rr_results; 3272 3273 sctp_rr_request = 3274 (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data; 3275 sctp_rr_response = 3276 (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data; 3277 sctp_rr_results = 3278 (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data; 3279 3280 if (debug) { 3281 fprintf(where,"netserver: recv_sctp_rr: entered...\n"); 3282 fflush(where); 3283 } 3284 3285 /* We want to set-up the listen socket with all the desired */ 3286 /* parameters and then let the initiator know that all is ready. If */ 3287 /* socket size defaults are to be used, then the initiator will have */ 3288 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 3289 /* send-back what they are. If that information cannot be determined, */ 3290 /* then we send-back -1's for the sizes. If things go wrong for any */ 3291 /* reason, we will drop back ten yards and punt. */ 3292 3293 /* If anything goes wrong, we want the remote to know about it. It */ 3294 /* would be best if the error that the remote reports to the user is */ 3295 /* the actual error we encountered, rather than some bogus unexpected */ 3296 /* response type message. */ 3297 3298 if (debug) { 3299 fprintf(where,"recv_sctp_rr: setting the response type...\n"); 3300 fflush(where); 3301 } 3302 3303 netperf_response.content.response_type = SCTP_RR_RESPONSE; 3304 3305 if (debug) { 3306 fprintf(where,"recv_sctp_rr: the response type is set...\n"); 3307 fflush(where); 3308 } 3309 3310 /* allocate the recv and send rings with the requested alignments */ 3311 /* and offsets. raj 7/94 */ 3312 if (debug) { 3313 fprintf(where,"recv_sctp_rr: requested recv alignment of %d offset %d\n", 3314 sctp_rr_request->recv_alignment, 3315 sctp_rr_request->recv_offset); 3316 fprintf(where,"recv_sctp_rr: requested send alignment of %d offset %d\n", 3317 sctp_rr_request->send_alignment, 3318 sctp_rr_request->send_offset); 3319 fflush(where); 3320 } 3321 3322 /* at some point, these need to come to us from the remote system */ 3323 if (send_width == 0) send_width = 1; 3324 if (recv_width == 0) recv_width = 1; 3325 3326 send_ring = allocate_buffer_ring(send_width, 3327 sctp_rr_request->response_size, 3328 sctp_rr_request->send_alignment, 3329 sctp_rr_request->send_offset); 3330 3331 recv_ring = allocate_buffer_ring(recv_width, 3332 sctp_rr_request->request_size, 3333 sctp_rr_request->recv_alignment, 3334 sctp_rr_request->recv_offset); 3335 3336 3337 /* Grab a socket to listen on, and then listen on it. */ 3338 3339 if (debug) { 3340 fprintf(where,"recv_sctp_rr: grabbing a socket...\n"); 3341 fflush(where); 3342 } 3343 3344 /* create_data_socket expects to find some things in the global */ 3345 /* variables, so set the globals based on the values in the request. */ 3346 /* once the socket has been created, we will set the response values */ 3347 /* based on the updated value of those globals. raj 7/94 */ 3348 lss_size_req = sctp_rr_request->send_buf_size; 3349 lsr_size_req = sctp_rr_request->recv_buf_size; 3350 loc_nodelay = sctp_rr_request->no_delay; 3351 loc_rcvavoid = sctp_rr_request->so_rcvavoid; 3352 loc_sndavoid = sctp_rr_request->so_sndavoid; 3353 non_block = sctp_rr_request->non_blocking; 3354 3355 set_hostname_and_port(local_name, 3356 port_buffer, 3357 nf_to_af(sctp_rr_request->ipfamily), 3358 sctp_rr_request->port); 3359 3360 local_res = complete_addrinfo(local_name, 3361 local_name, 3362 port_buffer, 3363 nf_to_af(sctp_rr_request->ipfamily), 3364 SOCK_STREAM, 3365 IPPROTO_SCTP, 3366 0); 3367 3368 s_listen = create_data_socket(local_res); 3369 3370 if (s_listen < 0) { 3371 netperf_response.content.serv_errno = errno; 3372 send_response(); 3373 3374 exit(1); 3375 } 3376 3377 /* Now, let's set-up the socket to listen for connections */ 3378 if (listen(s_listen, 5) == -1) { 3379 netperf_response.content.serv_errno = errno; 3380 close(s_listen); 3381 send_response(); 3382 3383 exit(1); 3384 } 3385 3386 3387 /* now get the port number assigned by the system */ 3388 addrlen = sizeof(myaddr_in); 3389 if (getsockname(s_listen, 3390 (struct sockaddr *)&myaddr_in, &addrlen) == -1){ 3391 netperf_response.content.serv_errno = errno; 3392 close(s_listen); 3393 send_response(); 3394 3395 exit(1); 3396 } 3397 3398 /* Now myaddr_in contains the port and the internet address this is */ 3399 /* returned to the sender also implicitly telling the sender that the */ 3400 /* socket buffer sizing has been done. */ 3401 3402 sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 3403 netperf_response.content.serv_errno = 0; 3404 3405 /* But wait, there's more. If the initiator wanted cpu measurements, */ 3406 /* then we must call the calibrate routine, which will return the max */ 3407 /* rate back to the initiator. If the CPU was not to be measured, or */ 3408 /* something went wrong with the calibration, we will return a 0.0 to */ 3409 /* the initiator. */ 3410 3411 sctp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 3412 sctp_rr_response->measure_cpu = 0; 3413 3414 if (sctp_rr_request->measure_cpu) { 3415 sctp_rr_response->measure_cpu = 1; 3416 sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate); 3417 } 3418 3419 3420 /* before we send the response back to the initiator, pull some of */ 3421 /* the socket parms from the globals */ 3422 sctp_rr_response->send_buf_size = lss_size; 3423 sctp_rr_response->recv_buf_size = lsr_size; 3424 sctp_rr_response->no_delay = loc_nodelay; 3425 sctp_rr_response->so_rcvavoid = loc_rcvavoid; 3426 sctp_rr_response->so_sndavoid = loc_sndavoid; 3427 sctp_rr_response->test_length = sctp_rr_request->test_length; 3428 send_response(); 3429 3430 addrlen = sizeof(peeraddr_in); 3431 3432 if ((s_data = accept(s_listen, 3433 (struct sockaddr *)&peeraddr_in, 3434 &addrlen)) == -1) { 3435 /* Let's just punt. The remote will be given some information */ 3436 close(s_listen); 3437 3438 exit(1); 3439 } 3440 3441 /* we do not need events on a 1-to-1 RR test. The test will finish 3442 * once all transactions are done. 3443 */ 3444 3445 /* now that we are connected, mark the socket as non-blocking */ 3446 if (non_block) { 3447 if (!set_nonblock(s_data)) { 3448 perror("netperf: set_nonblock"); 3449 exit(1); 3450 } 3451 } 3452 3453 #ifdef KLUDGE_SOCKET_OPTIONS 3454 /* this is for those systems which *INCORRECTLY* fail to pass */ 3455 /* attributes across an accept() call. Including this goes against */ 3456 /* my better judgement :( raj 11/95 */ 3457 3458 kludge_socket_options(s_data); 3459 3460 #endif /* KLUDGE_SOCKET_OPTIONS */ 3461 3462 if (debug) { 3463 fprintf(where,"recv_sctp_rr: accept completes on the data connection.\n"); 3464 fflush(where); 3465 } 3466 3467 /* Now it's time to start receiving data on the connection. We will */ 3468 /* first grab the apropriate counters and then start grabbing. */ 3469 3470 cpu_start(sctp_rr_request->measure_cpu); 3471 3472 /* The loop will exit when we hit the end of the test time, or when */ 3473 /* we have exchanged the requested number of transactions. */ 3474 3475 if (sctp_rr_request->test_length > 0) { 3476 times_up = 0; 3477 trans_remaining = 0; 3478 start_timer(sctp_rr_request->test_length + PAD_TIME); 3479 } 3480 else { 3481 times_up = 1; 3482 trans_remaining = sctp_rr_request->test_length * -1; 3483 } 3484 3485 trans_received = 0; 3486 3487 while ((!times_up) || (trans_remaining > 0)) { 3488 int msg_flags = 0; 3489 3490 temp_message_ptr = recv_ring->buffer_ptr; 3491 request_bytes_remaining = sctp_rr_request->request_size; 3492 while(!(msg_flags & MSG_EOR)) { 3493 if((request_bytes_recvd=sctp_recvmsg(s_data, 3494 temp_message_ptr, 3495 request_bytes_remaining, 3496 NULL, 0, 3497 NULL, &msg_flags)) < 0) { 3498 if (errno == EINTR) { 3499 /* the timer popped */ 3500 timed_out = 1; 3501 break; 3502 } else if (non_block && errno == EAGAIN) { 3503 continue; /* while request_bytes_remaining */ 3504 } 3505 netperf_response.content.serv_errno = errno; 3506 send_response(); 3507 exit(1); 3508 } 3509 request_bytes_remaining -= request_bytes_recvd; 3510 temp_message_ptr += request_bytes_recvd; 3511 } 3512 3513 recv_ring = recv_ring->next; 3514 3515 if (timed_out) { 3516 /* we hit the end of the test based on time - lets */ 3517 /* bail out of here now... */ 3518 if (debug) { 3519 fprintf(where,"yo55\n"); 3520 fflush(where); 3521 } 3522 break; 3523 } 3524 3525 3526 /* Now, send the response to the remote 3527 * In 1-to-1 API destination addr is not needed. 3528 */ 3529 while ((bytes_sent=sctp_sendmsg(s_data, 3530 send_ring->buffer_ptr, 3531 sctp_rr_request->response_size, 3532 NULL, 0, 3533 0, 0, 0, 0, 0)) == -1) { 3534 if (errno == EINTR) { 3535 /* the test timer has popped */ 3536 timed_out = 1; 3537 break; 3538 } else if (non_block && errno == EAGAIN) { 3539 continue; 3540 } 3541 3542 netperf_response.content.serv_errno = 982; 3543 send_response(); 3544 exit(1); 3545 } 3546 3547 if (timed_out) { 3548 /* we hit the end of the test based on time - lets */ 3549 /* bail out of here now... */ 3550 if (debug) { 3551 fprintf(where,"yo6\n"); 3552 fflush(where); 3553 } 3554 break; 3555 } 3556 3557 send_ring = send_ring->next; 3558 3559 trans_received++; 3560 if (trans_remaining) { 3561 trans_remaining--; 3562 } 3563 } 3564 3565 3566 /* The loop now exits due to timeout or transaction count being */ 3567 /* reached */ 3568 3569 cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time); 3570 3571 stop_timer(); 3572 3573 if (timed_out) { 3574 /* we ended the test by time, which was at least 2 seconds */ 3575 /* longer than we wanted to run. so, we want to subtract */ 3576 /* PAD_TIME from the elapsed_time. */ 3577 elapsed_time -= PAD_TIME; 3578 } 3579 3580 /* send the results to the sender */ 3581 3582 if (debug) { 3583 fprintf(where, 3584 "recv_sctp_rr: got %d transactions\n", 3585 trans_received); 3586 fflush(where); 3587 } 3588 3589 sctp_rr_results->bytes_received = (trans_received * 3590 (sctp_rr_request->request_size + 3591 sctp_rr_request->response_size)); 3592 sctp_rr_results->trans_received = trans_received; 3593 sctp_rr_results->elapsed_time = elapsed_time; 3594 sctp_rr_results->cpu_method = cpu_method; 3595 sctp_rr_results->num_cpus = lib_num_loc_cpus; 3596 if (sctp_rr_request->measure_cpu) { 3597 sctp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 3598 } 3599 3600 if (debug) { 3601 fprintf(where, 3602 "recv_sctp_rr: test complete, sending results.\n"); 3603 fflush(where); 3604 } 3605 3606 /* we are now done with the sockets */ 3607 send_response(); 3608 3609 close(s_data); 3610 close(s_listen); 3611 3612 } 3613 3614 3615 3617 /* this routine implements the sending (netperf) side of the 3618 SCTP_RR_1TOMANY test */ 3619 3620 void 3621 send_sctp_rr_1toMany( char remote_host[] ) 3622 { 3623 3624 char *tput_title = "\ 3625 Local /Remote\n\ 3626 Socket Size Request Resp. Elapsed Trans.\n\ 3627 Send Recv Size Size Time Rate \n\ 3628 bytes Bytes bytes bytes secs. per sec \n\n"; 3629 3630 char *tput_fmt_0 = 3631 "%7.2f\n"; 3632 3633 char *tput_fmt_1_line_1 = "\ 3634 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n"; 3635 char *tput_fmt_1_line_2 = "\ 3636 %-6d %-6d\n"; 3637 3638 char *cpu_title = "\ 3639 Local /Remote\n\ 3640 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\ 3641 Send Recv Size Size Time Rate local remote local remote\n\ 3642 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n"; 3643 3644 char *cpu_fmt_0 = 3645 "%6.3f %c\n"; 3646 3647 char *cpu_fmt_1_line_1 = "\ 3648 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n"; 3649 3650 char *cpu_fmt_1_line_2 = "\ 3651 %-6d %-6d\n"; 3652 3653 char *ksink_fmt = "\ 3654 Alignment Offset\n\ 3655 Local Remote Local Remote\n\ 3656 Send Recv Send Recv\n\ 3657 %5d %5d %5d %5d\n"; 3658 3659 3660 int timed_out = 0; 3661 float elapsed_time; 3662 3663 int len, j = 0; 3664 char *temp_message_ptr; 3665 int nummessages; 3666 int *send_socket; 3667 int trans_remaining; 3668 double bytes_xferd; 3669 int msg_flags = 0; 3670 3671 struct ring_elt *send_ring; 3672 struct ring_elt *recv_ring; 3673 3674 int rsp_bytes_left; 3675 int rsp_bytes_recvd; 3676 3677 float local_cpu_utilization; 3678 float local_service_demand; 3679 float remote_cpu_utilization; 3680 float remote_service_demand; 3681 double thruput; 3682 3683 struct addrinfo *local_res; 3684 struct addrinfo *remote_res; 3685 3686 struct sctp_rr_request_struct *sctp_rr_request; 3687 struct sctp_rr_response_struct *sctp_rr_response; 3688 struct sctp_rr_results_struct *sctp_rr_result; 3689 3690 #ifdef WANT_INTERVALS 3691 int interval_count; 3692 sigset_t signal_set; 3693 #endif /* WANT_INTERVALS */ 3694 3695 sctp_rr_request = 3696 (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data; 3697 sctp_rr_response = 3698 (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data; 3699 sctp_rr_result = 3700 (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data; 3701 3702 #ifdef WANT_HISTOGRAM 3703 time_hist = HIST_new_n(1); 3704 #endif /* WANT_HISTOGRAM */ 3705 3706 /* since we are now disconnected from the code that established the */ 3707 /* control socket, and since we want to be able to use different */ 3708 /* protocols and such, we are passed the name of the remote host and */ 3709 /* must turn that into the test specific addressing information. */ 3710 3711 complete_addrinfos(&remote_res, 3712 &local_res, 3713 remote_host, 3714 SOCK_SEQPACKET, 3715 IPPROTO_SCTP, 3716 0); 3717 3718 if ( print_headers ) { 3719 print_top_test_header("SCTP 1-TO-MANY REQUEST/RESPONSE TEST",local_res,remote_res); 3720 } 3721 3722 /* initialize a few counters */ 3723 3724 send_ring = NULL; 3725 recv_ring = NULL; 3726 confidence_iteration = 1; 3727 init_stat(); 3728 3729 send_socket = malloc(sizeof(int) * num_associations); 3730 if (send_socket == NULL) { 3731 fprintf(where, 3732 "Could not create the socket array for %d associations", 3733 num_associations); 3734 fflush(where); 3735 exit(1); 3736 } 3737 3738 /* we have a great-big while loop which controls the number of times */ 3739 /* we run a particular test. this is for the calculation of a */ 3740 /* confidence interval (I really should have stayed awake during */ 3741 /* probstats :). If the user did not request confidence measurement */ 3742 /* (no confidence is the default) then we will only go though the */ 3743 /* loop once. the confidence stuff originates from the folks at IBM */ 3744 3745 while (((confidence < 0) && (confidence_iteration < iteration_max)) || 3746 (confidence_iteration <= iteration_min)) { 3747 3748 /* initialize a few counters. we have to remember that we might be */ 3749 /* going through the loop more than once. */ 3750 3751 nummessages = 0; 3752 bytes_xferd = 0.0; 3753 times_up = 0; 3754 timed_out = 0; 3755 trans_remaining = 0; 3756 3757 /* set-up the data buffers with the requested alignment and offset. */ 3758 /* since this is a request/response test, default the send_width and */ 3759 /* recv_width to 1 and not two raj 7/94 */ 3760 3761 if (send_width == 0) send_width = 1; 3762 if (recv_width == 0) recv_width = 1; 3763 3764 if (send_ring == NULL) { 3765 send_ring = allocate_buffer_ring(send_width, 3766 req_size, 3767 local_send_align, 3768 local_send_offset); 3769 } 3770 3771 if (recv_ring == NULL) { 3772 recv_ring = allocate_buffer_ring(recv_width, 3773 rsp_size, 3774 local_recv_align, 3775 local_recv_offset); 3776 } 3777 3778 /* If the user has requested cpu utilization measurements, we must */ 3779 /* calibrate the cpu(s). We will perform this task within the tests */ 3780 /* themselves. If the user has specified the cpu rate, then */ 3781 /* calibrate_local_cpu will return rather quickly as it will have */ 3782 /* nothing to do. If local_cpu_rate is zero, then we will go through */ 3783 /* all the "normal" calibration stuff and return the rate back.*/ 3784 3785 if (local_cpu_usage) { 3786 local_cpu_rate = calibrate_local_cpu(local_cpu_rate); 3787 } 3788 3789 /* Tell the remote end to do a listen. The server alters the socket */ 3790 /* paramters on the other side at this point, hence the reason for */ 3791 /* all the values being passed in the setup message. If the user did */ 3792 /* not specify any of the parameters, they will be passed as 0, which */ 3793 /* will indicate to the remote that no changes beyond the system's */ 3794 /* default should be used. Alignment is the exception, it will */ 3795 /* default to 8, which will be no alignment alterations. */ 3796 3797 netperf_request.content.request_type = DO_SCTP_RR_MANY; 3798 sctp_rr_request->recv_buf_size = rsr_size_req; 3799 sctp_rr_request->send_buf_size = rss_size_req; 3800 sctp_rr_request->recv_alignment = remote_recv_align; 3801 sctp_rr_request->recv_offset = remote_recv_offset; 3802 sctp_rr_request->send_alignment = remote_send_align; 3803 sctp_rr_request->send_offset = remote_send_offset; 3804 sctp_rr_request->request_size = req_size; 3805 sctp_rr_request->response_size = rsp_size; 3806 sctp_rr_request->no_delay = rem_nodelay; 3807 sctp_rr_request->measure_cpu = remote_cpu_usage; 3808 sctp_rr_request->cpu_rate = remote_cpu_rate; 3809 sctp_rr_request->so_rcvavoid = rem_rcvavoid; 3810 sctp_rr_request->so_sndavoid = rem_sndavoid; 3811 if (test_time) { 3812 sctp_rr_request->test_length = test_time; 3813 } 3814 else { 3815 sctp_rr_request->test_length = test_trans * num_associations 3816 * -1; 3817 } 3818 sctp_rr_request->non_blocking = non_block; 3819 sctp_rr_request->port = atoi(remote_data_port); 3820 sctp_rr_request->ipfamily = af_to_nf(remote_res->ai_family); 3821 if (debug > 1) { 3822 fprintf(where,"netperf: send_sctp_rr_1toMany: requesting SCTP rr test\n"); 3823 } 3824 3825 send_request(); 3826 3827 /* The response from the remote will contain all of the relevant */ 3828 /* socket parameters for this test type. We will put them back into */ 3829 /* the variables here so they can be displayed if desired. The */ 3830 /* remote will have calibrated CPU if necessary, and will have done */ 3831 /* all the needed set-up we will have calibrated the cpu locally */ 3832 /* before sending the request, and will grab the counter value right*/ 3833 /* after the connect returns. The remote will grab the counter right*/ 3834 /* after the accept call. This saves the hassle of extra messages */ 3835 /* being sent for the sctp tests. */ 3836 3837 recv_response(); 3838 3839 if (!netperf_response.content.serv_errno) { 3840 rsr_size = sctp_rr_response->recv_buf_size; 3841 rss_size = sctp_rr_response->send_buf_size; 3842 rem_nodelay = sctp_rr_response->no_delay; 3843 remote_cpu_usage = sctp_rr_response->measure_cpu; 3844 remote_cpu_rate = sctp_rr_response->cpu_rate; 3845 /* make sure that port numbers are in network order */ 3846 set_port_number(remote_res, 3847 (unsigned short)sctp_rr_response->data_port_number); 3848 } 3849 else { 3850 Set_errno(netperf_response.content.serv_errno); 3851 fprintf(where, 3852 "netperf: remote error %d", 3853 netperf_response.content.serv_errno); 3854 perror(""); 3855 fflush(where); 3856 3857 exit(1); 3858 } 3859 3860 /*set up the data socket list */ 3861 for (j = 0; j < num_associations; j++) { 3862 send_socket[j] = create_data_socket(local_res); 3863 3864 if (send_socket < 0){ 3865 perror("netperf: send_sctp_rr_1toMany: sctp stream data socket"); 3866 exit(1); 3867 } 3868 3869 /*Connect up to the remote port on the data socket */ 3870 if (connect(send_socket[j], 3871 remote_res->ai_addr, 3872 remote_res->ai_addrlen) < 0){ 3873 perror("netperf: data socket connect failed"); 3874 3875 exit(1); 3876 } 3877 3878 /* The client end of the 1-to-Many test uses 1-to-1 sockets. 3879 * it doesn't need events. 3880 */ 3881 sctp_enable_events(send_socket[j], 0); 3882 3883 if (non_block) { 3884 if (!set_nonblock(send_socket[j])) { 3885 close(send_socket[j]); 3886 exit(1); 3887 } 3888 } 3889 } 3890 3891 /* Data Socket set-up is finished. If there were problems, either the */ 3892 /* connect would have failed, or the previous response would have */ 3893 /* indicated a problem. I failed to see the value of the extra */ 3894 /* message after the accept on the remote. If it failed, we'll see it */ 3895 /* here. If it didn't, we might as well start pumping data. */ 3896 3897 /* Set-up the test end conditions. For a request/response test, they */ 3898 /* can be either time or transaction based. */ 3899 3900 if (test_time) { 3901 /* The user wanted to end the test after a period of time. */ 3902 times_up = 0; 3903 trans_remaining = 0; 3904 start_timer(test_time); 3905 } 3906 else { 3907 /* The tester wanted to send a number of bytes. */ 3908 trans_remaining = test_bytes * num_associations; 3909 times_up = 1; 3910 } 3911 3912 /* The cpu_start routine will grab the current time and possibly */ 3913 /* value of the idle counter for later use in measuring cpu */ 3914 /* utilization and/or service demand and thruput. */ 3915 3916 cpu_start(local_cpu_usage); 3917 3918 #ifdef WANT_INTERVALS 3919 if ((interval_burst) || (demo_mode)) { 3920 /* zero means that we never pause, so we never should need the */ 3921 /* interval timer, unless we are in demo_mode */ 3922 start_itimer(interval_wate); 3923 } 3924 interval_count = interval_burst; 3925 /* get the signal set for the call to sigsuspend */ 3926 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { 3927 fprintf(where, 3928 "send_sctp_rr_1toMany: unable to get sigmask errno %d\n", 3929 errno); 3930 fflush(where); 3931 exit(1); 3932 } 3933 #endif /* WANT_INTERVALS */ 3934 3935 /* We use an "OR" to control test execution. When the test is */ 3936 /* controlled by time, the byte count check will always return false. */ 3937 /* When the test is controlled by byte count, the time test will */ 3938 /* always return false. When the test is finished, the whole */ 3939 /* expression will go false and we will stop sending data. I think I */ 3940 /* just arbitrarily decrement trans_remaining for the timed test, but */ 3941 /* will not do that just yet... One other question is whether or not */ 3942 /* the send buffer and the receive buffer should be the same buffer. */ 3943 3944 #ifdef WANT_FIRST_BURST 3945 { 3946 int i; 3947 for (j = 0; j < num_associations; j++) { 3948 for (i = 0; i < first_burst_size; i++) { 3949 if((len=sctp_sendmsg(send_socket[j], 3950 send_ring->buffer_ptr, send_size, 3951 remote_res->ai_addr, 3952 remote_res->ai_addrlen, 3953 0, 0, 0, 0, 0)) != req_size) { 3954 /* we should never hit the end of the test in the first burst */ 3955 perror("send_sctp_rr_1toMany: initial burst data send error"); 3956 exit(1); 3957 } 3958 } 3959 } 3960 } 3961 #endif /* WANT_FIRST_BURST */ 3962 3963 while ((!times_up) || (trans_remaining > 0)) { 3964 /* send the request. we assume that if we use a blocking socket, */ 3965 /* the request will be sent at one shot. */ 3966 3967 /* this is a fairly poor way of testing 1toMany connections. 3968 * For each association we measure round trip time to account for 3969 * any delay in lookups and delivery. To stress the server a bit 3970 * more we would need a distributed client test, or at least multiple 3971 * processes. I want to force as much paralellism as possible, but 3972 * this will do for the fist take. vlad 3973 */ 3974 for (j = 0; j < num_associations; j++) { 3975 #ifdef WANT_HISTOGRAM 3976 /* timestamp just before our call to send, and then again just */ 3977 /* after the receive raj 8/94 */ 3978 HIST_timestamp_start(time_hist); 3979 #endif /* WANT_HISTOGRAM */ 3980 3981 while ((len=sctp_sendmsg(send_socket[j], 3982 send_ring->buffer_ptr, send_size, 3983 remote_res->ai_addr, 3984 remote_res->ai_addrlen, 3985 0, 0, 0, 0, 0)) != req_size) { 3986 if (non_block && errno == EAGAIN) { 3987 /* try sending again */ 3988 continue; 3989 } else if ((errno == EINTR) || (errno == 0)) { 3990 /* we hit the end of a */ 3991 /* timed test. */ 3992 timed_out = 1; 3993 break; 3994 } 3995 perror("send_sctp_rr_1toMany: data send error"); 3996 exit(1); 3997 } 3998 3999 if (timed_out) { 4000 /* we may have been in a nested while loop - we need */ 4001 /* another call to break. */ 4002 break; 4003 } 4004 4005 /* setup for the next time */ 4006 send_ring = send_ring->next; 4007 4008 rsp_bytes_left = rsp_size; 4009 temp_message_ptr = recv_ring->buffer_ptr; 4010 while (!(msg_flags & MSG_EOR)) { 4011 if((rsp_bytes_recvd = sctp_recvmsg(send_socket[j], 4012 temp_message_ptr, 4013 rsp_bytes_left, 4014 NULL, 0, 4015 NULL, &msg_flags)) < 0) { 4016 if (errno == EINTR) { 4017 /* We hit the end of a timed test. */ 4018 timed_out = 1; 4019 break; 4020 } else if (non_block && errno == EAGAIN) { 4021 continue; 4022 } 4023 perror("send_sctp_rr_1toMany: data recv error"); 4024 exit(1); 4025 } 4026 rsp_bytes_left -= rsp_bytes_recvd; 4027 temp_message_ptr += rsp_bytes_recvd; 4028 } 4029 recv_ring = recv_ring->next; 4030 4031 if (timed_out) { 4032 /* we may have been in a nested while loop - we need */ 4033 /* another call to break. */ 4034 break; 4035 } 4036 4037 #ifdef WANT_HISTOGRAM 4038 HIST_timestamp_stop_add(time_hist); 4039 #endif /* WANT_HISTOGRAM */ 4040 4041 nummessages++; 4042 if (trans_remaining) { 4043 trans_remaining--; 4044 } 4045 4046 if (debug > 3) { 4047 if ((nummessages % 100) == 0) { 4048 fprintf(where, 4049 "Transaction %d completed\n", 4050 nummessages); 4051 fflush(where); 4052 } 4053 } 4054 } 4055 } 4056 4057 /* At this point we used to call shutdown on the data socket to be */ 4058 /* sure all the data was delivered, but this was not germane in a */ 4059 /* request/response test, and it was causing the tests to "hang" when */ 4060 /* they were being controlled by time. So, I have replaced this */ 4061 /* shutdown call with a call to close that can be found later in the */ 4062 /* procedure. */ 4063 4064 /* this call will always give us the elapsed time for the test, and */ 4065 /* will also store-away the necessaries for cpu utilization */ 4066 4067 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */ 4068 /* measured? how long */ 4069 /* did we really run? */ 4070 4071 /* Get the statistics from the remote end. The remote will have */ 4072 /* calculated CPU utilization. If it wasn't supposed to care, it */ 4073 /* will return obvious values. */ 4074 4075 recv_response(); 4076 if (!netperf_response.content.serv_errno) { 4077 if (debug) 4078 fprintf(where,"remote results obtained\n"); 4079 } 4080 else { 4081 Set_errno(netperf_response.content.serv_errno); 4082 fprintf(where,"netperf: remote error %d", 4083 netperf_response.content.serv_errno); 4084 perror(""); 4085 fflush(where); 4086 exit(1); 4087 } 4088 4089 /* We now calculate what our throughput was for the test. */ 4090 4091 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages); 4092 thruput = nummessages/elapsed_time; 4093 4094 if (local_cpu_usage || remote_cpu_usage) { 4095 /* We must now do a little math for service demand and cpu */ 4096 /* utilization for the system(s) */ 4097 /* Of course, some of the information might be bogus because */ 4098 /* there was no idle counter in the kernel(s). We need to make */ 4099 /* a note of this for the user's benefit...*/ 4100 if (local_cpu_usage) { 4101 local_cpu_utilization = calc_cpu_util(0.0); 4102 /* since calc_service demand is doing ms/Kunit we will */ 4103 /* multiply the number of transaction by 1024 to get */ 4104 /* "good" numbers */ 4105 local_service_demand = calc_service_demand((double) nummessages*1024, 4106 0.0, 4107 0.0, 4108 0); 4109 } 4110 else { 4111 local_cpu_utilization = (float) -1.0; 4112 local_service_demand = (float) -1.0; 4113 } 4114 4115 if (remote_cpu_usage) { 4116 remote_cpu_utilization = sctp_rr_result->cpu_util; 4117 /* since calc_service demand is doing ms/Kunit we will */ 4118 /* multiply the number of transaction by 1024 to get */ 4119 /* "good" numbers */ 4120 remote_service_demand = calc_service_demand((double) nummessages*1024, 4121 0.0, 4122 remote_cpu_utilization, 4123 sctp_rr_result->num_cpus); 4124 } 4125 else { 4126 remote_cpu_utilization = (float) -1.0; 4127 remote_service_demand = (float) -1.0; 4128 } 4129 4130 } 4131 else { 4132 /* we were not measuring cpu, for the confidence stuff, we */ 4133 /* should make it -1.0 */ 4134 local_cpu_utilization = (float) -1.0; 4135 local_service_demand = (float) -1.0; 4136 remote_cpu_utilization = (float) -1.0; 4137 remote_service_demand = (float) -1.0; 4138 } 4139 4140 /* at this point, we want to calculate the confidence information. */ 4141 /* if debugging is on, calculate_confidence will print-out the */ 4142 /* parameters we pass it */ 4143 4144 calculate_confidence(confidence_iteration, 4145 elapsed_time, 4146 thruput, 4147 local_cpu_utilization, 4148 remote_cpu_utilization, 4149 local_service_demand, 4150 remote_service_demand); 4151 4152 4153 confidence_iteration++; 4154 4155 /* we are now done with the socket, so close it */ 4156 for (j = 0; j < num_associations; j++) 4157 close(send_socket[j]); 4158 } 4159 4160 retrieve_confident_values(&elapsed_time, 4161 &thruput, 4162 &local_cpu_utilization, 4163 &remote_cpu_utilization, 4164 &local_service_demand, 4165 &remote_service_demand); 4166 4167 /* We are now ready to print all the information. If the user */ 4168 /* has specified zero-level verbosity, we will just print the */ 4169 /* local service demand, or the remote service demand. If the */ 4170 /* user has requested verbosity level 1, he will get the basic */ 4171 /* "streamperf" numbers. If the user has specified a verbosity */ 4172 /* of greater than 1, we will display a veritable plethora of */ 4173 /* background information from outside of this block as it it */ 4174 /* not cpu_measurement specific... */ 4175 4176 if (confidence < 0) { 4177 /* we did not hit confidence, but were we asked to look for it? */ 4178 if (iteration_max > 1) { 4179 display_confidence(); 4180 } 4181 } 4182 4183 if (local_cpu_usage || remote_cpu_usage) { 4184 local_cpu_method = format_cpu_method(cpu_method); 4185 remote_cpu_method = format_cpu_method(sctp_rr_result->cpu_method); 4186 4187 switch (verbosity) { 4188 case 0: 4189 if (local_cpu_usage) { 4190 fprintf(where, 4191 cpu_fmt_0, 4192 local_service_demand, 4193 local_cpu_method); 4194 } 4195 else { 4196 fprintf(where, 4197 cpu_fmt_0, 4198 remote_service_demand, 4199 remote_cpu_method); 4200 } 4201 break; 4202 case 1: 4203 case 2: 4204 if (print_headers) { 4205 fprintf(where, 4206 cpu_title, 4207 local_cpu_method, 4208 remote_cpu_method); 4209 } 4210 4211 fprintf(where, 4212 cpu_fmt_1_line_1, /* the format string */ 4213 lss_size, /* local sendbuf size */ 4214 lsr_size, 4215 req_size, /* how large were the requests */ 4216 rsp_size, /* guess */ 4217 elapsed_time, /* how long was the test */ 4218 thruput, 4219 local_cpu_utilization, /* local cpu */ 4220 remote_cpu_utilization, /* remote cpu */ 4221 local_service_demand, /* local service demand */ 4222 remote_service_demand); /* remote service demand */ 4223 fprintf(where, 4224 cpu_fmt_1_line_2, 4225 rss_size, 4226 rsr_size); 4227 break; 4228 } 4229 } 4230 else { 4231 /* The tester did not wish to measure service demand. */ 4232 4233 switch (verbosity) { 4234 case 0: 4235 fprintf(where, 4236 tput_fmt_0, 4237 thruput); 4238 break; 4239 case 1: 4240 case 2: 4241 if (print_headers) { 4242 fprintf(where,tput_title,format_units()); 4243 } 4244 4245 fprintf(where, 4246 tput_fmt_1_line_1, /* the format string */ 4247 lss_size, 4248 lsr_size, 4249 req_size, /* how large were the requests */ 4250 rsp_size, /* how large were the responses */ 4251 elapsed_time, /* how long did it take */ 4252 thruput); 4253 fprintf(where, 4254 tput_fmt_1_line_2, 4255 rss_size, /* remote recvbuf size */ 4256 rsr_size); 4257 4258 break; 4259 } 4260 } 4261 4262 /* it would be a good thing to include information about some of the */ 4263 /* other parameters that may have been set for this test, but at the */ 4264 /* moment, I do not wish to figure-out all the formatting, so I will */ 4265 /* just put this comment here to help remind me that it is something */ 4266 /* that should be done at a later time. */ 4267 4268 /* how to handle the verbose information in the presence of */ 4269 /* confidence intervals is yet to be determined... raj 11/94 */ 4270 if (verbosity > 1) { 4271 /* The user wanted to know it all, so we will give it to him. */ 4272 /* This information will include as much as we can find about */ 4273 /* TCP statistics, the alignments of the sends and receives */ 4274 /* and all that sort of rot... */ 4275 4276 fprintf(where, 4277 ksink_fmt, 4278 local_send_align, 4279 remote_recv_offset, 4280 local_send_offset, 4281 remote_recv_offset); 4282 4283 #ifdef WANT_HISTOGRAM 4284 fprintf(where,"\nHistogram of request/response times\n"); 4285 fflush(where); 4286 HIST_report(time_hist); 4287 #endif /* WANT_HISTOGRAM */ 4288 4289 } 4290 4291 } 4292 4293 4294 /* this routine implements the receive (netserver) side of a TCP_RR */ 4296 /* test */ 4297 void 4298 recv_sctp_rr_1toMany( void ) 4299 { 4300 4301 struct ring_elt *send_ring; 4302 struct ring_elt *recv_ring; 4303 4304 4305 struct sockaddr_in myaddr_in; /* needed to get the port number */ 4306 struct sockaddr_storage peeraddr; /* to communicate with peer */ 4307 struct addrinfo *local_res; 4308 char local_name[BUFSIZ]; 4309 char port_buffer[PORTBUFSIZE]; 4310 int msg_flags; 4311 4312 int s_rcv; 4313 socklen_t addrlen; 4314 int trans_received; 4315 int trans_remaining; 4316 int bytes_sent; 4317 int bytes_recvd; 4318 int recv_buf_size; 4319 int timed_out = 0; 4320 float elapsed_time; 4321 4322 struct sctp_rr_request_struct *sctp_rr_request; 4323 struct sctp_rr_response_struct *sctp_rr_response; 4324 struct sctp_rr_results_struct *sctp_rr_results; 4325 4326 sctp_rr_request = 4327 (struct sctp_rr_request_struct *)netperf_request.content.test_specific_data; 4328 sctp_rr_response = 4329 (struct sctp_rr_response_struct *)netperf_response.content.test_specific_data; 4330 sctp_rr_results = 4331 (struct sctp_rr_results_struct *)netperf_response.content.test_specific_data; 4332 4333 if (debug) { 4334 fprintf(where,"netserver: recv_sctp_rr_1toMany: entered...\n"); 4335 fflush(where); 4336 } 4337 4338 /* We want to set-up the listen socket with all the desired */ 4339 /* parameters and then let the initiator know that all is ready. If */ 4340 /* socket size defaults are to be used, then the initiator will have */ 4341 /* sent us 0's. If the socket sizes cannot be changed, then we will */ 4342 /* send-back what they are. If that information cannot be determined, */ 4343 /* then we send-back -1's for the sizes. If things go wrong for any */ 4344 /* reason, we will drop back ten yards and punt. */ 4345 4346 /* If anything goes wrong, we want the remote to know about it. It */ 4347 /* would be best if the error that the remote reports to the user is */ 4348 /* the actual error we encountered, rather than some bogus unexpected */ 4349 /* response type message. */ 4350 4351 if (debug) { 4352 fprintf(where,"recv_sctp_rr_1toMany: setting the response type...\n"); 4353 fflush(where); 4354 } 4355 4356 netperf_response.content.response_type = SCTP_RR_MANY_RESPONSE; 4357 4358 if (debug) { 4359 fprintf(where,"recv_sctp_rr_1toMany: the response type is set...\n"); 4360 fflush(where); 4361 } 4362 4363 /* allocate the recv and send rings with the requested alignments */ 4364 /* and offsets. raj 7/94 */ 4365 if (debug) { 4366 fprintf(where,"recv_sctp_rr_1toMany: requested recv alignment of %d offset %d\n", 4367 sctp_rr_request->recv_alignment, 4368 sctp_rr_request->recv_offset); 4369 fprintf(where,"recv_sctp_rr_1toMany: requested send alignment of %d offset %d\n", 4370 sctp_rr_request->send_alignment, 4371 sctp_rr_request->send_offset); 4372 fflush(where); 4373 } 4374 4375 /* at some point, these need to come to us from the remote system */ 4376 if (send_width == 0) send_width = 1; 4377 if (recv_width == 0) recv_width = 1; 4378 4379 send_ring = allocate_buffer_ring(send_width, 4380 sctp_rr_request->response_size, 4381 sctp_rr_request->send_alignment, 4382 sctp_rr_request->send_offset); 4383 4384 recv_ring = allocate_buffer_ring(recv_width, 4385 sctp_rr_request->request_size, 4386 sctp_rr_request->recv_alignment, 4387 sctp_rr_request->recv_offset); 4388 4389 4390 /* create_data_socket expects to find some things in the global */ 4391 /* variables, so set the globals based on the values in the request. */ 4392 /* once the socket has been created, we will set the response values */ 4393 /* based on the updated value of those globals. raj 7/94 */ 4394 lss_size_req = sctp_rr_request->send_buf_size; 4395 lsr_size_req = sctp_rr_request->recv_buf_size; 4396 loc_nodelay = sctp_rr_request->no_delay; 4397 loc_rcvavoid = sctp_rr_request->so_rcvavoid; 4398 loc_sndavoid = sctp_rr_request->so_sndavoid; 4399 non_block = sctp_rr_request->non_blocking; 4400 4401 set_hostname_and_port(local_name, 4402 port_buffer, 4403 nf_to_af(sctp_rr_request->ipfamily), 4404 sctp_rr_request->port); 4405 4406 local_res = complete_addrinfo(local_name, 4407 local_name, 4408 port_buffer, 4409 nf_to_af(sctp_rr_request->ipfamily), 4410 SOCK_SEQPACKET, 4411 IPPROTO_SCTP, 4412 0); 4413 4414 /* Grab a socket to listen on, and then listen on it. */ 4415 if (debug) { 4416 fprintf(where,"recv_sctp_rr_1toMany: grabbing a socket...\n"); 4417 fflush(where); 4418 } 4419 4420 s_rcv = create_data_socket(local_res); 4421 4422 if (s_rcv < 0) { 4423 netperf_response.content.serv_errno = errno; 4424 send_response(); 4425 4426 exit(1); 4427 } 4428 4429 /* Now, let's set-up the socket to listen for connections */ 4430 if (listen(s_rcv, 5) == -1) { 4431 netperf_response.content.serv_errno = errno; 4432 close(s_rcv); 4433 send_response(); 4434 4435 exit(1); 4436 } 4437 4438 4439 /* now get the port number assigned by the system */ 4440 addrlen = sizeof(myaddr_in); 4441 if (getsockname(s_rcv, 4442 (struct sockaddr *)&myaddr_in, &addrlen) == -1){ 4443 netperf_response.content.serv_errno = errno; 4444 close(s_rcv); 4445 send_response(); 4446 4447 exit(1); 4448 } 4449 4450 /* Now myaddr_in contains the port and the internet address this is */ 4451 /* returned to the sender also implicitly telling the sender that the */ 4452 /* socket buffer sizing has been done. */ 4453 4454 sctp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port); 4455 netperf_response.content.serv_errno = 0; 4456 4457 /* But wait, there's more. If the initiator wanted cpu measurements, */ 4458 /* then we must call the calibrate routine, which will return the max */ 4459 /* rate back to the initiator. If the CPU was not to be measured, or */ 4460 /* something went wrong with the calibration, we will return a 0.0 to */ 4461 /* the initiator. */ 4462 4463 sctp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */ 4464 sctp_rr_response->measure_cpu = 0; 4465 4466 if (sctp_rr_request->measure_cpu) { 4467 sctp_rr_response->measure_cpu = 1; 4468 sctp_rr_response->cpu_rate = calibrate_local_cpu(sctp_rr_request->cpu_rate); 4469 } 4470 4471 4472 /* before we send the response back to the initiator, pull some of */ 4473 /* the socket parms from the globals */ 4474 sctp_rr_response->send_buf_size = lss_size; 4475 sctp_rr_response->recv_buf_size = lsr_size; 4476 sctp_rr_response->no_delay = loc_nodelay; 4477 sctp_rr_response->so_rcvavoid = loc_rcvavoid; 4478 sctp_rr_response->so_sndavoid = loc_sndavoid; 4479 sctp_rr_response->test_length = sctp_rr_request->test_length; 4480 send_response(); 4481 4482 /* Don't need events */ 4483 sctp_enable_events(s_rcv, 0); 4484 4485 /* now that we are connected, mark the socket as non-blocking */ 4486 if (non_block) { 4487 if (!set_nonblock(s_rcv)) { 4488 perror("netperf: set_nonblock"); 4489 exit(1); 4490 } 4491 } 4492 4493 /* FIXME: The way 1-to-Many test operates right now, we are including 4494 * association setup time into our measurements. The reason for this 4495 * is that the client creates multiple endpoints and connects each 4496 * endpoint to us using the connect call. On this end we simply call 4497 * recvmsg() to get data becuase there is no equivalen of accept() for 4498 * 1-to-Many API. 4499 * I think this is OK, but if it were to be fixed, the server side 4500 * would need to know how many associations are being setup and 4501 * have a recvmsg() loop with SCTP_ASSOC_CHANGE events waiting for 4502 * all the associations to be be established. 4503 * I am punting on this for now. 4504 */ 4505 4506 4507 addrlen = sizeof(peeraddr); 4508 4509 /* Now it's time to start receiving data on the connection. We will */ 4510 /* first grab the apropriate counters and then start grabbing. */ 4511 4512 cpu_start(sctp_rr_request->measure_cpu); 4513 4514 /* The loop will exit when we hit the end of the test time, or when */ 4515 /* we have exchanged the requested number of transactions. */ 4516 4517 if (sctp_rr_request->test_length > 0) { 4518 times_up = 0; 4519 trans_remaining = 0; 4520 start_timer(sctp_rr_request->test_length + PAD_TIME); 4521 } 4522 else { 4523 times_up = 1; 4524 trans_remaining = sctp_rr_request->test_length * -1; 4525 } 4526 4527 trans_received = 0; 4528 4529 while ((!times_up) || (trans_remaining > 0)) { 4530 4531 recv_buf_size = sctp_rr_request->request_size; 4532 4533 /* Receive the data. We don't particularly care which association 4534 * the data came in on. We'll simply be doing a receive untill 4535 * we get and MSG_EOR flag (meaning that a single transmission was 4536 * received) and a send to the same address, so the RR would be for 4537 * the same associations. 4538 * We can get away with this because the client will establish all 4539 * the associations before transmitting any data. Any partial data 4540 * will not have EOR thus will we will not send a response untill 4541 * we get everything. 4542 */ 4543 4544 do { 4545 msg_flags = 0; 4546 if((bytes_recvd = sctp_recvmsg(s_rcv, 4547 recv_ring->buffer_ptr, 4548 recv_buf_size, 4549 (struct sockaddr *)&peeraddr, &addrlen, 4550 0, &msg_flags)) == SOCKET_ERROR) { 4551 if (SOCKET_EINTR(bytes_recvd)) { 4552 /* the timer popped */ 4553 timed_out = 1; 4554 break; 4555 } else if (non_block && errno == EAGAIN) { 4556 /* do recvmsg again */ 4557 continue; 4558 } 4559 netperf_response.content.serv_errno = errno; 4560 send_response(); 4561 exit(1); 4562 } 4563 } while(!(msg_flags & MSG_EOR)); 4564 4565 recv_ring = recv_ring->next; 4566 4567 if (timed_out) { 4568 /* we hit the end of the test based on time - lets */ 4569 /* bail out of here now... */ 4570 if (debug) { 4571 fprintf(where,"yo5\n"); 4572 fflush(where); 4573 } 4574 break; 4575 } 4576 4577 /* Now, send the response to the remote */ 4578 while ((bytes_sent=sctp_sendmsg(s_rcv, 4579 send_ring->buffer_ptr, 4580 sctp_rr_request->response_size, 4581 (struct sockaddr *)&peeraddr, addrlen, 4582 0, 0, 0, 0, 0)) == SOCKET_ERROR) { 4583 if (SOCKET_EINTR(bytes_sent)) { 4584 /* the test timer has popped */ 4585 timed_out = 1; 4586 break; 4587 } else if (non_block && errno == EAGAIN) { 4588 continue; 4589 } 4590 4591 netperf_response.content.serv_errno = 992; 4592 send_response(); 4593 exit(1); 4594 } 4595 4596 if (timed_out) { 4597 if (debug) { 4598 fprintf(where,"yo6\n"); 4599 fflush(where); 4600 } 4601 /* we hit the end of the test based on time - lets */ 4602 /* bail out of here now... */ 4603 break; 4604 } 4605 4606 send_ring = send_ring->next; 4607 4608 trans_received++; 4609 if (trans_remaining) { 4610 trans_remaining--; 4611 } 4612 } 4613 4614 4615 /* The loop now exits due to timeout or transaction count being */ 4616 /* reached */ 4617 4618 cpu_stop(sctp_rr_request->measure_cpu,&elapsed_time); 4619 4620 stop_timer(); 4621 4622 if (timed_out) { 4623 /* we ended the test by time, which was at least 2 seconds */ 4624 /* longer than we wanted to run. so, we want to subtract */ 4625 /* PAD_TIME from the elapsed_time. */ 4626 elapsed_time -= PAD_TIME; 4627 } 4628 4629 /* send the results to the sender */ 4630 4631 if (debug) { 4632 fprintf(where, 4633 "recv_sctp_rr: got %d transactions\n", 4634 trans_received); 4635 fflush(where); 4636 } 4637 4638 sctp_rr_results->bytes_received = (trans_received * 4639 (sctp_rr_request->request_size + 4640 sctp_rr_request->response_size)); 4641 sctp_rr_results->trans_received = trans_received; 4642 sctp_rr_results->elapsed_time = elapsed_time; 4643 sctp_rr_results->cpu_method = cpu_method; 4644 sctp_rr_results->num_cpus = lib_num_loc_cpus; 4645 if (sctp_rr_request->measure_cpu) { 4646 sctp_rr_results->cpu_util = calc_cpu_util(elapsed_time); 4647 } 4648 4649 if (debug) { 4650 fprintf(where, 4651 "recv_sctp_rr: test complete, sending results.\n"); 4652 fflush(where); 4653 } 4654 4655 /* we are now done with the sockets */ 4656 close(s_rcv); 4657 4658 send_response(); 4659 4660 } 4661 4662 4663 void 4664 print_sctp_usage( void ) 4665 { 4666 4667 printf("%s",sctp_usage); 4668 exit(1); 4669 4670 } 4671 4672 void 4673 scan_sctp_args( int argc, char *argv[] ) 4674 { 4675 4676 #define SOCKETS_ARGS "BDhH:I:L:m:M:P:r:s:S:VN:T:46" 4677 4678 extern char *optarg; /* pointer to option string */ 4679 4680 int c; 4681 4682 char 4683 arg1[BUFSIZ], /* argument holders */ 4684 arg2[BUFSIZ]; 4685 4686 if (no_control) { 4687 fprintf(where, 4688 "The SCTP tests do not know how to deal with no control tests\n"); 4689 exit(-1); 4690 } 4691 4692 strncpy(local_data_port,"0",sizeof(local_data_port)); 4693 strncpy(remote_data_port,"0",sizeof(remote_data_port)); 4694 4695 /* Go through all the command line arguments and break them */ 4696 /* out. For those options that take two parms, specifying only */ 4697 /* the first will set both to that value. Specifying only the */ 4698 /* second will leave the first untouched. To change only the */ 4699 /* first, use the form "first," (see the routine break_args.. */ 4700 4701 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) { 4702 switch (c) { 4703 case '?': 4704 case '4': 4705 remote_data_family = AF_INET; 4706 local_data_family = AF_INET; 4707 break; 4708 case '6': 4709 #if defined(AF_INET6) 4710 remote_data_family = AF_INET6; 4711 local_data_family = AF_INET6; 4712 #else 4713 fprintf(stderr, 4714 "This netperf was not compiled on an IPv6 capable host!\n"); 4715 fflush(stderr); 4716 exit(-1); 4717 #endif 4718 break; 4719 case 'h': 4720 print_sctp_usage(); 4721 exit(1); 4722 case 'b': 4723 #ifdef WANT_FIRST_BURST 4724 first_burst_size = atoi(optarg); 4725 #else /* WANT_FIRST_BURST */ 4726 printf("Initial request burst functionality not compiled-in!\n"); 4727 #endif /* WANT_FIRST_BURST */ 4728 break; 4729 case 'D': 4730 /* set the nodelay flag */ 4731 loc_nodelay = 1; 4732 rem_nodelay = 1; 4733 break; 4734 case 'H': 4735 break_args_explicit(optarg,arg1,arg2); 4736 if (arg1[0]) { 4737 /* make sure we leave room for the NULL termination boys and 4738 girls. raj 2005-02-82 */ 4739 remote_data_address = malloc(strlen(arg1)+1); 4740 strncpy(remote_data_address,arg1,strlen(arg1)); 4741 } 4742 if (arg2[0]) 4743 remote_data_family = parse_address_family(arg2); 4744 break; 4745 case 'L': 4746 break_args_explicit(optarg,arg1,arg2); 4747 if (arg1[0]) { 4748 /* make sure we leave room for the NULL termination boys and 4749 girls. raj 2005-02-82 */ 4750 local_data_address = malloc(strlen(arg1)+1); 4751 strncpy(local_data_address,arg1,strlen(arg1)); 4752 } 4753 if (arg2[0]) 4754 local_data_family = parse_address_family(arg2); 4755 break; 4756 case 'P': 4757 /* set the local and remote data port numbers for the tests to 4758 allow them to run through those blankety blank end-to-end 4759 breaking firewalls. raj 2004-06-15 */ 4760 break_args(optarg,arg1,arg2); 4761 if (arg1[0]) 4762 strncpy(local_data_port,arg1,sizeof(local_data_port)); 4763 if (arg2[0]) 4764 strncpy(remote_data_port,arg2,sizeof(remote_data_port)); 4765 break; 4766 case 's': 4767 /* set local socket sizes */ 4768 break_args(optarg,arg1,arg2); 4769 if (arg1[0]) 4770 lss_size_req = convert(arg1); 4771 if (arg2[0]) 4772 lsr_size_req = convert(arg2); 4773 break; 4774 case 'S': 4775 /* set remote socket sizes */ 4776 break_args(optarg,arg1,arg2); 4777 if (arg1[0]) 4778 rss_size_req = convert(arg1); 4779 if (arg2[0]) 4780 rsr_size_req = convert(arg2); 4781 break; 4782 case 'r': 4783 /* set the request/response sizes */ 4784 break_args(optarg,arg1,arg2); 4785 if (arg1[0]) 4786 req_size = convert(arg1); 4787 if (arg2[0]) 4788 rsp_size = convert(arg2); 4789 break; 4790 case 'm': 4791 /* set size of the buffer for each sent message */ 4792 send_size = convert(optarg); 4793 break; 4794 case 'M': 4795 /* set the size of the buffer for each received message */ 4796 recv_size = convert(optarg); 4797 break; 4798 case 't': 4799 /* set the test name */ 4800 strcpy(test_name,optarg); 4801 break; 4802 case 'W': 4803 /* set the "width" of the user space data */ 4804 /* buffer. This will be the number of */ 4805 /* send_size buffers malloc'd in the */ 4806 /* *_STREAM test. It may be enhanced to set */ 4807 /* both send and receive "widths" but for now */ 4808 /* it is just the sending *_STREAM. */ 4809 send_width = convert(optarg); 4810 break; 4811 case 'V': 4812 /* we want to do copy avoidance and will set */ 4813 /* it for everything, everywhere, if we really */ 4814 /* can. of course, we don't know anything */ 4815 /* about the remote... */ 4816 #ifdef SO_SND_COPYAVOID 4817 loc_sndavoid = 1; 4818 #else 4819 loc_sndavoid = 0; 4820 printf("Local send copy avoidance not available.\n"); 4821 #endif 4822 #ifdef SO_RCV_COPYAVOID 4823 loc_rcvavoid = 1; 4824 #else 4825 loc_rcvavoid = 0; 4826 printf("Local recv copy avoidance not available.\n"); 4827 #endif 4828 rem_sndavoid = 1; 4829 rem_rcvavoid = 1; 4830 break; 4831 case 'N': 4832 /* this opton allows the user to set the number of 4833 * messages to send. This in effect modifies the test 4834 * time. If we know the message size, then the we can 4835 * express the test time as message_size * number_messages 4836 */ 4837 msg_count = convert (optarg); 4838 if (msg_count > 0) 4839 test_time = 0; 4840 break; 4841 case 'B': 4842 non_block = 1; 4843 break; 4844 case 'T': 4845 num_associations = atoi(optarg); 4846 if (num_associations <= 1) { 4847 printf("Number of SCTP associations must be >= 1\n"); 4848 exit(1); 4849 } 4850 break; 4851 }; 4852 } 4853 } 4854 4855 #endif /* WANT_SCTP */ 4856