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