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