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