1 /* 2 * Copyright (c) 2009-2011, The Regents of the University of California, 3 * through Lawrence Berkeley National Laboratory (subject to receipt of any 4 * required approvals from the U.S. Dept. of Energy). All rights reserved. 5 * 6 * This code is distributed under a BSD style license, see the LICENSE file 7 * for complete information. 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <getopt.h> 14 #include <errno.h> 15 #include <signal.h> 16 #include <unistd.h> 17 #include <assert.h> 18 #include <fcntl.h> 19 #include <sys/socket.h> 20 #include <sys/types.h> 21 #include <netinet/in.h> 22 #include <arpa/inet.h> 23 #include <netdb.h> 24 #include <pthread.h> 25 #include <stdint.h> 26 #include <netinet/tcp.h> 27 #include <sys/time.h> 28 #include <sys/resource.h> 29 #include <sched.h> 30 #include <setjmp.h> 31 32 #include "net.h" 33 #include "iperf.h" 34 #include "iperf_api.h" 35 #include "iperf_udp.h" 36 #include "iperf_tcp.h" 37 #include "iperf_error.h" 38 #include "timer.h" 39 40 #include "units.h" 41 #include "tcp_window_size.h" 42 #include "iperf_util.h" 43 #include "locale.h" 44 45 jmp_buf env; /* to handle longjmp on signal */ 46 47 /*************************** Print usage functions ****************************/ 48 49 void 50 usage() 51 { 52 fprintf(stderr, usage_short); 53 } 54 55 56 void 57 usage_long() 58 { 59 fprintf(stderr, usage_long1); 60 fprintf(stderr, usage_long2); 61 } 62 63 64 void warning(char *str) 65 { 66 fprintf(stderr, "warning: %s\n", str); 67 } 68 69 70 /********************** Get/set test protocol structure ***********************/ 71 72 struct protocol * 73 get_protocol(struct iperf_test *test, int prot_id) 74 { 75 struct protocol *prot; 76 77 SLIST_FOREACH(prot, &test->protocols, protocols) { 78 if (prot->id == prot_id) 79 break; 80 } 81 82 if (prot == NULL) 83 i_errno = IEPROTOCOL; 84 85 return (prot); 86 } 87 88 int 89 set_protocol(struct iperf_test *test, int prot_id) 90 { 91 struct protocol *prot = NULL; 92 93 SLIST_FOREACH(prot, &test->protocols, protocols) { 94 if (prot->id == prot_id) { 95 test->protocol = prot; 96 return (0); 97 } 98 } 99 100 i_errno = IEPROTOCOL; 101 102 return (-1); 103 } 104 105 106 /************************** Iperf callback functions **************************/ 107 108 void 109 iperf_on_new_stream(struct iperf_stream *sp) 110 { 111 connect_msg(sp); 112 } 113 114 void 115 iperf_on_test_start(struct iperf_test *test) 116 { 117 if (test->verbose) { 118 if (test->settings->bytes) { 119 printf(test_start_bytes, test->protocol->name, test->num_streams, 120 test->settings->blksize, test->settings->bytes); 121 } else { 122 printf(test_start_time, test->protocol->name, test->num_streams, 123 test->settings->blksize, test->duration); 124 } 125 } 126 } 127 128 void 129 iperf_on_connect(struct iperf_test *test) 130 { 131 char ipr[INET6_ADDRSTRLEN]; 132 struct sockaddr_storage temp; 133 socklen_t len; 134 int domain, opt; 135 136 if (test->role == 'c') { 137 printf("Connecting to host %s, port %d\n", test->server_hostname, 138 test->server_port); 139 } else { 140 domain = test->settings->domain; 141 len = sizeof(temp); 142 getpeername(test->ctrl_sck, (struct sockaddr *) &temp, &len); 143 if (domain == AF_INET) { 144 inet_ntop(domain, &((struct sockaddr_in *) &temp)->sin_addr, ipr, sizeof(ipr)); 145 printf("Accepted connection from %s, port %d\n", ipr, ntohs(((struct sockaddr_in *) &temp)->sin_port)); 146 } else { 147 inet_ntop(domain, &((struct sockaddr_in6 *) &temp)->sin6_addr, ipr, sizeof(ipr)); 148 printf("Accepted connection from %s, port %d\n", ipr, ntohs(((struct sockaddr_in6 *) &temp)->sin6_port)); 149 } 150 } 151 if (test->verbose) { 152 printf(" Cookie: %s\n", test->cookie); 153 if (test->protocol->id == SOCK_STREAM) { 154 if (test->settings->mss) { 155 printf(" TCP MSS: %d\n", test->settings->mss); 156 } else { 157 len = sizeof(opt); 158 getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len); 159 printf(" TCP MSS: %d (default)\n", opt); 160 } 161 } 162 163 } 164 } 165 166 void 167 iperf_on_test_finish(struct iperf_test *test) 168 { 169 if (test->verbose) { 170 printf("Test Complete. Summary Results:\n"); 171 } 172 } 173 174 175 /******************************************************************************/ 176 177 int 178 iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) 179 { 180 static struct option longopts[] = 181 { 182 {"client", required_argument, NULL, 'c'}, 183 {"server", no_argument, NULL, 's'}, 184 {"time", required_argument, NULL, 't'}, 185 {"port", required_argument, NULL, 'p'}, 186 {"parallel", required_argument, NULL, 'P'}, 187 {"udp", no_argument, NULL, 'u'}, 188 {"bind", required_argument, NULL, 'B'}, 189 {"tcpInfo", no_argument, NULL, 'T'}, 190 {"bandwidth", required_argument, NULL, 'b'}, 191 {"length", required_argument, NULL, 'l'}, 192 {"window", required_argument, NULL, 'w'}, 193 {"interval", required_argument, NULL, 'i'}, 194 {"bytes", required_argument, NULL, 'n'}, 195 {"NoDelay", no_argument, NULL, 'N'}, 196 {"Set-mss", required_argument, NULL, 'M'}, 197 {"version", no_argument, NULL, 'v'}, 198 {"verbose", no_argument, NULL, 'V'}, 199 {"debug", no_argument, NULL, 'd'}, 200 {"help", no_argument, NULL, 'h'}, 201 {"daemon", no_argument, NULL, 'D'}, 202 {"format", required_argument, NULL, 'f'}, 203 {"reverse", no_argument, NULL, 'R'}, 204 {"version6", no_argument, NULL, '6'}, 205 206 /* XXX: The following ifdef needs to be split up. linux-congestion is not necessarily supported 207 * by systems that support tos. 208 */ 209 #ifdef ADD_WHEN_SUPPORTED 210 {"tos", required_argument, NULL, 'S'}, 211 {"linux-congestion", required_argument, NULL, 'Z'}, 212 #endif 213 {NULL, 0, NULL, 0} 214 }; 215 char ch; 216 217 while ((ch = getopt_long(argc, argv, "c:p:st:uP:B:b:l:w:i:n:RS:NTvh6VdM:f:", longopts, NULL)) != -1) { 218 switch (ch) { 219 case 'c': 220 if (test->role == 's') { 221 i_errno = IESERVCLIENT; 222 return (-1); 223 } else { 224 test->role = 'c'; 225 test->server_hostname = (char *) malloc(strlen(optarg)+1); 226 strncpy(test->server_hostname, optarg, strlen(optarg)+1); 227 } 228 break; 229 case 'p': 230 test->server_port = atoi(optarg); 231 break; 232 case 's': 233 if (test->role == 'c') { 234 i_errno = IESERVCLIENT; 235 return (-1); 236 } else { 237 test->role = 's'; 238 } 239 break; 240 case 't': 241 if (test->role == 's') { 242 i_errno = IECLIENTONLY; 243 return (-1); 244 } 245 test->duration = atoi(optarg); 246 if (test->duration > MAX_TIME) { 247 i_errno = IEDURATION; 248 return (-1); 249 } 250 break; 251 case 'u': 252 if (test->role == 's') { 253 warning("ignoring client only argument --udp (-u)"); 254 /* XXX: made a warning 255 i_errno = IECLIENTONLY; 256 return (-1); 257 */ 258 } 259 set_protocol(test, Pudp); 260 test->settings->blksize = DEFAULT_UDP_BLKSIZE; 261 break; 262 case 'P': 263 if (test->role == 's') { 264 i_errno = IECLIENTONLY; 265 return (-1); 266 } 267 test->num_streams = atoi(optarg); 268 if (test->num_streams > MAX_STREAMS) { 269 i_errno = IENUMSTREAMS; 270 return (-1); 271 } 272 break; 273 case 'B': 274 test->bind_address = (char *) malloc(strlen(optarg)+1); 275 strncpy(test->bind_address, optarg, strlen(optarg)+1); 276 break; 277 case 'b': 278 if (test->role == 's') { 279 i_errno = IECLIENTONLY; 280 return (-1); 281 } 282 test->settings->rate = unit_atof(optarg); 283 break; 284 case 'l': 285 if (test->role == 's') { 286 i_errno = IECLIENTONLY; 287 return (-1); 288 } 289 test->settings->blksize = unit_atoi(optarg); 290 if (test->settings->blksize > MAX_BLOCKSIZE) { 291 i_errno = IEBLOCKSIZE; 292 return (-1); 293 } 294 break; 295 case 'w': 296 // XXX: This is a socket buffer, not specific to TCP 297 if (test->role == 's') { 298 i_errno = IECLIENTONLY; 299 return (-1); 300 } 301 test->settings->socket_bufsize = unit_atof(optarg); 302 if (test->settings->socket_bufsize > MAX_TCP_BUFFER) { 303 i_errno = IEBUFSIZE; 304 return (-1); 305 } 306 break; 307 case 'i': 308 /* XXX: could potentially want separate stat collection and reporting intervals, 309 but just set them to be the same for now */ 310 test->stats_interval = atof(optarg); 311 test->reporter_interval = atof(optarg); 312 if (test->stats_interval > MAX_INTERVAL) { 313 i_errno = IEINTERVAL; 314 return (-1); 315 } 316 break; 317 case 'n': 318 if (test->role == 's') { 319 i_errno = IECLIENTONLY; 320 return (-1); 321 } 322 test->settings->bytes = unit_atoi(optarg); 323 break; 324 case 'N': 325 if (test->role == 's') { 326 i_errno = IECLIENTONLY; 327 return (-1); 328 } 329 test->no_delay = 1; 330 break; 331 case 'M': 332 if (test->role == 's') { 333 i_errno = IECLIENTONLY; 334 return (-1); 335 } 336 test->settings->mss = atoi(optarg); 337 if (test->settings->mss > MAX_MSS) { 338 i_errno = IEMSS; 339 return (-1); 340 } 341 break; 342 case 'f': 343 test->settings->unit_format = *optarg; 344 break; 345 case 'T': 346 #if !defined(linux) && !defined(__FreeBSD__) 347 // XXX: Should check to make sure UDP mode isn't set! 348 warning("TCP_INFO (-T) is not supported on your current platform"); 349 #else 350 test->tcp_info = 1; 351 #endif 352 break; 353 case '6': 354 test->settings->domain = AF_INET6; 355 break; 356 case 'V': 357 test->verbose = 1; 358 break; 359 case 'd': 360 test->debug = 1; 361 break; 362 case 'R': 363 if (test->role == 's') { 364 i_errno = IECLIENTONLY; 365 return (-1); 366 } 367 test->reverse = 1; 368 break; 369 case 'S': 370 if (test->role == 's') { 371 i_errno = IECLIENTONLY; 372 return (-1); 373 } 374 // XXX: Checking for errors in strtol is not portable. Leave as is? 375 test->settings->tos = strtol(optarg, NULL, 0); 376 break; 377 case 'v': 378 printf(version); 379 exit(0); 380 case 'h': 381 default: 382 usage_long(); 383 exit(1); 384 } 385 } 386 /* For subsequent calls to getopt */ 387 #ifdef __APPLE__ 388 optreset = 1; 389 #endif 390 optind = 0; 391 392 if ((test->role != 'c') && (test->role != 's')) { 393 i_errno = IENOROLE; 394 return (-1); 395 } 396 397 return (0); 398 } 399 400 int 401 all_data_sent(struct iperf_test * test) 402 { 403 if (test->settings->bytes > 0) { 404 if (test->bytes_sent >= (test->num_streams * test->settings->bytes)) { 405 return (1); 406 } 407 } 408 409 return (0); 410 } 411 412 int 413 iperf_send(struct iperf_test *test) 414 { 415 int result; 416 iperf_size_t bytes_sent; 417 fd_set temp_write_set; 418 struct timeval tv; 419 struct iperf_stream *sp; 420 421 memcpy(&temp_write_set, &test->write_set, sizeof(fd_set)); 422 tv.tv_sec = 15; 423 tv.tv_usec = 0; 424 425 result = select(test->max_fd + 1, NULL, &temp_write_set, NULL, &tv); 426 if (result < 0 && errno != EINTR) { 427 i_errno = IESELECT; 428 return (-1); 429 } 430 if (result > 0) { 431 SLIST_FOREACH(sp, &test->streams, streams) { 432 if (FD_ISSET(sp->socket, &temp_write_set)) { 433 if ((bytes_sent = sp->snd(sp)) < 0) { 434 i_errno = IESTREAMWRITE; 435 return (-1); 436 } 437 test->bytes_sent += bytes_sent; 438 FD_CLR(sp->socket, &temp_write_set); 439 } 440 } 441 } 442 443 return (0); 444 } 445 446 int 447 iperf_recv(struct iperf_test *test) 448 { 449 int result; 450 iperf_size_t bytes_sent; 451 fd_set temp_read_set; 452 struct timeval tv; 453 struct iperf_stream *sp; 454 455 memcpy(&temp_read_set, &test->read_set, sizeof(fd_set)); 456 tv.tv_sec = 15; 457 tv.tv_usec = 0; 458 459 result = select(test->max_fd + 1, &temp_read_set, NULL, NULL, &tv); 460 if (result < 0) { 461 i_errno = IESELECT; 462 return (-1); 463 } 464 if (result > 0) { 465 SLIST_FOREACH(sp, &test->streams, streams) { 466 if (FD_ISSET(sp->socket, &temp_read_set)) { 467 if ((bytes_sent = sp->rcv(sp)) < 0) { 468 i_errno = IESTREAMREAD; 469 return (-1); 470 } 471 test->bytes_sent += bytes_sent; 472 FD_CLR(sp->socket, &temp_read_set); 473 } 474 } 475 } 476 477 return (0); 478 } 479 480 int 481 iperf_init_test(struct iperf_test *test) 482 { 483 struct iperf_stream *sp; 484 time_t sec; 485 time_t usec; 486 487 if (test->protocol->init) { 488 if (test->protocol->init(test) < 0) 489 return (-1); 490 } 491 492 /* Set timers */ 493 if (test->settings->bytes == 0) { 494 test->timer = new_timer(test->duration, 0); 495 if (test->timer == NULL) 496 return (-1); 497 } 498 499 if (test->stats_interval != 0) { 500 sec = (time_t) test->stats_interval; 501 usec = (test->stats_interval - sec) * SEC_TO_US; 502 test->stats_timer = new_timer(sec, usec); 503 if (test->stats_timer == NULL) 504 return (-1); 505 } 506 if (test->reporter_interval != 0) { 507 sec = (time_t) test->reporter_interval; 508 usec = (test->reporter_interval - sec) * SEC_TO_US; 509 test->reporter_timer = new_timer(sec, usec); 510 if (test->reporter_timer == NULL) 511 return (-1); 512 } 513 514 /* Set start time */ 515 SLIST_FOREACH(sp, &test->streams, streams) { 516 if (gettimeofday(&sp->result->start_time, NULL) < 0) { 517 i_errno = IEINITTEST; 518 return (-1); 519 } 520 } 521 522 if (test->on_test_start) 523 test->on_test_start(test); 524 525 return (0); 526 } 527 528 529 /*********************************************************/ 530 531 int 532 package_parameters(struct iperf_test *test) 533 { 534 char pstring[256]; 535 char optbuf[128]; 536 memset(pstring, 0, 256*sizeof(char)); 537 538 *pstring = ' '; 539 540 if (test->protocol->id == Ptcp) { 541 strncat(pstring, "-p ", sizeof(pstring)); 542 } else if (test->protocol->id == Pudp) { 543 strncat(pstring, "-u ", sizeof(pstring)); 544 } 545 546 snprintf(optbuf, sizeof(optbuf), "-P %d ", test->num_streams); 547 strncat(pstring, optbuf, sizeof(pstring)); 548 549 if (test->reverse) 550 strncat(pstring, "-R ", sizeof(pstring)); 551 552 if (test->settings->socket_bufsize) { 553 snprintf(optbuf, sizeof(optbuf), "-w %d ", test->settings->socket_bufsize); 554 strncat(pstring, optbuf, sizeof(pstring)); 555 } 556 557 if (test->settings->rate) { 558 snprintf(optbuf, sizeof(optbuf), "-b %llu ", test->settings->rate); 559 strncat(pstring, optbuf, sizeof(pstring)); 560 } 561 562 if (test->settings->mss) { 563 snprintf(optbuf, sizeof(optbuf), "-m %d ", test->settings->mss); 564 strncat(pstring, optbuf, sizeof(pstring)); 565 } 566 567 if (test->no_delay) { 568 snprintf(optbuf, sizeof(optbuf), "-N "); 569 strncat(pstring, optbuf, sizeof(pstring)); 570 } 571 572 if (test->settings->bytes) { 573 snprintf(optbuf, sizeof(optbuf), "-n %llu ", test->settings->bytes); 574 strncat(pstring, optbuf, sizeof(pstring)); 575 } 576 577 if (test->duration) { 578 snprintf(optbuf, sizeof(optbuf), "-t %d ", test->duration); 579 strncat(pstring, optbuf, sizeof(pstring)); 580 } 581 582 if (test->settings->blksize) { 583 snprintf(optbuf, sizeof(optbuf), "-l %d ", test->settings->blksize); 584 strncat(pstring, optbuf, sizeof(pstring)); 585 } 586 587 if (test->settings->tos) { 588 snprintf(optbuf, sizeof(optbuf), "-S %d ", test->settings->tos); 589 strncat(pstring, optbuf, sizeof(pstring)); 590 } 591 592 *pstring = (char) (strlen(pstring) - 1); 593 594 if (Nwrite(test->ctrl_sck, pstring, strlen(pstring), Ptcp) < 0) { 595 i_errno = IESENDPARAMS; 596 return (-1); 597 } 598 599 return 0; 600 } 601 602 603 int 604 parse_parameters(struct iperf_test *test) 605 { 606 int n; 607 char *param, **params; 608 char len, ch; 609 char pstring[256]; 610 611 memset(pstring, 0, 256 * sizeof(char)); 612 613 if (Nread(test->ctrl_sck, &len, sizeof(char), Ptcp) < 0) { 614 i_errno = IERECVPARAMS; 615 return (-1); 616 } 617 618 if (Nread(test->ctrl_sck, pstring, len, Ptcp) < 0) { 619 i_errno = IERECVPARAMS; 620 return (-1); 621 } 622 623 for (param = strtok(pstring, " "), n = 0, params = NULL; param; param = strtok(NULL, " ")) { 624 if ((params = realloc(params, (n+1)*sizeof(char *))) == NULL) { 625 i_errno = IERECVPARAMS; 626 return (-1); 627 } 628 params[n] = param; 629 n++; 630 } 631 632 // XXX: Should we check for parameters exceeding maximum values here? 633 while ((ch = getopt(n, params, "pt:n:m:uNP:Rw:l:b:S:")) != -1) { 634 switch (ch) { 635 case 'p': 636 set_protocol(test, Ptcp); 637 break; 638 case 't': 639 test->duration = atoi(optarg); 640 break; 641 case 'n': 642 test->settings->bytes = atoll(optarg); 643 break; 644 case 'm': 645 test->settings->mss = atoi(optarg); 646 break; 647 case 'u': 648 set_protocol(test, Pudp); 649 break; 650 case 'N': 651 test->no_delay = 1; 652 break; 653 case 'P': 654 test->num_streams = atoi(optarg); 655 break; 656 case 'R': 657 test->reverse = 1; 658 break; 659 case 'w': 660 test->settings->socket_bufsize = atoi(optarg); 661 break; 662 case 'l': 663 test->settings->blksize = atoi(optarg); 664 break; 665 case 'b': 666 test->settings->rate = atoll(optarg); 667 break; 668 case 'S': 669 test->settings->tos = atoi(optarg); 670 break; 671 } 672 } 673 #ifdef __APPLE__ 674 optreset = 1; 675 #endif 676 optind = 0; 677 678 free(params); 679 680 return (0); 681 } 682 683 /** 684 * iperf_exchange_parameters - handles the param_Exchange part for client 685 * 686 */ 687 688 int 689 iperf_exchange_parameters(struct iperf_test * test) 690 { 691 int s, msg; 692 char state; 693 694 if (test->role == 'c') { 695 696 if (package_parameters(test) < 0) 697 return (-1); 698 699 } else { 700 701 if (parse_parameters(test) < 0) 702 return (-1); 703 704 if ((s = test->protocol->listen(test)) < 0) { 705 state = SERVER_ERROR; 706 if (Nwrite(test->ctrl_sck, &state, sizeof(state), Ptcp) < 0) { 707 i_errno = IESENDMESSAGE; 708 return (-1); 709 } 710 msg = htonl(i_errno); 711 if (Nwrite(test->ctrl_sck, &msg, sizeof(msg), Ptcp) < 0) { 712 i_errno = IECTRLWRITE; 713 return (-1); 714 } 715 msg = htonl(errno); 716 if (Nwrite(test->ctrl_sck, &msg, sizeof(msg), Ptcp) < 0) { 717 i_errno = IECTRLWRITE; 718 return (-1); 719 } 720 return (-1); 721 } 722 FD_SET(s, &test->read_set); 723 test->max_fd = (s > test->max_fd) ? s : test->max_fd; 724 test->prot_listener = s; 725 726 // Send the control message to create streams and start the test 727 test->state = CREATE_STREAMS; 728 if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) { 729 i_errno = IESENDMESSAGE; 730 return (-1); 731 } 732 733 } 734 735 return (0); 736 } 737 738 /*************************************************************/ 739 740 int 741 iperf_exchange_results(struct iperf_test *test) 742 { 743 unsigned int size; 744 char buf[128]; 745 char *results; 746 struct iperf_stream *sp; 747 iperf_size_t bytes_transferred; 748 749 if (test->role == 'c') { 750 /* Prepare results string and send to server */ 751 results = NULL; 752 size = 0; 753 754 snprintf(buf, 128, "-C %f\n", test->cpu_util); 755 size += strlen(buf); 756 if ((results = malloc(size+1)) == NULL) { 757 i_errno = IEPACKAGERESULTS; 758 return (-1); 759 } 760 *results = '\0'; 761 strncat(results, buf, size+1); 762 763 SLIST_FOREACH(sp, &test->streams, streams) { 764 bytes_transferred = (test->reverse ? sp->result->bytes_received : sp->result->bytes_sent); 765 snprintf(buf, 128, "%d:%llu,%lf,%d,%d\n", sp->id, bytes_transferred,sp->jitter, 766 sp->cnt_error, sp->packet_count); 767 size += strlen(buf); 768 if ((results = realloc(results, size+1)) == NULL) { 769 i_errno = IEPACKAGERESULTS; 770 return (-1); 771 } 772 /* 773 if (sp == SLIST_FIRST(&test->streams)) 774 *results = '\0'; 775 */ 776 strncat(results, buf, size+1); 777 } 778 size++; 779 size = htonl(size); 780 if (Nwrite(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) { 781 i_errno = IESENDRESULTS; 782 return (-1); 783 } 784 if (Nwrite(test->ctrl_sck, results, ntohl(size), Ptcp) < 0) { 785 i_errno = IESENDRESULTS; 786 return (-1); 787 } 788 free(results); 789 790 /* Get server results string */ 791 if (Nread(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) { 792 i_errno = IERECVRESULTS; 793 return (-1); 794 } 795 size = ntohl(size); 796 results = (char *) malloc(size * sizeof(char)); 797 if (results == NULL) { 798 i_errno = IERECVRESULTS; 799 return (-1); 800 } 801 if (Nread(test->ctrl_sck, results, size, Ptcp) < 0) { 802 i_errno = IERECVRESULTS; 803 return (-1); 804 } 805 806 // XXX: The only error this sets is IESTREAMID, which may never be reached. Consider making void. 807 if (parse_results(test, results) < 0) 808 return (-1); 809 810 free(results); 811 812 } else { 813 /* Get client results string */ 814 if (Nread(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) { 815 i_errno = IERECVRESULTS; 816 return (-1); 817 } 818 size = ntohl(size); 819 results = (char *) malloc(size * sizeof(char)); 820 if (results == NULL) { 821 i_errno = IERECVRESULTS; 822 return (-1); 823 } 824 if (Nread(test->ctrl_sck, results, size, Ptcp) < 0) { 825 i_errno = IERECVRESULTS; 826 return (-1); 827 } 828 829 // XXX: Same issue as with client 830 if (parse_results(test, results) < 0) 831 return (-1); 832 833 free(results); 834 835 /* Prepare results string and send to client */ 836 results = NULL; 837 size = 0; 838 839 snprintf(buf, 128, "-C %f\n", test->cpu_util); 840 size += strlen(buf); 841 if ((results = malloc(size+1)) == NULL) { 842 i_errno = IEPACKAGERESULTS; 843 return (-1); 844 } 845 *results = '\0'; 846 strncat(results, buf, size+1); 847 848 SLIST_FOREACH(sp, &test->streams, streams) { 849 bytes_transferred = (test->reverse ? sp->result->bytes_sent : sp->result->bytes_received); 850 snprintf(buf, 128, "%d:%llu,%lf,%d,%d\n", sp->id, bytes_transferred, sp->jitter, 851 sp->cnt_error, sp->packet_count); 852 size += strlen(buf); 853 if ((results = realloc(results, size+1)) == NULL) { 854 i_errno = IEPACKAGERESULTS; 855 return (-1); 856 } 857 /* 858 if (sp == SLIST_FIRST(&test->streams)) 859 *results = '\0'; 860 */ 861 strncat(results, buf, size+1); 862 } 863 size++; 864 size = htonl(size); 865 if (Nwrite(test->ctrl_sck, &size, sizeof(size), Ptcp) < 0) { 866 i_errno = IESENDRESULTS; 867 return (-1); 868 } 869 if (Nwrite(test->ctrl_sck, results, ntohl(size), Ptcp) < 0) { 870 i_errno = IESENDRESULTS; 871 return (-1); 872 } 873 free(results); 874 875 } 876 877 return (0); 878 } 879 880 /*************************************************************/ 881 882 int 883 parse_results(struct iperf_test *test, char *results) 884 { 885 int sid, cerror, pcount; 886 double jitter; 887 char *strp; 888 char *tok; 889 iperf_size_t bytes_transferred; 890 struct iperf_stream *sp; 891 892 /* Isolate the first line */ 893 strp = strchr(results, '\n'); 894 *strp = '\0'; 895 strp++; 896 897 for (tok = strtok(results, " "); tok; tok = strtok(NULL, " ")) { 898 if (strcmp(tok, "-C") == 0) { 899 test->remote_cpu_util = atof(strtok(NULL, " ")); 900 } 901 } 902 903 for (strp; *strp; strp = strchr(strp, '\n')+1) { 904 sscanf(strp, "%d:%llu,%lf,%d,%d\n", &sid, &bytes_transferred, &jitter, 905 &cerror, &pcount); 906 SLIST_FOREACH(sp, &test->streams, streams) 907 if (sp->id == sid) break; 908 if (sp == NULL) { 909 i_errno = IESTREAMID; 910 return (-1); 911 } 912 if ((test->role == 'c' && !test->reverse) || (test->role == 's' && test->reverse)) { 913 sp->jitter = jitter; 914 sp->cnt_error = cerror; 915 sp->packet_count = pcount; 916 sp->result->bytes_received = bytes_transferred; 917 } else 918 sp->result->bytes_sent = bytes_transferred; 919 } 920 921 return (0); 922 } 923 924 925 /*************************************************************/ 926 /** 927 * add_to_interval_list -- adds new interval to the interval_list 928 * XXX: Interval lists should use SLIST implementation fro queue 929 */ 930 931 void 932 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new) 933 { 934 struct iperf_interval_results *ip = NULL; 935 936 ip = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results)); 937 memcpy(ip, new, sizeof(struct iperf_interval_results)); 938 ip->next = NULL; 939 940 if (rp->interval_results == NULL) { /* if 1st interval */ 941 rp->interval_results = ip; 942 rp->last_interval_results = ip; /* pointer to last element in list */ 943 } else { /* add to end of list */ 944 rp->last_interval_results->next = ip; 945 rp->last_interval_results = ip; 946 } 947 } 948 949 950 /************************************************************/ 951 952 /** 953 * connect_msg -- displays connection message 954 * denoting sender/receiver details 955 * 956 */ 957 958 void 959 connect_msg(struct iperf_stream *sp) 960 { 961 char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN]; 962 int lport, rport, domain = sp->settings->domain; 963 964 if (domain == AF_INET) { 965 inet_ntop(domain, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl)); 966 inet_ntop(domain, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr)); 967 lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port); 968 rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port); 969 } else { 970 inet_ntop(domain, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl)); 971 inet_ntop(domain, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr)); 972 lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port); 973 rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port); 974 } 975 976 printf("[%3d] local %s port %d connected to %s port %d\n", 977 sp->socket, ipl, lport, ipr, rport); 978 } 979 980 981 /**************************************************************************/ 982 983 struct iperf_test * 984 iperf_new_test() 985 { 986 struct iperf_test *test; 987 988 test = (struct iperf_test *) malloc(sizeof(struct iperf_test)); 989 if (!test) { 990 i_errno = IENEWTEST; 991 return (NULL); 992 } 993 /* initialize everything to zero */ 994 memset(test, 0, sizeof(struct iperf_test)); 995 996 test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings)); 997 memset(test->settings, 0, sizeof(struct iperf_settings)); 998 999 return (test); 1000 } 1001 1002 /**************************************************************************/ 1003 int 1004 iperf_defaults(struct iperf_test * testp) 1005 { 1006 testp->duration = DURATION; 1007 testp->server_port = PORT; 1008 testp->ctrl_sck = -1; 1009 testp->prot_listener = -1; 1010 1011 testp->stats_callback = iperf_stats_callback; 1012 testp->reporter_callback = iperf_reporter_callback; 1013 1014 testp->stats_interval = 0; 1015 testp->reporter_interval = 0; 1016 testp->num_streams = 1; 1017 1018 testp->settings->domain = AF_INET; 1019 testp->settings->unit_format = 'a'; 1020 testp->settings->socket_bufsize = 0; /* use autotuning */ 1021 testp->settings->blksize = DEFAULT_TCP_BLKSIZE; 1022 testp->settings->rate = RATE; /* UDP only */ 1023 testp->settings->mss = 0; 1024 testp->settings->bytes = 0; 1025 memset(testp->cookie, 0, COOKIE_SIZE); 1026 1027 /* Set up protocol list */ 1028 SLIST_INIT(&testp->streams); 1029 SLIST_INIT(&testp->protocols); 1030 1031 struct protocol *tcp, *udp; 1032 tcp = (struct protocol *) malloc(sizeof(struct protocol)); 1033 if (!tcp) 1034 return (-1); 1035 memset(tcp, 0, sizeof(struct protocol)); 1036 udp = (struct protocol *) malloc(sizeof(struct protocol)); 1037 if (!udp) 1038 return (-1); 1039 memset(udp, 0, sizeof(struct protocol)); 1040 1041 tcp->id = Ptcp; 1042 tcp->name = "TCP"; 1043 tcp->accept = iperf_tcp_accept; 1044 tcp->listen = iperf_tcp_listen; 1045 tcp->connect = iperf_tcp_connect; 1046 tcp->send = iperf_tcp_send; 1047 tcp->recv = iperf_tcp_recv; 1048 tcp->init = NULL; 1049 SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols); 1050 1051 udp->id = Pudp; 1052 udp->name = "UDP"; 1053 udp->accept = iperf_udp_accept; 1054 udp->listen = iperf_udp_listen; 1055 udp->connect = iperf_udp_connect; 1056 udp->send = iperf_udp_send; 1057 udp->recv = iperf_udp_recv; 1058 udp->init = iperf_udp_init; 1059 SLIST_INSERT_AFTER(tcp, udp, protocols); 1060 1061 set_protocol(testp, Ptcp); 1062 1063 testp->on_new_stream = iperf_on_new_stream; 1064 testp->on_test_start = iperf_on_test_start; 1065 testp->on_connect = iperf_on_connect; 1066 testp->on_test_finish = iperf_on_test_finish; 1067 1068 return (0); 1069 } 1070 1071 1072 /**************************************************************************/ 1073 void 1074 iperf_free_test(struct iperf_test * test) 1075 { 1076 struct protocol *prot; 1077 struct iperf_stream *sp; 1078 1079 /* Free streams */ 1080 while (!SLIST_EMPTY(&test->streams)) { 1081 sp = SLIST_FIRST(&test->streams); 1082 SLIST_REMOVE_HEAD(&test->streams, streams); 1083 iperf_free_stream(sp); 1084 } 1085 1086 free(test->server_hostname); 1087 free(test->bind_address); 1088 free(test->settings); 1089 free_timer(test->timer); 1090 free_timer(test->stats_timer); 1091 free_timer(test->reporter_timer); 1092 1093 /* Free protocol list */ 1094 while (!SLIST_EMPTY(&test->protocols)) { 1095 prot = SLIST_FIRST(&test->protocols); 1096 SLIST_REMOVE_HEAD(&test->protocols, protocols); 1097 free(prot); 1098 } 1099 1100 /* XXX: Why are we setting these values to NULL? */ 1101 // test->streams = NULL; 1102 test->stats_callback = NULL; 1103 test->reporter_callback = NULL; 1104 free(test); 1105 } 1106 1107 1108 void 1109 iperf_reset_test(struct iperf_test *test) 1110 { 1111 struct iperf_stream *sp; 1112 1113 /* Free streams */ 1114 while (!SLIST_EMPTY(&test->streams)) { 1115 sp = SLIST_FIRST(&test->streams); 1116 SLIST_REMOVE_HEAD(&test->streams, streams); 1117 iperf_free_stream(sp); 1118 } 1119 free_timer(test->timer); 1120 free_timer(test->stats_timer); 1121 free_timer(test->reporter_timer); 1122 test->timer = NULL; 1123 test->stats_timer = NULL; 1124 test->reporter_timer = NULL; 1125 1126 SLIST_INIT(&test->streams); 1127 1128 test->role = 's'; 1129 set_protocol(test, Ptcp); 1130 test->duration = DURATION; 1131 test->state = 0; 1132 test->server_hostname = NULL; 1133 1134 test->ctrl_sck = -1; 1135 test->prot_listener = -1; 1136 1137 test->bytes_sent = 0; 1138 1139 test->reverse = 0; 1140 test->no_delay = 0; 1141 1142 FD_ZERO(&test->read_set); 1143 FD_ZERO(&test->write_set); 1144 1145 test->num_streams = 1; 1146 test->settings->socket_bufsize = 0; 1147 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 1148 test->settings->rate = RATE; /* UDP only */ 1149 test->settings->mss = 0; 1150 memset(test->cookie, 0, COOKIE_SIZE); 1151 } 1152 1153 1154 /**************************************************************************/ 1155 1156 /** 1157 * iperf_stats_callback -- handles the statistic gathering for both the client and server 1158 * 1159 * XXX: This function needs to be updated to reflect the new code 1160 */ 1161 1162 1163 void 1164 iperf_stats_callback(struct iperf_test * test) 1165 { 1166 struct iperf_stream *sp; 1167 struct iperf_stream_result *rp = NULL; 1168 struct iperf_interval_results *ip = NULL, temp; 1169 1170 SLIST_FOREACH(sp, &test->streams, streams) { 1171 rp = sp->result; 1172 1173 if ((test->role == 'c' && !test->reverse) || (test->role == 's' && test->reverse)) 1174 temp.bytes_transferred = rp->bytes_sent_this_interval; 1175 else 1176 temp.bytes_transferred = rp->bytes_received_this_interval; 1177 1178 ip = sp->result->interval_results; 1179 /* result->end_time contains timestamp of previous interval */ 1180 if ( ip != NULL ) /* not the 1st interval */ 1181 memcpy(&temp.interval_start_time, &sp->result->end_time, sizeof(struct timeval)); 1182 else /* or use timestamp from beginning */ 1183 memcpy(&temp.interval_start_time, &sp->result->start_time, sizeof(struct timeval)); 1184 /* now save time of end of this interval */ 1185 gettimeofday(&sp->result->end_time, NULL); 1186 memcpy(&temp.interval_end_time, &sp->result->end_time, sizeof(struct timeval)); 1187 temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1188 //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1189 if (test->tcp_info) 1190 get_tcpinfo(sp, &temp); 1191 add_to_interval_list(rp, &temp); 1192 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 1193 1194 } 1195 1196 } 1197 1198 static void 1199 iperf_print_intermediate(struct iperf_test *test) 1200 { 1201 char ubuf[UNIT_LEN]; 1202 char nbuf[UNIT_LEN]; 1203 struct iperf_stream *sp = NULL; 1204 iperf_size_t bytes = 0, bytes_sent = 0, bytes_received = 0; 1205 double start_time, end_time, avg_jitter; 1206 struct iperf_interval_results *ip = NULL; 1207 1208 SLIST_FOREACH(sp, &test->streams, streams) { 1209 print_interval_results(test, sp); 1210 bytes += sp->result->last_interval_results->bytes_transferred; /* sum up all streams */ 1211 } 1212 if (bytes <=0 ) { /* this can happen if timer goes off just when client exits */ 1213 fprintf(stderr, "error: bytes <= 0!\n"); 1214 return; 1215 } 1216 /* next build string with sum of all streams */ 1217 if (test->num_streams > 1) { 1218 sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */ 1219 ip = sp->result->last_interval_results; /* use 1st stream for timing info */ 1220 1221 unit_snprintf(ubuf, UNIT_LEN, (double) (bytes), 'A'); 1222 unit_snprintf(nbuf, UNIT_LEN, (double) (bytes / ip->interval_duration), 1223 test->settings->unit_format); 1224 1225 start_time = timeval_diff(&sp->result->start_time,&ip->interval_start_time); 1226 end_time = timeval_diff(&sp->result->start_time,&ip->interval_end_time); 1227 printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf); 1228 } 1229 if (test->tcp_info) { 1230 print_tcpinfo(test); 1231 } 1232 } 1233 1234 static void 1235 iperf_print_results (struct iperf_test *test) 1236 { 1237 1238 int total_packets = 0, lost_packets = 0; 1239 char ubuf[UNIT_LEN]; 1240 char nbuf[UNIT_LEN]; 1241 struct iperf_stream *sp = NULL; 1242 iperf_size_t bytes = 0, bytes_sent = 0, bytes_received = 0; 1243 iperf_size_t total_sent = 0, total_received = 0; 1244 double start_time, end_time, avg_jitter; 1245 struct iperf_interval_results *ip = NULL; 1246 /* print final summary for all intervals */ 1247 1248 printf(report_bw_header); 1249 1250 start_time = 0.; 1251 sp = SLIST_FIRST(&test->streams); 1252 end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); 1253 SLIST_FOREACH(sp, &test->streams, streams) { 1254 bytes_sent = sp->result->bytes_sent; 1255 bytes_received = sp->result->bytes_received; 1256 total_sent += bytes_sent; 1257 total_received += bytes_received; 1258 1259 if (test->protocol->id == Pudp) { 1260 total_packets += sp->packet_count; 1261 lost_packets += sp->cnt_error; 1262 avg_jitter += sp->jitter; 1263 } 1264 1265 if (bytes_sent > 0) { 1266 unit_snprintf(ubuf, UNIT_LEN, (double) (bytes_sent), 'A'); 1267 unit_snprintf(nbuf, UNIT_LEN, (double) (bytes_sent / end_time), test->settings->unit_format); 1268 if (test->protocol->id == Ptcp) { 1269 printf(" Sent\n"); 1270 printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf); 1271 } else { 1272 printf(report_bw_jitter_loss_format, sp->socket, start_time, 1273 end_time, ubuf, nbuf, sp->jitter * 1000, sp->cnt_error, 1274 sp->packet_count, (double) (100.0 * sp->cnt_error / sp->packet_count)); 1275 if (test->role == 'c') { 1276 printf(report_datagrams, sp->socket, sp->packet_count); 1277 } 1278 if (sp->outoforder_packets > 0) 1279 printf(report_sum_outoforder, start_time, end_time, sp->cnt_error); 1280 } 1281 } 1282 if (bytes_received > 0) { 1283 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A'); 1284 unit_snprintf(nbuf, UNIT_LEN, (double) (bytes_received / end_time), test->settings->unit_format); 1285 if (test->protocol->id == Ptcp) { 1286 printf(" Received\n"); 1287 printf(report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf); 1288 } 1289 } 1290 } 1291 1292 if (test->num_streams > 1) { 1293 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A'); 1294 unit_snprintf(nbuf, UNIT_LEN, (double) total_sent / end_time, test->settings->unit_format); 1295 if (test->protocol->id == Ptcp) { 1296 printf(" Total sent\n"); 1297 printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf); 1298 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A'); 1299 unit_snprintf(nbuf, UNIT_LEN, (double) (total_received / end_time), test->settings->unit_format); 1300 printf(" Total received\n"); 1301 printf(report_sum_bw_format, start_time, end_time, ubuf, nbuf); 1302 } else { 1303 avg_jitter /= test->num_streams; 1304 printf(report_sum_bw_jitter_loss_format, start_time, end_time, ubuf, nbuf, avg_jitter, 1305 lost_packets, total_packets, (double) (100.0 * lost_packets / total_packets)); 1306 } 1307 } 1308 1309 if (test->tcp_info) { 1310 print_tcpinfo(test); 1311 } 1312 1313 if (test->verbose) { 1314 printf("Host CPU Utilization: %.1f%%\n", test->cpu_util); 1315 printf("Remote CPU Utilization: %.1f%%\n", test->remote_cpu_util); 1316 } 1317 } 1318 1319 /**************************************************************************/ 1320 1321 /** 1322 * iperf_reporter_callback -- handles the report printing 1323 * 1324 */ 1325 1326 void 1327 iperf_reporter_callback(struct iperf_test * test) 1328 { 1329 int total_packets = 0, lost_packets = 0; 1330 char ubuf[UNIT_LEN]; 1331 char nbuf[UNIT_LEN]; 1332 struct iperf_stream *sp = NULL; 1333 iperf_size_t bytes = 0, bytes_sent = 0, bytes_received = 0; 1334 iperf_size_t total_sent = 0, total_received = 0; 1335 double start_time, end_time, avg_jitter; 1336 struct iperf_interval_results *ip = NULL; 1337 1338 switch (test->state) { 1339 case TEST_RUNNING: 1340 case STREAM_RUNNING: 1341 /* print interval results for each stream */ 1342 iperf_print_intermediate(test); 1343 break; 1344 case DISPLAY_RESULTS: 1345 iperf_print_intermediate(test); 1346 iperf_print_results(test); 1347 break; 1348 } 1349 1350 } 1351 1352 /**************************************************************************/ 1353 void 1354 print_interval_results(struct iperf_test * test, struct iperf_stream * sp) 1355 { 1356 char ubuf[UNIT_LEN]; 1357 char nbuf[UNIT_LEN]; 1358 double st = 0., et = 0.; 1359 struct iperf_interval_results *ir = NULL; 1360 1361 ir = sp->result->last_interval_results; /* get last entry in linked list */ 1362 if (ir == NULL) { 1363 printf("print_interval_results Error: interval_results = NULL \n"); 1364 return; 1365 } 1366 if (sp == SLIST_FIRST(&test->streams)) { 1367 printf(report_bw_header); 1368 } 1369 1370 unit_snprintf(ubuf, UNIT_LEN, (double) (ir->bytes_transferred), 'A'); 1371 unit_snprintf(nbuf, UNIT_LEN, (double) (ir->bytes_transferred / ir->interval_duration), 1372 test->settings->unit_format); 1373 1374 st = timeval_diff(&sp->result->start_time,&ir->interval_start_time); 1375 et = timeval_diff(&sp->result->start_time,&ir->interval_end_time); 1376 1377 printf(report_bw_format, sp->socket, st, et, ubuf, nbuf); 1378 1379 /* doing aggregate TCP_INFO reporting for now... 1380 if (test->tcp_info) 1381 print_tcpinfo(ir); 1382 */ 1383 1384 } 1385 1386 /**************************************************************************/ 1387 void 1388 iperf_free_stream(struct iperf_stream * sp) 1389 { 1390 struct iperf_interval_results *ip, *np; 1391 1392 /* XXX: need to free interval list too! */ 1393 free(sp->buffer); 1394 for (ip = sp->result->interval_results; ip; ip = np) { 1395 np = ip->next; 1396 free(ip); 1397 } 1398 free(sp->result); 1399 free(sp->send_timer); 1400 free(sp); 1401 } 1402 1403 /**************************************************************************/ 1404 struct iperf_stream * 1405 iperf_new_stream(struct iperf_test *test, int s) 1406 { 1407 int i; 1408 struct iperf_stream *sp; 1409 1410 sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream)); 1411 if (!sp) { 1412 i_errno = IECREATESTREAM; 1413 return (NULL); 1414 } 1415 1416 memset(sp, 0, sizeof(struct iperf_stream)); 1417 1418 sp->buffer = (char *) malloc(test->settings->blksize); 1419 sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result)); 1420 sp->settings = test->settings; 1421 1422 if (!sp->buffer) { 1423 i_errno = IECREATESTREAM; 1424 return (NULL); 1425 } 1426 if (!sp->result) { 1427 i_errno = IECREATESTREAM; 1428 return (NULL); 1429 } 1430 1431 memset(sp->result, 0, sizeof(struct iperf_stream_result)); 1432 1433 /* Randomize the buffer */ 1434 srandom(time(NULL)); 1435 for (i = 0; i < test->settings->blksize; ++i) 1436 sp->buffer[i] = random(); 1437 1438 /* Set socket */ 1439 sp->socket = s; 1440 1441 sp->snd = test->protocol->send; 1442 sp->rcv = test->protocol->recv; 1443 1444 /* Initialize stream */ 1445 if (iperf_init_stream(sp, test) < 0) 1446 return (NULL); 1447 iperf_add_stream(test, sp); 1448 1449 return (sp); 1450 } 1451 1452 /**************************************************************************/ 1453 int 1454 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test) 1455 { 1456 socklen_t len; 1457 int opt; 1458 1459 len = sizeof(struct sockaddr_storage); 1460 if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) { 1461 i_errno = IEINITSTREAM; 1462 return (-1); 1463 } 1464 len = sizeof(struct sockaddr_storage); 1465 if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) { 1466 i_errno = IEINITSTREAM; 1467 return (-1); 1468 } 1469 /* Set IP TOS */ 1470 if ((opt = test->settings->tos)) { 1471 if (test->settings->domain == AF_INET6) { 1472 #ifdef IPV6_TCLASS 1473 if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) { 1474 i_errno = IESETCOS; 1475 return (-1); 1476 } 1477 #else 1478 i_errno = IESETCOS; 1479 return (-1); 1480 #endif 1481 } else { 1482 if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) { 1483 i_errno = IESETTOS; 1484 return (-1); 1485 } 1486 } 1487 } 1488 1489 return (0); 1490 } 1491 1492 /**************************************************************************/ 1493 void 1494 iperf_add_stream(struct iperf_test * test, struct iperf_stream * sp) 1495 { 1496 int i; 1497 struct iperf_stream *n, *prev; 1498 1499 if (SLIST_EMPTY(&test->streams)) { 1500 SLIST_INSERT_HEAD(&test->streams, sp, streams); 1501 sp->id = 1; 1502 } else { 1503 // for (n = test->streams, i = 2; n->next; n = n->next, ++i); 1504 i = 2; 1505 SLIST_FOREACH(n, &test->streams, streams) { 1506 prev = n; 1507 ++i; 1508 } 1509 SLIST_INSERT_AFTER(prev, sp, streams); 1510 sp->id = i; 1511 } 1512 } 1513 1514 void 1515 sig_handler(int sig) 1516 { 1517 longjmp(env, 1); 1518 } 1519 1520