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