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