1 /* 2 * Copyright (c) 2009-2014, 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 #define _GNU_SOURCE 11 #define __USE_GNU 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <getopt.h> 17 #include <errno.h> 18 #include <signal.h> 19 #include <unistd.h> 20 #include <assert.h> 21 #include <fcntl.h> 22 #include <sys/socket.h> 23 #include <sys/types.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <netdb.h> 27 #include <pthread.h> 28 #include <stdint.h> 29 #include <netinet/tcp.h> 30 #include <sys/time.h> 31 #include <sys/resource.h> 32 #include <sys/mman.h> 33 #include <sys/stat.h> 34 #include <sched.h> 35 #include <setjmp.h> 36 #include <stdarg.h> 37 38 #if defined(__FreeBSD__) 39 #include <sys/param.h> 40 #include <sys/cpuset.h> 41 #endif 42 43 #include "net.h" 44 #include "iperf.h" 45 #include "iperf_api.h" 46 #include "iperf_udp.h" 47 #include "iperf_tcp.h" 48 #include "iperf_sctp.h" 49 #include "timer.h" 50 51 #include "cjson.h" 52 #include "units.h" 53 #include "tcp_window_size.h" 54 #include "iperf_util.h" 55 #include "locale.h" 56 57 58 /* Forwards. */ 59 static int send_parameters(struct iperf_test *test); 60 static int get_parameters(struct iperf_test *test); 61 static int send_results(struct iperf_test *test); 62 static int get_results(struct iperf_test *test); 63 static int diskfile_send(struct iperf_stream *sp); 64 static int diskfile_recv(struct iperf_stream *sp); 65 static int JSON_write(int fd, cJSON *json); 66 static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams); 67 static cJSON *JSON_read(int fd); 68 69 70 /*************************** Print usage functions ****************************/ 71 72 void 73 usage() 74 { 75 fputs(usage_shortstr, stderr); 76 } 77 78 79 void 80 usage_long() 81 { 82 fprintf(stderr, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE / 1024); 83 } 84 85 86 void warning(char *str) 87 { 88 fprintf(stderr, "warning: %s\n", str); 89 } 90 91 92 /************** Getter routines for some fields inside iperf_test *************/ 93 94 int 95 iperf_get_verbose(struct iperf_test *ipt) 96 { 97 return ipt->verbose; 98 } 99 100 int 101 iperf_get_control_socket(struct iperf_test *ipt) 102 { 103 return ipt->ctrl_sck; 104 } 105 106 int 107 iperf_get_test_omit(struct iperf_test *ipt) 108 { 109 return ipt->omit; 110 } 111 112 int 113 iperf_get_test_duration(struct iperf_test *ipt) 114 { 115 return ipt->duration; 116 } 117 118 uint64_t 119 iperf_get_test_rate(struct iperf_test *ipt) 120 { 121 return ipt->settings->rate; 122 } 123 124 int 125 iperf_get_test_burst(struct iperf_test *ipt) 126 { 127 return ipt->settings->burst; 128 } 129 130 char 131 iperf_get_test_role(struct iperf_test *ipt) 132 { 133 return ipt->role; 134 } 135 136 int 137 iperf_get_test_reverse(struct iperf_test *ipt) 138 { 139 return ipt->reverse; 140 } 141 142 int 143 iperf_get_test_blksize(struct iperf_test *ipt) 144 { 145 return ipt->settings->blksize; 146 } 147 148 int 149 iperf_get_test_socket_bufsize(struct iperf_test *ipt) 150 { 151 return ipt->settings->socket_bufsize; 152 } 153 154 double 155 iperf_get_test_reporter_interval(struct iperf_test *ipt) 156 { 157 return ipt->reporter_interval; 158 } 159 160 double 161 iperf_get_test_stats_interval(struct iperf_test *ipt) 162 { 163 return ipt->stats_interval; 164 } 165 166 int 167 iperf_get_test_num_streams(struct iperf_test *ipt) 168 { 169 return ipt->num_streams; 170 } 171 172 int 173 iperf_get_test_server_port(struct iperf_test *ipt) 174 { 175 return ipt->server_port; 176 } 177 178 char* 179 iperf_get_test_server_hostname(struct iperf_test *ipt) 180 { 181 return ipt->server_hostname; 182 } 183 184 int 185 iperf_get_test_protocol_id(struct iperf_test *ipt) 186 { 187 return ipt->protocol->id; 188 } 189 190 int 191 iperf_get_test_json_output(struct iperf_test *ipt) 192 { 193 return ipt->json_output; 194 } 195 196 int 197 iperf_get_test_zerocopy(struct iperf_test *ipt) 198 { 199 return ipt->zerocopy; 200 } 201 202 int 203 iperf_get_test_may_use_sigalrm(struct iperf_test *ipt) 204 { 205 return ipt->may_use_sigalrm; 206 } 207 208 /************** Setter routines for some fields inside iperf_test *************/ 209 210 void 211 iperf_set_verbose(struct iperf_test *ipt, int verbose) 212 { 213 ipt->verbose = verbose; 214 } 215 216 void 217 iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck) 218 { 219 ipt->ctrl_sck = ctrl_sck; 220 } 221 222 void 223 iperf_set_test_omit(struct iperf_test *ipt, int omit) 224 { 225 ipt->omit = omit; 226 } 227 228 void 229 iperf_set_test_duration(struct iperf_test *ipt, int duration) 230 { 231 ipt->duration = duration; 232 } 233 234 void 235 iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval) 236 { 237 ipt->reporter_interval = reporter_interval; 238 } 239 240 void 241 iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval) 242 { 243 ipt->stats_interval = stats_interval; 244 } 245 246 void 247 iperf_set_test_state(struct iperf_test *ipt, signed char state) 248 { 249 ipt->state = state; 250 } 251 252 void 253 iperf_set_test_blksize(struct iperf_test *ipt, int blksize) 254 { 255 ipt->settings->blksize = blksize; 256 } 257 258 void 259 iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate) 260 { 261 ipt->settings->rate = rate; 262 } 263 264 void 265 iperf_set_test_burst(struct iperf_test *ipt, int burst) 266 { 267 ipt->settings->burst = burst; 268 } 269 270 void 271 iperf_set_test_server_port(struct iperf_test *ipt, int server_port) 272 { 273 ipt->server_port = server_port; 274 } 275 276 void 277 iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize) 278 { 279 ipt->settings->socket_bufsize = socket_bufsize; 280 } 281 282 void 283 iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams) 284 { 285 ipt->num_streams = num_streams; 286 } 287 288 static void 289 check_sender_has_retransmits(struct iperf_test *ipt) 290 { 291 if (ipt->sender && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits()) 292 ipt->sender_has_retransmits = 1; 293 else 294 ipt->sender_has_retransmits = 0; 295 } 296 297 void 298 iperf_set_test_role(struct iperf_test *ipt, char role) 299 { 300 ipt->role = role; 301 if (role == 'c') 302 ipt->sender = 1; 303 else if (role == 's') 304 ipt->sender = 0; 305 if (ipt->reverse) 306 ipt->sender = ! ipt->sender; 307 check_sender_has_retransmits(ipt); 308 } 309 310 void 311 iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname) 312 { 313 ipt->server_hostname = strdup(server_hostname); 314 } 315 316 void 317 iperf_set_test_reverse(struct iperf_test *ipt, int reverse) 318 { 319 ipt->reverse = reverse; 320 if (ipt->reverse) 321 ipt->sender = ! ipt->sender; 322 check_sender_has_retransmits(ipt); 323 } 324 325 void 326 iperf_set_test_json_output(struct iperf_test *ipt, int json_output) 327 { 328 ipt->json_output = json_output; 329 } 330 331 int 332 iperf_has_zerocopy( void ) 333 { 334 return has_sendfile(); 335 } 336 337 void 338 iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy) 339 { 340 ipt->zerocopy = zerocopy; 341 } 342 343 void 344 iperf_set_test_may_use_sigalrm(struct iperf_test *ipt, int may_use_sigalrm) 345 { 346 ipt->may_use_sigalrm = may_use_sigalrm; 347 } 348 349 /********************** Get/set test protocol structure ***********************/ 350 351 struct protocol * 352 get_protocol(struct iperf_test *test, int prot_id) 353 { 354 struct protocol *prot; 355 356 SLIST_FOREACH(prot, &test->protocols, protocols) { 357 if (prot->id == prot_id) 358 break; 359 } 360 361 if (prot == NULL) 362 i_errno = IEPROTOCOL; 363 364 return prot; 365 } 366 367 int 368 set_protocol(struct iperf_test *test, int prot_id) 369 { 370 struct protocol *prot = NULL; 371 372 SLIST_FOREACH(prot, &test->protocols, protocols) { 373 if (prot->id == prot_id) { 374 test->protocol = prot; 375 check_sender_has_retransmits(test); 376 return 0; 377 } 378 } 379 380 i_errno = IEPROTOCOL; 381 return -1; 382 } 383 384 385 /************************** Iperf callback functions **************************/ 386 387 void 388 iperf_on_new_stream(struct iperf_stream *sp) 389 { 390 connect_msg(sp); 391 } 392 393 void 394 iperf_on_test_start(struct iperf_test *test) 395 { 396 if (test->json_output) { 397 cJSON_AddItemToObject(test->json_start, "test_start", iperf_json_printf("protocol: %s num_streams: %d blksize: %d omit: %d duration: %d bytes: %d blocks: %d", test->protocol->name, (int64_t) test->num_streams, (int64_t) test->settings->blksize, (int64_t) test->omit, (int64_t) test->duration, (int64_t) test->settings->bytes, (int64_t) test->settings->blocks)); 398 } else { 399 if (test->verbose) { 400 if (test->settings->bytes) 401 iprintf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes); 402 else if (test->settings->blocks) 403 iprintf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks); 404 else 405 iprintf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration); 406 } 407 } 408 } 409 410 /* This converts an IPv6 string address from IPv4-mapped format into regular 411 ** old IPv4 format, which is easier on the eyes of network veterans. 412 ** 413 ** If the v6 address is not v4-mapped it is left alone. 414 */ 415 static void 416 mapped_v4_to_regular_v4(char *str) 417 { 418 char *prefix = "::ffff:"; 419 int prefix_len; 420 421 prefix_len = strlen(prefix); 422 if (strncmp(str, prefix, prefix_len) == 0) { 423 int str_len = strlen(str); 424 memmove(str, str + prefix_len, str_len - prefix_len + 1); 425 } 426 } 427 428 void 429 iperf_on_connect(struct iperf_test *test) 430 { 431 time_t now_secs; 432 const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT"; 433 char now_str[100]; 434 char ipr[INET6_ADDRSTRLEN]; 435 int port; 436 struct sockaddr_storage sa; 437 struct sockaddr_in *sa_inP; 438 struct sockaddr_in6 *sa_in6P; 439 socklen_t len; 440 int opt; 441 442 now_secs = time((time_t*) 0); 443 (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs)); 444 if (test->json_output) 445 cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s timesecs: %d", now_str, (int64_t) now_secs)); 446 else if (test->verbose) 447 iprintf(test, report_time, now_str); 448 449 if (test->role == 'c') { 450 if (test->json_output) 451 cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d", test->server_hostname, (int64_t) test->server_port)); 452 else { 453 iprintf(test, report_connecting, test->server_hostname, test->server_port); 454 if (test->reverse) 455 iprintf(test, report_reverse, test->server_hostname); 456 } 457 } else { 458 len = sizeof(sa); 459 getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len); 460 if (getsockdomain(test->ctrl_sck) == AF_INET) { 461 sa_inP = (struct sockaddr_in *) &sa; 462 inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr)); 463 port = ntohs(sa_inP->sin_port); 464 } else { 465 sa_in6P = (struct sockaddr_in6 *) &sa; 466 inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr)); 467 port = ntohs(sa_in6P->sin6_port); 468 } 469 mapped_v4_to_regular_v4(ipr); 470 if (test->json_output) 471 cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s port: %d", ipr, (int64_t) port)); 472 else 473 iprintf(test, report_accepted, ipr, port); 474 } 475 if (test->json_output) { 476 cJSON_AddStringToObject(test->json_start, "cookie", test->cookie); 477 if (test->protocol->id == SOCK_STREAM) { 478 if (test->settings->mss) 479 cJSON_AddIntToObject(test->json_start, "tcp_mss", test->settings->mss); 480 else { 481 len = sizeof(opt); 482 getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len); 483 cJSON_AddIntToObject(test->json_start, "tcp_mss_default", opt); 484 } 485 } 486 } else if (test->verbose) { 487 iprintf(test, report_cookie, test->cookie); 488 if (test->protocol->id == SOCK_STREAM) { 489 if (test->settings->mss) 490 iprintf(test, " TCP MSS: %d\n", test->settings->mss); 491 else { 492 len = sizeof(opt); 493 getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len); 494 iprintf(test, " TCP MSS: %d (default)\n", opt); 495 } 496 } 497 498 } 499 } 500 501 void 502 iperf_on_test_finish(struct iperf_test *test) 503 { 504 } 505 506 507 /******************************************************************************/ 508 509 int 510 iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) 511 { 512 static struct option longopts[] = 513 { 514 {"port", required_argument, NULL, 'p'}, 515 {"format", required_argument, NULL, 'f'}, 516 {"interval", required_argument, NULL, 'i'}, 517 {"daemon", no_argument, NULL, 'D'}, 518 {"verbose", no_argument, NULL, 'V'}, 519 {"json", no_argument, NULL, 'J'}, 520 {"version", no_argument, NULL, 'v'}, 521 {"server", no_argument, NULL, 's'}, 522 {"client", required_argument, NULL, 'c'}, 523 {"udp", no_argument, NULL, 'u'}, 524 {"bandwidth", required_argument, NULL, 'b'}, 525 {"time", required_argument, NULL, 't'}, 526 {"bytes", required_argument, NULL, 'n'}, 527 {"blockcount", required_argument, NULL, 'k'}, 528 {"length", required_argument, NULL, 'l'}, 529 {"parallel", required_argument, NULL, 'P'}, 530 {"reverse", no_argument, NULL, 'R'}, 531 {"window", required_argument, NULL, 'w'}, 532 {"bind", required_argument, NULL, 'B'}, 533 {"set-mss", required_argument, NULL, 'M'}, 534 {"no-delay", no_argument, NULL, 'N'}, 535 {"version4", no_argument, NULL, '4'}, 536 {"version6", no_argument, NULL, '6'}, 537 {"tos", required_argument, NULL, 'S'}, 538 {"flowlabel", required_argument, NULL, 'L'}, 539 {"zerocopy", no_argument, NULL, 'Z'}, 540 {"omit", required_argument, NULL, 'O'}, 541 {"file", required_argument, NULL, 'F'}, 542 #if defined(linux) || defined(__FreeBSD__) 543 {"affinity", required_argument, NULL, 'A'}, 544 #endif 545 {"title", required_argument, NULL, 'T'}, 546 #if defined(linux) && defined(TCP_CONGESTION) 547 {"linux-congestion", required_argument, NULL, 'C'}, 548 #endif 549 #if defined(linux) || defined(__FreeBSD__) 550 {"sctp", no_argument, NULL, OPT_SCTP}, 551 #endif 552 {"pidfile", required_argument, NULL, 'I'}, 553 {"debug", no_argument, NULL, 'd'}, 554 {"help", no_argument, NULL, 'h'}, 555 {NULL, 0, NULL, 0} 556 }; 557 int flag; 558 int blksize; 559 int server_flag, client_flag, rate_flag, duration_flag; 560 #if defined(linux) || defined(__FreeBSD__) 561 char* comma; 562 #endif 563 char* slash; 564 565 blksize = 0; 566 server_flag = client_flag = rate_flag = duration_flag = 0; 567 while ((flag = getopt_long(argc, argv, "p:f:i:DVJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:h", longopts, NULL)) != -1) { 568 switch (flag) { 569 case 'p': 570 test->server_port = atoi(optarg); 571 break; 572 case 'f': 573 test->settings->unit_format = *optarg; 574 break; 575 case 'i': 576 /* XXX: could potentially want separate stat collection and reporting intervals, 577 but just set them to be the same for now */ 578 test->stats_interval = test->reporter_interval = atof(optarg); 579 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) { 580 i_errno = IEINTERVAL; 581 return -1; 582 } 583 break; 584 case 'D': 585 test->daemon = 1; 586 server_flag = 1; 587 break; 588 case 'V': 589 test->verbose = 1; 590 break; 591 case 'J': 592 test->json_output = 1; 593 break; 594 case 'v': 595 printf("%s\n%s\n", version, get_system_info()); 596 exit(0); 597 case 's': 598 if (test->role == 'c') { 599 i_errno = IESERVCLIENT; 600 return -1; 601 } 602 iperf_set_test_role(test, 's'); 603 break; 604 case 'c': 605 if (test->role == 's') { 606 i_errno = IESERVCLIENT; 607 return -1; 608 } 609 iperf_set_test_role(test, 'c'); 610 iperf_set_test_server_hostname(test, optarg); 611 break; 612 case 'u': 613 set_protocol(test, Pudp); 614 client_flag = 1; 615 break; 616 case OPT_SCTP: 617 #if defined(linux) || defined(__FreeBSD__) 618 set_protocol(test, Psctp); 619 client_flag = 1; 620 #else /* linux */ 621 i_errno = IEUNIMP; 622 return -1; 623 #endif /* linux */ 624 break; 625 626 case 'b': 627 slash = strchr(optarg, '/'); 628 if (slash) { 629 *slash = '\0'; 630 ++slash; 631 test->settings->burst = atoi(slash); 632 if (test->settings->burst <= 0 || 633 test->settings->burst > MAX_BURST) { 634 i_errno = IEBURST; 635 return -1; 636 } 637 } 638 test->settings->rate = unit_atof(optarg); 639 rate_flag = 1; 640 client_flag = 1; 641 break; 642 case 't': 643 test->duration = atoi(optarg); 644 if (test->duration > MAX_TIME) { 645 i_errno = IEDURATION; 646 return -1; 647 } 648 duration_flag = 1; 649 client_flag = 1; 650 break; 651 case 'n': 652 test->settings->bytes = unit_atoi(optarg); 653 client_flag = 1; 654 break; 655 case 'k': 656 test->settings->blocks = unit_atoi(optarg); 657 client_flag = 1; 658 break; 659 case 'l': 660 blksize = unit_atoi(optarg); 661 client_flag = 1; 662 break; 663 case 'P': 664 test->num_streams = atoi(optarg); 665 if (test->num_streams > MAX_STREAMS) { 666 i_errno = IENUMSTREAMS; 667 return -1; 668 } 669 client_flag = 1; 670 break; 671 case 'R': 672 iperf_set_test_reverse(test, 1); 673 client_flag = 1; 674 break; 675 case 'w': 676 // XXX: This is a socket buffer, not specific to TCP 677 test->settings->socket_bufsize = unit_atof(optarg); 678 if (test->settings->socket_bufsize > MAX_TCP_BUFFER) { 679 i_errno = IEBUFSIZE; 680 return -1; 681 } 682 client_flag = 1; 683 break; 684 case 'B': 685 test->bind_address = strdup(optarg); 686 break; 687 case 'M': 688 test->settings->mss = atoi(optarg); 689 if (test->settings->mss > MAX_MSS) { 690 i_errno = IEMSS; 691 return -1; 692 } 693 client_flag = 1; 694 break; 695 case 'N': 696 test->no_delay = 1; 697 client_flag = 1; 698 break; 699 case '4': 700 test->settings->domain = AF_INET; 701 break; 702 case '6': 703 test->settings->domain = AF_INET6; 704 break; 705 case 'S': 706 test->settings->tos = strtol(optarg, NULL, 0); 707 client_flag = 1; 708 break; 709 case 'L': 710 #if defined(linux) 711 test->settings->flowlabel = strtol(optarg, NULL, 0); 712 if (test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) { 713 i_errno = IESETFLOW; 714 return -1; 715 } 716 client_flag = 1; 717 #else /* linux */ 718 i_errno = IEUNIMP; 719 return -1; 720 #endif /* linux */ 721 break; 722 case 'Z': 723 if (!has_sendfile()) { 724 i_errno = IENOSENDFILE; 725 return -1; 726 } 727 test->zerocopy = 1; 728 client_flag = 1; 729 break; 730 case 'O': 731 test->omit = atoi(optarg); 732 if (test->omit < 0 || test->omit > 60) { 733 i_errno = IEOMIT; 734 return -1; 735 } 736 client_flag = 1; 737 break; 738 case 'F': 739 test->diskfile_name = optarg; 740 break; 741 case 'A': 742 #if defined(linux) || defined(__FreeBSD__) 743 test->affinity = atoi(optarg); 744 if (test->affinity < 0 || test->affinity > 1024) { 745 i_errno = IEAFFINITY; 746 return -1; 747 } 748 comma = strchr(optarg, ','); 749 if (comma != NULL) { 750 test->server_affinity = atoi(comma+1); 751 if (test->server_affinity < 0 || test->server_affinity > 1024) { 752 i_errno = IEAFFINITY; 753 return -1; 754 } 755 client_flag = 1; 756 } 757 #else 758 i_errno = IEUNIMP; 759 return -1; 760 #endif 761 break; 762 case 'T': 763 test->title = malloc(strlen(optarg) + 4); 764 sprintf(test->title, "%s: ", optarg); 765 client_flag = 1; 766 break; 767 case 'C': 768 #if defined(linux) && defined(TCP_CONGESTION) 769 test->congestion = strdup(optarg); 770 client_flag = 1; 771 #else /* linux */ 772 i_errno = IEUNIMP; 773 return -1; 774 #endif /* linux */ 775 break; 776 case 'd': 777 test->debug = 1; 778 break; 779 case 'I': 780 test->pidfile = strdup(optarg); 781 server_flag = 1; 782 break; 783 case 'h': 784 default: 785 usage_long(); 786 exit(1); 787 } 788 } 789 790 /* Check flag / role compatibility. */ 791 if (test->role == 'c' && server_flag) { 792 i_errno = IESERVERONLY; 793 return -1; 794 } 795 if (test->role == 's' && client_flag) { 796 i_errno = IECLIENTONLY; 797 return -1; 798 } 799 800 if (blksize == 0) { 801 if (test->protocol->id == Pudp) 802 blksize = DEFAULT_UDP_BLKSIZE; 803 else 804 blksize = DEFAULT_TCP_BLKSIZE; 805 } 806 if (blksize <= 0 || blksize > MAX_BLOCKSIZE) { 807 i_errno = IEBLOCKSIZE; 808 return -1; 809 } 810 test->settings->blksize = blksize; 811 812 if (!rate_flag) 813 test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0; 814 815 if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag) 816 test->duration = 0; 817 818 /* Disallow specifying multiple test end conditions. The code actually 819 ** works just fine without this prohibition. As soon as any one of the 820 ** three possible end conditions is met, the test ends. So this check 821 ** could be removed if desired. 822 */ 823 if ((duration_flag && test->settings->bytes != 0) || 824 (duration_flag && test->settings->blocks != 0) || 825 (test->settings->bytes != 0 && test->settings->blocks != 0)) { 826 i_errno = IEENDCONDITIONS; 827 return -1; 828 } 829 830 /* For subsequent calls to getopt */ 831 #ifdef __APPLE__ 832 optreset = 1; 833 #endif 834 optind = 0; 835 836 if ((test->role != 'c') && (test->role != 's')) { 837 i_errno = IENOROLE; 838 return -1; 839 } 840 841 return 0; 842 } 843 844 int 845 iperf_set_send_state(struct iperf_test *test, signed char state) 846 { 847 test->state = state; 848 if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) { 849 i_errno = IESENDMESSAGE; 850 return -1; 851 } 852 return 0; 853 } 854 855 void 856 iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP) 857 { 858 double seconds; 859 uint64_t bits_per_second; 860 861 if (sp->test->done) 862 return; 863 seconds = timeval_diff(&sp->result->start_time, nowP); 864 bits_per_second = sp->result->bytes_sent * 8 / seconds; 865 if (bits_per_second < sp->test->settings->rate) { 866 sp->green_light = 1; 867 FD_SET(sp->socket, &sp->test->write_set); 868 } else { 869 sp->green_light = 0; 870 FD_CLR(sp->socket, &sp->test->write_set); 871 } 872 } 873 874 int 875 iperf_send(struct iperf_test *test, fd_set *write_setP) 876 { 877 register int multisend, r; 878 register struct iperf_stream *sp; 879 struct timeval now; 880 881 /* Can we do multisend mode? */ 882 if (test->settings->burst != 0) 883 multisend = test->settings->burst; 884 else if (test->settings->rate == 0) 885 multisend = test->multisend; 886 else 887 multisend = 1; /* nope */ 888 889 for (; multisend > 0; --multisend) { 890 if (test->settings->rate != 0 && test->settings->burst == 0) 891 gettimeofday(&now, NULL); 892 SLIST_FOREACH(sp, &test->streams, streams) { 893 if (sp->green_light && 894 (write_setP == NULL || FD_ISSET(sp->socket, write_setP))) { 895 if ((r = sp->snd(sp)) < 0) { 896 if (r == NET_SOFTERROR) 897 break; 898 i_errno = IESTREAMWRITE; 899 return r; 900 } 901 test->bytes_sent += r; 902 ++test->blocks_sent; 903 if (test->settings->rate != 0 && test->settings->burst == 0) 904 iperf_check_throttle(sp, &now); 905 if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) 906 break; 907 if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks) 908 break; 909 } 910 } 911 } 912 if (test->settings->burst != 0) { 913 gettimeofday(&now, NULL); 914 SLIST_FOREACH(sp, &test->streams, streams) 915 iperf_check_throttle(sp, &now); 916 } 917 if (write_setP != NULL) 918 SLIST_FOREACH(sp, &test->streams, streams) 919 if (FD_ISSET(sp->socket, write_setP)) 920 FD_CLR(sp->socket, write_setP); 921 922 return 0; 923 } 924 925 int 926 iperf_recv(struct iperf_test *test, fd_set *read_setP) 927 { 928 int r; 929 struct iperf_stream *sp; 930 931 SLIST_FOREACH(sp, &test->streams, streams) { 932 if (FD_ISSET(sp->socket, read_setP)) { 933 if ((r = sp->rcv(sp)) < 0) { 934 i_errno = IESTREAMREAD; 935 return r; 936 } 937 test->bytes_sent += r; 938 ++test->blocks_sent; 939 FD_CLR(sp->socket, read_setP); 940 } 941 } 942 943 return 0; 944 } 945 946 int 947 iperf_init_test(struct iperf_test *test) 948 { 949 struct timeval now; 950 struct iperf_stream *sp; 951 952 if (test->protocol->init) { 953 if (test->protocol->init(test) < 0) 954 return -1; 955 } 956 957 /* Init each stream. */ 958 if (gettimeofday(&now, NULL) < 0) { 959 i_errno = IEINITTEST; 960 return -1; 961 } 962 SLIST_FOREACH(sp, &test->streams, streams) { 963 sp->result->start_time = now; 964 } 965 966 if (test->on_test_start) 967 test->on_test_start(test); 968 969 return 0; 970 } 971 972 static void 973 send_timer_proc(TimerClientData client_data, struct timeval *nowP) 974 { 975 struct iperf_stream *sp = client_data.p; 976 977 /* All we do here is set or clear the flag saying that this stream may 978 ** be sent to. The actual sending gets done in the send proc, after 979 ** checking the flag. 980 */ 981 iperf_check_throttle(sp, nowP); 982 } 983 984 int 985 iperf_create_send_timers(struct iperf_test * test) 986 { 987 struct timeval now; 988 struct iperf_stream *sp; 989 TimerClientData cd; 990 991 if (gettimeofday(&now, NULL) < 0) { 992 i_errno = IEINITTEST; 993 return -1; 994 } 995 SLIST_FOREACH(sp, &test->streams, streams) { 996 sp->green_light = 1; 997 if (test->settings->rate != 0) { 998 cd.p = sp; 999 sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1); 1000 /* (Repeat every tenth second - arbitrary often value.) */ 1001 if (sp->send_timer == NULL) { 1002 i_errno = IEINITTEST; 1003 return -1; 1004 } 1005 } 1006 } 1007 return 0; 1008 } 1009 1010 /** 1011 * iperf_exchange_parameters - handles the param_Exchange part for client 1012 * 1013 */ 1014 1015 int 1016 iperf_exchange_parameters(struct iperf_test *test) 1017 { 1018 int s; 1019 int32_t err; 1020 1021 if (test->role == 'c') { 1022 1023 if (send_parameters(test) < 0) 1024 return -1; 1025 1026 } else { 1027 1028 if (get_parameters(test) < 0) 1029 return -1; 1030 1031 if ((s = test->protocol->listen(test)) < 0) { 1032 if (iperf_set_send_state(test, SERVER_ERROR) != 0) 1033 return -1; 1034 err = htonl(i_errno); 1035 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1036 i_errno = IECTRLWRITE; 1037 return -1; 1038 } 1039 err = htonl(errno); 1040 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1041 i_errno = IECTRLWRITE; 1042 return -1; 1043 } 1044 return -1; 1045 } 1046 FD_SET(s, &test->read_set); 1047 test->max_fd = (s > test->max_fd) ? s : test->max_fd; 1048 test->prot_listener = s; 1049 1050 // Send the control message to create streams and start the test 1051 if (iperf_set_send_state(test, CREATE_STREAMS) != 0) 1052 return -1; 1053 1054 } 1055 1056 return 0; 1057 } 1058 1059 /*************************************************************/ 1060 1061 int 1062 iperf_exchange_results(struct iperf_test *test) 1063 { 1064 if (test->role == 'c') { 1065 /* Send results to server. */ 1066 if (send_results(test) < 0) 1067 return -1; 1068 /* Get server results. */ 1069 if (get_results(test) < 0) 1070 return -1; 1071 } else { 1072 /* Get client results. */ 1073 if (get_results(test) < 0) 1074 return -1; 1075 /* Send results to client. */ 1076 if (send_results(test) < 0) 1077 return -1; 1078 } 1079 return 0; 1080 } 1081 1082 /*************************************************************/ 1083 1084 static int 1085 send_parameters(struct iperf_test *test) 1086 { 1087 int r = 0; 1088 cJSON *j; 1089 1090 j = cJSON_CreateObject(); 1091 if (j == NULL) { 1092 i_errno = IESENDPARAMS; 1093 r = -1; 1094 } else { 1095 if (test->protocol->id == Ptcp) 1096 cJSON_AddTrueToObject(j, "tcp"); 1097 else if (test->protocol->id == Pudp) 1098 cJSON_AddTrueToObject(j, "udp"); 1099 else if (test->protocol->id == Psctp) 1100 cJSON_AddTrueToObject(j, "sctp"); 1101 cJSON_AddIntToObject(j, "omit", test->omit); 1102 if (test->server_affinity != -1) 1103 cJSON_AddIntToObject(j, "server_affinity", test->server_affinity); 1104 if (test->duration) 1105 cJSON_AddIntToObject(j, "time", test->duration); 1106 if (test->settings->bytes) 1107 cJSON_AddIntToObject(j, "num", test->settings->bytes); 1108 if (test->settings->blocks) 1109 cJSON_AddIntToObject(j, "blockcount", test->settings->blocks); 1110 if (test->settings->mss) 1111 cJSON_AddIntToObject(j, "MSS", test->settings->mss); 1112 if (test->no_delay) 1113 cJSON_AddTrueToObject(j, "nodelay"); 1114 cJSON_AddIntToObject(j, "parallel", test->num_streams); 1115 if (test->reverse) 1116 cJSON_AddTrueToObject(j, "reverse"); 1117 if (test->settings->socket_bufsize) 1118 cJSON_AddIntToObject(j, "window", test->settings->socket_bufsize); 1119 if (test->settings->blksize) 1120 cJSON_AddIntToObject(j, "len", test->settings->blksize); 1121 if (test->settings->rate) 1122 cJSON_AddIntToObject(j, "bandwidth", test->settings->rate); 1123 if (test->settings->burst) 1124 cJSON_AddIntToObject(j, "burst", test->settings->burst); 1125 if (test->settings->tos) 1126 cJSON_AddIntToObject(j, "TOS", test->settings->tos); 1127 if (test->settings->flowlabel) 1128 cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel); 1129 if (test->title) 1130 cJSON_AddStringToObject(j, "title", test->title); 1131 if (test->congestion) 1132 cJSON_AddStringToObject(j, "congestion", test->congestion); 1133 if (JSON_write(test->ctrl_sck, j) < 0) { 1134 i_errno = IESENDPARAMS; 1135 r = -1; 1136 } 1137 cJSON_Delete(j); 1138 } 1139 return r; 1140 } 1141 1142 /*************************************************************/ 1143 1144 static int 1145 get_parameters(struct iperf_test *test) 1146 { 1147 int r = 0; 1148 cJSON *j; 1149 cJSON *j_p; 1150 1151 j = JSON_read(test->ctrl_sck); 1152 if (j == NULL) { 1153 i_errno = IERECVPARAMS; 1154 r = -1; 1155 } else { 1156 if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL) 1157 set_protocol(test, Ptcp); 1158 if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL) 1159 set_protocol(test, Pudp); 1160 if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL) 1161 set_protocol(test, Psctp); 1162 if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL) 1163 test->omit = j_p->valueint; 1164 if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL) 1165 test->server_affinity = j_p->valueint; 1166 if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL) 1167 test->duration = j_p->valueint; 1168 if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL) 1169 test->settings->bytes = j_p->valueint; 1170 if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL) 1171 test->settings->blocks = j_p->valueint; 1172 if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL) 1173 test->settings->mss = j_p->valueint; 1174 if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL) 1175 test->no_delay = 1; 1176 if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL) 1177 test->num_streams = j_p->valueint; 1178 if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL) 1179 iperf_set_test_reverse(test, 1); 1180 if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL) 1181 test->settings->socket_bufsize = j_p->valueint; 1182 if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL) 1183 test->settings->blksize = j_p->valueint; 1184 if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL) 1185 test->settings->rate = j_p->valueint; 1186 if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL) 1187 test->settings->burst = j_p->valueint; 1188 if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) 1189 test->settings->tos = j_p->valueint; 1190 if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL) 1191 test->settings->flowlabel = j_p->valueint; 1192 if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL) 1193 test->title = strdup(j_p->valuestring); 1194 if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL) 1195 test->congestion = strdup(j_p->valuestring); 1196 if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits()) 1197 test->sender_has_retransmits = 1; 1198 cJSON_Delete(j); 1199 } 1200 return r; 1201 } 1202 1203 /*************************************************************/ 1204 1205 static int 1206 send_results(struct iperf_test *test) 1207 { 1208 int r = 0; 1209 cJSON *j; 1210 cJSON *j_streams; 1211 struct iperf_stream *sp; 1212 cJSON *j_stream; 1213 int sender_has_retransmits; 1214 iperf_size_t bytes_transferred; 1215 int retransmits; 1216 1217 j = cJSON_CreateObject(); 1218 if (j == NULL) { 1219 i_errno = IEPACKAGERESULTS; 1220 r = -1; 1221 } else { 1222 cJSON_AddFloatToObject(j, "cpu_util_total", test->cpu_util[0]); 1223 cJSON_AddFloatToObject(j, "cpu_util_user", test->cpu_util[1]); 1224 cJSON_AddFloatToObject(j, "cpu_util_system", test->cpu_util[2]); 1225 if ( ! test->sender ) 1226 sender_has_retransmits = -1; 1227 else 1228 sender_has_retransmits = test->sender_has_retransmits; 1229 cJSON_AddIntToObject(j, "sender_has_retransmits", sender_has_retransmits); 1230 j_streams = cJSON_CreateArray(); 1231 if (j_streams == NULL) { 1232 i_errno = IEPACKAGERESULTS; 1233 r = -1; 1234 } else { 1235 cJSON_AddItemToObject(j, "streams", j_streams); 1236 SLIST_FOREACH(sp, &test->streams, streams) { 1237 j_stream = cJSON_CreateObject(); 1238 if (j_stream == NULL) { 1239 i_errno = IEPACKAGERESULTS; 1240 r = -1; 1241 } else { 1242 cJSON_AddItemToArray(j_streams, j_stream); 1243 bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received; 1244 retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1; 1245 cJSON_AddIntToObject(j_stream, "id", sp->id); 1246 cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred); 1247 cJSON_AddIntToObject(j_stream, "retransmits", retransmits); 1248 cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter); 1249 cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error); 1250 cJSON_AddIntToObject(j_stream, "packets", sp->packet_count); 1251 } 1252 } 1253 if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) { 1254 i_errno = IESENDRESULTS; 1255 r = -1; 1256 } 1257 } 1258 cJSON_Delete(j); 1259 } 1260 return r; 1261 } 1262 1263 /*************************************************************/ 1264 1265 static int 1266 get_results(struct iperf_test *test) 1267 { 1268 int r = 0; 1269 cJSON *j; 1270 cJSON *j_cpu_util_total; 1271 cJSON *j_cpu_util_user; 1272 cJSON *j_cpu_util_system; 1273 cJSON *j_sender_has_retransmits; 1274 int result_has_retransmits; 1275 cJSON *j_streams; 1276 int n, i; 1277 cJSON *j_stream; 1278 cJSON *j_id; 1279 cJSON *j_bytes; 1280 cJSON *j_retransmits; 1281 cJSON *j_jitter; 1282 cJSON *j_errors; 1283 cJSON *j_packets; 1284 int sid, cerror, pcount; 1285 double jitter; 1286 iperf_size_t bytes_transferred; 1287 int retransmits; 1288 struct iperf_stream *sp; 1289 1290 j = JSON_read(test->ctrl_sck); 1291 if (j == NULL) { 1292 i_errno = IERECVRESULTS; 1293 r = -1; 1294 } else { 1295 j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total"); 1296 j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user"); 1297 j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system"); 1298 j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits"); 1299 if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) { 1300 i_errno = IERECVRESULTS; 1301 r = -1; 1302 } else { 1303 test->remote_cpu_util[0] = j_cpu_util_total->valuefloat; 1304 test->remote_cpu_util[1] = j_cpu_util_user->valuefloat; 1305 test->remote_cpu_util[2] = j_cpu_util_system->valuefloat; 1306 result_has_retransmits = j_sender_has_retransmits->valueint; 1307 if (! test->sender) 1308 test->sender_has_retransmits = result_has_retransmits; 1309 j_streams = cJSON_GetObjectItem(j, "streams"); 1310 if (j_streams == NULL) { 1311 i_errno = IERECVRESULTS; 1312 r = -1; 1313 } else { 1314 n = cJSON_GetArraySize(j_streams); 1315 for (i=0; i<n; ++i) { 1316 j_stream = cJSON_GetArrayItem(j_streams, i); 1317 if (j_stream == NULL) { 1318 i_errno = IERECVRESULTS; 1319 r = -1; 1320 } else { 1321 j_id = cJSON_GetObjectItem(j_stream, "id"); 1322 j_bytes = cJSON_GetObjectItem(j_stream, "bytes"); 1323 j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits"); 1324 j_jitter = cJSON_GetObjectItem(j_stream, "jitter"); 1325 j_errors = cJSON_GetObjectItem(j_stream, "errors"); 1326 j_packets = cJSON_GetObjectItem(j_stream, "packets"); 1327 if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) { 1328 i_errno = IERECVRESULTS; 1329 r = -1; 1330 } else { 1331 sid = j_id->valueint; 1332 bytes_transferred = j_bytes->valueint; 1333 retransmits = j_retransmits->valueint; 1334 jitter = j_jitter->valuefloat; 1335 cerror = j_errors->valueint; 1336 pcount = j_packets->valueint; 1337 SLIST_FOREACH(sp, &test->streams, streams) 1338 if (sp->id == sid) break; 1339 if (sp == NULL) { 1340 i_errno = IESTREAMID; 1341 r = -1; 1342 } else { 1343 if (test->sender) { 1344 sp->jitter = jitter; 1345 sp->cnt_error = cerror; 1346 sp->packet_count = pcount; 1347 sp->result->bytes_received = bytes_transferred; 1348 } else { 1349 sp->result->bytes_sent = bytes_transferred; 1350 sp->result->stream_retrans = retransmits; 1351 } 1352 } 1353 } 1354 } 1355 } 1356 } 1357 } 1358 cJSON_Delete(j); 1359 } 1360 return r; 1361 } 1362 1363 /*************************************************************/ 1364 1365 static int 1366 JSON_write(int fd, cJSON *json) 1367 { 1368 uint32_t hsize, nsize; 1369 char *str; 1370 int r = 0; 1371 1372 str = cJSON_PrintUnformatted(json); 1373 if (str == NULL) 1374 r = -1; 1375 else { 1376 hsize = strlen(str); 1377 nsize = htonl(hsize); 1378 if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0) 1379 r = -1; 1380 else { 1381 if (Nwrite(fd, str, hsize, Ptcp) < 0) 1382 r = -1; 1383 } 1384 free(str); 1385 } 1386 return r; 1387 } 1388 1389 /*************************************************************/ 1390 1391 static cJSON * 1392 JSON_read(int fd) 1393 { 1394 uint32_t hsize, nsize; 1395 char *str; 1396 cJSON *json = NULL; 1397 1398 if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) { 1399 hsize = ntohl(nsize); 1400 str = (char *) malloc(hsize+1); /* +1 for EOS */ 1401 if (str != NULL) { 1402 if (Nread(fd, str, hsize, Ptcp) >= 0) { 1403 str[hsize] = '\0'; /* add the EOS */ 1404 json = cJSON_Parse(str); 1405 } 1406 } 1407 free(str); 1408 } 1409 return json; 1410 } 1411 1412 /*************************************************************/ 1413 /** 1414 * add_to_interval_list -- adds new interval to the interval_list 1415 */ 1416 1417 void 1418 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new) 1419 { 1420 struct iperf_interval_results *irp; 1421 1422 irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results)); 1423 memcpy(irp, new, sizeof(struct iperf_interval_results)); 1424 TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries); 1425 } 1426 1427 1428 /************************************************************/ 1429 1430 /** 1431 * connect_msg -- displays connection message 1432 * denoting sender/receiver details 1433 * 1434 */ 1435 1436 void 1437 connect_msg(struct iperf_stream *sp) 1438 { 1439 char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN]; 1440 int lport, rport; 1441 1442 if (getsockdomain(sp->socket) == AF_INET) { 1443 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl)); 1444 mapped_v4_to_regular_v4(ipl); 1445 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr)); 1446 mapped_v4_to_regular_v4(ipr); 1447 lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port); 1448 rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port); 1449 } else { 1450 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl)); 1451 mapped_v4_to_regular_v4(ipl); 1452 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr)); 1453 mapped_v4_to_regular_v4(ipr); 1454 lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port); 1455 rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port); 1456 } 1457 1458 if (sp->test->json_output) 1459 cJSON_AddItemToObject(sp->test->json_start, "connected", iperf_json_printf("socket: %d local_host: %s local_port: %d remote_host: %s remote_port: %d", (int64_t) sp->socket, ipl, (int64_t) lport, ipr, (int64_t) rport)); 1460 else 1461 iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport); 1462 } 1463 1464 1465 /**************************************************************************/ 1466 1467 struct iperf_test * 1468 iperf_new_test() 1469 { 1470 struct iperf_test *test; 1471 1472 test = (struct iperf_test *) malloc(sizeof(struct iperf_test)); 1473 if (!test) { 1474 i_errno = IENEWTEST; 1475 return NULL; 1476 } 1477 /* initialize everything to zero */ 1478 memset(test, 0, sizeof(struct iperf_test)); 1479 1480 test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings)); 1481 if (!test->settings) { 1482 free(test); 1483 i_errno = IENEWTEST; 1484 return NULL; 1485 } 1486 memset(test->settings, 0, sizeof(struct iperf_settings)); 1487 1488 return test; 1489 } 1490 1491 /**************************************************************************/ 1492 1493 struct protocol * 1494 protocol_new(void) 1495 { 1496 struct protocol *proto; 1497 1498 proto = malloc(sizeof(struct protocol)); 1499 if(!proto) { 1500 return NULL; 1501 } 1502 memset(proto, 0, sizeof(struct protocol)); 1503 1504 return proto; 1505 } 1506 1507 void 1508 protocol_free(struct protocol *proto) 1509 { 1510 free(proto); 1511 } 1512 1513 /**************************************************************************/ 1514 int 1515 iperf_defaults(struct iperf_test *testp) 1516 { 1517 struct protocol *tcp, *udp, *sctp; 1518 1519 testp->omit = OMIT; 1520 testp->duration = DURATION; 1521 testp->diskfile_name = (char*) 0; 1522 testp->affinity = -1; 1523 testp->server_affinity = -1; 1524 #if defined(__FreeBSD__) 1525 CPU_ZERO(&testp->cpumask); 1526 #endif 1527 testp->title = NULL; 1528 testp->congestion = NULL; 1529 testp->server_port = PORT; 1530 testp->ctrl_sck = -1; 1531 testp->prot_listener = -1; 1532 1533 testp->stats_callback = iperf_stats_callback; 1534 testp->reporter_callback = iperf_reporter_callback; 1535 1536 testp->stats_interval = testp->reporter_interval = 1; 1537 testp->num_streams = 1; 1538 1539 testp->settings->domain = AF_UNSPEC; 1540 testp->settings->unit_format = 'a'; 1541 testp->settings->socket_bufsize = 0; /* use autotuning */ 1542 testp->settings->blksize = DEFAULT_TCP_BLKSIZE; 1543 testp->settings->rate = 0; 1544 testp->settings->burst = 0; 1545 testp->settings->mss = 0; 1546 testp->settings->bytes = 0; 1547 testp->settings->blocks = 0; 1548 memset(testp->cookie, 0, COOKIE_SIZE); 1549 1550 testp->multisend = 10; /* arbitrary */ 1551 testp->may_use_sigalrm = 0; 1552 1553 /* Set up protocol list */ 1554 SLIST_INIT(&testp->streams); 1555 SLIST_INIT(&testp->protocols); 1556 1557 tcp = protocol_new(); 1558 if (!tcp) 1559 return -1; 1560 1561 tcp->id = Ptcp; 1562 tcp->name = "TCP"; 1563 tcp->accept = iperf_tcp_accept; 1564 tcp->listen = iperf_tcp_listen; 1565 tcp->connect = iperf_tcp_connect; 1566 tcp->send = iperf_tcp_send; 1567 tcp->recv = iperf_tcp_recv; 1568 tcp->init = NULL; 1569 SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols); 1570 1571 udp = protocol_new(); 1572 if (!udp) { 1573 protocol_free(tcp); 1574 return -1; 1575 } 1576 1577 udp->id = Pudp; 1578 udp->name = "UDP"; 1579 udp->accept = iperf_udp_accept; 1580 udp->listen = iperf_udp_listen; 1581 udp->connect = iperf_udp_connect; 1582 udp->send = iperf_udp_send; 1583 udp->recv = iperf_udp_recv; 1584 udp->init = iperf_udp_init; 1585 SLIST_INSERT_AFTER(tcp, udp, protocols); 1586 1587 set_protocol(testp, Ptcp); 1588 1589 sctp = protocol_new(); 1590 if (!sctp) { 1591 protocol_free(tcp); 1592 protocol_free(udp); 1593 return -1; 1594 } 1595 1596 sctp->id = Psctp; 1597 sctp->name = "SCTP"; 1598 sctp->accept = iperf_sctp_accept; 1599 sctp->listen = iperf_sctp_listen; 1600 sctp->connect = iperf_sctp_connect; 1601 sctp->send = iperf_sctp_send; 1602 sctp->recv = iperf_sctp_recv; 1603 sctp->init = iperf_sctp_init; 1604 1605 SLIST_INSERT_AFTER(udp, sctp, protocols); 1606 1607 testp->on_new_stream = iperf_on_new_stream; 1608 testp->on_test_start = iperf_on_test_start; 1609 testp->on_connect = iperf_on_connect; 1610 testp->on_test_finish = iperf_on_test_finish; 1611 1612 return 0; 1613 } 1614 1615 1616 /**************************************************************************/ 1617 void 1618 iperf_free_test(struct iperf_test *test) 1619 { 1620 struct protocol *prot; 1621 struct iperf_stream *sp; 1622 1623 /* Free streams */ 1624 while (!SLIST_EMPTY(&test->streams)) { 1625 sp = SLIST_FIRST(&test->streams); 1626 SLIST_REMOVE_HEAD(&test->streams, streams); 1627 iperf_free_stream(sp); 1628 } 1629 1630 if (test->server_hostname) 1631 free(test->server_hostname); 1632 if (test->bind_address) 1633 free(test->bind_address); 1634 free(test->settings); 1635 if (test->title) 1636 free(test->title); 1637 if (test->congestion) 1638 free(test->congestion); 1639 if (test->omit_timer != NULL) 1640 tmr_cancel(test->omit_timer); 1641 if (test->timer != NULL) 1642 tmr_cancel(test->timer); 1643 if (test->stats_timer != NULL) 1644 tmr_cancel(test->stats_timer); 1645 if (test->reporter_timer != NULL) 1646 tmr_cancel(test->reporter_timer); 1647 1648 /* Free protocol list */ 1649 while (!SLIST_EMPTY(&test->protocols)) { 1650 prot = SLIST_FIRST(&test->protocols); 1651 SLIST_REMOVE_HEAD(&test->protocols, protocols); 1652 free(prot); 1653 } 1654 1655 /* XXX: Why are we setting these values to NULL? */ 1656 // test->streams = NULL; 1657 test->stats_callback = NULL; 1658 test->reporter_callback = NULL; 1659 free(test); 1660 } 1661 1662 1663 void 1664 iperf_reset_test(struct iperf_test *test) 1665 { 1666 struct iperf_stream *sp; 1667 1668 /* Free streams */ 1669 while (!SLIST_EMPTY(&test->streams)) { 1670 sp = SLIST_FIRST(&test->streams); 1671 SLIST_REMOVE_HEAD(&test->streams, streams); 1672 iperf_free_stream(sp); 1673 } 1674 if (test->omit_timer != NULL) { 1675 tmr_cancel(test->omit_timer); 1676 test->omit_timer = NULL; 1677 } 1678 if (test->timer != NULL) { 1679 tmr_cancel(test->timer); 1680 test->timer = NULL; 1681 } 1682 if (test->stats_timer != NULL) { 1683 tmr_cancel(test->stats_timer); 1684 test->stats_timer = NULL; 1685 } 1686 if (test->reporter_timer != NULL) { 1687 tmr_cancel(test->reporter_timer); 1688 test->reporter_timer = NULL; 1689 } 1690 test->done = 0; 1691 1692 SLIST_INIT(&test->streams); 1693 1694 test->role = 's'; 1695 test->sender = 0; 1696 test->sender_has_retransmits = 0; 1697 set_protocol(test, Ptcp); 1698 test->omit = OMIT; 1699 test->duration = DURATION; 1700 test->server_affinity = -1; 1701 #if defined(__FreeBSD__) 1702 CPU_ZERO(&test->cpumask); 1703 #endif 1704 test->state = 0; 1705 1706 if(test->title) { 1707 free(test->title); 1708 test->title = NULL; 1709 } 1710 if(test->server_hostname) { 1711 free(test->server_hostname); 1712 test->server_hostname = NULL; 1713 } 1714 if(test->bind_address) { 1715 free(test->bind_address); 1716 test->bind_address = NULL; 1717 } 1718 if(test->congestion) { 1719 free(test->congestion); 1720 test->congestion = NULL; 1721 } 1722 1723 test->ctrl_sck = -1; 1724 test->prot_listener = -1; 1725 1726 test->bytes_sent = 0; 1727 test->blocks_sent = 0; 1728 1729 test->reverse = 0; 1730 test->no_delay = 0; 1731 1732 FD_ZERO(&test->read_set); 1733 FD_ZERO(&test->write_set); 1734 1735 test->num_streams = 1; 1736 test->settings->socket_bufsize = 0; 1737 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 1738 test->settings->rate = 0; 1739 test->settings->burst = 0; 1740 test->settings->mss = 0; 1741 memset(test->cookie, 0, COOKIE_SIZE); 1742 test->multisend = 10; /* arbitrary */ 1743 } 1744 1745 1746 /* Reset all of a test's stats back to zero. Called when the omitting 1747 ** period is over. 1748 */ 1749 void 1750 iperf_reset_stats(struct iperf_test *test) 1751 { 1752 struct timeval now; 1753 struct iperf_stream *sp; 1754 struct iperf_stream_result *rp; 1755 1756 test->bytes_sent = 0; 1757 test->blocks_sent = 0; 1758 gettimeofday(&now, NULL); 1759 SLIST_FOREACH(sp, &test->streams, streams) { 1760 sp->omitted_packet_count = sp->packet_count; 1761 sp->jitter = 0; 1762 sp->outoforder_packets = 0; 1763 sp->cnt_error = 0; 1764 rp = sp->result; 1765 rp->bytes_sent = rp->bytes_received = 0; 1766 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 1767 if (test->sender && test->sender_has_retransmits) { 1768 struct iperf_interval_results ir; /* temporary results structure */ 1769 save_tcpinfo(sp, &ir); 1770 rp->stream_prev_total_retrans = get_total_retransmits(&ir); 1771 } 1772 rp->stream_retrans = 0; 1773 rp->start_time = now; 1774 } 1775 } 1776 1777 1778 /**************************************************************************/ 1779 1780 /** 1781 * iperf_stats_callback -- handles the statistic gathering for both the client and server 1782 * 1783 * XXX: This function needs to be updated to reflect the new code 1784 */ 1785 1786 1787 void 1788 iperf_stats_callback(struct iperf_test *test) 1789 { 1790 struct iperf_stream *sp; 1791 struct iperf_stream_result *rp = NULL; 1792 struct iperf_interval_results *irp, temp; 1793 1794 temp.omitted = test->omitting; 1795 SLIST_FOREACH(sp, &test->streams, streams) { 1796 rp = sp->result; 1797 1798 temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval; 1799 1800 irp = TAILQ_LAST(&rp->interval_results, irlisthead); 1801 /* result->end_time contains timestamp of previous interval */ 1802 if ( irp != NULL ) /* not the 1st interval */ 1803 memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval)); 1804 else /* or use timestamp from beginning */ 1805 memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval)); 1806 /* now save time of end of this interval */ 1807 gettimeofday(&rp->end_time, NULL); 1808 memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval)); 1809 temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1810 //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1811 if (test->protocol->id == Ptcp) { 1812 if ( has_tcpinfo()) { 1813 save_tcpinfo(sp, &temp); 1814 if (test->sender && test->sender_has_retransmits) { 1815 long total_retrans = get_total_retransmits(&temp); 1816 temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans; 1817 rp->stream_retrans += temp.interval_retrans; 1818 rp->stream_prev_total_retrans = total_retrans; 1819 1820 temp.snd_cwnd = get_snd_cwnd(&temp); 1821 } 1822 } 1823 } else { 1824 if (irp == NULL) { 1825 temp.interval_packet_count = sp->packet_count; 1826 temp.interval_outoforder_packets = sp->outoforder_packets; 1827 temp.interval_cnt_error = sp->cnt_error; 1828 } else { 1829 temp.interval_packet_count = sp->packet_count - irp->packet_count; 1830 temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets; 1831 temp.interval_cnt_error = sp->cnt_error - irp->cnt_error; 1832 } 1833 temp.packet_count = sp->packet_count; 1834 temp.jitter = sp->jitter; 1835 temp.outoforder_packets = sp->outoforder_packets; 1836 temp.cnt_error = sp->cnt_error; 1837 } 1838 add_to_interval_list(rp, &temp); 1839 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 1840 } 1841 } 1842 1843 static void 1844 iperf_print_intermediate(struct iperf_test *test) 1845 { 1846 char ubuf[UNIT_LEN]; 1847 char nbuf[UNIT_LEN]; 1848 struct iperf_stream *sp = NULL; 1849 struct iperf_interval_results *irp; 1850 iperf_size_t bytes = 0; 1851 double bandwidth; 1852 int retransmits = 0; 1853 double start_time, end_time; 1854 cJSON *json_interval; 1855 cJSON *json_interval_streams; 1856 int total_packets = 0, lost_packets = 0; 1857 double avg_jitter = 0.0, lost_percent; 1858 1859 if (test->json_output) { 1860 json_interval = cJSON_CreateObject(); 1861 if (json_interval == NULL) 1862 return; 1863 cJSON_AddItemToArray(test->json_intervals, json_interval); 1864 json_interval_streams = cJSON_CreateArray(); 1865 if (json_interval_streams == NULL) 1866 return; 1867 cJSON_AddItemToObject(json_interval, "streams", json_interval_streams); 1868 } else { 1869 json_interval = NULL; 1870 json_interval_streams = NULL; 1871 } 1872 1873 SLIST_FOREACH(sp, &test->streams, streams) { 1874 print_interval_results(test, sp, json_interval_streams); 1875 /* sum up all streams */ 1876 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); 1877 if (irp == NULL) { 1878 iperf_err(test, "iperf_print_intermediate error: interval_results is NULL"); 1879 return; 1880 } 1881 bytes += irp->bytes_transferred; 1882 if (test->protocol->id == Ptcp) { 1883 if (test->sender && test->sender_has_retransmits) { 1884 retransmits += irp->interval_retrans; 1885 } 1886 } else { 1887 total_packets += irp->interval_packet_count; 1888 lost_packets += irp->interval_cnt_error; 1889 avg_jitter += irp->jitter; 1890 } 1891 } 1892 1893 /* next build string with sum of all streams */ 1894 if (test->num_streams > 1) { 1895 sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */ 1896 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */ 1897 1898 unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A'); 1899 bandwidth = (double) bytes / (double) irp->interval_duration; 1900 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 1901 1902 start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time); 1903 end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time); 1904 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 1905 if (test->sender && test->sender_has_retransmits) { 1906 /* Interval sum, TCP with retransmits. */ 1907 if (test->json_output) 1908 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) retransmits, irp->omitted)); /* XXX irp->omitted or test->omitting? */ 1909 else 1910 iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */ 1911 } else { 1912 /* Interval sum, TCP without retransmits. */ 1913 if (test->json_output) 1914 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, test->omitting)); 1915 else 1916 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:""); 1917 } 1918 } else { 1919 /* Interval sum, UDP. */ 1920 if (test->sender) { 1921 if (test->json_output) 1922 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f packets: %d omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (int64_t) total_packets, test->omitting)); 1923 else 1924 iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:""); 1925 } else { 1926 avg_jitter /= test->num_streams; 1927 lost_percent = 100.0 * lost_packets / total_packets; 1928 if (test->json_output) 1929 cJSON_AddItemToObject(json_interval, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f omitted: %b", (double) start_time, (double) end_time, (double) irp->interval_duration, (int64_t) bytes, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent, test->omitting)); 1930 else 1931 iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, test->omitting?report_omitted:""); 1932 } 1933 } 1934 } 1935 } 1936 1937 static void 1938 iperf_print_results(struct iperf_test *test) 1939 { 1940 1941 cJSON *json_summary_streams = NULL; 1942 cJSON *json_summary_stream = NULL; 1943 int total_retransmits = 0; 1944 int total_packets = 0, lost_packets = 0; 1945 char ubuf[UNIT_LEN]; 1946 char nbuf[UNIT_LEN]; 1947 struct stat sb; 1948 char sbuf[UNIT_LEN]; 1949 struct iperf_stream *sp = NULL; 1950 iperf_size_t bytes_sent, total_sent = 0; 1951 iperf_size_t bytes_received, total_received = 0; 1952 double start_time, end_time, avg_jitter = 0.0, lost_percent; 1953 double bandwidth; 1954 1955 /* print final summary for all intervals */ 1956 1957 if (test->json_output) { 1958 json_summary_streams = cJSON_CreateArray(); 1959 if (json_summary_streams == NULL) 1960 return; 1961 cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams); 1962 } else { 1963 iprintf(test, "%s", report_bw_separator); 1964 if (test->verbose) 1965 iprintf(test, "%s", report_summary); 1966 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 1967 if (test->sender_has_retransmits) 1968 iprintf(test, "%s", report_bw_retrans_header); 1969 else 1970 iprintf(test, "%s", report_bw_header); 1971 } else 1972 iprintf(test, "%s", report_bw_udp_header); 1973 } 1974 1975 start_time = 0.; 1976 sp = SLIST_FIRST(&test->streams); 1977 end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); 1978 SLIST_FOREACH(sp, &test->streams, streams) { 1979 if (test->json_output) { 1980 json_summary_stream = cJSON_CreateObject(); 1981 if (json_summary_stream == NULL) 1982 return; 1983 cJSON_AddItemToArray(json_summary_streams, json_summary_stream); 1984 } 1985 1986 bytes_sent = sp->result->bytes_sent; 1987 bytes_received = sp->result->bytes_received; 1988 total_sent += bytes_sent; 1989 total_received += bytes_received; 1990 1991 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 1992 if (test->sender_has_retransmits) { 1993 total_retransmits += sp->result->stream_retrans; 1994 } 1995 } else { 1996 total_packets += (sp->packet_count - sp->omitted_packet_count); 1997 lost_packets += sp->cnt_error; 1998 avg_jitter += sp->jitter; 1999 } 2000 2001 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A'); 2002 bandwidth = (double) bytes_sent / (double) end_time; 2003 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2004 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2005 if (test->sender_has_retransmits) { 2006 /* Summary, TCP with retransmits. */ 2007 if (test->json_output) 2008 cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans)); 2009 else 2010 iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender); 2011 } else { 2012 /* Summary, TCP without retransmits. */ 2013 if (test->json_output) 2014 cJSON_AddItemToObject(json_summary_stream, "sender", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8)); 2015 else 2016 iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender); 2017 } 2018 } else { 2019 /* Summary, UDP. */ 2020 lost_percent = 100.0 * sp->cnt_error / (sp->packet_count - sp->omitted_packet_count); 2021 if (test->json_output) 2022 cJSON_AddItemToObject(json_summary_stream, "udp", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) sp->cnt_error, (int64_t) (sp->packet_count - sp->omitted_packet_count), (double) lost_percent)); 2023 else { 2024 iprintf(test, report_bw_udp_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->jitter * 1000.0, sp->cnt_error, (sp->packet_count - sp->omitted_packet_count), lost_percent, ""); 2025 if (test->role == 'c') 2026 iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count)); 2027 if (sp->outoforder_packets > 0) 2028 iprintf(test, report_sum_outoforder, start_time, end_time, sp->cnt_error); 2029 } 2030 } 2031 2032 if (sp->diskfile_fd >= 0) { 2033 if (fstat(sp->diskfile_fd, &sb) == 0) { 2034 int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 ); 2035 unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A'); 2036 if (test->json_output) 2037 cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d size: %d percent: %d filename: %s", (int64_t) bytes_sent, (int64_t) sb.st_size, (int64_t) percent, test->diskfile_name)); 2038 else 2039 iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name); 2040 } 2041 } 2042 2043 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A'); 2044 bandwidth = (double) bytes_received / (double) end_time; 2045 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2046 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2047 if (test->json_output) 2048 cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8)); 2049 else 2050 iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver); 2051 } 2052 } 2053 2054 if (test->num_streams > 1) { 2055 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A'); 2056 bandwidth = (double) total_sent / (double) end_time; 2057 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2058 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2059 if (test->sender_has_retransmits) { 2060 /* Summary sum, TCP with retransmits. */ 2061 if (test->json_output) 2062 cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits)); 2063 else 2064 iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender); 2065 } else { 2066 /* Summary sum, TCP without retransmits. */ 2067 if (test->json_output) 2068 cJSON_AddItemToObject(test->json_end, "sum_sent", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8)); 2069 else 2070 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender); 2071 } 2072 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A'); 2073 bandwidth = (double) total_received / (double) end_time; 2074 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2075 if (test->json_output) 2076 cJSON_AddItemToObject(test->json_end, "sum_received", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_received, bandwidth * 8)); 2077 else 2078 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver); 2079 } else { 2080 /* Summary sum, UDP. */ 2081 avg_jitter /= test->num_streams; 2082 lost_percent = 100.0 * lost_packets / total_packets; 2083 if (test->json_output) 2084 cJSON_AddItemToObject(test->json_end, "sum", iperf_json_printf("start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f", (double) start_time, (double) end_time, (double) end_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent)); 2085 else 2086 iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, ""); 2087 } 2088 } 2089 2090 if (test->json_output) 2091 cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f host_user: %f host_system: %f remote_total: %f remote_user: %f remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2])); 2092 else if (test->verbose) 2093 iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]); 2094 } 2095 2096 /**************************************************************************/ 2097 2098 /** 2099 * iperf_reporter_callback -- handles the report printing 2100 * 2101 */ 2102 2103 void 2104 iperf_reporter_callback(struct iperf_test *test) 2105 { 2106 switch (test->state) { 2107 case TEST_RUNNING: 2108 case STREAM_RUNNING: 2109 /* print interval results for each stream */ 2110 iperf_print_intermediate(test); 2111 break; 2112 case DISPLAY_RESULTS: 2113 iperf_print_intermediate(test); 2114 iperf_print_results(test); 2115 break; 2116 } 2117 2118 } 2119 2120 /**************************************************************************/ 2121 static void 2122 print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams) 2123 { 2124 char ubuf[UNIT_LEN]; 2125 char nbuf[UNIT_LEN]; 2126 char cbuf[UNIT_LEN]; 2127 double st = 0., et = 0.; 2128 struct iperf_interval_results *irp = NULL; 2129 double bandwidth, lost_percent; 2130 2131 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */ 2132 if (irp == NULL) { 2133 iperf_err(test, "print_interval_results error: interval_results is NULL"); 2134 return; 2135 } 2136 if (!test->json_output) { 2137 /* First stream? */ 2138 if (sp == SLIST_FIRST(&test->streams)) { 2139 /* It it's the first interval, print the header; 2140 ** else if there's more than one stream, print the separator; 2141 ** else nothing. 2142 */ 2143 if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) { 2144 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2145 if (test->sender && test->sender_has_retransmits) 2146 iprintf(test, "%s", report_bw_retrans_cwnd_header); 2147 else 2148 iprintf(test, "%s", report_bw_header); 2149 } else { 2150 if (test->sender) 2151 iprintf(test, "%s", report_bw_udp_sender_header); 2152 else 2153 iprintf(test, "%s", report_bw_udp_header); 2154 } 2155 } else if (test->num_streams > 1) 2156 iprintf(test, "%s", report_bw_separator); 2157 } 2158 } 2159 2160 unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A'); 2161 bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration; 2162 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2163 2164 st = timeval_diff(&sp->result->start_time, &irp->interval_start_time); 2165 et = timeval_diff(&sp->result->start_time, &irp->interval_end_time); 2166 2167 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2168 if (test->sender && test->sender_has_retransmits) { 2169 /* Interval, TCP with retransmits. */ 2170 if (test->json_output) 2171 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d snd_cwnd: %d omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, irp->omitted)); 2172 else 2173 unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A'); 2174 iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:""); 2175 } else { 2176 /* Interval, TCP without retransmits. */ 2177 if (test->json_output) 2178 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, irp->omitted)); 2179 else 2180 iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:""); 2181 } 2182 } else { 2183 /* Interval, UDP. */ 2184 if (test->sender) { 2185 if (test->json_output) 2186 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f packets: %d omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_packet_count, irp->omitted)); 2187 else 2188 iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:""); 2189 } else { 2190 lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count; 2191 if (test->json_output) 2192 cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f jitter_ms: %f lost_packets: %d packets: %d lost_percent: %f omitted: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (double) irp->jitter * 1000.0, (int64_t) irp->interval_cnt_error, (int64_t) irp->interval_packet_count, (double) lost_percent, irp->omitted)); 2193 else 2194 iprintf(test, report_bw_udp_format, sp->socket, st, et, ubuf, nbuf, irp->jitter * 1000.0, irp->interval_cnt_error, irp->interval_packet_count, lost_percent, irp->omitted?report_omitted:""); 2195 } 2196 } 2197 } 2198 2199 /**************************************************************************/ 2200 void 2201 iperf_free_stream(struct iperf_stream *sp) 2202 { 2203 struct iperf_interval_results *irp, *nirp; 2204 2205 /* XXX: need to free interval list too! */ 2206 munmap(sp->buffer, sp->test->settings->blksize); 2207 close(sp->buffer_fd); 2208 if (sp->diskfile_fd >= 0) 2209 close(sp->diskfile_fd); 2210 for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != TAILQ_END(sp->result->interval_results); irp = nirp) { 2211 nirp = TAILQ_NEXT(irp, irlistentries); 2212 free(irp); 2213 } 2214 free(sp->result); 2215 if (sp->send_timer != NULL) 2216 tmr_cancel(sp->send_timer); 2217 free(sp); 2218 } 2219 2220 /**************************************************************************/ 2221 struct iperf_stream * 2222 iperf_new_stream(struct iperf_test *test, int s) 2223 { 2224 int i; 2225 struct iperf_stream *sp; 2226 char template[] = "/tmp/iperf3.XXXXXX"; 2227 2228 h_errno = 0; 2229 2230 sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream)); 2231 if (!sp) { 2232 i_errno = IECREATESTREAM; 2233 return NULL; 2234 } 2235 2236 memset(sp, 0, sizeof(struct iperf_stream)); 2237 2238 sp->test = test; 2239 sp->settings = test->settings; 2240 sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result)); 2241 if (!sp->result) { 2242 free(sp); 2243 i_errno = IECREATESTREAM; 2244 return NULL; 2245 } 2246 2247 memset(sp->result, 0, sizeof(struct iperf_stream_result)); 2248 TAILQ_INIT(&sp->result->interval_results); 2249 2250 /* Create and randomize the buffer */ 2251 sp->buffer_fd = mkstemp(template); 2252 if (sp->buffer_fd == -1) { 2253 i_errno = IECREATESTREAM; 2254 free(sp->result); 2255 free(sp); 2256 return NULL; 2257 } 2258 if (unlink(template) < 0) { 2259 i_errno = IECREATESTREAM; 2260 free(sp->result); 2261 free(sp); 2262 return NULL; 2263 } 2264 if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) { 2265 i_errno = IECREATESTREAM; 2266 free(sp->result); 2267 free(sp); 2268 return NULL; 2269 } 2270 sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0); 2271 if (sp->buffer == MAP_FAILED) { 2272 i_errno = IECREATESTREAM; 2273 free(sp->result); 2274 free(sp); 2275 return NULL; 2276 } 2277 srandom(time(NULL)); 2278 for (i = 0; i < test->settings->blksize; ++i) 2279 sp->buffer[i] = random(); 2280 2281 /* Set socket */ 2282 sp->socket = s; 2283 2284 sp->snd = test->protocol->send; 2285 sp->rcv = test->protocol->recv; 2286 2287 if (test->diskfile_name != (char*) 0) { 2288 sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC)); 2289 if (sp->diskfile_fd == -1) { 2290 i_errno = IEFILE; 2291 munmap(sp->buffer, sp->test->settings->blksize); 2292 free(sp->result); 2293 free(sp); 2294 return NULL; 2295 } 2296 sp->snd2 = sp->snd; 2297 sp->snd = diskfile_send; 2298 sp->rcv2 = sp->rcv; 2299 sp->rcv = diskfile_recv; 2300 } else 2301 sp->diskfile_fd = -1; 2302 2303 /* Initialize stream */ 2304 if (iperf_init_stream(sp, test) < 0) { 2305 close(sp->buffer_fd); 2306 munmap(sp->buffer, sp->test->settings->blksize); 2307 free(sp->result); 2308 free(sp); 2309 return NULL; 2310 } 2311 iperf_add_stream(test, sp); 2312 2313 return sp; 2314 } 2315 2316 /**************************************************************************/ 2317 int 2318 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test) 2319 { 2320 socklen_t len; 2321 int opt; 2322 2323 len = sizeof(struct sockaddr_storage); 2324 if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) { 2325 i_errno = IEINITSTREAM; 2326 return -1; 2327 } 2328 len = sizeof(struct sockaddr_storage); 2329 if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) { 2330 i_errno = IEINITSTREAM; 2331 return -1; 2332 } 2333 2334 /* Set IP TOS */ 2335 if ((opt = test->settings->tos)) { 2336 if (getsockdomain(sp->socket) == AF_INET6) { 2337 #ifdef IPV6_TCLASS 2338 if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) { 2339 i_errno = IESETCOS; 2340 return -1; 2341 } 2342 #else 2343 i_errno = IESETCOS; 2344 return -1; 2345 #endif 2346 } else { 2347 if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) { 2348 i_errno = IESETTOS; 2349 return -1; 2350 } 2351 } 2352 } 2353 2354 return 0; 2355 } 2356 2357 /**************************************************************************/ 2358 void 2359 iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp) 2360 { 2361 int i; 2362 struct iperf_stream *n, *prev; 2363 2364 if (SLIST_EMPTY(&test->streams)) { 2365 SLIST_INSERT_HEAD(&test->streams, sp, streams); 2366 sp->id = 1; 2367 } else { 2368 // for (n = test->streams, i = 2; n->next; n = n->next, ++i); 2369 i = 2; 2370 SLIST_FOREACH(n, &test->streams, streams) { 2371 prev = n; 2372 ++i; 2373 } 2374 SLIST_INSERT_AFTER(prev, sp, streams); 2375 sp->id = i; 2376 } 2377 } 2378 2379 /* This pair of routines gets inserted into the snd/rcv function pointers 2380 ** when there's a -F flag. They handle the file stuff and call the real 2381 ** snd/rcv functions, which have been saved in snd2/rcv2. 2382 ** 2383 ** The advantage of doing it this way is that in the much more common 2384 ** case of no -F flag, there is zero extra overhead. 2385 */ 2386 2387 static int 2388 diskfile_send(struct iperf_stream *sp) 2389 { 2390 int r; 2391 2392 r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize); 2393 if (r == 0) 2394 sp->test->done = 1; 2395 else 2396 r = sp->snd2(sp); 2397 return r; 2398 } 2399 2400 static int 2401 diskfile_recv(struct iperf_stream *sp) 2402 { 2403 int r; 2404 2405 r = sp->rcv2(sp); 2406 if (r > 0) { 2407 (void) write(sp->diskfile_fd, sp->buffer, r); 2408 (void) fsync(sp->diskfile_fd); 2409 } 2410 return r; 2411 } 2412 2413 2414 void 2415 iperf_catch_sigend(void (*handler)(int)) 2416 { 2417 signal(SIGINT, handler); 2418 signal(SIGTERM, handler); 2419 signal(SIGHUP, handler); 2420 } 2421 2422 void 2423 iperf_got_sigend(struct iperf_test *test) 2424 { 2425 /* 2426 * If we're the client, or if we're a server and running a test, 2427 * then dump out the accumulated stats so far. 2428 */ 2429 if (test->role == 'c' || 2430 (test->role == 's' && test->state == TEST_RUNNING)) { 2431 2432 test->done = 1; 2433 cpu_util(test->cpu_util); 2434 test->stats_callback(test); 2435 test->state = DISPLAY_RESULTS; /* change local state only */ 2436 if (test->on_test_finish) 2437 test->on_test_finish(test); 2438 test->reporter_callback(test); 2439 } 2440 2441 if (test->ctrl_sck >= 0) { 2442 test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE; 2443 (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp); 2444 } 2445 i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM; 2446 iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno)); 2447 } 2448 2449 /* Try to write a PID file if requested, return -1 on an error. */ 2450 int 2451 iperf_create_pidfile(struct iperf_test *test) 2452 { 2453 if (test->pidfile) { 2454 int fd; 2455 char buf[8]; 2456 fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); 2457 if (fd < 0) { 2458 return -1; 2459 } 2460 snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */ 2461 if (write(fd, buf, strlen(buf) + 1) < 0) { 2462 return -1; 2463 } 2464 if (close(fd) < 0) { 2465 return -1; 2466 }; 2467 } 2468 return 0; 2469 } 2470 2471 /* Get rid of a PID file, return -1 on error. */ 2472 int 2473 iperf_delete_pidfile(struct iperf_test *test) 2474 { 2475 if (test->pidfile) { 2476 if (unlink(test->pidfile) < 0) { 2477 return -1; 2478 } 2479 } 2480 return 0; 2481 } 2482 2483 int 2484 iperf_json_start(struct iperf_test *test) 2485 { 2486 test->json_top = cJSON_CreateObject(); 2487 if (test->json_top == NULL) 2488 return -1; 2489 if (test->title) 2490 cJSON_AddStringToObject(test->json_top, "title", test->title); 2491 test->json_start = cJSON_CreateObject(); 2492 if (test->json_start == NULL) 2493 return -1; 2494 cJSON_AddItemToObject(test->json_top, "start", test->json_start); 2495 test->json_intervals = cJSON_CreateArray(); 2496 if (test->json_intervals == NULL) 2497 return -1; 2498 cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals); 2499 test->json_end = cJSON_CreateObject(); 2500 if (test->json_end == NULL) 2501 return -1; 2502 cJSON_AddItemToObject(test->json_top, "end", test->json_end); 2503 return 0; 2504 } 2505 2506 int 2507 iperf_json_finish(struct iperf_test *test) 2508 { 2509 char *str; 2510 2511 str = cJSON_Print(test->json_top); 2512 if (str == NULL) 2513 return -1; 2514 fputs(str, stdout); 2515 putchar('\n'); 2516 fflush(stdout); 2517 free(str); 2518 cJSON_Delete(test->json_top); 2519 test->json_top = test->json_start = test->json_intervals = test->json_end = NULL; 2520 return 0; 2521 } 2522 2523 2524 /* CPU affinity stuff - Linux and FreeBSD only. */ 2525 2526 int 2527 iperf_setaffinity(struct iperf_test *test, int affinity) 2528 { 2529 #ifdef linux 2530 cpu_set_t cpu_set; 2531 2532 CPU_ZERO(&cpu_set); 2533 CPU_SET(affinity, &cpu_set); 2534 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 2535 i_errno = IEAFFINITY; 2536 return -1; 2537 } 2538 return 0; 2539 #elif (__FreeBSD__) 2540 cpuset_t cpumask; 2541 2542 if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 2543 sizeof(cpuset_t), &test->cpumask) != 0) { 2544 i_errno = IEAFFINITY; 2545 return -1; 2546 } 2547 2548 CPU_ZERO(&cpumask); 2549 CPU_SET(affinity, &cpumask); 2550 2551 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 2552 sizeof(cpuset_t), &cpumask) != 0) { 2553 i_errno = IEAFFINITY; 2554 return -1; 2555 } 2556 return 0; 2557 #else /* Linux or FreeBSD */ 2558 i_errno = IEAFFINITY; 2559 return -1; 2560 #endif /* Linux or FreeBSD*/ 2561 } 2562 2563 int 2564 iperf_clearaffinity(struct iperf_test *test) 2565 { 2566 #ifdef linux 2567 cpu_set_t cpu_set; 2568 int i; 2569 2570 CPU_ZERO(&cpu_set); 2571 for (i = 0; i < CPU_SETSIZE; ++i) 2572 CPU_SET(i, &cpu_set); 2573 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 2574 i_errno = IEAFFINITY; 2575 return -1; 2576 } 2577 return 0; 2578 #elif (__FreeBSD__) 2579 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 2580 sizeof(cpuset_t), &test->cpumask) != 0) { 2581 i_errno = IEAFFINITY; 2582 return -1; 2583 } 2584 return 0; 2585 #else /* Linux or FreeBSD */ 2586 i_errno = IEAFFINITY; 2587 return -1; 2588 #endif /* Linux or FreeBSD */ 2589 } 2590 2591 int 2592 iprintf(struct iperf_test *test, const char* format, ...) 2593 { 2594 va_list argp; 2595 int r; 2596 2597 if (test->title) 2598 fputs(test->title, stdout); 2599 va_start(argp, format); 2600 r = vprintf(format, argp); 2601 va_end(argp); 2602 return r; 2603 } 2604