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