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 if (test->debug) { 814 printf("fubar\n"); 815 } 816 817 /* Set logging to a file if specified, otherwise use the default (stdout) */ 818 if (test->logfile) { 819 test->outfile = fopen(test->logfile, "a+"); 820 if (test->outfile == NULL) { 821 i_errno = IELOGFILE; 822 return -1; 823 } 824 } 825 826 /* Check flag / role compatibility. */ 827 if (test->role == 'c' && server_flag) { 828 i_errno = IESERVERONLY; 829 return -1; 830 } 831 if (test->role == 's' && client_flag) { 832 i_errno = IECLIENTONLY; 833 return -1; 834 } 835 836 if (blksize == 0) { 837 if (test->protocol->id == Pudp) 838 blksize = DEFAULT_UDP_BLKSIZE; 839 else if (test->protocol->id == Psctp) 840 blksize = DEFAULT_SCTP_BLKSIZE; 841 else 842 blksize = DEFAULT_TCP_BLKSIZE; 843 } 844 if (blksize <= 0 || blksize > MAX_BLOCKSIZE) { 845 i_errno = IEBLOCKSIZE; 846 return -1; 847 } 848 test->settings->blksize = blksize; 849 850 if (!rate_flag) 851 test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0; 852 853 if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag) 854 test->duration = 0; 855 856 /* Disallow specifying multiple test end conditions. The code actually 857 ** works just fine without this prohibition. As soon as any one of the 858 ** three possible end conditions is met, the test ends. So this check 859 ** could be removed if desired. 860 */ 861 if ((duration_flag && test->settings->bytes != 0) || 862 (duration_flag && test->settings->blocks != 0) || 863 (test->settings->bytes != 0 && test->settings->blocks != 0)) { 864 i_errno = IEENDCONDITIONS; 865 return -1; 866 } 867 868 /* For subsequent calls to getopt */ 869 #ifdef __APPLE__ 870 optreset = 1; 871 #endif 872 optind = 0; 873 874 if ((test->role != 'c') && (test->role != 's')) { 875 i_errno = IENOROLE; 876 return -1; 877 } 878 879 return 0; 880 } 881 882 int 883 iperf_set_send_state(struct iperf_test *test, signed char state) 884 { 885 test->state = state; 886 if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) { 887 i_errno = IESENDMESSAGE; 888 return -1; 889 } 890 return 0; 891 } 892 893 void 894 iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP) 895 { 896 double seconds; 897 uint64_t bits_per_second; 898 899 if (sp->test->done) 900 return; 901 seconds = timeval_diff(&sp->result->start_time, nowP); 902 bits_per_second = sp->result->bytes_sent * 8 / seconds; 903 if (bits_per_second < sp->test->settings->rate) { 904 sp->green_light = 1; 905 FD_SET(sp->socket, &sp->test->write_set); 906 } else { 907 sp->green_light = 0; 908 FD_CLR(sp->socket, &sp->test->write_set); 909 } 910 } 911 912 int 913 iperf_send(struct iperf_test *test, fd_set *write_setP) 914 { 915 register int multisend, r; 916 register struct iperf_stream *sp; 917 struct timeval now; 918 919 /* Can we do multisend mode? */ 920 if (test->settings->burst != 0) 921 multisend = test->settings->burst; 922 else if (test->settings->rate == 0) 923 multisend = test->multisend; 924 else 925 multisend = 1; /* nope */ 926 927 for (; multisend > 0; --multisend) { 928 if (test->settings->rate != 0 && test->settings->burst == 0) 929 gettimeofday(&now, NULL); 930 SLIST_FOREACH(sp, &test->streams, streams) { 931 if (sp->green_light && 932 (write_setP == NULL || FD_ISSET(sp->socket, write_setP))) { 933 if ((r = sp->snd(sp)) < 0) { 934 if (r == NET_SOFTERROR) 935 break; 936 i_errno = IESTREAMWRITE; 937 return r; 938 } 939 test->bytes_sent += r; 940 ++test->blocks_sent; 941 if (test->settings->rate != 0 && test->settings->burst == 0) 942 iperf_check_throttle(sp, &now); 943 if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) 944 break; 945 if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks) 946 break; 947 } 948 } 949 } 950 if (test->settings->burst != 0) { 951 gettimeofday(&now, NULL); 952 SLIST_FOREACH(sp, &test->streams, streams) 953 iperf_check_throttle(sp, &now); 954 } 955 if (write_setP != NULL) 956 SLIST_FOREACH(sp, &test->streams, streams) 957 if (FD_ISSET(sp->socket, write_setP)) 958 FD_CLR(sp->socket, write_setP); 959 960 return 0; 961 } 962 963 int 964 iperf_recv(struct iperf_test *test, fd_set *read_setP) 965 { 966 int r; 967 struct iperf_stream *sp; 968 969 SLIST_FOREACH(sp, &test->streams, streams) { 970 if (FD_ISSET(sp->socket, read_setP)) { 971 if ((r = sp->rcv(sp)) < 0) { 972 i_errno = IESTREAMREAD; 973 return r; 974 } 975 test->bytes_sent += r; 976 ++test->blocks_sent; 977 FD_CLR(sp->socket, read_setP); 978 } 979 } 980 981 return 0; 982 } 983 984 int 985 iperf_init_test(struct iperf_test *test) 986 { 987 struct timeval now; 988 struct iperf_stream *sp; 989 990 if (test->protocol->init) { 991 if (test->protocol->init(test) < 0) 992 return -1; 993 } 994 995 /* Init each stream. */ 996 if (gettimeofday(&now, NULL) < 0) { 997 i_errno = IEINITTEST; 998 return -1; 999 } 1000 SLIST_FOREACH(sp, &test->streams, streams) { 1001 sp->result->start_time = now; 1002 } 1003 1004 if (test->on_test_start) 1005 test->on_test_start(test); 1006 1007 return 0; 1008 } 1009 1010 static void 1011 send_timer_proc(TimerClientData client_data, struct timeval *nowP) 1012 { 1013 struct iperf_stream *sp = client_data.p; 1014 1015 /* All we do here is set or clear the flag saying that this stream may 1016 ** be sent to. The actual sending gets done in the send proc, after 1017 ** checking the flag. 1018 */ 1019 iperf_check_throttle(sp, nowP); 1020 } 1021 1022 int 1023 iperf_create_send_timers(struct iperf_test * test) 1024 { 1025 struct timeval now; 1026 struct iperf_stream *sp; 1027 TimerClientData cd; 1028 1029 if (gettimeofday(&now, NULL) < 0) { 1030 i_errno = IEINITTEST; 1031 return -1; 1032 } 1033 SLIST_FOREACH(sp, &test->streams, streams) { 1034 sp->green_light = 1; 1035 if (test->settings->rate != 0) { 1036 cd.p = sp; 1037 sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, 100000L, 1); 1038 /* (Repeat every tenth second - arbitrary often value.) */ 1039 if (sp->send_timer == NULL) { 1040 i_errno = IEINITTEST; 1041 return -1; 1042 } 1043 } 1044 } 1045 return 0; 1046 } 1047 1048 /** 1049 * iperf_exchange_parameters - handles the param_Exchange part for client 1050 * 1051 */ 1052 1053 int 1054 iperf_exchange_parameters(struct iperf_test *test) 1055 { 1056 int s; 1057 int32_t err; 1058 1059 if (test->role == 'c') { 1060 1061 if (send_parameters(test) < 0) 1062 return -1; 1063 1064 } else { 1065 1066 if (get_parameters(test) < 0) 1067 return -1; 1068 1069 if ((s = test->protocol->listen(test)) < 0) { 1070 if (iperf_set_send_state(test, SERVER_ERROR) != 0) 1071 return -1; 1072 err = htonl(i_errno); 1073 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1074 i_errno = IECTRLWRITE; 1075 return -1; 1076 } 1077 err = htonl(errno); 1078 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1079 i_errno = IECTRLWRITE; 1080 return -1; 1081 } 1082 return -1; 1083 } 1084 FD_SET(s, &test->read_set); 1085 test->max_fd = (s > test->max_fd) ? s : test->max_fd; 1086 test->prot_listener = s; 1087 1088 // Send the control message to create streams and start the test 1089 if (iperf_set_send_state(test, CREATE_STREAMS) != 0) 1090 return -1; 1091 1092 } 1093 1094 return 0; 1095 } 1096 1097 /*************************************************************/ 1098 1099 int 1100 iperf_exchange_results(struct iperf_test *test) 1101 { 1102 if (test->role == 'c') { 1103 /* Send results to server. */ 1104 if (send_results(test) < 0) 1105 return -1; 1106 /* Get server results. */ 1107 if (get_results(test) < 0) 1108 return -1; 1109 } else { 1110 /* Get client results. */ 1111 if (get_results(test) < 0) 1112 return -1; 1113 /* Send results to client. */ 1114 if (send_results(test) < 0) 1115 return -1; 1116 } 1117 return 0; 1118 } 1119 1120 /*************************************************************/ 1121 1122 static int 1123 send_parameters(struct iperf_test *test) 1124 { 1125 int r = 0; 1126 cJSON *j; 1127 1128 j = cJSON_CreateObject(); 1129 if (j == NULL) { 1130 i_errno = IESENDPARAMS; 1131 r = -1; 1132 } else { 1133 if (test->protocol->id == Ptcp) 1134 cJSON_AddTrueToObject(j, "tcp"); 1135 else if (test->protocol->id == Pudp) 1136 cJSON_AddTrueToObject(j, "udp"); 1137 else if (test->protocol->id == Psctp) 1138 cJSON_AddTrueToObject(j, "sctp"); 1139 cJSON_AddIntToObject(j, "omit", test->omit); 1140 if (test->server_affinity != -1) 1141 cJSON_AddIntToObject(j, "server_affinity", test->server_affinity); 1142 if (test->duration) 1143 cJSON_AddIntToObject(j, "time", test->duration); 1144 if (test->settings->bytes) 1145 cJSON_AddIntToObject(j, "num", test->settings->bytes); 1146 if (test->settings->blocks) 1147 cJSON_AddIntToObject(j, "blockcount", test->settings->blocks); 1148 if (test->settings->mss) 1149 cJSON_AddIntToObject(j, "MSS", test->settings->mss); 1150 if (test->no_delay) 1151 cJSON_AddTrueToObject(j, "nodelay"); 1152 cJSON_AddIntToObject(j, "parallel", test->num_streams); 1153 if (test->reverse) 1154 cJSON_AddTrueToObject(j, "reverse"); 1155 if (test->settings->socket_bufsize) 1156 cJSON_AddIntToObject(j, "window", test->settings->socket_bufsize); 1157 if (test->settings->blksize) 1158 cJSON_AddIntToObject(j, "len", test->settings->blksize); 1159 if (test->settings->rate) 1160 cJSON_AddIntToObject(j, "bandwidth", test->settings->rate); 1161 if (test->settings->burst) 1162 cJSON_AddIntToObject(j, "burst", test->settings->burst); 1163 if (test->settings->tos) 1164 cJSON_AddIntToObject(j, "TOS", test->settings->tos); 1165 if (test->settings->flowlabel) 1166 cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel); 1167 if (test->title) 1168 cJSON_AddStringToObject(j, "title", test->title); 1169 if (test->congestion) 1170 cJSON_AddStringToObject(j, "congestion", test->congestion); 1171 if (JSON_write(test->ctrl_sck, j) < 0) { 1172 i_errno = IESENDPARAMS; 1173 r = -1; 1174 } 1175 cJSON_Delete(j); 1176 } 1177 return r; 1178 } 1179 1180 /*************************************************************/ 1181 1182 static int 1183 get_parameters(struct iperf_test *test) 1184 { 1185 int r = 0; 1186 cJSON *j; 1187 cJSON *j_p; 1188 1189 j = JSON_read(test->ctrl_sck); 1190 if (j == NULL) { 1191 i_errno = IERECVPARAMS; 1192 r = -1; 1193 } else { 1194 if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL) 1195 set_protocol(test, Ptcp); 1196 if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL) 1197 set_protocol(test, Pudp); 1198 if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL) 1199 set_protocol(test, Psctp); 1200 if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL) 1201 test->omit = j_p->valueint; 1202 if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL) 1203 test->server_affinity = j_p->valueint; 1204 if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL) 1205 test->duration = j_p->valueint; 1206 if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL) 1207 test->settings->bytes = j_p->valueint; 1208 if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL) 1209 test->settings->blocks = j_p->valueint; 1210 if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL) 1211 test->settings->mss = j_p->valueint; 1212 if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL) 1213 test->no_delay = 1; 1214 if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL) 1215 test->num_streams = j_p->valueint; 1216 if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL) 1217 iperf_set_test_reverse(test, 1); 1218 if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL) 1219 test->settings->socket_bufsize = j_p->valueint; 1220 if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL) 1221 test->settings->blksize = j_p->valueint; 1222 if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL) 1223 test->settings->rate = j_p->valueint; 1224 if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL) 1225 test->settings->burst = j_p->valueint; 1226 if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) 1227 test->settings->tos = j_p->valueint; 1228 if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL) 1229 test->settings->flowlabel = j_p->valueint; 1230 if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL) 1231 test->title = strdup(j_p->valuestring); 1232 if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL) 1233 test->congestion = strdup(j_p->valuestring); 1234 if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits()) 1235 test->sender_has_retransmits = 1; 1236 cJSON_Delete(j); 1237 } 1238 return r; 1239 } 1240 1241 /*************************************************************/ 1242 1243 static int 1244 send_results(struct iperf_test *test) 1245 { 1246 int r = 0; 1247 cJSON *j; 1248 cJSON *j_streams; 1249 struct iperf_stream *sp; 1250 cJSON *j_stream; 1251 int sender_has_retransmits; 1252 iperf_size_t bytes_transferred; 1253 int retransmits; 1254 1255 j = cJSON_CreateObject(); 1256 if (j == NULL) { 1257 i_errno = IEPACKAGERESULTS; 1258 r = -1; 1259 } else { 1260 cJSON_AddFloatToObject(j, "cpu_util_total", test->cpu_util[0]); 1261 cJSON_AddFloatToObject(j, "cpu_util_user", test->cpu_util[1]); 1262 cJSON_AddFloatToObject(j, "cpu_util_system", test->cpu_util[2]); 1263 if ( ! test->sender ) 1264 sender_has_retransmits = -1; 1265 else 1266 sender_has_retransmits = test->sender_has_retransmits; 1267 cJSON_AddIntToObject(j, "sender_has_retransmits", sender_has_retransmits); 1268 j_streams = cJSON_CreateArray(); 1269 if (j_streams == NULL) { 1270 i_errno = IEPACKAGERESULTS; 1271 r = -1; 1272 } else { 1273 cJSON_AddItemToObject(j, "streams", j_streams); 1274 SLIST_FOREACH(sp, &test->streams, streams) { 1275 j_stream = cJSON_CreateObject(); 1276 if (j_stream == NULL) { 1277 i_errno = IEPACKAGERESULTS; 1278 r = -1; 1279 } else { 1280 cJSON_AddItemToArray(j_streams, j_stream); 1281 bytes_transferred = test->sender ? sp->result->bytes_sent : sp->result->bytes_received; 1282 retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1; 1283 cJSON_AddIntToObject(j_stream, "id", sp->id); 1284 cJSON_AddIntToObject(j_stream, "bytes", bytes_transferred); 1285 cJSON_AddIntToObject(j_stream, "retransmits", retransmits); 1286 cJSON_AddFloatToObject(j_stream, "jitter", sp->jitter); 1287 cJSON_AddIntToObject(j_stream, "errors", sp->cnt_error); 1288 cJSON_AddIntToObject(j_stream, "packets", sp->packet_count); 1289 } 1290 } 1291 if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) { 1292 i_errno = IESENDRESULTS; 1293 r = -1; 1294 } 1295 } 1296 cJSON_Delete(j); 1297 } 1298 return r; 1299 } 1300 1301 /*************************************************************/ 1302 1303 static int 1304 get_results(struct iperf_test *test) 1305 { 1306 int r = 0; 1307 cJSON *j; 1308 cJSON *j_cpu_util_total; 1309 cJSON *j_cpu_util_user; 1310 cJSON *j_cpu_util_system; 1311 cJSON *j_sender_has_retransmits; 1312 int result_has_retransmits; 1313 cJSON *j_streams; 1314 int n, i; 1315 cJSON *j_stream; 1316 cJSON *j_id; 1317 cJSON *j_bytes; 1318 cJSON *j_retransmits; 1319 cJSON *j_jitter; 1320 cJSON *j_errors; 1321 cJSON *j_packets; 1322 int sid, cerror, pcount; 1323 double jitter; 1324 iperf_size_t bytes_transferred; 1325 int retransmits; 1326 struct iperf_stream *sp; 1327 1328 j = JSON_read(test->ctrl_sck); 1329 if (j == NULL) { 1330 i_errno = IERECVRESULTS; 1331 r = -1; 1332 } else { 1333 j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total"); 1334 j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user"); 1335 j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system"); 1336 j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits"); 1337 if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) { 1338 i_errno = IERECVRESULTS; 1339 r = -1; 1340 } else { 1341 test->remote_cpu_util[0] = j_cpu_util_total->valuefloat; 1342 test->remote_cpu_util[1] = j_cpu_util_user->valuefloat; 1343 test->remote_cpu_util[2] = j_cpu_util_system->valuefloat; 1344 result_has_retransmits = j_sender_has_retransmits->valueint; 1345 if (! test->sender) 1346 test->sender_has_retransmits = result_has_retransmits; 1347 j_streams = cJSON_GetObjectItem(j, "streams"); 1348 if (j_streams == NULL) { 1349 i_errno = IERECVRESULTS; 1350 r = -1; 1351 } else { 1352 n = cJSON_GetArraySize(j_streams); 1353 for (i=0; i<n; ++i) { 1354 j_stream = cJSON_GetArrayItem(j_streams, i); 1355 if (j_stream == NULL) { 1356 i_errno = IERECVRESULTS; 1357 r = -1; 1358 } else { 1359 j_id = cJSON_GetObjectItem(j_stream, "id"); 1360 j_bytes = cJSON_GetObjectItem(j_stream, "bytes"); 1361 j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits"); 1362 j_jitter = cJSON_GetObjectItem(j_stream, "jitter"); 1363 j_errors = cJSON_GetObjectItem(j_stream, "errors"); 1364 j_packets = cJSON_GetObjectItem(j_stream, "packets"); 1365 if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) { 1366 i_errno = IERECVRESULTS; 1367 r = -1; 1368 } else { 1369 sid = j_id->valueint; 1370 bytes_transferred = j_bytes->valueint; 1371 retransmits = j_retransmits->valueint; 1372 jitter = j_jitter->valuefloat; 1373 cerror = j_errors->valueint; 1374 pcount = j_packets->valueint; 1375 SLIST_FOREACH(sp, &test->streams, streams) 1376 if (sp->id == sid) break; 1377 if (sp == NULL) { 1378 i_errno = IESTREAMID; 1379 r = -1; 1380 } else { 1381 if (test->sender) { 1382 sp->jitter = jitter; 1383 sp->cnt_error = cerror; 1384 sp->packet_count = pcount; 1385 sp->result->bytes_received = bytes_transferred; 1386 } else { 1387 sp->result->bytes_sent = bytes_transferred; 1388 sp->result->stream_retrans = retransmits; 1389 } 1390 } 1391 } 1392 } 1393 } 1394 } 1395 } 1396 cJSON_Delete(j); 1397 } 1398 return r; 1399 } 1400 1401 /*************************************************************/ 1402 1403 static int 1404 JSON_write(int fd, cJSON *json) 1405 { 1406 uint32_t hsize, nsize; 1407 char *str; 1408 int r = 0; 1409 1410 str = cJSON_PrintUnformatted(json); 1411 if (str == NULL) 1412 r = -1; 1413 else { 1414 hsize = strlen(str); 1415 nsize = htonl(hsize); 1416 if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0) 1417 r = -1; 1418 else { 1419 if (Nwrite(fd, str, hsize, Ptcp) < 0) 1420 r = -1; 1421 } 1422 free(str); 1423 } 1424 return r; 1425 } 1426 1427 /*************************************************************/ 1428 1429 static cJSON * 1430 JSON_read(int fd) 1431 { 1432 uint32_t hsize, nsize; 1433 char *str; 1434 cJSON *json = NULL; 1435 1436 if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) { 1437 hsize = ntohl(nsize); 1438 str = (char *) malloc(hsize+1); /* +1 for EOS */ 1439 if (str != NULL) { 1440 if (Nread(fd, str, hsize, Ptcp) >= 0) { 1441 str[hsize] = '\0'; /* add the EOS */ 1442 json = cJSON_Parse(str); 1443 } 1444 } 1445 free(str); 1446 } 1447 return json; 1448 } 1449 1450 /*************************************************************/ 1451 /** 1452 * add_to_interval_list -- adds new interval to the interval_list 1453 */ 1454 1455 void 1456 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new) 1457 { 1458 struct iperf_interval_results *irp; 1459 1460 irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results)); 1461 memcpy(irp, new, sizeof(struct iperf_interval_results)); 1462 TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries); 1463 } 1464 1465 1466 /************************************************************/ 1467 1468 /** 1469 * connect_msg -- displays connection message 1470 * denoting sender/receiver details 1471 * 1472 */ 1473 1474 void 1475 connect_msg(struct iperf_stream *sp) 1476 { 1477 char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN]; 1478 int lport, rport; 1479 1480 if (getsockdomain(sp->socket) == AF_INET) { 1481 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl)); 1482 mapped_v4_to_regular_v4(ipl); 1483 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr)); 1484 mapped_v4_to_regular_v4(ipr); 1485 lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port); 1486 rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port); 1487 } else { 1488 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl)); 1489 mapped_v4_to_regular_v4(ipl); 1490 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr)); 1491 mapped_v4_to_regular_v4(ipr); 1492 lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port); 1493 rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port); 1494 } 1495 1496 if (sp->test->json_output) 1497 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)); 1498 else 1499 iprintf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport); 1500 } 1501 1502 1503 /**************************************************************************/ 1504 1505 struct iperf_test * 1506 iperf_new_test() 1507 { 1508 struct iperf_test *test; 1509 1510 test = (struct iperf_test *) malloc(sizeof(struct iperf_test)); 1511 if (!test) { 1512 i_errno = IENEWTEST; 1513 return NULL; 1514 } 1515 /* initialize everything to zero */ 1516 memset(test, 0, sizeof(struct iperf_test)); 1517 1518 test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings)); 1519 if (!test->settings) { 1520 free(test); 1521 i_errno = IENEWTEST; 1522 return NULL; 1523 } 1524 memset(test->settings, 0, sizeof(struct iperf_settings)); 1525 1526 /* By default all output goes to stdout */ 1527 test->outfile = stdout; 1528 1529 return test; 1530 } 1531 1532 /**************************************************************************/ 1533 1534 struct protocol * 1535 protocol_new(void) 1536 { 1537 struct protocol *proto; 1538 1539 proto = malloc(sizeof(struct protocol)); 1540 if(!proto) { 1541 return NULL; 1542 } 1543 memset(proto, 0, sizeof(struct protocol)); 1544 1545 return proto; 1546 } 1547 1548 void 1549 protocol_free(struct protocol *proto) 1550 { 1551 free(proto); 1552 } 1553 1554 /**************************************************************************/ 1555 int 1556 iperf_defaults(struct iperf_test *testp) 1557 { 1558 struct protocol *tcp, *udp; 1559 #if defined(HAVE_SCTP) 1560 struct protocol *sctp; 1561 #endif /* HAVE_SCTP */ 1562 1563 testp->omit = OMIT; 1564 testp->duration = DURATION; 1565 testp->diskfile_name = (char*) 0; 1566 testp->affinity = -1; 1567 testp->server_affinity = -1; 1568 #if defined(HAVE_CPUSET_SETAFFINITY) 1569 CPU_ZERO(&testp->cpumask); 1570 #endif /* HAVE_CPUSET_SETAFFINITY */ 1571 testp->title = NULL; 1572 testp->congestion = NULL; 1573 testp->server_port = PORT; 1574 testp->ctrl_sck = -1; 1575 testp->prot_listener = -1; 1576 1577 testp->stats_callback = iperf_stats_callback; 1578 testp->reporter_callback = iperf_reporter_callback; 1579 1580 testp->stats_interval = testp->reporter_interval = 1; 1581 testp->num_streams = 1; 1582 1583 testp->settings->domain = AF_UNSPEC; 1584 testp->settings->unit_format = 'a'; 1585 testp->settings->socket_bufsize = 0; /* use autotuning */ 1586 testp->settings->blksize = DEFAULT_TCP_BLKSIZE; 1587 testp->settings->rate = 0; 1588 testp->settings->burst = 0; 1589 testp->settings->mss = 0; 1590 testp->settings->bytes = 0; 1591 testp->settings->blocks = 0; 1592 memset(testp->cookie, 0, COOKIE_SIZE); 1593 1594 testp->multisend = 10; /* arbitrary */ 1595 1596 /* Set up protocol list */ 1597 SLIST_INIT(&testp->streams); 1598 SLIST_INIT(&testp->protocols); 1599 1600 tcp = protocol_new(); 1601 if (!tcp) 1602 return -1; 1603 1604 tcp->id = Ptcp; 1605 tcp->name = "TCP"; 1606 tcp->accept = iperf_tcp_accept; 1607 tcp->listen = iperf_tcp_listen; 1608 tcp->connect = iperf_tcp_connect; 1609 tcp->send = iperf_tcp_send; 1610 tcp->recv = iperf_tcp_recv; 1611 tcp->init = NULL; 1612 SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols); 1613 1614 udp = protocol_new(); 1615 if (!udp) { 1616 protocol_free(tcp); 1617 return -1; 1618 } 1619 1620 udp->id = Pudp; 1621 udp->name = "UDP"; 1622 udp->accept = iperf_udp_accept; 1623 udp->listen = iperf_udp_listen; 1624 udp->connect = iperf_udp_connect; 1625 udp->send = iperf_udp_send; 1626 udp->recv = iperf_udp_recv; 1627 udp->init = iperf_udp_init; 1628 SLIST_INSERT_AFTER(tcp, udp, protocols); 1629 1630 set_protocol(testp, Ptcp); 1631 1632 #if defined(HAVE_SCTP) 1633 sctp = protocol_new(); 1634 if (!sctp) { 1635 protocol_free(tcp); 1636 protocol_free(udp); 1637 return -1; 1638 } 1639 1640 sctp->id = Psctp; 1641 sctp->name = "SCTP"; 1642 sctp->accept = iperf_sctp_accept; 1643 sctp->listen = iperf_sctp_listen; 1644 sctp->connect = iperf_sctp_connect; 1645 sctp->send = iperf_sctp_send; 1646 sctp->recv = iperf_sctp_recv; 1647 sctp->init = iperf_sctp_init; 1648 1649 SLIST_INSERT_AFTER(udp, sctp, protocols); 1650 #endif /* HAVE_SCTP */ 1651 1652 testp->on_new_stream = iperf_on_new_stream; 1653 testp->on_test_start = iperf_on_test_start; 1654 testp->on_connect = iperf_on_connect; 1655 testp->on_test_finish = iperf_on_test_finish; 1656 1657 return 0; 1658 } 1659 1660 1661 /**************************************************************************/ 1662 void 1663 iperf_free_test(struct iperf_test *test) 1664 { 1665 struct protocol *prot; 1666 struct iperf_stream *sp; 1667 1668 /* Free streams */ 1669 while (!SLIST_EMPTY(&test->streams)) { 1670 sp = SLIST_FIRST(&test->streams); 1671 SLIST_REMOVE_HEAD(&test->streams, streams); 1672 iperf_free_stream(sp); 1673 } 1674 1675 if (test->server_hostname) 1676 free(test->server_hostname); 1677 if (test->bind_address) 1678 free(test->bind_address); 1679 free(test->settings); 1680 if (test->title) 1681 free(test->title); 1682 if (test->congestion) 1683 free(test->congestion); 1684 if (test->omit_timer != NULL) 1685 tmr_cancel(test->omit_timer); 1686 if (test->timer != NULL) 1687 tmr_cancel(test->timer); 1688 if (test->stats_timer != NULL) 1689 tmr_cancel(test->stats_timer); 1690 if (test->reporter_timer != NULL) 1691 tmr_cancel(test->reporter_timer); 1692 1693 /* Free protocol list */ 1694 while (!SLIST_EMPTY(&test->protocols)) { 1695 prot = SLIST_FIRST(&test->protocols); 1696 SLIST_REMOVE_HEAD(&test->protocols, protocols); 1697 free(prot); 1698 } 1699 1700 if (test->json_output_string) { 1701 free(test->json_output_string); 1702 test->json_output_string = NULL; 1703 } 1704 1705 /* XXX: Why are we setting these values to NULL? */ 1706 // test->streams = NULL; 1707 test->stats_callback = NULL; 1708 test->reporter_callback = NULL; 1709 free(test); 1710 } 1711 1712 1713 void 1714 iperf_reset_test(struct iperf_test *test) 1715 { 1716 struct iperf_stream *sp; 1717 1718 /* Free streams */ 1719 while (!SLIST_EMPTY(&test->streams)) { 1720 sp = SLIST_FIRST(&test->streams); 1721 SLIST_REMOVE_HEAD(&test->streams, streams); 1722 iperf_free_stream(sp); 1723 } 1724 if (test->omit_timer != NULL) { 1725 tmr_cancel(test->omit_timer); 1726 test->omit_timer = NULL; 1727 } 1728 if (test->timer != NULL) { 1729 tmr_cancel(test->timer); 1730 test->timer = NULL; 1731 } 1732 if (test->stats_timer != NULL) { 1733 tmr_cancel(test->stats_timer); 1734 test->stats_timer = NULL; 1735 } 1736 if (test->reporter_timer != NULL) { 1737 tmr_cancel(test->reporter_timer); 1738 test->reporter_timer = NULL; 1739 } 1740 test->done = 0; 1741 1742 SLIST_INIT(&test->streams); 1743 1744 test->role = 's'; 1745 test->sender = 0; 1746 test->sender_has_retransmits = 0; 1747 set_protocol(test, Ptcp); 1748 test->omit = OMIT; 1749 test->duration = DURATION; 1750 test->server_affinity = -1; 1751 #if defined(HAVE_CPUSET_SETAFFINITY) 1752 CPU_ZERO(&test->cpumask); 1753 #endif /* HAVE_CPUSET_SETAFFINITY */ 1754 test->state = 0; 1755 1756 if(test->title) { 1757 free(test->title); 1758 test->title = NULL; 1759 } 1760 if(test->server_hostname) { 1761 free(test->server_hostname); 1762 test->server_hostname = NULL; 1763 } 1764 if(test->bind_address) { 1765 free(test->bind_address); 1766 test->bind_address = NULL; 1767 } 1768 if(test->congestion) { 1769 free(test->congestion); 1770 test->congestion = NULL; 1771 } 1772 1773 test->ctrl_sck = -1; 1774 test->prot_listener = -1; 1775 1776 test->bytes_sent = 0; 1777 test->blocks_sent = 0; 1778 1779 test->reverse = 0; 1780 test->no_delay = 0; 1781 1782 FD_ZERO(&test->read_set); 1783 FD_ZERO(&test->write_set); 1784 1785 test->num_streams = 1; 1786 test->settings->socket_bufsize = 0; 1787 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 1788 test->settings->rate = 0; 1789 test->settings->burst = 0; 1790 test->settings->mss = 0; 1791 memset(test->cookie, 0, COOKIE_SIZE); 1792 test->multisend = 10; /* arbitrary */ 1793 } 1794 1795 1796 /* Reset all of a test's stats back to zero. Called when the omitting 1797 ** period is over. 1798 */ 1799 void 1800 iperf_reset_stats(struct iperf_test *test) 1801 { 1802 struct timeval now; 1803 struct iperf_stream *sp; 1804 struct iperf_stream_result *rp; 1805 1806 test->bytes_sent = 0; 1807 test->blocks_sent = 0; 1808 gettimeofday(&now, NULL); 1809 SLIST_FOREACH(sp, &test->streams, streams) { 1810 sp->omitted_packet_count = sp->packet_count; 1811 sp->jitter = 0; 1812 sp->outoforder_packets = 0; 1813 sp->cnt_error = 0; 1814 rp = sp->result; 1815 rp->bytes_sent = rp->bytes_received = 0; 1816 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 1817 if (test->sender && test->sender_has_retransmits) { 1818 struct iperf_interval_results ir; /* temporary results structure */ 1819 save_tcpinfo(sp, &ir); 1820 rp->stream_prev_total_retrans = get_total_retransmits(&ir); 1821 } 1822 rp->stream_retrans = 0; 1823 rp->start_time = now; 1824 } 1825 } 1826 1827 1828 /**************************************************************************/ 1829 1830 /** 1831 * iperf_stats_callback -- handles the statistic gathering for both the client and server 1832 * 1833 * XXX: This function needs to be updated to reflect the new code 1834 */ 1835 1836 1837 void 1838 iperf_stats_callback(struct iperf_test *test) 1839 { 1840 struct iperf_stream *sp; 1841 struct iperf_stream_result *rp = NULL; 1842 struct iperf_interval_results *irp, temp; 1843 1844 temp.omitted = test->omitting; 1845 SLIST_FOREACH(sp, &test->streams, streams) { 1846 rp = sp->result; 1847 1848 temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval; 1849 1850 irp = TAILQ_LAST(&rp->interval_results, irlisthead); 1851 /* result->end_time contains timestamp of previous interval */ 1852 if ( irp != NULL ) /* not the 1st interval */ 1853 memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval)); 1854 else /* or use timestamp from beginning */ 1855 memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval)); 1856 /* now save time of end of this interval */ 1857 gettimeofday(&rp->end_time, NULL); 1858 memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval)); 1859 temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1860 //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 1861 if (test->protocol->id == Ptcp) { 1862 if ( has_tcpinfo()) { 1863 save_tcpinfo(sp, &temp); 1864 if (test->sender && test->sender_has_retransmits) { 1865 long total_retrans = get_total_retransmits(&temp); 1866 temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans; 1867 rp->stream_retrans += temp.interval_retrans; 1868 rp->stream_prev_total_retrans = total_retrans; 1869 1870 temp.snd_cwnd = get_snd_cwnd(&temp); 1871 } 1872 } 1873 } else { 1874 if (irp == NULL) { 1875 temp.interval_packet_count = sp->packet_count; 1876 temp.interval_outoforder_packets = sp->outoforder_packets; 1877 temp.interval_cnt_error = sp->cnt_error; 1878 } else { 1879 temp.interval_packet_count = sp->packet_count - irp->packet_count; 1880 temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets; 1881 temp.interval_cnt_error = sp->cnt_error - irp->cnt_error; 1882 } 1883 temp.packet_count = sp->packet_count; 1884 temp.jitter = sp->jitter; 1885 temp.outoforder_packets = sp->outoforder_packets; 1886 temp.cnt_error = sp->cnt_error; 1887 } 1888 add_to_interval_list(rp, &temp); 1889 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 1890 } 1891 } 1892 1893 static void 1894 iperf_print_intermediate(struct iperf_test *test) 1895 { 1896 char ubuf[UNIT_LEN]; 1897 char nbuf[UNIT_LEN]; 1898 struct iperf_stream *sp = NULL; 1899 struct iperf_interval_results *irp; 1900 iperf_size_t bytes = 0; 1901 double bandwidth; 1902 int retransmits = 0; 1903 double start_time, end_time; 1904 cJSON *json_interval; 1905 cJSON *json_interval_streams; 1906 int total_packets = 0, lost_packets = 0; 1907 double avg_jitter = 0.0, lost_percent; 1908 1909 if (test->json_output) { 1910 json_interval = cJSON_CreateObject(); 1911 if (json_interval == NULL) 1912 return; 1913 cJSON_AddItemToArray(test->json_intervals, json_interval); 1914 json_interval_streams = cJSON_CreateArray(); 1915 if (json_interval_streams == NULL) 1916 return; 1917 cJSON_AddItemToObject(json_interval, "streams", json_interval_streams); 1918 } else { 1919 json_interval = NULL; 1920 json_interval_streams = NULL; 1921 } 1922 1923 SLIST_FOREACH(sp, &test->streams, streams) { 1924 print_interval_results(test, sp, json_interval_streams); 1925 /* sum up all streams */ 1926 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); 1927 if (irp == NULL) { 1928 iperf_err(test, "iperf_print_intermediate error: interval_results is NULL"); 1929 return; 1930 } 1931 bytes += irp->bytes_transferred; 1932 if (test->protocol->id == Ptcp) { 1933 if (test->sender && test->sender_has_retransmits) { 1934 retransmits += irp->interval_retrans; 1935 } 1936 } else { 1937 total_packets += irp->interval_packet_count; 1938 lost_packets += irp->interval_cnt_error; 1939 avg_jitter += irp->jitter; 1940 } 1941 } 1942 1943 /* next build string with sum of all streams */ 1944 if (test->num_streams > 1 || test->json_output) { 1945 sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */ 1946 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */ 1947 1948 unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A'); 1949 bandwidth = (double) bytes / (double) irp->interval_duration; 1950 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 1951 1952 start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time); 1953 end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time); 1954 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 1955 if (test->sender && test->sender_has_retransmits) { 1956 /* Interval sum, TCP with retransmits. */ 1957 if (test->json_output) 1958 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? */ 1959 else 1960 iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */ 1961 } else { 1962 /* Interval sum, TCP without retransmits. */ 1963 if (test->json_output) 1964 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)); 1965 else 1966 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:""); 1967 } 1968 } else { 1969 /* Interval sum, UDP. */ 1970 if (test->sender) { 1971 if (test->json_output) 1972 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)); 1973 else 1974 iprintf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:""); 1975 } else { 1976 avg_jitter /= test->num_streams; 1977 lost_percent = 100.0 * lost_packets / total_packets; 1978 if (test->json_output) 1979 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)); 1980 else 1981 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:""); 1982 } 1983 } 1984 } 1985 } 1986 1987 static void 1988 iperf_print_results(struct iperf_test *test) 1989 { 1990 1991 cJSON *json_summary_streams = NULL; 1992 cJSON *json_summary_stream = NULL; 1993 int total_retransmits = 0; 1994 int total_packets = 0, lost_packets = 0; 1995 char ubuf[UNIT_LEN]; 1996 char nbuf[UNIT_LEN]; 1997 struct stat sb; 1998 char sbuf[UNIT_LEN]; 1999 struct iperf_stream *sp = NULL; 2000 iperf_size_t bytes_sent, total_sent = 0; 2001 iperf_size_t bytes_received, total_received = 0; 2002 double start_time, end_time, avg_jitter = 0.0, lost_percent; 2003 double bandwidth; 2004 2005 /* print final summary for all intervals */ 2006 2007 if (test->json_output) { 2008 json_summary_streams = cJSON_CreateArray(); 2009 if (json_summary_streams == NULL) 2010 return; 2011 cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams); 2012 } else { 2013 iprintf(test, "%s", report_bw_separator); 2014 if (test->verbose) 2015 iprintf(test, "%s", report_summary); 2016 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2017 if (test->sender_has_retransmits) 2018 iprintf(test, "%s", report_bw_retrans_header); 2019 else 2020 iprintf(test, "%s", report_bw_header); 2021 } else 2022 iprintf(test, "%s", report_bw_udp_header); 2023 } 2024 2025 start_time = 0.; 2026 sp = SLIST_FIRST(&test->streams); 2027 end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); 2028 SLIST_FOREACH(sp, &test->streams, streams) { 2029 if (test->json_output) { 2030 json_summary_stream = cJSON_CreateObject(); 2031 if (json_summary_stream == NULL) 2032 return; 2033 cJSON_AddItemToArray(json_summary_streams, json_summary_stream); 2034 } 2035 2036 bytes_sent = sp->result->bytes_sent; 2037 bytes_received = sp->result->bytes_received; 2038 total_sent += bytes_sent; 2039 total_received += bytes_received; 2040 2041 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2042 if (test->sender_has_retransmits) { 2043 total_retransmits += sp->result->stream_retrans; 2044 } 2045 } else { 2046 total_packets += (sp->packet_count - sp->omitted_packet_count); 2047 lost_packets += sp->cnt_error; 2048 avg_jitter += sp->jitter; 2049 } 2050 2051 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A'); 2052 bandwidth = (double) bytes_sent / (double) end_time; 2053 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2054 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2055 if (test->sender_has_retransmits) { 2056 /* Summary, TCP with retransmits. */ 2057 if (test->json_output) 2058 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)); 2059 else 2060 iprintf(test, report_bw_retrans_format, sp->socket, start_time, end_time, ubuf, nbuf, sp->result->stream_retrans, report_sender); 2061 } else { 2062 /* Summary, TCP without retransmits. */ 2063 if (test->json_output) 2064 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)); 2065 else 2066 iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_sender); 2067 } 2068 } else { 2069 /* Summary, UDP. */ 2070 lost_percent = 100.0 * sp->cnt_error / (sp->packet_count - sp->omitted_packet_count); 2071 if (test->json_output) 2072 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)); 2073 else { 2074 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, ""); 2075 if (test->role == 'c') 2076 iprintf(test, report_datagrams, sp->socket, (sp->packet_count - sp->omitted_packet_count)); 2077 if (sp->outoforder_packets > 0) 2078 iprintf(test, report_sum_outoforder, start_time, end_time, sp->cnt_error); 2079 } 2080 } 2081 2082 if (sp->diskfile_fd >= 0) { 2083 if (fstat(sp->diskfile_fd, &sb) == 0) { 2084 int percent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 ); 2085 unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A'); 2086 if (test->json_output) 2087 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)); 2088 else 2089 iprintf(test, report_diskfile, ubuf, sbuf, percent, test->diskfile_name); 2090 } 2091 } 2092 2093 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A'); 2094 bandwidth = (double) bytes_received / (double) end_time; 2095 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2096 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2097 if (test->json_output) 2098 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)); 2099 else 2100 iprintf(test, report_bw_format, sp->socket, start_time, end_time, ubuf, nbuf, report_receiver); 2101 } 2102 } 2103 2104 if (test->num_streams > 1 || test->json_output) { 2105 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A'); 2106 bandwidth = (double) total_sent / (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->sender_has_retransmits) { 2110 /* Summary sum, TCP with retransmits. */ 2111 if (test->json_output) 2112 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)); 2113 else 2114 iprintf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, total_retransmits, report_sender); 2115 } else { 2116 /* Summary sum, TCP without retransmits. */ 2117 if (test->json_output) 2118 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)); 2119 else 2120 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_sender); 2121 } 2122 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A'); 2123 bandwidth = (double) total_received / (double) end_time; 2124 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2125 if (test->json_output) 2126 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)); 2127 else 2128 iprintf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, report_receiver); 2129 } else { 2130 /* Summary sum, UDP. */ 2131 avg_jitter /= test->num_streams; 2132 lost_percent = 100.0 * lost_packets / total_packets; 2133 if (test->json_output) 2134 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)); 2135 else 2136 iprintf(test, report_sum_bw_udp_format, start_time, end_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, total_packets, lost_percent, ""); 2137 } 2138 } 2139 2140 if (test->json_output) 2141 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])); 2142 else if (test->verbose) 2143 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]); 2144 } 2145 2146 /**************************************************************************/ 2147 2148 /** 2149 * iperf_reporter_callback -- handles the report printing 2150 * 2151 */ 2152 2153 void 2154 iperf_reporter_callback(struct iperf_test *test) 2155 { 2156 switch (test->state) { 2157 case TEST_RUNNING: 2158 case STREAM_RUNNING: 2159 /* print interval results for each stream */ 2160 iperf_print_intermediate(test); 2161 break; 2162 case DISPLAY_RESULTS: 2163 iperf_print_intermediate(test); 2164 iperf_print_results(test); 2165 break; 2166 } 2167 2168 } 2169 2170 /**************************************************************************/ 2171 static void 2172 print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams) 2173 { 2174 char ubuf[UNIT_LEN]; 2175 char nbuf[UNIT_LEN]; 2176 char cbuf[UNIT_LEN]; 2177 double st = 0., et = 0.; 2178 struct iperf_interval_results *irp = NULL; 2179 double bandwidth, lost_percent; 2180 2181 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */ 2182 if (irp == NULL) { 2183 iperf_err(test, "print_interval_results error: interval_results is NULL"); 2184 return; 2185 } 2186 if (!test->json_output) { 2187 /* First stream? */ 2188 if (sp == SLIST_FIRST(&test->streams)) { 2189 /* It it's the first interval, print the header; 2190 ** else if there's more than one stream, print the separator; 2191 ** else nothing. 2192 */ 2193 if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) { 2194 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2195 if (test->sender && test->sender_has_retransmits) 2196 iprintf(test, "%s", report_bw_retrans_cwnd_header); 2197 else 2198 iprintf(test, "%s", report_bw_header); 2199 } else { 2200 if (test->sender) 2201 iprintf(test, "%s", report_bw_udp_sender_header); 2202 else 2203 iprintf(test, "%s", report_bw_udp_header); 2204 } 2205 } else if (test->num_streams > 1) 2206 iprintf(test, "%s", report_bw_separator); 2207 } 2208 } 2209 2210 unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A'); 2211 bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration; 2212 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2213 2214 st = timeval_diff(&sp->result->start_time, &irp->interval_start_time); 2215 et = timeval_diff(&sp->result->start_time, &irp->interval_end_time); 2216 2217 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2218 if (test->sender && test->sender_has_retransmits) { 2219 /* Interval, TCP with retransmits. */ 2220 if (test->json_output) 2221 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)); 2222 else 2223 unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A'); 2224 iprintf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:""); 2225 } else { 2226 /* Interval, TCP without retransmits. */ 2227 if (test->json_output) 2228 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)); 2229 else 2230 iprintf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:""); 2231 } 2232 } else { 2233 /* Interval, UDP. */ 2234 if (test->sender) { 2235 if (test->json_output) 2236 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)); 2237 else 2238 iprintf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:""); 2239 } else { 2240 lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count; 2241 if (test->json_output) 2242 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)); 2243 else 2244 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:""); 2245 } 2246 } 2247 } 2248 2249 /**************************************************************************/ 2250 void 2251 iperf_free_stream(struct iperf_stream *sp) 2252 { 2253 struct iperf_interval_results *irp, *nirp; 2254 2255 /* XXX: need to free interval list too! */ 2256 munmap(sp->buffer, sp->test->settings->blksize); 2257 close(sp->buffer_fd); 2258 if (sp->diskfile_fd >= 0) 2259 close(sp->diskfile_fd); 2260 for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != TAILQ_END(sp->result->interval_results); irp = nirp) { 2261 nirp = TAILQ_NEXT(irp, irlistentries); 2262 free(irp); 2263 } 2264 free(sp->result); 2265 if (sp->send_timer != NULL) 2266 tmr_cancel(sp->send_timer); 2267 free(sp); 2268 } 2269 2270 /**************************************************************************/ 2271 struct iperf_stream * 2272 iperf_new_stream(struct iperf_test *test, int s) 2273 { 2274 int i; 2275 struct iperf_stream *sp; 2276 char template[] = "/tmp/iperf3.XXXXXX"; 2277 2278 h_errno = 0; 2279 2280 sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream)); 2281 if (!sp) { 2282 i_errno = IECREATESTREAM; 2283 return NULL; 2284 } 2285 2286 memset(sp, 0, sizeof(struct iperf_stream)); 2287 2288 sp->test = test; 2289 sp->settings = test->settings; 2290 sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result)); 2291 if (!sp->result) { 2292 free(sp); 2293 i_errno = IECREATESTREAM; 2294 return NULL; 2295 } 2296 2297 memset(sp->result, 0, sizeof(struct iperf_stream_result)); 2298 TAILQ_INIT(&sp->result->interval_results); 2299 2300 /* Create and randomize the buffer */ 2301 sp->buffer_fd = mkstemp(template); 2302 if (sp->buffer_fd == -1) { 2303 i_errno = IECREATESTREAM; 2304 free(sp->result); 2305 free(sp); 2306 return NULL; 2307 } 2308 if (unlink(template) < 0) { 2309 i_errno = IECREATESTREAM; 2310 free(sp->result); 2311 free(sp); 2312 return NULL; 2313 } 2314 if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) { 2315 i_errno = IECREATESTREAM; 2316 free(sp->result); 2317 free(sp); 2318 return NULL; 2319 } 2320 sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0); 2321 if (sp->buffer == MAP_FAILED) { 2322 i_errno = IECREATESTREAM; 2323 free(sp->result); 2324 free(sp); 2325 return NULL; 2326 } 2327 srandom(time(NULL)); 2328 for (i = 0; i < test->settings->blksize; ++i) 2329 sp->buffer[i] = random(); 2330 2331 /* Set socket */ 2332 sp->socket = s; 2333 2334 sp->snd = test->protocol->send; 2335 sp->rcv = test->protocol->recv; 2336 2337 if (test->diskfile_name != (char*) 0) { 2338 sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC)); 2339 if (sp->diskfile_fd == -1) { 2340 i_errno = IEFILE; 2341 munmap(sp->buffer, sp->test->settings->blksize); 2342 free(sp->result); 2343 free(sp); 2344 return NULL; 2345 } 2346 sp->snd2 = sp->snd; 2347 sp->snd = diskfile_send; 2348 sp->rcv2 = sp->rcv; 2349 sp->rcv = diskfile_recv; 2350 } else 2351 sp->diskfile_fd = -1; 2352 2353 /* Initialize stream */ 2354 if (iperf_init_stream(sp, test) < 0) { 2355 close(sp->buffer_fd); 2356 munmap(sp->buffer, sp->test->settings->blksize); 2357 free(sp->result); 2358 free(sp); 2359 return NULL; 2360 } 2361 iperf_add_stream(test, sp); 2362 2363 return sp; 2364 } 2365 2366 /**************************************************************************/ 2367 int 2368 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test) 2369 { 2370 socklen_t len; 2371 int opt; 2372 2373 len = sizeof(struct sockaddr_storage); 2374 if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) { 2375 i_errno = IEINITSTREAM; 2376 return -1; 2377 } 2378 len = sizeof(struct sockaddr_storage); 2379 if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) { 2380 i_errno = IEINITSTREAM; 2381 return -1; 2382 } 2383 2384 /* Set IP TOS */ 2385 if ((opt = test->settings->tos)) { 2386 if (getsockdomain(sp->socket) == AF_INET6) { 2387 #ifdef IPV6_TCLASS 2388 if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) { 2389 i_errno = IESETCOS; 2390 return -1; 2391 } 2392 #else 2393 i_errno = IESETCOS; 2394 return -1; 2395 #endif 2396 } else { 2397 if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) { 2398 i_errno = IESETTOS; 2399 return -1; 2400 } 2401 } 2402 } 2403 2404 return 0; 2405 } 2406 2407 /**************************************************************************/ 2408 void 2409 iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp) 2410 { 2411 int i; 2412 struct iperf_stream *n, *prev; 2413 2414 if (SLIST_EMPTY(&test->streams)) { 2415 SLIST_INSERT_HEAD(&test->streams, sp, streams); 2416 sp->id = 1; 2417 } else { 2418 // for (n = test->streams, i = 2; n->next; n = n->next, ++i); 2419 i = 2; 2420 SLIST_FOREACH(n, &test->streams, streams) { 2421 prev = n; 2422 ++i; 2423 } 2424 SLIST_INSERT_AFTER(prev, sp, streams); 2425 sp->id = i; 2426 } 2427 } 2428 2429 /* This pair of routines gets inserted into the snd/rcv function pointers 2430 ** when there's a -F flag. They handle the file stuff and call the real 2431 ** snd/rcv functions, which have been saved in snd2/rcv2. 2432 ** 2433 ** The advantage of doing it this way is that in the much more common 2434 ** case of no -F flag, there is zero extra overhead. 2435 */ 2436 2437 static int 2438 diskfile_send(struct iperf_stream *sp) 2439 { 2440 int r; 2441 2442 r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize); 2443 if (r == 0) 2444 sp->test->done = 1; 2445 else 2446 r = sp->snd2(sp); 2447 return r; 2448 } 2449 2450 static int 2451 diskfile_recv(struct iperf_stream *sp) 2452 { 2453 int r; 2454 2455 r = sp->rcv2(sp); 2456 if (r > 0) { 2457 (void) write(sp->diskfile_fd, sp->buffer, r); 2458 (void) fsync(sp->diskfile_fd); 2459 } 2460 return r; 2461 } 2462 2463 2464 void 2465 iperf_catch_sigend(void (*handler)(int)) 2466 { 2467 signal(SIGINT, handler); 2468 signal(SIGTERM, handler); 2469 signal(SIGHUP, handler); 2470 } 2471 2472 void 2473 iperf_got_sigend(struct iperf_test *test) 2474 { 2475 /* 2476 * If we're the client, or if we're a server and running a test, 2477 * then dump out the accumulated stats so far. 2478 */ 2479 if (test->role == 'c' || 2480 (test->role == 's' && test->state == TEST_RUNNING)) { 2481 2482 test->done = 1; 2483 cpu_util(test->cpu_util); 2484 test->stats_callback(test); 2485 test->state = DISPLAY_RESULTS; /* change local state only */ 2486 if (test->on_test_finish) 2487 test->on_test_finish(test); 2488 test->reporter_callback(test); 2489 } 2490 2491 if (test->ctrl_sck >= 0) { 2492 test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE; 2493 (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp); 2494 } 2495 i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM; 2496 iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno)); 2497 } 2498 2499 /* Try to write a PID file if requested, return -1 on an error. */ 2500 int 2501 iperf_create_pidfile(struct iperf_test *test) 2502 { 2503 if (test->pidfile) { 2504 int fd; 2505 char buf[8]; 2506 fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); 2507 if (fd < 0) { 2508 return -1; 2509 } 2510 snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */ 2511 if (write(fd, buf, strlen(buf) + 1) < 0) { 2512 return -1; 2513 } 2514 if (close(fd) < 0) { 2515 return -1; 2516 }; 2517 } 2518 return 0; 2519 } 2520 2521 /* Get rid of a PID file, return -1 on error. */ 2522 int 2523 iperf_delete_pidfile(struct iperf_test *test) 2524 { 2525 if (test->pidfile) { 2526 if (unlink(test->pidfile) < 0) { 2527 return -1; 2528 } 2529 } 2530 return 0; 2531 } 2532 2533 int 2534 iperf_json_start(struct iperf_test *test) 2535 { 2536 test->json_top = cJSON_CreateObject(); 2537 if (test->json_top == NULL) 2538 return -1; 2539 if (test->title) 2540 cJSON_AddStringToObject(test->json_top, "title", test->title); 2541 test->json_start = cJSON_CreateObject(); 2542 if (test->json_start == NULL) 2543 return -1; 2544 cJSON_AddItemToObject(test->json_top, "start", test->json_start); 2545 test->json_intervals = cJSON_CreateArray(); 2546 if (test->json_intervals == NULL) 2547 return -1; 2548 cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals); 2549 test->json_end = cJSON_CreateObject(); 2550 if (test->json_end == NULL) 2551 return -1; 2552 cJSON_AddItemToObject(test->json_top, "end", test->json_end); 2553 return 0; 2554 } 2555 2556 int 2557 iperf_json_finish(struct iperf_test *test) 2558 { 2559 test->json_output_string = cJSON_Print(test->json_top); 2560 if (test->json_output_string == NULL) 2561 return -1; 2562 fprintf(test->outfile, "%s\n", test->json_output_string); 2563 iflush(test); 2564 cJSON_Delete(test->json_top); 2565 test->json_top = test->json_start = test->json_intervals = test->json_end = NULL; 2566 return 0; 2567 } 2568 2569 2570 /* CPU affinity stuff - Linux and FreeBSD only. */ 2571 2572 int 2573 iperf_setaffinity(struct iperf_test *test, int affinity) 2574 { 2575 #if defined(HAVE_SCHED_SETAFFINITY) 2576 cpu_set_t cpu_set; 2577 2578 CPU_ZERO(&cpu_set); 2579 CPU_SET(affinity, &cpu_set); 2580 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 2581 i_errno = IEAFFINITY; 2582 return -1; 2583 } 2584 return 0; 2585 #elif defined(HAVE_CPUSET_SETAFFINITY) 2586 cpuset_t cpumask; 2587 2588 if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 2589 sizeof(cpuset_t), &test->cpumask) != 0) { 2590 i_errno = IEAFFINITY; 2591 return -1; 2592 } 2593 2594 CPU_ZERO(&cpumask); 2595 CPU_SET(affinity, &cpumask); 2596 2597 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 2598 sizeof(cpuset_t), &cpumask) != 0) { 2599 i_errno = IEAFFINITY; 2600 return -1; 2601 } 2602 return 0; 2603 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 2604 i_errno = IEAFFINITY; 2605 return -1; 2606 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 2607 } 2608 2609 int 2610 iperf_clearaffinity(struct iperf_test *test) 2611 { 2612 #if defined(HAVE_SCHED_SETAFFINITY) 2613 cpu_set_t cpu_set; 2614 int i; 2615 2616 CPU_ZERO(&cpu_set); 2617 for (i = 0; i < CPU_SETSIZE; ++i) 2618 CPU_SET(i, &cpu_set); 2619 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 2620 i_errno = IEAFFINITY; 2621 return -1; 2622 } 2623 return 0; 2624 #elif defined(HAVE_CPUSET_SETAFFINITY) 2625 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 2626 sizeof(cpuset_t), &test->cpumask) != 0) { 2627 i_errno = IEAFFINITY; 2628 return -1; 2629 } 2630 return 0; 2631 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 2632 i_errno = IEAFFINITY; 2633 return -1; 2634 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 2635 } 2636 2637 int 2638 iprintf(struct iperf_test *test, const char* format, ...) 2639 { 2640 va_list argp; 2641 int r; 2642 2643 if (test->title) 2644 fprintf(test->outfile, "%s: ", test->title); 2645 va_start(argp, format); 2646 r = vfprintf(test->outfile, format, argp); 2647 va_end(argp); 2648 return r; 2649 } 2650 2651 int 2652 iflush(struct iperf_test *test) 2653 { 2654 return fflush(test->outfile); 2655 } 2656