1 /* 2 * iperf, Copyright (c) 2014-2017, The Regents of the University of 3 * California, through Lawrence Berkeley National Laboratory (subject 4 * to receipt of any required approvals from the U.S. Dept. of 5 * Energy). All rights reserved. 6 * 7 * If you have questions about your rights to use or distribute this 8 * software, please contact Berkeley Lab's Technology Transfer 9 * Department at [email protected]. 10 * 11 * NOTICE. This software is owned by the U.S. Department of Energy. 12 * As such, the U.S. Government has been granted for itself and others 13 * acting on its behalf a paid-up, nonexclusive, irrevocable, 14 * worldwide license in the Software to reproduce, prepare derivative 15 * works, and perform publicly and display publicly. Beginning five 16 * (5) years after the date permission to assert copyright is obtained 17 * from the U.S. Department of Energy, and subject to any subsequent 18 * five (5) year renewals, the U.S. Government is granted for itself 19 * and others acting on its behalf a paid-up, nonexclusive, 20 * irrevocable, worldwide license in the Software to reproduce, 21 * prepare derivative works, distribute copies to the public, perform 22 * publicly and display publicly, and to permit others to do so. 23 * 24 * This code is distributed under a BSD style license, see the LICENSE file 25 * for complete information. 26 */ 27 #define _GNU_SOURCE 28 #define __USE_GNU 29 30 #include "iperf_config.h" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <getopt.h> 36 #include <errno.h> 37 #include <signal.h> 38 #include <unistd.h> 39 #include <assert.h> 40 #include <fcntl.h> 41 #include <sys/socket.h> 42 #include <sys/types.h> 43 #include <netinet/in.h> 44 #include <arpa/inet.h> 45 #include <netdb.h> 46 #include <pthread.h> 47 #ifdef HAVE_STDINT_H 48 #include <stdint.h> 49 #endif 50 #include <netinet/tcp.h> 51 #include <sys/time.h> 52 #include <sys/resource.h> 53 #include <sys/mman.h> 54 #include <sys/stat.h> 55 #include <sched.h> 56 #include <setjmp.h> 57 #include <stdarg.h> 58 59 #if defined(HAVE_CPUSET_SETAFFINITY) 60 #include <sys/param.h> 61 #include <sys/cpuset.h> 62 #endif /* HAVE_CPUSET_SETAFFINITY */ 63 64 #include "net.h" 65 #include "iperf.h" 66 #include "iperf_api.h" 67 #include "iperf_udp.h" 68 #include "iperf_tcp.h" 69 #if defined(HAVE_SCTP) 70 #include "iperf_sctp.h" 71 #endif /* HAVE_SCTP */ 72 #include "timer.h" 73 74 #include "cjson.h" 75 #include "units.h" 76 #include "tcp_window_size.h" 77 #include "iperf_util.h" 78 #include "iperf_locale.h" 79 #include "version.h" 80 #if defined(HAVE_SSL) 81 #include "iperf_auth.h" 82 #endif /* HAVE_SSL */ 83 84 /* Forwards. */ 85 static int send_parameters(struct iperf_test *test); 86 static int get_parameters(struct iperf_test *test); 87 static int send_results(struct iperf_test *test); 88 static int get_results(struct iperf_test *test); 89 static int diskfile_send(struct iperf_stream *sp); 90 static int diskfile_recv(struct iperf_stream *sp); 91 static int JSON_write(int fd, cJSON *json); 92 static void print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams); 93 static cJSON *JSON_read(int fd); 94 95 96 /*************************** Print usage functions ****************************/ 97 98 void 99 usage() 100 { 101 fputs(usage_shortstr, stderr); 102 } 103 104 105 void 106 usage_long(FILE *f) 107 { 108 fprintf(f, usage_longstr, UDP_RATE / (1024*1024), DURATION, DEFAULT_TCP_BLKSIZE / 1024, DEFAULT_UDP_BLKSIZE / 1024); 109 } 110 111 112 void warning(char *str) 113 { 114 fprintf(stderr, "warning: %s\n", str); 115 } 116 117 118 /************** Getter routines for some fields inside iperf_test *************/ 119 120 int 121 iperf_get_verbose(struct iperf_test *ipt) 122 { 123 return ipt->verbose; 124 } 125 126 int 127 iperf_get_control_socket(struct iperf_test *ipt) 128 { 129 return ipt->ctrl_sck; 130 } 131 132 int 133 iperf_get_control_socket_mss(struct iperf_test *ipt) 134 { 135 return ipt->ctrl_sck_mss; 136 } 137 138 int 139 iperf_get_test_omit(struct iperf_test *ipt) 140 { 141 return ipt->omit; 142 } 143 144 int 145 iperf_get_test_duration(struct iperf_test *ipt) 146 { 147 return ipt->duration; 148 } 149 150 uint64_t 151 iperf_get_test_rate(struct iperf_test *ipt) 152 { 153 return ipt->settings->rate; 154 } 155 156 uint64_t 157 iperf_get_test_fqrate(struct iperf_test *ipt) 158 { 159 return ipt->settings->fqrate; 160 } 161 162 int 163 iperf_get_test_burst(struct iperf_test *ipt) 164 { 165 return ipt->settings->burst; 166 } 167 168 char 169 iperf_get_test_role(struct iperf_test *ipt) 170 { 171 return ipt->role; 172 } 173 174 int 175 iperf_get_test_reverse(struct iperf_test *ipt) 176 { 177 return ipt->reverse; 178 } 179 180 int 181 iperf_get_test_blksize(struct iperf_test *ipt) 182 { 183 return ipt->settings->blksize; 184 } 185 186 FILE * 187 iperf_get_test_outfile (struct iperf_test *ipt) 188 { 189 return ipt->outfile; 190 } 191 192 int 193 iperf_get_test_socket_bufsize(struct iperf_test *ipt) 194 { 195 return ipt->settings->socket_bufsize; 196 } 197 198 double 199 iperf_get_test_reporter_interval(struct iperf_test *ipt) 200 { 201 return ipt->reporter_interval; 202 } 203 204 double 205 iperf_get_test_stats_interval(struct iperf_test *ipt) 206 { 207 return ipt->stats_interval; 208 } 209 210 int 211 iperf_get_test_num_streams(struct iperf_test *ipt) 212 { 213 return ipt->num_streams; 214 } 215 216 int 217 iperf_get_test_server_port(struct iperf_test *ipt) 218 { 219 return ipt->server_port; 220 } 221 222 char* 223 iperf_get_test_server_hostname(struct iperf_test *ipt) 224 { 225 return ipt->server_hostname; 226 } 227 228 char* 229 iperf_get_test_template(struct iperf_test *ipt) 230 { 231 return ipt->tmp_template; 232 } 233 234 int 235 iperf_get_test_protocol_id(struct iperf_test *ipt) 236 { 237 return ipt->protocol->id; 238 } 239 240 int 241 iperf_get_test_json_output(struct iperf_test *ipt) 242 { 243 return ipt->json_output; 244 } 245 246 char * 247 iperf_get_test_json_output_string(struct iperf_test *ipt) 248 { 249 return ipt->json_output_string; 250 } 251 252 int 253 iperf_get_test_zerocopy(struct iperf_test *ipt) 254 { 255 return ipt->zerocopy; 256 } 257 258 int 259 iperf_get_test_get_server_output(struct iperf_test *ipt) 260 { 261 return ipt->get_server_output; 262 } 263 264 char 265 iperf_get_test_unit_format(struct iperf_test *ipt) 266 { 267 return ipt->settings->unit_format; 268 } 269 270 char * 271 iperf_get_test_bind_address(struct iperf_test *ipt) 272 { 273 return ipt->bind_address; 274 } 275 276 int 277 iperf_get_test_udp_counters_64bit(struct iperf_test *ipt) 278 { 279 return ipt->udp_counters_64bit; 280 } 281 282 int 283 iperf_get_test_one_off(struct iperf_test *ipt) 284 { 285 return ipt->one_off; 286 } 287 288 /************** Setter routines for some fields inside iperf_test *************/ 289 290 void 291 iperf_set_verbose(struct iperf_test *ipt, int verbose) 292 { 293 ipt->verbose = verbose; 294 } 295 296 void 297 iperf_set_control_socket(struct iperf_test *ipt, int ctrl_sck) 298 { 299 ipt->ctrl_sck = ctrl_sck; 300 } 301 302 void 303 iperf_set_test_omit(struct iperf_test *ipt, int omit) 304 { 305 ipt->omit = omit; 306 } 307 308 void 309 iperf_set_test_duration(struct iperf_test *ipt, int duration) 310 { 311 ipt->duration = duration; 312 } 313 314 void 315 iperf_set_test_reporter_interval(struct iperf_test *ipt, double reporter_interval) 316 { 317 ipt->reporter_interval = reporter_interval; 318 } 319 320 void 321 iperf_set_test_stats_interval(struct iperf_test *ipt, double stats_interval) 322 { 323 ipt->stats_interval = stats_interval; 324 } 325 326 void 327 iperf_set_test_state(struct iperf_test *ipt, signed char state) 328 { 329 ipt->state = state; 330 } 331 332 void 333 iperf_set_test_blksize(struct iperf_test *ipt, int blksize) 334 { 335 ipt->settings->blksize = blksize; 336 } 337 338 void 339 iperf_set_test_rate(struct iperf_test *ipt, uint64_t rate) 340 { 341 ipt->settings->rate = rate; 342 } 343 344 void 345 iperf_set_test_fqrate(struct iperf_test *ipt, uint64_t fqrate) 346 { 347 ipt->settings->fqrate = fqrate; 348 } 349 350 void 351 iperf_set_test_burst(struct iperf_test *ipt, int burst) 352 { 353 ipt->settings->burst = burst; 354 } 355 356 void 357 iperf_set_test_server_port(struct iperf_test *ipt, int srv_port) 358 { 359 ipt->server_port = srv_port; 360 } 361 362 void 363 iperf_set_test_socket_bufsize(struct iperf_test *ipt, int socket_bufsize) 364 { 365 ipt->settings->socket_bufsize = socket_bufsize; 366 } 367 368 void 369 iperf_set_test_num_streams(struct iperf_test *ipt, int num_streams) 370 { 371 ipt->num_streams = num_streams; 372 } 373 374 static void 375 check_sender_has_retransmits(struct iperf_test *ipt) 376 { 377 if (ipt->sender && ipt->protocol->id == Ptcp && has_tcpinfo_retransmits()) 378 ipt->sender_has_retransmits = 1; 379 else 380 ipt->sender_has_retransmits = 0; 381 } 382 383 void 384 iperf_set_test_role(struct iperf_test *ipt, char role) 385 { 386 ipt->role = role; 387 if (role == 'c') 388 ipt->sender = 1; 389 else if (role == 's') 390 ipt->sender = 0; 391 if (ipt->reverse) 392 ipt->sender = ! ipt->sender; 393 check_sender_has_retransmits(ipt); 394 } 395 396 void 397 iperf_set_test_server_hostname(struct iperf_test *ipt, char *server_hostname) 398 { 399 ipt->server_hostname = strdup(server_hostname); 400 } 401 402 void 403 iperf_set_test_template(struct iperf_test *ipt, char *tmp_template) 404 { 405 ipt->tmp_template = strdup(tmp_template); 406 } 407 408 void 409 iperf_set_test_reverse(struct iperf_test *ipt, int reverse) 410 { 411 ipt->reverse = reverse; 412 if (ipt->reverse) 413 ipt->sender = ! ipt->sender; 414 check_sender_has_retransmits(ipt); 415 } 416 417 void 418 iperf_set_test_json_output(struct iperf_test *ipt, int json_output) 419 { 420 ipt->json_output = json_output; 421 } 422 423 int 424 iperf_has_zerocopy( void ) 425 { 426 return has_sendfile(); 427 } 428 429 void 430 iperf_set_test_zerocopy(struct iperf_test *ipt, int zerocopy) 431 { 432 ipt->zerocopy = (zerocopy && has_sendfile()); 433 } 434 435 void 436 iperf_set_test_get_server_output(struct iperf_test *ipt, int get_server_output) 437 { 438 ipt->get_server_output = get_server_output; 439 } 440 441 void 442 iperf_set_test_unit_format(struct iperf_test *ipt, char unit_format) 443 { 444 ipt->settings->unit_format = unit_format; 445 } 446 447 void 448 iperf_set_test_bind_address(struct iperf_test *ipt, char *bnd_address) 449 { 450 ipt->bind_address = strdup(bnd_address); 451 } 452 453 void 454 iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit) 455 { 456 ipt->udp_counters_64bit = udp_counters_64bit; 457 } 458 459 void 460 iperf_set_test_one_off(struct iperf_test *ipt, int one_off) 461 { 462 ipt->one_off = one_off; 463 } 464 465 /********************** Get/set test protocol structure ***********************/ 466 467 struct protocol * 468 get_protocol(struct iperf_test *test, int prot_id) 469 { 470 struct protocol *prot; 471 472 SLIST_FOREACH(prot, &test->protocols, protocols) { 473 if (prot->id == prot_id) 474 break; 475 } 476 477 if (prot == NULL) 478 i_errno = IEPROTOCOL; 479 480 return prot; 481 } 482 483 int 484 set_protocol(struct iperf_test *test, int prot_id) 485 { 486 struct protocol *prot = NULL; 487 488 SLIST_FOREACH(prot, &test->protocols, protocols) { 489 if (prot->id == prot_id) { 490 test->protocol = prot; 491 check_sender_has_retransmits(test); 492 return 0; 493 } 494 } 495 496 i_errno = IEPROTOCOL; 497 return -1; 498 } 499 500 501 /************************** Iperf callback functions **************************/ 502 503 void 504 iperf_on_new_stream(struct iperf_stream *sp) 505 { 506 connect_msg(sp); 507 } 508 509 void 510 iperf_on_test_start(struct iperf_test *test) 511 { 512 if (test->json_output) { 513 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 reverse: %d tos: %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, test->reverse?(int64_t)1:(int64_t)0, test->settings->tos)); 514 } else { 515 if (test->verbose) { 516 if (test->settings->bytes) 517 iperf_printf(test, test_start_bytes, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->bytes, test->settings->tos); 518 else if (test->settings->blocks) 519 iperf_printf(test, test_start_blocks, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->settings->blocks, test->settings->tos); 520 else 521 iperf_printf(test, test_start_time, test->protocol->name, test->num_streams, test->settings->blksize, test->omit, test->duration, test->settings->tos); 522 } 523 } 524 } 525 526 /* This converts an IPv6 string address from IPv4-mapped format into regular 527 ** old IPv4 format, which is easier on the eyes of network veterans. 528 ** 529 ** If the v6 address is not v4-mapped it is left alone. 530 */ 531 static void 532 mapped_v4_to_regular_v4(char *str) 533 { 534 char *prefix = "::ffff:"; 535 int prefix_len; 536 537 prefix_len = strlen(prefix); 538 if (strncmp(str, prefix, prefix_len) == 0) { 539 int str_len = strlen(str); 540 memmove(str, str + prefix_len, str_len - prefix_len + 1); 541 } 542 } 543 544 void 545 iperf_on_connect(struct iperf_test *test) 546 { 547 time_t now_secs; 548 const char* rfc1123_fmt = "%a, %d %b %Y %H:%M:%S GMT"; 549 char now_str[100]; 550 char ipr[INET6_ADDRSTRLEN]; 551 int port; 552 struct sockaddr_storage sa; 553 struct sockaddr_in *sa_inP; 554 struct sockaddr_in6 *sa_in6P; 555 socklen_t len; 556 557 now_secs = time((time_t*) 0); 558 (void) strftime(now_str, sizeof(now_str), rfc1123_fmt, gmtime(&now_secs)); 559 if (test->json_output) 560 cJSON_AddItemToObject(test->json_start, "timestamp", iperf_json_printf("time: %s timesecs: %d", now_str, (int64_t) now_secs)); 561 else if (test->verbose) 562 iperf_printf(test, report_time, now_str); 563 564 if (test->role == 'c') { 565 if (test->json_output) 566 cJSON_AddItemToObject(test->json_start, "connecting_to", iperf_json_printf("host: %s port: %d", test->server_hostname, (int64_t) test->server_port)); 567 else { 568 iperf_printf(test, report_connecting, test->server_hostname, test->server_port); 569 if (test->reverse) 570 iperf_printf(test, report_reverse, test->server_hostname); 571 } 572 } else { 573 len = sizeof(sa); 574 getpeername(test->ctrl_sck, (struct sockaddr *) &sa, &len); 575 if (getsockdomain(test->ctrl_sck) == AF_INET) { 576 sa_inP = (struct sockaddr_in *) &sa; 577 inet_ntop(AF_INET, &sa_inP->sin_addr, ipr, sizeof(ipr)); 578 port = ntohs(sa_inP->sin_port); 579 } else { 580 sa_in6P = (struct sockaddr_in6 *) &sa; 581 inet_ntop(AF_INET6, &sa_in6P->sin6_addr, ipr, sizeof(ipr)); 582 port = ntohs(sa_in6P->sin6_port); 583 } 584 mapped_v4_to_regular_v4(ipr); 585 if (test->json_output) 586 cJSON_AddItemToObject(test->json_start, "accepted_connection", iperf_json_printf("host: %s port: %d", ipr, (int64_t) port)); 587 else 588 iperf_printf(test, report_accepted, ipr, port); 589 } 590 if (test->json_output) { 591 cJSON_AddStringToObject(test->json_start, "cookie", test->cookie); 592 if (test->protocol->id == SOCK_STREAM) { 593 if (test->settings->mss) 594 cJSON_AddNumberToObject(test->json_start, "tcp_mss", test->settings->mss); 595 else { 596 cJSON_AddNumberToObject(test->json_start, "tcp_mss_default", test->ctrl_sck_mss); 597 } 598 } 599 } else if (test->verbose) { 600 iperf_printf(test, report_cookie, test->cookie); 601 if (test->protocol->id == SOCK_STREAM) { 602 if (test->settings->mss) 603 iperf_printf(test, " TCP MSS: %d\n", test->settings->mss); 604 else { 605 iperf_printf(test, " TCP MSS: %d (default)\n", test->ctrl_sck_mss); 606 } 607 } 608 609 } 610 } 611 612 void 613 iperf_on_test_finish(struct iperf_test *test) 614 { 615 } 616 617 618 /******************************************************************************/ 619 620 int 621 iperf_parse_arguments(struct iperf_test *test, int argc, char **argv) 622 { 623 static struct option longopts[] = 624 { 625 {"port", required_argument, NULL, 'p'}, 626 {"format", required_argument, NULL, 'f'}, 627 {"interval", required_argument, NULL, 'i'}, 628 {"daemon", no_argument, NULL, 'D'}, 629 {"one-off", no_argument, NULL, '1'}, 630 {"verbose", no_argument, NULL, 'V'}, 631 {"json", no_argument, NULL, 'J'}, 632 {"version", no_argument, NULL, 'v'}, 633 {"server", no_argument, NULL, 's'}, 634 {"client", required_argument, NULL, 'c'}, 635 {"udp", no_argument, NULL, 'u'}, 636 {"bitrate", required_argument, NULL, 'b'}, 637 {"bandwidth", required_argument, NULL, 'b'}, 638 {"time", required_argument, NULL, 't'}, 639 {"bytes", required_argument, NULL, 'n'}, 640 {"blockcount", required_argument, NULL, 'k'}, 641 {"length", required_argument, NULL, 'l'}, 642 {"parallel", required_argument, NULL, 'P'}, 643 {"reverse", no_argument, NULL, 'R'}, 644 {"window", required_argument, NULL, 'w'}, 645 {"bind", required_argument, NULL, 'B'}, 646 {"cport", required_argument, NULL, OPT_CLIENT_PORT}, 647 {"set-mss", required_argument, NULL, 'M'}, 648 {"no-delay", no_argument, NULL, 'N'}, 649 {"version4", no_argument, NULL, '4'}, 650 {"version6", no_argument, NULL, '6'}, 651 {"tos", required_argument, NULL, 'S'}, 652 {"dscp", required_argument, NULL, OPT_DSCP}, 653 #if defined(HAVE_FLOWLABEL) 654 {"flowlabel", required_argument, NULL, 'L'}, 655 #endif /* HAVE_FLOWLABEL */ 656 {"zerocopy", no_argument, NULL, 'Z'}, 657 {"omit", required_argument, NULL, 'O'}, 658 {"file", required_argument, NULL, 'F'}, 659 #if defined(HAVE_CPU_AFFINITY) 660 {"affinity", required_argument, NULL, 'A'}, 661 #endif /* HAVE_CPU_AFFINITY */ 662 {"title", required_argument, NULL, 'T'}, 663 #if defined(HAVE_TCP_CONGESTION) 664 {"congestion", required_argument, NULL, 'C'}, 665 {"linux-congestion", required_argument, NULL, 'C'}, 666 #endif /* HAVE_TCP_CONGESTION */ 667 #if defined(HAVE_SCTP) 668 {"sctp", no_argument, NULL, OPT_SCTP}, 669 {"nstreams", required_argument, NULL, OPT_NUMSTREAMS}, 670 {"xbind", required_argument, NULL, 'X'}, 671 #endif 672 {"pidfile", required_argument, NULL, 'I'}, 673 {"logfile", required_argument, NULL, OPT_LOGFILE}, 674 {"forceflush", no_argument, NULL, OPT_FORCEFLUSH}, 675 {"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT}, 676 {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT}, 677 {"no-fq-socket-pacing", no_argument, NULL, OPT_NO_FQ_SOCKET_PACING}, 678 #if defined(HAVE_SSL) 679 {"username", required_argument, NULL, OPT_CLIENT_USERNAME}, 680 {"rsa-public-key-path", required_argument, NULL, OPT_CLIENT_RSA_PUBLIC_KEY}, 681 {"rsa-private-key-path", required_argument, NULL, OPT_SERVER_RSA_PRIVATE_KEY}, 682 {"authorized-users-path", required_argument, NULL, OPT_SERVER_AUTHORIZED_USERS}, 683 #endif /* HAVE_SSL */ 684 {"fq-rate", required_argument, NULL, OPT_FQ_RATE}, 685 {"pacing-timer", required_argument, NULL, OPT_PACING_TIMER}, 686 {"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT}, 687 {"debug", no_argument, NULL, 'd'}, 688 {"help", no_argument, NULL, 'h'}, 689 {NULL, 0, NULL, 0} 690 }; 691 int flag; 692 int blksize; 693 int server_flag, client_flag, rate_flag, duration_flag; 694 char *endptr; 695 #if defined(HAVE_CPU_AFFINITY) 696 char* comma; 697 #endif /* HAVE_CPU_AFFINITY */ 698 char* slash; 699 struct xbind_entry *xbe; 700 double farg; 701 702 blksize = 0; 703 server_flag = client_flag = rate_flag = duration_flag = 0; 704 #if defined(HAVE_SSL) 705 char *client_username = NULL, *client_rsa_public_key = NULL; 706 #endif /* HAVE_SSL */ 707 708 while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) { 709 switch (flag) { 710 case 'p': 711 test->server_port = atoi(optarg); 712 break; 713 case 'f': 714 if (!optarg) { 715 i_errno = IEBADFORMAT; 716 return -1; 717 } 718 test->settings->unit_format = *optarg; 719 if (test->settings->unit_format == 'k' || 720 test->settings->unit_format == 'K' || 721 test->settings->unit_format == 'm' || 722 test->settings->unit_format == 'M' || 723 test->settings->unit_format == 'g' || 724 test->settings->unit_format == 'G' || 725 test->settings->unit_format == 't' || 726 test->settings->unit_format == 'T') { 727 break; 728 } 729 else { 730 i_errno = IEBADFORMAT; 731 return -1; 732 } 733 break; 734 case 'i': 735 /* XXX: could potentially want separate stat collection and reporting intervals, 736 but just set them to be the same for now */ 737 test->stats_interval = test->reporter_interval = atof(optarg); 738 if ((test->stats_interval < MIN_INTERVAL || test->stats_interval > MAX_INTERVAL) && test->stats_interval != 0) { 739 i_errno = IEINTERVAL; 740 return -1; 741 } 742 break; 743 case 'D': 744 test->daemon = 1; 745 server_flag = 1; 746 break; 747 case '1': 748 test->one_off = 1; 749 server_flag = 1; 750 break; 751 case 'V': 752 test->verbose = 1; 753 break; 754 case 'J': 755 test->json_output = 1; 756 break; 757 case 'v': 758 printf("%s (cJSON %s)\n%s\n%s\n", version, cJSON_Version(), get_system_info(), 759 get_optional_features()); 760 exit(0); 761 case 's': 762 if (test->role == 'c') { 763 i_errno = IESERVCLIENT; 764 return -1; 765 } 766 iperf_set_test_role(test, 's'); 767 break; 768 case 'c': 769 if (test->role == 's') { 770 i_errno = IESERVCLIENT; 771 return -1; 772 } 773 iperf_set_test_role(test, 'c'); 774 iperf_set_test_server_hostname(test, optarg); 775 break; 776 case 'u': 777 set_protocol(test, Pudp); 778 client_flag = 1; 779 break; 780 case OPT_SCTP: 781 #if defined(HAVE_SCTP) 782 set_protocol(test, Psctp); 783 client_flag = 1; 784 break; 785 #else /* HAVE_SCTP */ 786 i_errno = IEUNIMP; 787 return -1; 788 #endif /* HAVE_SCTP */ 789 790 case OPT_NUMSTREAMS: 791 #if defined(linux) || defined(__FreeBSD__) 792 test->settings->num_ostreams = unit_atoi(optarg); 793 client_flag = 1; 794 #else /* linux */ 795 i_errno = IEUNIMP; 796 return -1; 797 #endif /* linux */ 798 case 'b': 799 slash = strchr(optarg, '/'); 800 if (slash) { 801 *slash = '\0'; 802 ++slash; 803 test->settings->burst = atoi(slash); 804 if (test->settings->burst <= 0 || 805 test->settings->burst > MAX_BURST) { 806 i_errno = IEBURST; 807 return -1; 808 } 809 } 810 test->settings->rate = unit_atof_rate(optarg); 811 rate_flag = 1; 812 client_flag = 1; 813 break; 814 case 't': 815 test->duration = atoi(optarg); 816 if (test->duration > MAX_TIME) { 817 i_errno = IEDURATION; 818 return -1; 819 } 820 duration_flag = 1; 821 client_flag = 1; 822 break; 823 case 'n': 824 test->settings->bytes = unit_atoi(optarg); 825 client_flag = 1; 826 break; 827 case 'k': 828 test->settings->blocks = unit_atoi(optarg); 829 client_flag = 1; 830 break; 831 case 'l': 832 blksize = unit_atoi(optarg); 833 client_flag = 1; 834 break; 835 case 'P': 836 test->num_streams = atoi(optarg); 837 if (test->num_streams > MAX_STREAMS) { 838 i_errno = IENUMSTREAMS; 839 return -1; 840 } 841 client_flag = 1; 842 break; 843 case 'R': 844 iperf_set_test_reverse(test, 1); 845 client_flag = 1; 846 break; 847 case 'w': 848 // XXX: This is a socket buffer, not specific to TCP 849 // Do sanity checks as double-precision floating point 850 // to avoid possible integer overflows. 851 farg = unit_atof(optarg); 852 if (farg > (double) MAX_TCP_BUFFER) { 853 i_errno = IEBUFSIZE; 854 return -1; 855 } 856 test->settings->socket_bufsize = (int) farg; 857 client_flag = 1; 858 break; 859 case 'B': 860 test->bind_address = strdup(optarg); 861 break; 862 case OPT_CLIENT_PORT: 863 test->bind_port = atoi(optarg); 864 break; 865 case 'M': 866 test->settings->mss = atoi(optarg); 867 if (test->settings->mss > MAX_MSS) { 868 i_errno = IEMSS; 869 return -1; 870 } 871 client_flag = 1; 872 break; 873 case 'N': 874 test->no_delay = 1; 875 client_flag = 1; 876 break; 877 case '4': 878 test->settings->domain = AF_INET; 879 break; 880 case '6': 881 test->settings->domain = AF_INET6; 882 break; 883 case 'S': 884 test->settings->tos = strtol(optarg, &endptr, 0); 885 if (endptr == optarg || 886 test->settings->tos < 0 || 887 test->settings->tos > 255) { 888 i_errno = IEBADTOS; 889 return -1; 890 } 891 client_flag = 1; 892 break; 893 case OPT_DSCP: 894 test->settings->tos = parse_qos(optarg); 895 if(test->settings->tos < 0) { 896 i_errno = IEBADTOS; 897 return -1; 898 } 899 client_flag = 1; 900 break; 901 case 'L': 902 #if defined(HAVE_FLOWLABEL) 903 test->settings->flowlabel = strtol(optarg, &endptr, 0); 904 if (endptr == optarg || 905 test->settings->flowlabel < 1 || test->settings->flowlabel > 0xfffff) { 906 i_errno = IESETFLOW; 907 return -1; 908 } 909 client_flag = 1; 910 #else /* HAVE_FLOWLABEL */ 911 i_errno = IEUNIMP; 912 return -1; 913 #endif /* HAVE_FLOWLABEL */ 914 break; 915 case 'X': 916 xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry)); 917 if (!xbe) { 918 i_errno = IESETSCTPBINDX; 919 return -1; 920 } 921 memset(xbe, 0, sizeof(*xbe)); 922 xbe->name = strdup(optarg); 923 if (!xbe->name) { 924 i_errno = IESETSCTPBINDX; 925 return -1; 926 } 927 TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link); 928 break; 929 case 'Z': 930 if (!has_sendfile()) { 931 i_errno = IENOSENDFILE; 932 return -1; 933 } 934 test->zerocopy = 1; 935 client_flag = 1; 936 break; 937 case 'O': 938 test->omit = atoi(optarg); 939 if (test->omit < 0 || test->omit > 60) { 940 i_errno = IEOMIT; 941 return -1; 942 } 943 client_flag = 1; 944 break; 945 case 'F': 946 test->diskfile_name = optarg; 947 break; 948 case 'A': 949 #if defined(HAVE_CPU_AFFINITY) 950 test->affinity = strtol(optarg, &endptr, 0); 951 if (endptr == optarg || 952 test->affinity < 0 || test->affinity > 1024) { 953 i_errno = IEAFFINITY; 954 return -1; 955 } 956 comma = strchr(optarg, ','); 957 if (comma != NULL) { 958 test->server_affinity = atoi(comma+1); 959 if (test->server_affinity < 0 || test->server_affinity > 1024) { 960 i_errno = IEAFFINITY; 961 return -1; 962 } 963 client_flag = 1; 964 } 965 #else /* HAVE_CPU_AFFINITY */ 966 i_errno = IEUNIMP; 967 return -1; 968 #endif /* HAVE_CPU_AFFINITY */ 969 break; 970 case 'T': 971 test->title = strdup(optarg); 972 client_flag = 1; 973 break; 974 case 'C': 975 #if defined(HAVE_TCP_CONGESTION) 976 test->congestion = strdup(optarg); 977 client_flag = 1; 978 #else /* HAVE_TCP_CONGESTION */ 979 i_errno = IEUNIMP; 980 return -1; 981 #endif /* HAVE_TCP_CONGESTION */ 982 break; 983 case 'd': 984 test->debug = 1; 985 break; 986 case 'I': 987 test->pidfile = strdup(optarg); 988 server_flag = 1; 989 break; 990 case OPT_LOGFILE: 991 test->logfile = strdup(optarg); 992 break; 993 case OPT_FORCEFLUSH: 994 test->forceflush = 1; 995 break; 996 case OPT_GET_SERVER_OUTPUT: 997 test->get_server_output = 1; 998 client_flag = 1; 999 break; 1000 case OPT_UDP_COUNTERS_64BIT: 1001 test->udp_counters_64bit = 1; 1002 break; 1003 case OPT_NO_FQ_SOCKET_PACING: 1004 #if defined(HAVE_SO_MAX_PACING_RATE) 1005 printf("Warning: --no-fq-socket-pacing is deprecated\n"); 1006 test->settings->fqrate = 0; 1007 client_flag = 1; 1008 #else /* HAVE_SO_MAX_PACING_RATE */ 1009 i_errno = IEUNIMP; 1010 return -1; 1011 #endif 1012 break; 1013 case OPT_FQ_RATE: 1014 #if defined(HAVE_SO_MAX_PACING_RATE) 1015 test->settings->fqrate = unit_atof_rate(optarg); 1016 client_flag = 1; 1017 #else /* HAVE_SO_MAX_PACING_RATE */ 1018 i_errno = IEUNIMP; 1019 return -1; 1020 #endif 1021 break; 1022 #if defined(HAVE_SSL) 1023 case OPT_CLIENT_USERNAME: 1024 client_username = strdup(optarg); 1025 break; 1026 case OPT_CLIENT_RSA_PUBLIC_KEY: 1027 client_rsa_public_key = strdup(optarg); 1028 break; 1029 case OPT_SERVER_RSA_PRIVATE_KEY: 1030 test->server_rsa_private_key = strdup(optarg); 1031 break; 1032 case OPT_SERVER_AUTHORIZED_USERS: 1033 test->server_authorized_users = strdup(optarg); 1034 break; 1035 #endif /* HAVE_SSL */ 1036 case OPT_PACING_TIMER: 1037 test->settings->pacing_timer = unit_atoi(optarg); 1038 client_flag = 1; 1039 break; 1040 case OPT_CONNECT_TIMEOUT: 1041 test->settings->connect_timeout = unit_atoi(optarg); 1042 client_flag = 1; 1043 break; 1044 case 'h': 1045 usage_long(stdout); 1046 exit(0); 1047 default: 1048 usage_long(stderr); 1049 exit(1); 1050 } 1051 } 1052 1053 /* Set logging to a file if specified, otherwise use the default (stdout) */ 1054 if (test->logfile) { 1055 test->outfile = fopen(test->logfile, "a+"); 1056 if (test->outfile == NULL) { 1057 i_errno = IELOGFILE; 1058 return -1; 1059 } 1060 } 1061 1062 /* Check flag / role compatibility. */ 1063 if (test->role == 'c' && server_flag) { 1064 i_errno = IESERVERONLY; 1065 return -1; 1066 } 1067 if (test->role == 's' && client_flag) { 1068 i_errno = IECLIENTONLY; 1069 return -1; 1070 } 1071 1072 #if defined(HAVE_SSL) 1073 1074 if (test->role == 's' && (client_username || client_rsa_public_key)){ 1075 i_errno = IECLIENTONLY; 1076 return -1; 1077 } else if (test->role == 'c' && (client_username || client_rsa_public_key) && 1078 !(client_username && client_rsa_public_key)) { 1079 i_errno = IESETCLIENTAUTH; 1080 return -1; 1081 } else if (test->role == 'c' && (client_username && client_rsa_public_key)){ 1082 1083 char *client_password = NULL; 1084 size_t s; 1085 if (iperf_getpass(&client_password, &s, stdin) < 0){ 1086 return -1; 1087 } 1088 1089 if (strlen(client_username) > 20 || strlen(client_password) > 20){ 1090 i_errno = IESETCLIENTAUTH; 1091 return -1; 1092 } 1093 1094 if (test_load_pubkey(client_rsa_public_key) < 0){ 1095 i_errno = IESETCLIENTAUTH; 1096 return -1; 1097 } 1098 encode_auth_setting(client_username, client_password, client_rsa_public_key, &test->settings->authtoken); 1099 } 1100 1101 if (test->role == 'c' && (test->server_rsa_private_key || test->server_authorized_users)){ 1102 i_errno = IESERVERONLY; 1103 return -1; 1104 } else if (test->role == 's' && (test->server_rsa_private_key || test->server_authorized_users) && 1105 !(test->server_rsa_private_key && test->server_authorized_users)) { 1106 i_errno = IESETSERVERAUTH; 1107 return -1; 1108 } else if (test->role == 's' && test->server_rsa_private_key && test_load_private_key(test->server_rsa_private_key) < 0){ 1109 i_errno = IESETSERVERAUTH; 1110 return -1; 1111 } 1112 #endif //HAVE_SSL 1113 if (!test->bind_address && test->bind_port) { 1114 i_errno = IEBIND; 1115 return -1; 1116 } 1117 if (blksize == 0) { 1118 if (test->protocol->id == Pudp) 1119 blksize = 0; /* try to dynamically determine from MSS */ 1120 else if (test->protocol->id == Psctp) 1121 blksize = DEFAULT_SCTP_BLKSIZE; 1122 else 1123 blksize = DEFAULT_TCP_BLKSIZE; 1124 } 1125 if ((test->protocol->id != Pudp && blksize <= 0) 1126 || blksize > MAX_BLOCKSIZE) { 1127 i_errno = IEBLOCKSIZE; 1128 return -1; 1129 } 1130 if (test->protocol->id == Pudp && 1131 (blksize > 0 && 1132 (blksize < MIN_UDP_BLOCKSIZE || blksize > MAX_UDP_BLOCKSIZE))) { 1133 i_errno = IEUDPBLOCKSIZE; 1134 return -1; 1135 } 1136 test->settings->blksize = blksize; 1137 1138 if (!rate_flag) 1139 test->settings->rate = test->protocol->id == Pudp ? UDP_RATE : 0; 1140 1141 if ((test->settings->bytes != 0 || test->settings->blocks != 0) && ! duration_flag) 1142 test->duration = 0; 1143 1144 /* Disallow specifying multiple test end conditions. The code actually 1145 ** works just fine without this prohibition. As soon as any one of the 1146 ** three possible end conditions is met, the test ends. So this check 1147 ** could be removed if desired. 1148 */ 1149 if ((duration_flag && test->settings->bytes != 0) || 1150 (duration_flag && test->settings->blocks != 0) || 1151 (test->settings->bytes != 0 && test->settings->blocks != 0)) { 1152 i_errno = IEENDCONDITIONS; 1153 return -1; 1154 } 1155 1156 /* For subsequent calls to getopt */ 1157 #ifdef __APPLE__ 1158 optreset = 1; 1159 #endif 1160 optind = 0; 1161 1162 if ((test->role != 'c') && (test->role != 's')) { 1163 i_errno = IENOROLE; 1164 return -1; 1165 } 1166 1167 return 0; 1168 } 1169 1170 int 1171 iperf_set_send_state(struct iperf_test *test, signed char state) 1172 { 1173 test->state = state; 1174 if (Nwrite(test->ctrl_sck, (char*) &state, sizeof(state), Ptcp) < 0) { 1175 i_errno = IESENDMESSAGE; 1176 return -1; 1177 } 1178 return 0; 1179 } 1180 1181 void 1182 iperf_check_throttle(struct iperf_stream *sp, struct timeval *nowP) 1183 { 1184 double seconds; 1185 uint64_t bits_per_second; 1186 1187 if (sp->test->done) 1188 return; 1189 seconds = timeval_diff(&sp->result->start_time_fixed, nowP); 1190 bits_per_second = sp->result->bytes_sent * 8 / seconds; 1191 if (bits_per_second < sp->test->settings->rate) { 1192 sp->green_light = 1; 1193 FD_SET(sp->socket, &sp->test->write_set); 1194 } else { 1195 sp->green_light = 0; 1196 FD_CLR(sp->socket, &sp->test->write_set); 1197 } 1198 } 1199 1200 int 1201 iperf_send(struct iperf_test *test, fd_set *write_setP) 1202 { 1203 register int multisend, r, streams_active; 1204 register struct iperf_stream *sp; 1205 struct timeval now; 1206 1207 /* Can we do multisend mode? */ 1208 if (test->settings->burst != 0) 1209 multisend = test->settings->burst; 1210 else if (test->settings->rate == 0) 1211 multisend = test->multisend; 1212 else 1213 multisend = 1; /* nope */ 1214 1215 for (; multisend > 0; --multisend) { 1216 if (test->settings->rate != 0 && test->settings->burst == 0) 1217 gettimeofday(&now, NULL); 1218 streams_active = 0; 1219 SLIST_FOREACH(sp, &test->streams, streams) { 1220 if ((sp->green_light && 1221 (write_setP == NULL || FD_ISSET(sp->socket, write_setP)))) { 1222 if ((r = sp->snd(sp)) < 0) { 1223 if (r == NET_SOFTERROR) 1224 break; 1225 i_errno = IESTREAMWRITE; 1226 return r; 1227 } 1228 streams_active = 1; 1229 test->bytes_sent += r; 1230 ++test->blocks_sent; 1231 if (test->settings->rate != 0 && test->settings->burst == 0) 1232 iperf_check_throttle(sp, &now); 1233 if (multisend > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) 1234 break; 1235 if (multisend > 1 && test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks) 1236 break; 1237 } 1238 } 1239 if (!streams_active) 1240 break; 1241 } 1242 if (test->settings->burst != 0) { 1243 gettimeofday(&now, NULL); 1244 SLIST_FOREACH(sp, &test->streams, streams) 1245 iperf_check_throttle(sp, &now); 1246 } 1247 if (write_setP != NULL) 1248 SLIST_FOREACH(sp, &test->streams, streams) 1249 if (FD_ISSET(sp->socket, write_setP)) 1250 FD_CLR(sp->socket, write_setP); 1251 1252 return 0; 1253 } 1254 1255 int 1256 iperf_recv(struct iperf_test *test, fd_set *read_setP) 1257 { 1258 int r; 1259 struct iperf_stream *sp; 1260 1261 SLIST_FOREACH(sp, &test->streams, streams) { 1262 if (FD_ISSET(sp->socket, read_setP)) { 1263 if ((r = sp->rcv(sp)) < 0) { 1264 i_errno = IESTREAMREAD; 1265 return r; 1266 } 1267 test->bytes_sent += r; 1268 ++test->blocks_sent; 1269 FD_CLR(sp->socket, read_setP); 1270 } 1271 } 1272 1273 return 0; 1274 } 1275 1276 int 1277 iperf_init_test(struct iperf_test *test) 1278 { 1279 struct timeval now; 1280 struct iperf_stream *sp; 1281 1282 if (test->protocol->init) { 1283 if (test->protocol->init(test) < 0) 1284 return -1; 1285 } 1286 1287 /* Init each stream. */ 1288 if (gettimeofday(&now, NULL) < 0) { 1289 i_errno = IEINITTEST; 1290 return -1; 1291 } 1292 SLIST_FOREACH(sp, &test->streams, streams) { 1293 sp->result->start_time = sp->result->start_time_fixed = now; 1294 } 1295 1296 if (test->on_test_start) 1297 test->on_test_start(test); 1298 1299 return 0; 1300 } 1301 1302 static void 1303 send_timer_proc(TimerClientData client_data, struct timeval *nowP) 1304 { 1305 struct iperf_stream *sp = client_data.p; 1306 1307 /* All we do here is set or clear the flag saying that this stream may 1308 ** be sent to. The actual sending gets done in the send proc, after 1309 ** checking the flag. 1310 */ 1311 iperf_check_throttle(sp, nowP); 1312 } 1313 1314 int 1315 iperf_create_send_timers(struct iperf_test * test) 1316 { 1317 struct timeval now; 1318 struct iperf_stream *sp; 1319 TimerClientData cd; 1320 1321 if (gettimeofday(&now, NULL) < 0) { 1322 i_errno = IEINITTEST; 1323 return -1; 1324 } 1325 SLIST_FOREACH(sp, &test->streams, streams) { 1326 sp->green_light = 1; 1327 if (test->settings->rate != 0) { 1328 cd.p = sp; 1329 /* (Repeat every millisecond - arbitrary value to provide smooth pacing.) */ 1330 sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, test->settings->pacing_timer, 1); 1331 if (sp->send_timer == NULL) { 1332 i_errno = IEINITTEST; 1333 return -1; 1334 } 1335 } 1336 } 1337 return 0; 1338 } 1339 1340 #if defined(HAVE_SSL) 1341 int test_is_authorized(struct iperf_test *test){ 1342 if ( !(test->server_rsa_private_key && test->server_authorized_users)) { 1343 return 0; 1344 } 1345 1346 if (test->settings->authtoken){ 1347 char *username = NULL, *password = NULL; 1348 time_t ts; 1349 decode_auth_setting(test->debug, test->settings->authtoken, test->server_rsa_private_key, &username, &password, &ts); 1350 int ret = check_authentication(username, password, ts, test->server_authorized_users); 1351 if (ret == 0){ 1352 iperf_printf(test, report_authetication_successed, username, ts); 1353 return 0; 1354 } else { 1355 iperf_printf(test, report_authetication_failed, username, ts); 1356 return -1; 1357 } 1358 } 1359 return -1; 1360 } 1361 #endif //HAVE_SSL 1362 1363 /** 1364 * iperf_exchange_parameters - handles the param_Exchange part for client 1365 * 1366 */ 1367 1368 int 1369 iperf_exchange_parameters(struct iperf_test *test) 1370 { 1371 int s; 1372 int32_t err; 1373 1374 if (test->role == 'c') { 1375 1376 if (send_parameters(test) < 0) 1377 return -1; 1378 1379 } else { 1380 1381 if (get_parameters(test) < 0) 1382 return -1; 1383 1384 #if defined(HAVE_SSL) 1385 if (test_is_authorized(test) < 0){ 1386 if (iperf_set_send_state(test, SERVER_ERROR) != 0) 1387 return -1; 1388 i_errno = IEAUTHTEST; 1389 err = htonl(i_errno); 1390 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1391 i_errno = IECTRLWRITE; 1392 return -1; 1393 } 1394 return -1; 1395 } 1396 #endif //HAVE_SSL 1397 1398 if ((s = test->protocol->listen(test)) < 0) { 1399 if (iperf_set_send_state(test, SERVER_ERROR) != 0) 1400 return -1; 1401 err = htonl(i_errno); 1402 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1403 i_errno = IECTRLWRITE; 1404 return -1; 1405 } 1406 err = htonl(errno); 1407 if (Nwrite(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 1408 i_errno = IECTRLWRITE; 1409 return -1; 1410 } 1411 return -1; 1412 } 1413 FD_SET(s, &test->read_set); 1414 test->max_fd = (s > test->max_fd) ? s : test->max_fd; 1415 test->prot_listener = s; 1416 1417 // Send the control message to create streams and start the test 1418 if (iperf_set_send_state(test, CREATE_STREAMS) != 0) 1419 return -1; 1420 1421 } 1422 1423 return 0; 1424 } 1425 1426 /*************************************************************/ 1427 1428 int 1429 iperf_exchange_results(struct iperf_test *test) 1430 { 1431 if (test->role == 'c') { 1432 /* Send results to server. */ 1433 if (send_results(test) < 0) 1434 return -1; 1435 /* Get server results. */ 1436 if (get_results(test) < 0) 1437 return -1; 1438 } else { 1439 /* Get client results. */ 1440 if (get_results(test) < 0) 1441 return -1; 1442 /* Send results to client. */ 1443 if (send_results(test) < 0) 1444 return -1; 1445 } 1446 return 0; 1447 } 1448 1449 /*************************************************************/ 1450 1451 static int 1452 send_parameters(struct iperf_test *test) 1453 { 1454 int r = 0; 1455 cJSON *j; 1456 1457 j = cJSON_CreateObject(); 1458 if (j == NULL) { 1459 i_errno = IESENDPARAMS; 1460 r = -1; 1461 } else { 1462 if (test->protocol->id == Ptcp) 1463 cJSON_AddTrueToObject(j, "tcp"); 1464 else if (test->protocol->id == Pudp) 1465 cJSON_AddTrueToObject(j, "udp"); 1466 else if (test->protocol->id == Psctp) 1467 cJSON_AddTrueToObject(j, "sctp"); 1468 cJSON_AddNumberToObject(j, "omit", test->omit); 1469 if (test->server_affinity != -1) 1470 cJSON_AddNumberToObject(j, "server_affinity", test->server_affinity); 1471 if (test->duration) 1472 cJSON_AddNumberToObject(j, "time", test->duration); 1473 if (test->settings->bytes) 1474 cJSON_AddNumberToObject(j, "num", test->settings->bytes); 1475 if (test->settings->blocks) 1476 cJSON_AddNumberToObject(j, "blockcount", test->settings->blocks); 1477 if (test->settings->mss) 1478 cJSON_AddNumberToObject(j, "MSS", test->settings->mss); 1479 if (test->no_delay) 1480 cJSON_AddTrueToObject(j, "nodelay"); 1481 cJSON_AddNumberToObject(j, "parallel", test->num_streams); 1482 if (test->reverse) 1483 cJSON_AddTrueToObject(j, "reverse"); 1484 if (test->settings->socket_bufsize) 1485 cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize); 1486 if (test->settings->blksize) 1487 cJSON_AddNumberToObject(j, "len", test->settings->blksize); 1488 if (test->settings->rate) 1489 cJSON_AddNumberToObject(j, "bandwidth", test->settings->rate); 1490 if (test->settings->fqrate) 1491 cJSON_AddNumberToObject(j, "fqrate", test->settings->fqrate); 1492 if (test->settings->pacing_timer) 1493 cJSON_AddNumberToObject(j, "pacing_timer", test->settings->pacing_timer); 1494 if (test->settings->burst) 1495 cJSON_AddNumberToObject(j, "burst", test->settings->burst); 1496 if (test->settings->tos) 1497 cJSON_AddNumberToObject(j, "TOS", test->settings->tos); 1498 if (test->settings->flowlabel) 1499 cJSON_AddNumberToObject(j, "flowlabel", test->settings->flowlabel); 1500 if (test->title) 1501 cJSON_AddStringToObject(j, "title", test->title); 1502 if (test->congestion) 1503 cJSON_AddStringToObject(j, "congestion", test->congestion); 1504 if (test->congestion_used) 1505 cJSON_AddStringToObject(j, "congestion_used", test->congestion_used); 1506 if (test->get_server_output) 1507 cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test)); 1508 if (test->udp_counters_64bit) 1509 cJSON_AddNumberToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test)); 1510 #if defined(HAVE_SSL) 1511 if (test->settings->authtoken) 1512 cJSON_AddStringToObject(j, "authtoken", test->settings->authtoken); 1513 #endif // HAVE_SSL 1514 cJSON_AddStringToObject(j, "client_version", IPERF_VERSION); 1515 1516 if (test->debug) { 1517 printf("send_parameters:\n%s\n", cJSON_Print(j)); 1518 } 1519 1520 if (JSON_write(test->ctrl_sck, j) < 0) { 1521 i_errno = IESENDPARAMS; 1522 r = -1; 1523 } 1524 cJSON_Delete(j); 1525 } 1526 return r; 1527 } 1528 1529 /*************************************************************/ 1530 1531 static int 1532 get_parameters(struct iperf_test *test) 1533 { 1534 int r = 0; 1535 cJSON *j; 1536 cJSON *j_p; 1537 1538 j = JSON_read(test->ctrl_sck); 1539 if (j == NULL) { 1540 i_errno = IERECVPARAMS; 1541 r = -1; 1542 } else { 1543 if (test->debug) { 1544 printf("get_parameters:\n%s\n", cJSON_Print(j)); 1545 } 1546 1547 if ((j_p = cJSON_GetObjectItem(j, "tcp")) != NULL) 1548 set_protocol(test, Ptcp); 1549 if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL) 1550 set_protocol(test, Pudp); 1551 if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL) 1552 set_protocol(test, Psctp); 1553 if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL) 1554 test->omit = j_p->valueint; 1555 if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL) 1556 test->server_affinity = j_p->valueint; 1557 if ((j_p = cJSON_GetObjectItem(j, "time")) != NULL) 1558 test->duration = j_p->valueint; 1559 if ((j_p = cJSON_GetObjectItem(j, "num")) != NULL) 1560 test->settings->bytes = j_p->valueint; 1561 if ((j_p = cJSON_GetObjectItem(j, "blockcount")) != NULL) 1562 test->settings->blocks = j_p->valueint; 1563 if ((j_p = cJSON_GetObjectItem(j, "MSS")) != NULL) 1564 test->settings->mss = j_p->valueint; 1565 if ((j_p = cJSON_GetObjectItem(j, "nodelay")) != NULL) 1566 test->no_delay = 1; 1567 if ((j_p = cJSON_GetObjectItem(j, "parallel")) != NULL) 1568 test->num_streams = j_p->valueint; 1569 if ((j_p = cJSON_GetObjectItem(j, "reverse")) != NULL) 1570 iperf_set_test_reverse(test, 1); 1571 if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL) 1572 test->settings->socket_bufsize = j_p->valueint; 1573 if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL) 1574 test->settings->blksize = j_p->valueint; 1575 if ((j_p = cJSON_GetObjectItem(j, "bandwidth")) != NULL) 1576 test->settings->rate = j_p->valueint; 1577 if ((j_p = cJSON_GetObjectItem(j, "fqrate")) != NULL) 1578 test->settings->fqrate = j_p->valueint; 1579 if ((j_p = cJSON_GetObjectItem(j, "pacing_timer")) != NULL) 1580 test->settings->pacing_timer = j_p->valueint; 1581 if ((j_p = cJSON_GetObjectItem(j, "burst")) != NULL) 1582 test->settings->burst = j_p->valueint; 1583 if ((j_p = cJSON_GetObjectItem(j, "TOS")) != NULL) 1584 test->settings->tos = j_p->valueint; 1585 if ((j_p = cJSON_GetObjectItem(j, "flowlabel")) != NULL) 1586 test->settings->flowlabel = j_p->valueint; 1587 if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL) 1588 test->title = strdup(j_p->valuestring); 1589 if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL) 1590 test->congestion = strdup(j_p->valuestring); 1591 if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL) 1592 test->congestion_used = strdup(j_p->valuestring); 1593 if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL) 1594 iperf_set_test_get_server_output(test, 1); 1595 if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL) 1596 iperf_set_test_udp_counters_64bit(test, 1); 1597 #if defined(HAVE_SSL) 1598 if ((j_p = cJSON_GetObjectItem(j, "authtoken")) != NULL) 1599 test->settings->authtoken = strdup(j_p->valuestring); 1600 #endif //HAVE_SSL 1601 if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits()) 1602 test->sender_has_retransmits = 1; 1603 cJSON_Delete(j); 1604 } 1605 return r; 1606 } 1607 1608 /*************************************************************/ 1609 1610 static int 1611 send_results(struct iperf_test *test) 1612 { 1613 int r = 0; 1614 cJSON *j; 1615 cJSON *j_streams; 1616 struct iperf_stream *sp; 1617 cJSON *j_stream; 1618 int sender_has_retransmits; 1619 iperf_size_t bytes_transferred; 1620 int retransmits; 1621 double start_time, end_time; 1622 1623 j = cJSON_CreateObject(); 1624 if (j == NULL) { 1625 i_errno = IEPACKAGERESULTS; 1626 r = -1; 1627 } else { 1628 cJSON_AddNumberToObject(j, "cpu_util_total", test->cpu_util[0]); 1629 cJSON_AddNumberToObject(j, "cpu_util_user", test->cpu_util[1]); 1630 cJSON_AddNumberToObject(j, "cpu_util_system", test->cpu_util[2]); 1631 if ( ! test->sender ) 1632 sender_has_retransmits = -1; 1633 else 1634 sender_has_retransmits = test->sender_has_retransmits; 1635 cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits); 1636 if ( test->congestion_used ) { 1637 cJSON_AddStringToObject(j, "congestion_used", test->congestion_used); 1638 } 1639 1640 /* If on the server and sending server output, then do this */ 1641 if (test->role == 's' && test->get_server_output) { 1642 if (test->json_output) { 1643 /* Add JSON output */ 1644 cJSON_AddItemReferenceToObject(j, "server_output_json", test->json_top); 1645 } 1646 else { 1647 /* Add textual output */ 1648 size_t buflen = 0; 1649 1650 /* Figure out how much room we need to hold the complete output string */ 1651 struct iperf_textline *t; 1652 TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) { 1653 buflen += strlen(t->line); 1654 } 1655 1656 /* Allocate and build it up from the component lines */ 1657 char *output = calloc(buflen + 1, 1); 1658 TAILQ_FOREACH(t, &(test->server_output_list), textlineentries) { 1659 strncat(output, t->line, buflen); 1660 buflen -= strlen(t->line); 1661 } 1662 1663 cJSON_AddStringToObject(j, "server_output_text", output); 1664 free(output); 1665 } 1666 } 1667 1668 j_streams = cJSON_CreateArray(); 1669 if (j_streams == NULL) { 1670 i_errno = IEPACKAGERESULTS; 1671 r = -1; 1672 } else { 1673 cJSON_AddItemToObject(j, "streams", j_streams); 1674 SLIST_FOREACH(sp, &test->streams, streams) { 1675 j_stream = cJSON_CreateObject(); 1676 if (j_stream == NULL) { 1677 i_errno = IEPACKAGERESULTS; 1678 r = -1; 1679 } else { 1680 cJSON_AddItemToArray(j_streams, j_stream); 1681 bytes_transferred = test->sender ? (sp->result->bytes_sent - sp->result->bytes_sent_omit) : sp->result->bytes_received; 1682 retransmits = (test->sender && test->sender_has_retransmits) ? sp->result->stream_retrans : -1; 1683 cJSON_AddNumberToObject(j_stream, "id", sp->id); 1684 cJSON_AddNumberToObject(j_stream, "bytes", bytes_transferred); 1685 cJSON_AddNumberToObject(j_stream, "retransmits", retransmits); 1686 cJSON_AddNumberToObject(j_stream, "jitter", sp->jitter); 1687 cJSON_AddNumberToObject(j_stream, "errors", sp->cnt_error); 1688 cJSON_AddNumberToObject(j_stream, "packets", sp->packet_count); 1689 1690 start_time = timeval_diff(&sp->result->start_time, &sp->result->start_time); 1691 end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); 1692 cJSON_AddNumberToObject(j_stream, "start_time", start_time); 1693 cJSON_AddNumberToObject(j_stream, "end_time", end_time); 1694 1695 } 1696 } 1697 if (r == 0 && test->debug) { 1698 printf("send_results\n%s\n", cJSON_Print(j)); 1699 } 1700 if (r == 0 && JSON_write(test->ctrl_sck, j) < 0) { 1701 i_errno = IESENDRESULTS; 1702 r = -1; 1703 } 1704 } 1705 cJSON_Delete(j); 1706 } 1707 return r; 1708 } 1709 1710 /*************************************************************/ 1711 1712 static int 1713 get_results(struct iperf_test *test) 1714 { 1715 int r = 0; 1716 cJSON *j; 1717 cJSON *j_cpu_util_total; 1718 cJSON *j_cpu_util_user; 1719 cJSON *j_cpu_util_system; 1720 cJSON *j_remote_congestion_used; 1721 cJSON *j_sender_has_retransmits; 1722 int result_has_retransmits; 1723 cJSON *j_streams; 1724 int n, i; 1725 cJSON *j_stream; 1726 cJSON *j_id; 1727 cJSON *j_bytes; 1728 cJSON *j_retransmits; 1729 cJSON *j_jitter; 1730 cJSON *j_errors; 1731 cJSON *j_packets; 1732 cJSON *j_server_output; 1733 cJSON *j_start_time, *j_end_time; 1734 int sid, cerror, pcount; 1735 double jitter; 1736 iperf_size_t bytes_transferred; 1737 int retransmits; 1738 struct iperf_stream *sp; 1739 1740 j = JSON_read(test->ctrl_sck); 1741 if (j == NULL) { 1742 i_errno = IERECVRESULTS; 1743 r = -1; 1744 } else { 1745 j_cpu_util_total = cJSON_GetObjectItem(j, "cpu_util_total"); 1746 j_cpu_util_user = cJSON_GetObjectItem(j, "cpu_util_user"); 1747 j_cpu_util_system = cJSON_GetObjectItem(j, "cpu_util_system"); 1748 j_sender_has_retransmits = cJSON_GetObjectItem(j, "sender_has_retransmits"); 1749 if (j_cpu_util_total == NULL || j_cpu_util_user == NULL || j_cpu_util_system == NULL || j_sender_has_retransmits == NULL) { 1750 i_errno = IERECVRESULTS; 1751 r = -1; 1752 } else { 1753 if (test->debug) { 1754 printf("get_results\n%s\n", cJSON_Print(j)); 1755 } 1756 1757 test->remote_cpu_util[0] = j_cpu_util_total->valuedouble; 1758 test->remote_cpu_util[1] = j_cpu_util_user->valuedouble; 1759 test->remote_cpu_util[2] = j_cpu_util_system->valuedouble; 1760 result_has_retransmits = j_sender_has_retransmits->valueint; 1761 if (! test->sender) 1762 test->sender_has_retransmits = result_has_retransmits; 1763 j_streams = cJSON_GetObjectItem(j, "streams"); 1764 if (j_streams == NULL) { 1765 i_errno = IERECVRESULTS; 1766 r = -1; 1767 } else { 1768 n = cJSON_GetArraySize(j_streams); 1769 for (i=0; i<n; ++i) { 1770 j_stream = cJSON_GetArrayItem(j_streams, i); 1771 if (j_stream == NULL) { 1772 i_errno = IERECVRESULTS; 1773 r = -1; 1774 } else { 1775 j_id = cJSON_GetObjectItem(j_stream, "id"); 1776 j_bytes = cJSON_GetObjectItem(j_stream, "bytes"); 1777 j_retransmits = cJSON_GetObjectItem(j_stream, "retransmits"); 1778 j_jitter = cJSON_GetObjectItem(j_stream, "jitter"); 1779 j_errors = cJSON_GetObjectItem(j_stream, "errors"); 1780 j_packets = cJSON_GetObjectItem(j_stream, "packets"); 1781 j_start_time = cJSON_GetObjectItem(j_stream, "start_time"); 1782 j_end_time = cJSON_GetObjectItem(j_stream, "end_time"); 1783 if (j_id == NULL || j_bytes == NULL || j_retransmits == NULL || j_jitter == NULL || j_errors == NULL || j_packets == NULL) { 1784 i_errno = IERECVRESULTS; 1785 r = -1; 1786 } else { 1787 sid = j_id->valueint; 1788 bytes_transferred = j_bytes->valueint; 1789 retransmits = j_retransmits->valueint; 1790 jitter = j_jitter->valuedouble; 1791 cerror = j_errors->valueint; 1792 pcount = j_packets->valueint; 1793 SLIST_FOREACH(sp, &test->streams, streams) 1794 if (sp->id == sid) break; 1795 if (sp == NULL) { 1796 i_errno = IESTREAMID; 1797 r = -1; 1798 } else { 1799 if (test->sender) { 1800 sp->jitter = jitter; 1801 sp->cnt_error = cerror; 1802 sp->peer_packet_count = pcount; 1803 sp->result->bytes_received = bytes_transferred; 1804 /* 1805 * We have to handle the possibilty that 1806 * start_time and end_time might not be 1807 * available; this is the case for older (pre-3.2) 1808 * servers. 1809 * 1810 * We need to have result structure members to hold 1811 * the both sides' start_time and end_time. 1812 */ 1813 if (j_start_time && j_end_time) { 1814 sp->result->receiver_time = j_end_time->valuedouble - j_start_time->valuedouble; 1815 } 1816 else { 1817 sp->result->receiver_time = 0.0; 1818 } 1819 } else { 1820 sp->peer_packet_count = pcount; 1821 sp->result->bytes_sent = bytes_transferred; 1822 sp->result->stream_retrans = retransmits; 1823 if (j_start_time && j_end_time) { 1824 sp->result->sender_time = j_end_time->valuedouble - j_start_time->valuedouble; 1825 } 1826 else { 1827 sp->result->sender_time = 0.0; 1828 } 1829 } 1830 } 1831 } 1832 } 1833 } 1834 /* 1835 * If we're the client and we're supposed to get remote results, 1836 * look them up and process accordingly. 1837 */ 1838 if (test->role == 'c' && iperf_get_test_get_server_output(test)) { 1839 /* Look for JSON. If we find it, grab the object so it doesn't get deleted. */ 1840 j_server_output = cJSON_DetachItemFromObject(j, "server_output_json"); 1841 if (j_server_output != NULL) { 1842 test->json_server_output = j_server_output; 1843 } 1844 else { 1845 /* No JSON, look for textual output. Make a copy of the text for later. */ 1846 j_server_output = cJSON_GetObjectItem(j, "server_output_text"); 1847 if (j_server_output != NULL) { 1848 test->server_output_text = strdup(j_server_output->valuestring); 1849 } 1850 } 1851 } 1852 } 1853 } 1854 1855 j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used"); 1856 if (j_remote_congestion_used != NULL) { 1857 test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring); 1858 } 1859 1860 cJSON_Delete(j); 1861 } 1862 return r; 1863 } 1864 1865 /*************************************************************/ 1866 1867 static int 1868 JSON_write(int fd, cJSON *json) 1869 { 1870 uint32_t hsize, nsize; 1871 char *str; 1872 int r = 0; 1873 1874 str = cJSON_PrintUnformatted(json); 1875 if (str == NULL) 1876 r = -1; 1877 else { 1878 hsize = strlen(str); 1879 nsize = htonl(hsize); 1880 if (Nwrite(fd, (char*) &nsize, sizeof(nsize), Ptcp) < 0) 1881 r = -1; 1882 else { 1883 if (Nwrite(fd, str, hsize, Ptcp) < 0) 1884 r = -1; 1885 } 1886 free(str); 1887 } 1888 return r; 1889 } 1890 1891 /*************************************************************/ 1892 1893 static cJSON * 1894 JSON_read(int fd) 1895 { 1896 uint32_t hsize, nsize; 1897 char *str; 1898 cJSON *json = NULL; 1899 int rc; 1900 1901 /* 1902 * Read a four-byte integer, which is the length of the JSON to follow. 1903 * Then read the JSON into a buffer and parse it. Return a parsed JSON 1904 * structure, NULL if there was an error. 1905 */ 1906 if (Nread(fd, (char*) &nsize, sizeof(nsize), Ptcp) >= 0) { 1907 hsize = ntohl(nsize); 1908 /* Allocate a buffer to hold the JSON */ 1909 str = (char *) calloc(sizeof(char), hsize+1); /* +1 for trailing null */ 1910 if (str != NULL) { 1911 rc = Nread(fd, str, hsize, Ptcp); 1912 if (rc >= 0) { 1913 /* 1914 * We should be reading in the number of bytes corresponding to the 1915 * length in that 4-byte integer. If we don't the socket might have 1916 * prematurely closed. Only do the JSON parsing if we got the 1917 * correct number of bytes. 1918 */ 1919 if (rc == hsize) { 1920 json = cJSON_Parse(str); 1921 } 1922 else { 1923 printf("WARNING: Size of data read does not correspond to offered length\n"); 1924 } 1925 } 1926 } 1927 free(str); 1928 } 1929 return json; 1930 } 1931 1932 /*************************************************************/ 1933 /** 1934 * add_to_interval_list -- adds new interval to the interval_list 1935 */ 1936 1937 void 1938 add_to_interval_list(struct iperf_stream_result * rp, struct iperf_interval_results * new) 1939 { 1940 struct iperf_interval_results *irp; 1941 1942 irp = (struct iperf_interval_results *) malloc(sizeof(struct iperf_interval_results)); 1943 memcpy(irp, new, sizeof(struct iperf_interval_results)); 1944 TAILQ_INSERT_TAIL(&rp->interval_results, irp, irlistentries); 1945 } 1946 1947 1948 /************************************************************/ 1949 1950 /** 1951 * connect_msg -- displays connection message 1952 * denoting sender/receiver details 1953 * 1954 */ 1955 1956 void 1957 connect_msg(struct iperf_stream *sp) 1958 { 1959 char ipl[INET6_ADDRSTRLEN], ipr[INET6_ADDRSTRLEN]; 1960 int lport, rport; 1961 1962 if (getsockdomain(sp->socket) == AF_INET) { 1963 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->local_addr)->sin_addr, ipl, sizeof(ipl)); 1964 mapped_v4_to_regular_v4(ipl); 1965 inet_ntop(AF_INET, (void *) &((struct sockaddr_in *) &sp->remote_addr)->sin_addr, ipr, sizeof(ipr)); 1966 mapped_v4_to_regular_v4(ipr); 1967 lport = ntohs(((struct sockaddr_in *) &sp->local_addr)->sin_port); 1968 rport = ntohs(((struct sockaddr_in *) &sp->remote_addr)->sin_port); 1969 } else { 1970 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->local_addr)->sin6_addr, ipl, sizeof(ipl)); 1971 mapped_v4_to_regular_v4(ipl); 1972 inet_ntop(AF_INET6, (void *) &((struct sockaddr_in6 *) &sp->remote_addr)->sin6_addr, ipr, sizeof(ipr)); 1973 mapped_v4_to_regular_v4(ipr); 1974 lport = ntohs(((struct sockaddr_in6 *) &sp->local_addr)->sin6_port); 1975 rport = ntohs(((struct sockaddr_in6 *) &sp->remote_addr)->sin6_port); 1976 } 1977 1978 if (sp->test->json_output) 1979 cJSON_AddItemToArray(sp->test->json_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)); 1980 else 1981 iperf_printf(sp->test, report_connected, sp->socket, ipl, lport, ipr, rport); 1982 } 1983 1984 1985 /**************************************************************************/ 1986 1987 struct iperf_test * 1988 iperf_new_test() 1989 { 1990 struct iperf_test *test; 1991 1992 test = (struct iperf_test *) malloc(sizeof(struct iperf_test)); 1993 if (!test) { 1994 i_errno = IENEWTEST; 1995 return NULL; 1996 } 1997 /* initialize everything to zero */ 1998 memset(test, 0, sizeof(struct iperf_test)); 1999 2000 test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings)); 2001 if (!test->settings) { 2002 free(test); 2003 i_errno = IENEWTEST; 2004 return NULL; 2005 } 2006 memset(test->settings, 0, sizeof(struct iperf_settings)); 2007 2008 /* By default all output goes to stdout */ 2009 test->outfile = stdout; 2010 2011 return test; 2012 } 2013 2014 /**************************************************************************/ 2015 2016 struct protocol * 2017 protocol_new(void) 2018 { 2019 struct protocol *proto; 2020 2021 proto = malloc(sizeof(struct protocol)); 2022 if(!proto) { 2023 return NULL; 2024 } 2025 memset(proto, 0, sizeof(struct protocol)); 2026 2027 return proto; 2028 } 2029 2030 void 2031 protocol_free(struct protocol *proto) 2032 { 2033 free(proto); 2034 } 2035 2036 /**************************************************************************/ 2037 int 2038 iperf_defaults(struct iperf_test *testp) 2039 { 2040 struct protocol *tcp, *udp; 2041 #if defined(HAVE_SCTP) 2042 struct protocol *sctp; 2043 #endif /* HAVE_SCTP */ 2044 2045 testp->omit = OMIT; 2046 testp->duration = DURATION; 2047 testp->diskfile_name = (char*) 0; 2048 testp->affinity = -1; 2049 testp->server_affinity = -1; 2050 TAILQ_INIT(&testp->xbind_addrs); 2051 #if defined(HAVE_CPUSET_SETAFFINITY) 2052 CPU_ZERO(&testp->cpumask); 2053 #endif /* HAVE_CPUSET_SETAFFINITY */ 2054 testp->title = NULL; 2055 testp->congestion = NULL; 2056 testp->congestion_used = NULL; 2057 testp->remote_congestion_used = NULL; 2058 testp->server_port = PORT; 2059 testp->ctrl_sck = -1; 2060 testp->prot_listener = -1; 2061 2062 testp->stats_callback = iperf_stats_callback; 2063 testp->reporter_callback = iperf_reporter_callback; 2064 2065 testp->stats_interval = testp->reporter_interval = 1; 2066 testp->num_streams = 1; 2067 2068 testp->settings->domain = AF_UNSPEC; 2069 testp->settings->unit_format = 'a'; 2070 testp->settings->socket_bufsize = 0; /* use autotuning */ 2071 testp->settings->blksize = DEFAULT_TCP_BLKSIZE; 2072 testp->settings->rate = 0; 2073 testp->settings->fqrate = 0; 2074 testp->settings->pacing_timer = 1000; 2075 testp->settings->burst = 0; 2076 testp->settings->mss = 0; 2077 testp->settings->bytes = 0; 2078 testp->settings->blocks = 0; 2079 testp->settings->connect_timeout = -1; 2080 memset(testp->cookie, 0, COOKIE_SIZE); 2081 2082 testp->multisend = 10; /* arbitrary */ 2083 2084 /* Set up protocol list */ 2085 SLIST_INIT(&testp->streams); 2086 SLIST_INIT(&testp->protocols); 2087 2088 tcp = protocol_new(); 2089 if (!tcp) 2090 return -1; 2091 2092 tcp->id = Ptcp; 2093 tcp->name = "TCP"; 2094 tcp->accept = iperf_tcp_accept; 2095 tcp->listen = iperf_tcp_listen; 2096 tcp->connect = iperf_tcp_connect; 2097 tcp->send = iperf_tcp_send; 2098 tcp->recv = iperf_tcp_recv; 2099 tcp->init = NULL; 2100 SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols); 2101 2102 udp = protocol_new(); 2103 if (!udp) { 2104 protocol_free(tcp); 2105 return -1; 2106 } 2107 2108 udp->id = Pudp; 2109 udp->name = "UDP"; 2110 udp->accept = iperf_udp_accept; 2111 udp->listen = iperf_udp_listen; 2112 udp->connect = iperf_udp_connect; 2113 udp->send = iperf_udp_send; 2114 udp->recv = iperf_udp_recv; 2115 udp->init = iperf_udp_init; 2116 SLIST_INSERT_AFTER(tcp, udp, protocols); 2117 2118 set_protocol(testp, Ptcp); 2119 2120 #if defined(HAVE_SCTP) 2121 sctp = protocol_new(); 2122 if (!sctp) { 2123 protocol_free(tcp); 2124 protocol_free(udp); 2125 return -1; 2126 } 2127 2128 sctp->id = Psctp; 2129 sctp->name = "SCTP"; 2130 sctp->accept = iperf_sctp_accept; 2131 sctp->listen = iperf_sctp_listen; 2132 sctp->connect = iperf_sctp_connect; 2133 sctp->send = iperf_sctp_send; 2134 sctp->recv = iperf_sctp_recv; 2135 sctp->init = iperf_sctp_init; 2136 2137 SLIST_INSERT_AFTER(udp, sctp, protocols); 2138 #endif /* HAVE_SCTP */ 2139 2140 testp->on_new_stream = iperf_on_new_stream; 2141 testp->on_test_start = iperf_on_test_start; 2142 testp->on_connect = iperf_on_connect; 2143 testp->on_test_finish = iperf_on_test_finish; 2144 2145 TAILQ_INIT(&testp->server_output_list); 2146 2147 return 0; 2148 } 2149 2150 2151 /**************************************************************************/ 2152 void 2153 iperf_free_test(struct iperf_test *test) 2154 { 2155 struct protocol *prot; 2156 struct iperf_stream *sp; 2157 2158 /* Free streams */ 2159 while (!SLIST_EMPTY(&test->streams)) { 2160 sp = SLIST_FIRST(&test->streams); 2161 SLIST_REMOVE_HEAD(&test->streams, streams); 2162 iperf_free_stream(sp); 2163 } 2164 2165 if (test->server_hostname) 2166 free(test->server_hostname); 2167 if (test->tmp_template) 2168 free(test->tmp_template); 2169 if (test->bind_address) 2170 free(test->bind_address); 2171 if (!TAILQ_EMPTY(&test->xbind_addrs)) { 2172 struct xbind_entry *xbe; 2173 2174 while (!TAILQ_EMPTY(&test->xbind_addrs)) { 2175 xbe = TAILQ_FIRST(&test->xbind_addrs); 2176 TAILQ_REMOVE(&test->xbind_addrs, xbe, link); 2177 if (xbe->ai) 2178 freeaddrinfo(xbe->ai); 2179 free(xbe->name); 2180 free(xbe); 2181 } 2182 } 2183 if (test->settings) 2184 free(test->settings); 2185 if (test->title) 2186 free(test->title); 2187 if (test->congestion) 2188 free(test->congestion); 2189 if (test->congestion_used) 2190 free(test->congestion_used); 2191 if (test->remote_congestion_used) 2192 free(test->remote_congestion_used); 2193 if (test->omit_timer != NULL) 2194 tmr_cancel(test->omit_timer); 2195 if (test->timer != NULL) 2196 tmr_cancel(test->timer); 2197 if (test->stats_timer != NULL) 2198 tmr_cancel(test->stats_timer); 2199 if (test->reporter_timer != NULL) 2200 tmr_cancel(test->reporter_timer); 2201 2202 /* Free protocol list */ 2203 while (!SLIST_EMPTY(&test->protocols)) { 2204 prot = SLIST_FIRST(&test->protocols); 2205 SLIST_REMOVE_HEAD(&test->protocols, protocols); 2206 free(prot); 2207 } 2208 2209 if (test->server_output_text) { 2210 free(test->server_output_text); 2211 test->server_output_text = NULL; 2212 } 2213 2214 if (test->json_output_string) { 2215 free(test->json_output_string); 2216 test->json_output_string = NULL; 2217 } 2218 2219 /* Free output line buffers, if any (on the server only) */ 2220 struct iperf_textline *t; 2221 while (!TAILQ_EMPTY(&test->server_output_list)) { 2222 t = TAILQ_FIRST(&test->server_output_list); 2223 TAILQ_REMOVE(&test->server_output_list, t, textlineentries); 2224 free(t->line); 2225 free(t); 2226 } 2227 2228 /* sctp_bindx: do not free the arguments, only the resolver results */ 2229 if (!TAILQ_EMPTY(&test->xbind_addrs)) { 2230 struct xbind_entry *xbe; 2231 2232 TAILQ_FOREACH(xbe, &test->xbind_addrs, link) { 2233 if (xbe->ai) { 2234 freeaddrinfo(xbe->ai); 2235 xbe->ai = NULL; 2236 } 2237 } 2238 } 2239 2240 /* XXX: Why are we setting these values to NULL? */ 2241 // test->streams = NULL; 2242 test->stats_callback = NULL; 2243 test->reporter_callback = NULL; 2244 free(test); 2245 } 2246 2247 2248 void 2249 iperf_reset_test(struct iperf_test *test) 2250 { 2251 struct iperf_stream *sp; 2252 2253 /* Free streams */ 2254 while (!SLIST_EMPTY(&test->streams)) { 2255 sp = SLIST_FIRST(&test->streams); 2256 SLIST_REMOVE_HEAD(&test->streams, streams); 2257 iperf_free_stream(sp); 2258 } 2259 if (test->omit_timer != NULL) { 2260 tmr_cancel(test->omit_timer); 2261 test->omit_timer = NULL; 2262 } 2263 if (test->timer != NULL) { 2264 tmr_cancel(test->timer); 2265 test->timer = NULL; 2266 } 2267 if (test->stats_timer != NULL) { 2268 tmr_cancel(test->stats_timer); 2269 test->stats_timer = NULL; 2270 } 2271 if (test->reporter_timer != NULL) { 2272 tmr_cancel(test->reporter_timer); 2273 test->reporter_timer = NULL; 2274 } 2275 test->done = 0; 2276 2277 SLIST_INIT(&test->streams); 2278 2279 test->role = 's'; 2280 test->sender = 0; 2281 test->sender_has_retransmits = 0; 2282 set_protocol(test, Ptcp); 2283 test->omit = OMIT; 2284 test->duration = DURATION; 2285 test->server_affinity = -1; 2286 #if defined(HAVE_CPUSET_SETAFFINITY) 2287 CPU_ZERO(&test->cpumask); 2288 #endif /* HAVE_CPUSET_SETAFFINITY */ 2289 test->state = 0; 2290 2291 test->ctrl_sck = -1; 2292 test->prot_listener = -1; 2293 2294 test->bytes_sent = 0; 2295 test->blocks_sent = 0; 2296 2297 test->reverse = 0; 2298 test->no_delay = 0; 2299 2300 FD_ZERO(&test->read_set); 2301 FD_ZERO(&test->write_set); 2302 2303 test->num_streams = 1; 2304 test->settings->socket_bufsize = 0; 2305 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 2306 test->settings->rate = 0; 2307 test->settings->burst = 0; 2308 test->settings->mss = 0; 2309 memset(test->cookie, 0, COOKIE_SIZE); 2310 test->multisend = 10; /* arbitrary */ 2311 test->udp_counters_64bit = 0; 2312 if (test->title) { 2313 free(test->title); 2314 test->title = NULL; 2315 } 2316 2317 /* Free output line buffers, if any (on the server only) */ 2318 struct iperf_textline *t; 2319 while (!TAILQ_EMPTY(&test->server_output_list)) { 2320 t = TAILQ_FIRST(&test->server_output_list); 2321 TAILQ_REMOVE(&test->server_output_list, t, textlineentries); 2322 free(t->line); 2323 free(t); 2324 } 2325 } 2326 2327 2328 /* Reset all of a test's stats back to zero. Called when the omitting 2329 ** period is over. 2330 */ 2331 void 2332 iperf_reset_stats(struct iperf_test *test) 2333 { 2334 struct timeval now; 2335 struct iperf_stream *sp; 2336 struct iperf_stream_result *rp; 2337 2338 test->bytes_sent = 0; 2339 test->blocks_sent = 0; 2340 gettimeofday(&now, NULL); 2341 SLIST_FOREACH(sp, &test->streams, streams) { 2342 sp->omitted_packet_count = sp->packet_count; 2343 sp->omitted_cnt_error = sp->cnt_error; 2344 sp->omitted_outoforder_packets = sp->outoforder_packets; 2345 sp->jitter = 0; 2346 rp = sp->result; 2347 rp->bytes_sent_omit = rp->bytes_sent; 2348 rp->bytes_received = 0; 2349 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 2350 if (test->sender && test->sender_has_retransmits) { 2351 struct iperf_interval_results ir; /* temporary results structure */ 2352 save_tcpinfo(sp, &ir); 2353 rp->stream_prev_total_retrans = get_total_retransmits(&ir); 2354 } 2355 rp->stream_retrans = 0; 2356 rp->start_time = now; 2357 } 2358 } 2359 2360 2361 /**************************************************************************/ 2362 2363 /** 2364 * Gather statistics during a test. 2365 * This function works for both the client and server side. 2366 */ 2367 void 2368 iperf_stats_callback(struct iperf_test *test) 2369 { 2370 struct iperf_stream *sp; 2371 struct iperf_stream_result *rp = NULL; 2372 struct iperf_interval_results *irp, temp; 2373 2374 temp.omitted = test->omitting; 2375 SLIST_FOREACH(sp, &test->streams, streams) { 2376 rp = sp->result; 2377 2378 temp.bytes_transferred = test->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval; 2379 2380 irp = TAILQ_LAST(&rp->interval_results, irlisthead); 2381 /* result->end_time contains timestamp of previous interval */ 2382 if ( irp != NULL ) /* not the 1st interval */ 2383 memcpy(&temp.interval_start_time, &rp->end_time, sizeof(struct timeval)); 2384 else /* or use timestamp from beginning */ 2385 memcpy(&temp.interval_start_time, &rp->start_time, sizeof(struct timeval)); 2386 /* now save time of end of this interval */ 2387 gettimeofday(&rp->end_time, NULL); 2388 memcpy(&temp.interval_end_time, &rp->end_time, sizeof(struct timeval)); 2389 temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 2390 //temp.interval_duration = timeval_diff(&temp.interval_start_time, &temp.interval_end_time); 2391 if (test->protocol->id == Ptcp) { 2392 if ( has_tcpinfo()) { 2393 save_tcpinfo(sp, &temp); 2394 if (test->sender && test->sender_has_retransmits) { 2395 long total_retrans = get_total_retransmits(&temp); 2396 temp.interval_retrans = total_retrans - rp->stream_prev_total_retrans; 2397 rp->stream_retrans += temp.interval_retrans; 2398 rp->stream_prev_total_retrans = total_retrans; 2399 2400 temp.snd_cwnd = get_snd_cwnd(&temp); 2401 if (temp.snd_cwnd > rp->stream_max_snd_cwnd) { 2402 rp->stream_max_snd_cwnd = temp.snd_cwnd; 2403 } 2404 2405 temp.rtt = get_rtt(&temp); 2406 if (temp.rtt > rp->stream_max_rtt) { 2407 rp->stream_max_rtt = temp.rtt; 2408 } 2409 if (rp->stream_min_rtt == 0 || 2410 temp.rtt < rp->stream_min_rtt) { 2411 rp->stream_min_rtt = temp.rtt; 2412 } 2413 rp->stream_sum_rtt += temp.rtt; 2414 rp->stream_count_rtt++; 2415 2416 temp.rttvar = get_rttvar(&temp); 2417 temp.pmtu = get_pmtu(&temp); 2418 } 2419 } 2420 } else { 2421 if (irp == NULL) { 2422 temp.interval_packet_count = sp->packet_count; 2423 temp.interval_outoforder_packets = sp->outoforder_packets; 2424 temp.interval_cnt_error = sp->cnt_error; 2425 } else { 2426 temp.interval_packet_count = sp->packet_count - irp->packet_count; 2427 temp.interval_outoforder_packets = sp->outoforder_packets - irp->outoforder_packets; 2428 temp.interval_cnt_error = sp->cnt_error - irp->cnt_error; 2429 } 2430 temp.packet_count = sp->packet_count; 2431 temp.jitter = sp->jitter; 2432 temp.outoforder_packets = sp->outoforder_packets; 2433 temp.cnt_error = sp->cnt_error; 2434 } 2435 add_to_interval_list(rp, &temp); 2436 rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0; 2437 } 2438 } 2439 2440 /** 2441 * Print intermediate results during a test (interval report). 2442 * Uses print_interval_results to print the results for each stream, 2443 * then prints an interval summary for all streams in this 2444 * interval. 2445 */ 2446 static void 2447 iperf_print_intermediate(struct iperf_test *test) 2448 { 2449 char ubuf[UNIT_LEN]; 2450 char nbuf[UNIT_LEN]; 2451 struct iperf_stream *sp = NULL; 2452 struct iperf_interval_results *irp; 2453 iperf_size_t bytes = 0; 2454 double bandwidth; 2455 int retransmits = 0; 2456 double start_time, end_time; 2457 cJSON *json_interval; 2458 cJSON *json_interval_streams; 2459 int total_packets = 0, lost_packets = 0; 2460 double avg_jitter = 0.0, lost_percent; 2461 2462 /* 2463 * Due to timing oddities, there can be cases, especially on the 2464 * server side, where at the end of a test there is a fairly short 2465 * interval with no data transferred. This could caused by 2466 * the control and data flows sharing the same path in the network, 2467 * and having the control messages for stopping the test being 2468 * queued behind the data packets. 2469 * 2470 * We'd like to try to omit that last interval when it happens, to 2471 * avoid cluttering data and output with useless stuff. 2472 * So we're going to try to ignore very short intervals (less than 2473 * 10% of the interval time) that have no data. 2474 */ 2475 int interval_ok = 0; 2476 SLIST_FOREACH(sp, &test->streams, streams) { 2477 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); 2478 if (irp) { 2479 double interval_len = timeval_diff(&irp->interval_start_time, 2480 &irp->interval_end_time); 2481 if (test->debug) { 2482 printf("interval_len %f bytes_transferred %lu\n", interval_len, irp->bytes_transferred); 2483 } 2484 2485 /* 2486 * If the interval is at least 10% the normal interval 2487 * length, or if there were actual bytes transferrred, 2488 * then we want to keep this interval. 2489 */ 2490 if (interval_len >= test->stats_interval * 0.10 || 2491 irp->bytes_transferred > 0) { 2492 interval_ok = 1; 2493 if (test->debug) { 2494 printf("interval forces keep\n"); 2495 } 2496 } 2497 } 2498 } 2499 if (!interval_ok) { 2500 if (test->debug) { 2501 printf("ignoring short interval with no data\n"); 2502 } 2503 return; 2504 } 2505 2506 if (test->json_output) { 2507 json_interval = cJSON_CreateObject(); 2508 if (json_interval == NULL) 2509 return; 2510 cJSON_AddItemToArray(test->json_intervals, json_interval); 2511 json_interval_streams = cJSON_CreateArray(); 2512 if (json_interval_streams == NULL) 2513 return; 2514 cJSON_AddItemToObject(json_interval, "streams", json_interval_streams); 2515 } else { 2516 json_interval = NULL; 2517 json_interval_streams = NULL; 2518 } 2519 2520 SLIST_FOREACH(sp, &test->streams, streams) { 2521 print_interval_results(test, sp, json_interval_streams); 2522 /* sum up all streams */ 2523 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); 2524 if (irp == NULL) { 2525 iperf_err(test, "iperf_print_intermediate error: interval_results is NULL"); 2526 return; 2527 } 2528 bytes += irp->bytes_transferred; 2529 if (test->protocol->id == Ptcp) { 2530 if (test->sender && test->sender_has_retransmits) { 2531 retransmits += irp->interval_retrans; 2532 } 2533 } else { 2534 total_packets += irp->interval_packet_count; 2535 lost_packets += irp->interval_cnt_error; 2536 avg_jitter += irp->jitter; 2537 } 2538 } 2539 2540 /* next build string with sum of all streams */ 2541 if (test->num_streams > 1 || test->json_output) { 2542 sp = SLIST_FIRST(&test->streams); /* reset back to 1st stream */ 2543 /* Only do this of course if there was a first stream */ 2544 if (sp) { 2545 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* use 1st stream for timing info */ 2546 2547 unit_snprintf(ubuf, UNIT_LEN, (double) bytes, 'A'); 2548 bandwidth = (double) bytes / (double) irp->interval_duration; 2549 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2550 2551 start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time); 2552 end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time); 2553 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2554 if (test->sender && test->sender_has_retransmits) { 2555 /* Interval sum, TCP with retransmits. */ 2556 if (test->json_output) 2557 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? */ 2558 else 2559 iperf_printf(test, report_sum_bw_retrans_format, start_time, end_time, ubuf, nbuf, retransmits, irp->omitted?report_omitted:""); /* XXX irp->omitted or test->omitting? */ 2560 } else { 2561 /* Interval sum, TCP without retransmits. */ 2562 if (test->json_output) 2563 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)); 2564 else 2565 iperf_printf(test, report_sum_bw_format, start_time, end_time, ubuf, nbuf, test->omitting?report_omitted:""); 2566 } 2567 } else { 2568 /* Interval sum, UDP. */ 2569 if (test->sender) { 2570 if (test->json_output) 2571 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)); 2572 else 2573 iperf_printf(test, report_sum_bw_udp_sender_format, start_time, end_time, ubuf, nbuf, total_packets, test->omitting?report_omitted:""); 2574 } else { 2575 avg_jitter /= test->num_streams; 2576 if (total_packets > 0) { 2577 lost_percent = 100.0 * lost_packets / total_packets; 2578 } 2579 else { 2580 lost_percent = 0.0; 2581 } 2582 if (test->json_output) 2583 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)); 2584 else 2585 iperf_printf(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:""); 2586 } 2587 } 2588 } 2589 } 2590 } 2591 2592 /** 2593 * Print overall summary statistics at the end of a test. 2594 */ 2595 static void 2596 iperf_print_results(struct iperf_test *test) 2597 { 2598 2599 cJSON *json_summary_streams = NULL; 2600 cJSON *json_summary_stream = NULL; 2601 int total_retransmits = 0; 2602 int total_packets = 0, lost_packets = 0; 2603 int sender_packet_count = 0, receiver_packet_count = 0; /* for this stream, this interval */ 2604 int sender_total_packets = 0, receiver_total_packets = 0; /* running total */ 2605 char ubuf[UNIT_LEN]; 2606 char nbuf[UNIT_LEN]; 2607 struct stat sb; 2608 char sbuf[UNIT_LEN]; 2609 struct iperf_stream *sp = NULL; 2610 iperf_size_t bytes_sent, total_sent = 0; 2611 iperf_size_t bytes_received, total_received = 0; 2612 double start_time, end_time = 0.0, avg_jitter = 0.0, lost_percent = 0.0; 2613 double sender_time = 0.0, receiver_time = 0.0; 2614 double bandwidth; 2615 2616 /* print final summary for all intervals */ 2617 2618 if (test->json_output) { 2619 json_summary_streams = cJSON_CreateArray(); 2620 if (json_summary_streams == NULL) 2621 return; 2622 cJSON_AddItemToObject(test->json_end, "streams", json_summary_streams); 2623 } else { 2624 iperf_printf(test, "%s", report_bw_separator); 2625 if (test->verbose) 2626 iperf_printf(test, "%s", report_summary); 2627 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2628 if (test->sender_has_retransmits) 2629 iperf_printf(test, "%s", report_bw_retrans_header); 2630 else 2631 iperf_printf(test, "%s", report_bw_header); 2632 } else 2633 iperf_printf(test, "%s", report_bw_udp_header); 2634 } 2635 2636 start_time = 0.; 2637 sp = SLIST_FIRST(&test->streams); 2638 /* 2639 * If there is at least one stream, then figure out the length of time 2640 * we were running the tests and print out some statistics about 2641 * the streams. It's possible to not have any streams at all 2642 * if the client got interrupted before it got to do anything. 2643 * 2644 * Also note that we try to keep seperate values for the sender 2645 * and receiver ending times. Earlier iperf (3.1 and earlier) 2646 * servers didn't send that to the clients, so in this case we fall 2647 * back to using the client's ending timestamp. The fallback is 2648 * basically emulating what iperf 3.1 did. 2649 */ 2650 if (sp) { 2651 end_time = timeval_diff(&sp->result->start_time, &sp->result->end_time); 2652 if (test->sender) { 2653 sp->result->sender_time = end_time; 2654 if (sp->result->receiver_time == 0.0) { 2655 sp->result->receiver_time = sp->result->sender_time; 2656 } 2657 } 2658 else { 2659 sp->result->receiver_time = end_time; 2660 if (sp->result->sender_time == 0.0) { 2661 sp->result->sender_time = sp->result->receiver_time; 2662 } 2663 } 2664 sender_time = sp->result->sender_time; 2665 receiver_time = sp->result->receiver_time; 2666 SLIST_FOREACH(sp, &test->streams, streams) { 2667 if (test->json_output) { 2668 json_summary_stream = cJSON_CreateObject(); 2669 if (json_summary_stream == NULL) 2670 return; 2671 cJSON_AddItemToArray(json_summary_streams, json_summary_stream); 2672 } 2673 2674 bytes_sent = sp->result->bytes_sent - sp->result->bytes_sent_omit; 2675 bytes_received = sp->result->bytes_received; 2676 total_sent += bytes_sent; 2677 total_received += bytes_received; 2678 2679 if (test->sender) { 2680 sender_packet_count = sp->packet_count; 2681 receiver_packet_count = sp->peer_packet_count; 2682 } 2683 else { 2684 sender_packet_count = sp->peer_packet_count; 2685 receiver_packet_count = sp->packet_count; 2686 } 2687 2688 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2689 if (test->sender_has_retransmits) { 2690 total_retransmits += sp->result->stream_retrans; 2691 } 2692 } else { 2693 /* 2694 * Running total of the total number of packets. Use the sender packet count if we 2695 * have it, otherwise use the receiver packet count. 2696 */ 2697 int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count; 2698 total_packets += (packet_count - sp->omitted_packet_count); 2699 sender_total_packets += (sender_packet_count - sp->omitted_packet_count); 2700 receiver_total_packets += (receiver_packet_count - sp->omitted_packet_count); 2701 lost_packets += (sp->cnt_error - sp->omitted_cnt_error); 2702 avg_jitter += sp->jitter; 2703 } 2704 2705 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A'); 2706 if (sender_time > 0.0) { 2707 bandwidth = (double) bytes_sent / (double) sender_time; 2708 } 2709 else { 2710 bandwidth = 0.0; 2711 } 2712 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2713 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2714 if (test->sender_has_retransmits) { 2715 /* Sender summary, TCP and SCTP with retransmits. */ 2716 if (test->json_output) 2717 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 max_snd_cwnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt))); 2718 else 2719 if (test->role == 's' && !test->sender) { 2720 if (test->verbose) 2721 iperf_printf(test, report_sender_not_available_format, sp->socket); 2722 } 2723 else { 2724 iperf_printf(test, report_bw_retrans_format, sp->socket, start_time, sender_time, ubuf, nbuf, sp->result->stream_retrans, report_sender); 2725 } 2726 } else { 2727 /* Sender summary, TCP and SCTP without retransmits. */ 2728 if (test->json_output) 2729 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) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8)); 2730 else 2731 if (test->role == 's' && !test->sender) { 2732 if (test->verbose) 2733 iperf_printf(test, report_sender_not_available_format, sp->socket); 2734 } 2735 else { 2736 iperf_printf(test, report_bw_format, sp->socket, start_time, sender_time, ubuf, nbuf, report_sender); 2737 } 2738 } 2739 } else { 2740 /* Sender summary, UDP. */ 2741 if (sender_packet_count - sp->omitted_packet_count > 0) { 2742 lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (sender_packet_count - sp->omitted_packet_count); 2743 } 2744 else { 2745 lost_percent = 0.0; 2746 } 2747 if (test->json_output) { 2748 /* 2749 * For hysterical raisins, we only emit one JSON 2750 * object for the UDP summary, and it contains 2751 * information for both the sender and receiver 2752 * side. 2753 * 2754 * The JSON format as currently defined only includes one 2755 * value for the number of packets. We usually want that 2756 * to be the sender's value (how many packets were sent 2757 * by the sender). However this value might not be 2758 * available on the receiver in certain circumstances 2759 * specifically on the server side for a normal test or 2760 * the client side for a reverse-mode test. If this 2761 * is the case, then use the receiver's count of packets 2762 * instead. 2763 */ 2764 int packet_count = sender_packet_count ? sender_packet_count : receiver_packet_count; 2765 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 out_of_order: %d", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (double) sp->jitter * 1000.0, (int64_t) (sp->cnt_error - sp->omitted_cnt_error), (int64_t) (packet_count - sp->omitted_packet_count), (double) lost_percent, (int64_t) (sp->outoforder_packets - sp->omitted_outoforder_packets))); 2766 } 2767 else { 2768 /* 2769 * Due to ordering of messages on the control channel, 2770 * the server cannot report on client-side summary 2771 * statistics. If we're the server, omit one set of 2772 * summary statistics to avoid giving meaningless 2773 * results. 2774 */ 2775 if (test->role == 's' && !test->sender) { 2776 if (test->verbose) 2777 iperf_printf(test, report_sender_not_available_format, sp->socket); 2778 } 2779 else { 2780 iperf_printf(test, report_bw_udp_format, sp->socket, start_time, sender_time, ubuf, nbuf, 0.0, 0, (sender_packet_count - sp->omitted_packet_count), (double) 0, report_sender); 2781 } 2782 if ((sp->outoforder_packets - sp->omitted_outoforder_packets) > 0) 2783 iperf_printf(test, report_sum_outoforder, start_time, sender_time, (sp->outoforder_packets - sp->omitted_outoforder_packets)); 2784 } 2785 } 2786 2787 if (sp->diskfile_fd >= 0) { 2788 if (fstat(sp->diskfile_fd, &sb) == 0) { 2789 /* In the odd case that it's a zero-sized file, say it was all transferred. */ 2790 int percent_sent = 100, percent_received = 100; 2791 if (sb.st_size > 0) { 2792 percent_sent = (int) ( ( (double) bytes_sent / (double) sb.st_size ) * 100.0 ); 2793 percent_received = (int) ( ( (double) bytes_received / (double) sb.st_size ) * 100.0 ); 2794 } 2795 unit_snprintf(sbuf, UNIT_LEN, (double) sb.st_size, 'A'); 2796 if (test->json_output) 2797 cJSON_AddItemToObject(json_summary_stream, "diskfile", iperf_json_printf("sent: %d received: %d size: %d percent_sent: %d percent_received: %d filename: %s", (int64_t) bytes_sent, (int64_t) bytes_received, (int64_t) sb.st_size, (int64_t) percent_sent, (int64_t) percent_received, test->diskfile_name)); 2798 else 2799 if (test->sender) { 2800 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_sent, test->diskfile_name); 2801 } 2802 else { 2803 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A'); 2804 iperf_printf(test, report_diskfile, ubuf, sbuf, percent_received, test->diskfile_name); 2805 } 2806 } 2807 } 2808 2809 unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A'); 2810 if (receiver_time > 0) { 2811 bandwidth = (double) bytes_received / (double) receiver_time; 2812 } 2813 else { 2814 bandwidth = 0.0; 2815 } 2816 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2817 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2818 /* Receiver summary, TCP and SCTP */ 2819 if (test->json_output) 2820 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) receiver_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8)); 2821 else 2822 if (test->role == 's' && test->sender) { 2823 if (test->verbose) 2824 iperf_printf(test, report_receiver_not_available_format, sp->socket); 2825 } 2826 else { 2827 iperf_printf(test, report_bw_format, sp->socket, start_time, receiver_time, ubuf, nbuf, report_receiver); 2828 } 2829 } 2830 else { 2831 /* 2832 * Receiver summary, UDP. Note that JSON was emitted with 2833 * the sender summary, so we only deal with human-readable 2834 * data here. 2835 */ 2836 if (! test->json_output) { 2837 if (receiver_packet_count - sp->omitted_packet_count > 0) { 2838 lost_percent = 100.0 * (sp->cnt_error - sp->omitted_cnt_error) / (receiver_packet_count - sp->omitted_packet_count); 2839 } 2840 else { 2841 lost_percent = 0.0; 2842 } 2843 2844 if (test->role == 's' && test->sender) { 2845 if (test->verbose) 2846 iperf_printf(test, report_receiver_not_available_format, sp->socket); 2847 } 2848 else { 2849 iperf_printf(test, report_bw_udp_format, sp->socket, start_time, receiver_time, ubuf, nbuf, sp->jitter * 1000.0, (sp->cnt_error - sp->omitted_cnt_error), (receiver_packet_count - sp->omitted_packet_count), lost_percent, report_receiver); 2850 } 2851 } 2852 } 2853 } 2854 } 2855 2856 if (test->num_streams > 1 || test->json_output) { 2857 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A'); 2858 /* If no tests were run, arbitrarily set bandwidth to 0. */ 2859 if (sender_time > 0.0) { 2860 bandwidth = (double) total_sent / (double) sender_time; 2861 } 2862 else { 2863 bandwidth = 0.0; 2864 } 2865 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2866 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 2867 if (test->sender_has_retransmits) { 2868 /* Summary sum, TCP with retransmits. */ 2869 if (test->json_output) 2870 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) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8, (int64_t) total_retransmits)); 2871 else 2872 if (test->role == 's' && !test->sender) { 2873 if (test->verbose) 2874 iperf_printf(test, report_sender_not_available_format, sp->socket); 2875 } 2876 else { 2877 iperf_printf(test, report_sum_bw_retrans_format, start_time, sender_time, ubuf, nbuf, total_retransmits, report_sender); 2878 } 2879 } else { 2880 /* Summary sum, TCP without retransmits. */ 2881 if (test->json_output) 2882 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) sender_time, (double) sender_time, (int64_t) total_sent, bandwidth * 8)); 2883 else 2884 if (test->role == 's' && !test->sender) { 2885 if (test->verbose) 2886 iperf_printf(test, report_sender_not_available_format, sp->socket); 2887 } 2888 else { 2889 iperf_printf(test, report_sum_bw_format, start_time, sender_time, ubuf, nbuf, report_sender); 2890 } 2891 } 2892 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A'); 2893 /* If no tests were run, set received bandwidth to 0 */ 2894 if (receiver_time > 0.0) { 2895 bandwidth = (double) total_received / (double) receiver_time; 2896 } 2897 else { 2898 bandwidth = 0.0; 2899 } 2900 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2901 if (test->json_output) 2902 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) receiver_time, (double) receiver_time, (int64_t) total_received, bandwidth * 8)); 2903 else 2904 if (test->role == 's' && test->sender) { 2905 if (test->verbose) 2906 iperf_printf(test, report_receiver_not_available_format, sp->socket); 2907 } 2908 else { 2909 iperf_printf(test, report_sum_bw_format, start_time, receiver_time, ubuf, nbuf, report_receiver); 2910 } 2911 } else { 2912 /* Summary sum, UDP. */ 2913 avg_jitter /= test->num_streams; 2914 /* If no packets were sent, arbitrarily set loss percentage to 0. */ 2915 if (total_packets > 0) { 2916 lost_percent = 100.0 * lost_packets / total_packets; 2917 } 2918 else { 2919 lost_percent = 0.0; 2920 } 2921 if (test->json_output) 2922 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) receiver_time, (double) receiver_time, (int64_t) total_sent, bandwidth * 8, (double) avg_jitter * 1000.0, (int64_t) lost_packets, (int64_t) total_packets, (double) lost_percent)); 2923 else { 2924 /* 2925 * On the client we have both sender and receiver overall summary 2926 * stats. On the server we have only the side that was on the 2927 * server. Output whatever we have. 2928 */ 2929 if (! (test->role == 's' && !test->sender) ) { 2930 unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A'); 2931 iperf_printf(test, report_sum_bw_udp_format, start_time, sender_time, ubuf, nbuf, 0.0, 0, sender_total_packets, 0.0, "sender"); 2932 } 2933 if (! (test->role == 's' && test->sender) ) { 2934 2935 unit_snprintf(ubuf, UNIT_LEN, (double) total_received, 'A'); 2936 /* Compute received bandwidth. */ 2937 if (end_time > 0.0) { 2938 bandwidth = (double) total_received / (double) receiver_time; 2939 } 2940 else { 2941 bandwidth = 0.0; 2942 } 2943 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 2944 iperf_printf(test, report_sum_bw_udp_format, start_time, receiver_time, ubuf, nbuf, avg_jitter * 1000.0, lost_packets, receiver_total_packets, lost_percent, "receiver"); 2945 } 2946 } 2947 } 2948 } 2949 2950 if (test->json_output) { 2951 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])); 2952 if (test->protocol->id == Ptcp) { 2953 char *snd_congestion = NULL, *rcv_congestion = NULL; 2954 if (test->sender) { 2955 snd_congestion = test->congestion_used; 2956 rcv_congestion = test->remote_congestion_used; 2957 } 2958 else { 2959 snd_congestion = test->remote_congestion_used; 2960 rcv_congestion = test->congestion_used; 2961 } 2962 if (snd_congestion) { 2963 cJSON_AddStringToObject(test->json_end, "sender_tcp_congestion", snd_congestion); 2964 } 2965 if (rcv_congestion) { 2966 cJSON_AddStringToObject(test->json_end, "receiver_tcp_congestion", rcv_congestion); 2967 } 2968 } 2969 } 2970 else { 2971 if (test->verbose) { 2972 iperf_printf(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]); 2973 2974 if (test->protocol->id == Ptcp) { 2975 char *snd_congestion = NULL, *rcv_congestion = NULL; 2976 if (test->sender) { 2977 snd_congestion = test->congestion_used; 2978 rcv_congestion = test->remote_congestion_used; 2979 } 2980 else { 2981 snd_congestion = test->remote_congestion_used; 2982 rcv_congestion = test->congestion_used; 2983 } 2984 if (snd_congestion) { 2985 iperf_printf(test, "snd_tcp_congestion %s\n", snd_congestion); 2986 } 2987 if (rcv_congestion) { 2988 iperf_printf(test, "rcv_tcp_congestion %s\n", rcv_congestion); 2989 } 2990 } 2991 } 2992 2993 /* Print server output if we're on the client and it was requested/provided */ 2994 if (test->role == 'c' && iperf_get_test_get_server_output(test)) { 2995 if (test->json_server_output) { 2996 iperf_printf(test, "\nServer JSON output:\n%s\n", cJSON_Print(test->json_server_output)); 2997 cJSON_Delete(test->json_server_output); 2998 test->json_server_output = NULL; 2999 } 3000 if (test->server_output_text) { 3001 iperf_printf(test, "\nServer output:\n%s\n", test->server_output_text); 3002 test->server_output_text = NULL; 3003 } 3004 } 3005 } 3006 } 3007 3008 /**************************************************************************/ 3009 3010 /** 3011 * Main report-printing callback. 3012 * Prints results either during a test (interval report only) or 3013 * after the entire test has been run (last interval report plus 3014 * overall summary). 3015 */ 3016 void 3017 iperf_reporter_callback(struct iperf_test *test) 3018 { 3019 switch (test->state) { 3020 case TEST_RUNNING: 3021 case STREAM_RUNNING: 3022 /* print interval results for each stream */ 3023 iperf_print_intermediate(test); 3024 break; 3025 case TEST_END: 3026 case DISPLAY_RESULTS: 3027 iperf_print_intermediate(test); 3028 iperf_print_results(test); 3029 break; 3030 } 3031 3032 } 3033 3034 /** 3035 * Print the interval results for one stream. 3036 * This function needs to know about the overall test so it can determine the 3037 * context for printing headers, separators, etc. 3038 */ 3039 static void 3040 print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *json_interval_streams) 3041 { 3042 char ubuf[UNIT_LEN]; 3043 char nbuf[UNIT_LEN]; 3044 char cbuf[UNIT_LEN]; 3045 double st = 0., et = 0.; 3046 struct iperf_interval_results *irp = NULL; 3047 double bandwidth, lost_percent; 3048 3049 irp = TAILQ_LAST(&sp->result->interval_results, irlisthead); /* get last entry in linked list */ 3050 if (irp == NULL) { 3051 iperf_err(test, "print_interval_results error: interval_results is NULL"); 3052 return; 3053 } 3054 if (!test->json_output) { 3055 /* First stream? */ 3056 if (sp == SLIST_FIRST(&test->streams)) { 3057 /* It it's the first interval, print the header; 3058 ** else if there's more than one stream, print the separator; 3059 ** else nothing. 3060 */ 3061 if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) { 3062 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 3063 if (test->sender && test->sender_has_retransmits) 3064 iperf_printf(test, "%s", report_bw_retrans_cwnd_header); 3065 else 3066 iperf_printf(test, "%s", report_bw_header); 3067 } else { 3068 if (test->sender) 3069 iperf_printf(test, "%s", report_bw_udp_sender_header); 3070 else 3071 iperf_printf(test, "%s", report_bw_udp_header); 3072 } 3073 } else if (test->num_streams > 1) 3074 iperf_printf(test, "%s", report_bw_separator); 3075 } 3076 } 3077 3078 unit_snprintf(ubuf, UNIT_LEN, (double) (irp->bytes_transferred), 'A'); 3079 if (irp->interval_duration > 0.0) { 3080 bandwidth = (double) irp->bytes_transferred / (double) irp->interval_duration; 3081 } 3082 else { 3083 bandwidth = 0.0; 3084 } 3085 unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format); 3086 3087 st = timeval_diff(&sp->result->start_time, &irp->interval_start_time); 3088 et = timeval_diff(&sp->result->start_time, &irp->interval_end_time); 3089 3090 if (test->protocol->id == Ptcp || test->protocol->id == Psctp) { 3091 if (test->sender && test->sender_has_retransmits) { 3092 /* Interval, TCP with retransmits. */ 3093 if (test->json_output) 3094 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 rtt: %d rttvar: %d pmtu: %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, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted)); 3095 else { 3096 unit_snprintf(cbuf, UNIT_LEN, irp->snd_cwnd, 'A'); 3097 iperf_printf(test, report_bw_retrans_cwnd_format, sp->socket, st, et, ubuf, nbuf, irp->interval_retrans, cbuf, irp->omitted?report_omitted:""); 3098 } 3099 } else { 3100 /* Interval, TCP without retransmits. */ 3101 if (test->json_output) 3102 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)); 3103 else 3104 iperf_printf(test, report_bw_format, sp->socket, st, et, ubuf, nbuf, irp->omitted?report_omitted:""); 3105 } 3106 } else { 3107 /* Interval, UDP. */ 3108 if (test->sender) { 3109 if (test->json_output) 3110 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)); 3111 else 3112 iperf_printf(test, report_bw_udp_sender_format, sp->socket, st, et, ubuf, nbuf, irp->interval_packet_count, irp->omitted?report_omitted:""); 3113 } else { 3114 if (irp->interval_packet_count > 0) { 3115 lost_percent = 100.0 * irp->interval_cnt_error / irp->interval_packet_count; 3116 } 3117 else { 3118 lost_percent = 0.0; 3119 } 3120 if (test->json_output) 3121 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)); 3122 else 3123 iperf_printf(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:""); 3124 } 3125 } 3126 3127 if (test->logfile || test->forceflush) 3128 iflush(test); 3129 } 3130 3131 /**************************************************************************/ 3132 void 3133 iperf_free_stream(struct iperf_stream *sp) 3134 { 3135 struct iperf_interval_results *irp, *nirp; 3136 3137 /* XXX: need to free interval list too! */ 3138 munmap(sp->buffer, sp->test->settings->blksize); 3139 close(sp->buffer_fd); 3140 if (sp->diskfile_fd >= 0) 3141 close(sp->diskfile_fd); 3142 for (irp = TAILQ_FIRST(&sp->result->interval_results); irp != NULL; irp = nirp) { 3143 nirp = TAILQ_NEXT(irp, irlistentries); 3144 free(irp); 3145 } 3146 free(sp->result); 3147 if (sp->send_timer != NULL) 3148 tmr_cancel(sp->send_timer); 3149 free(sp); 3150 } 3151 3152 /**************************************************************************/ 3153 struct iperf_stream * 3154 iperf_new_stream(struct iperf_test *test, int s) 3155 { 3156 struct iperf_stream *sp; 3157 3158 char template[1024]; 3159 if (test->tmp_template) { 3160 snprintf(template, sizeof(template) / sizeof(char), "%s", test->tmp_template); 3161 } else { 3162 //find the system temporary dir *unix, windows, cygwin support 3163 char* tempdir = getenv("TMPDIR"); 3164 if (tempdir == 0){ 3165 tempdir = getenv("TEMP"); 3166 } 3167 if (tempdir == 0){ 3168 tempdir = getenv("TMP"); 3169 } 3170 if (tempdir == 0){ 3171 tempdir = "/tmp"; 3172 } 3173 snprintf(template, sizeof(template) / sizeof(char), "%s/iperf3.XXXXXX", tempdir); 3174 } 3175 3176 sp = (struct iperf_stream *) malloc(sizeof(struct iperf_stream)); 3177 if (!sp) { 3178 i_errno = IECREATESTREAM; 3179 return NULL; 3180 } 3181 3182 memset(sp, 0, sizeof(struct iperf_stream)); 3183 3184 sp->test = test; 3185 sp->settings = test->settings; 3186 sp->result = (struct iperf_stream_result *) malloc(sizeof(struct iperf_stream_result)); 3187 if (!sp->result) { 3188 free(sp); 3189 i_errno = IECREATESTREAM; 3190 return NULL; 3191 } 3192 3193 memset(sp->result, 0, sizeof(struct iperf_stream_result)); 3194 TAILQ_INIT(&sp->result->interval_results); 3195 3196 /* Create and randomize the buffer */ 3197 sp->buffer_fd = mkstemp(template); 3198 if (sp->buffer_fd == -1) { 3199 i_errno = IECREATESTREAM; 3200 free(sp->result); 3201 free(sp); 3202 return NULL; 3203 } 3204 if (unlink(template) < 0) { 3205 i_errno = IECREATESTREAM; 3206 free(sp->result); 3207 free(sp); 3208 return NULL; 3209 } 3210 if (ftruncate(sp->buffer_fd, test->settings->blksize) < 0) { 3211 i_errno = IECREATESTREAM; 3212 free(sp->result); 3213 free(sp); 3214 return NULL; 3215 } 3216 sp->buffer = (char *) mmap(NULL, test->settings->blksize, PROT_READ|PROT_WRITE, MAP_PRIVATE, sp->buffer_fd, 0); 3217 if (sp->buffer == MAP_FAILED) { 3218 i_errno = IECREATESTREAM; 3219 free(sp->result); 3220 free(sp); 3221 return NULL; 3222 } 3223 3224 /* Set socket */ 3225 sp->socket = s; 3226 3227 sp->snd = test->protocol->send; 3228 sp->rcv = test->protocol->recv; 3229 3230 if (test->diskfile_name != (char*) 0) { 3231 sp->diskfile_fd = open(test->diskfile_name, test->sender ? O_RDONLY : (O_WRONLY|O_CREAT|O_TRUNC), S_IRUSR|S_IWUSR); 3232 if (sp->diskfile_fd == -1) { 3233 i_errno = IEFILE; 3234 munmap(sp->buffer, sp->test->settings->blksize); 3235 free(sp->result); 3236 free(sp); 3237 return NULL; 3238 } 3239 sp->snd2 = sp->snd; 3240 sp->snd = diskfile_send; 3241 sp->rcv2 = sp->rcv; 3242 sp->rcv = diskfile_recv; 3243 } else 3244 sp->diskfile_fd = -1; 3245 3246 /* Initialize stream */ 3247 if ((readentropy(sp->buffer, test->settings->blksize) < 0) || 3248 (iperf_init_stream(sp, test) < 0)) { 3249 close(sp->buffer_fd); 3250 munmap(sp->buffer, sp->test->settings->blksize); 3251 free(sp->result); 3252 free(sp); 3253 return NULL; 3254 } 3255 iperf_add_stream(test, sp); 3256 3257 return sp; 3258 } 3259 3260 /**************************************************************************/ 3261 int 3262 iperf_init_stream(struct iperf_stream *sp, struct iperf_test *test) 3263 { 3264 socklen_t len; 3265 int opt; 3266 3267 len = sizeof(struct sockaddr_storage); 3268 if (getsockname(sp->socket, (struct sockaddr *) &sp->local_addr, &len) < 0) { 3269 i_errno = IEINITSTREAM; 3270 return -1; 3271 } 3272 len = sizeof(struct sockaddr_storage); 3273 if (getpeername(sp->socket, (struct sockaddr *) &sp->remote_addr, &len) < 0) { 3274 i_errno = IEINITSTREAM; 3275 return -1; 3276 } 3277 3278 /* Set IP TOS */ 3279 if ((opt = test->settings->tos)) { 3280 if (getsockdomain(sp->socket) == AF_INET6) { 3281 #ifdef IPV6_TCLASS 3282 if (setsockopt(sp->socket, IPPROTO_IPV6, IPV6_TCLASS, &opt, sizeof(opt)) < 0) { 3283 i_errno = IESETCOS; 3284 return -1; 3285 } 3286 #else 3287 i_errno = IESETCOS; 3288 return -1; 3289 #endif 3290 } else { 3291 if (setsockopt(sp->socket, IPPROTO_IP, IP_TOS, &opt, sizeof(opt)) < 0) { 3292 i_errno = IESETTOS; 3293 return -1; 3294 } 3295 } 3296 } 3297 3298 return 0; 3299 } 3300 3301 /**************************************************************************/ 3302 void 3303 iperf_add_stream(struct iperf_test *test, struct iperf_stream *sp) 3304 { 3305 int i; 3306 struct iperf_stream *n, *prev; 3307 3308 if (SLIST_EMPTY(&test->streams)) { 3309 SLIST_INSERT_HEAD(&test->streams, sp, streams); 3310 sp->id = 1; 3311 } else { 3312 // for (n = test->streams, i = 2; n->next; n = n->next, ++i); 3313 i = 2; 3314 SLIST_FOREACH(n, &test->streams, streams) { 3315 prev = n; 3316 ++i; 3317 } 3318 SLIST_INSERT_AFTER(prev, sp, streams); 3319 sp->id = i; 3320 } 3321 } 3322 3323 /* This pair of routines gets inserted into the snd/rcv function pointers 3324 ** when there's a -F flag. They handle the file stuff and call the real 3325 ** snd/rcv functions, which have been saved in snd2/rcv2. 3326 ** 3327 ** The advantage of doing it this way is that in the much more common 3328 ** case of no -F flag, there is zero extra overhead. 3329 */ 3330 3331 static int 3332 diskfile_send(struct iperf_stream *sp) 3333 { 3334 int r; 3335 static int rtot; 3336 3337 /* if needed, read enough data from the disk to fill up the buffer */ 3338 if (sp->diskfile_left < sp->test->settings->blksize && !sp->test->done) { 3339 r = read(sp->diskfile_fd, sp->buffer, sp->test->settings->blksize - 3340 sp->diskfile_left); 3341 rtot += r; 3342 if (sp->test->debug) { 3343 printf("read %d bytes from file, %d total\n", r, rtot); 3344 if (r != sp->test->settings->blksize - sp->diskfile_left) 3345 printf("possible eof\n"); 3346 } 3347 /* If there's no data left in the file or in the buffer, we're done */ 3348 if (r == 0 && sp->diskfile_left == 0) { 3349 sp->test->done = 1; 3350 if (sp->test->debug) 3351 printf("done\n"); 3352 } 3353 } 3354 3355 r = sp->snd2(sp); 3356 if (r < 0) { 3357 return r; 3358 } 3359 /* 3360 * Compute how much data is in the buffer but didn't get sent. 3361 * If there are bytes that got left behind, slide them to the 3362 * front of the buffer so they can hopefully go out on the next 3363 * pass. 3364 */ 3365 sp->diskfile_left = sp->test->settings->blksize - r; 3366 if (sp->diskfile_left && sp->diskfile_left < sp->test->settings->blksize) { 3367 memcpy(sp->buffer, 3368 sp->buffer + (sp->test->settings->blksize - sp->diskfile_left), 3369 sp->diskfile_left); 3370 if (sp->test->debug) 3371 printf("Shifting %d bytes by %d\n", sp->diskfile_left, (sp->test->settings->blksize - sp->diskfile_left)); 3372 } 3373 return r; 3374 } 3375 3376 static int 3377 diskfile_recv(struct iperf_stream *sp) 3378 { 3379 int r; 3380 3381 r = sp->rcv2(sp); 3382 if (r > 0) { 3383 (void) write(sp->diskfile_fd, sp->buffer, r); 3384 (void) fsync(sp->diskfile_fd); 3385 } 3386 return r; 3387 } 3388 3389 3390 void 3391 iperf_catch_sigend(void (*handler)(int)) 3392 { 3393 signal(SIGINT, handler); 3394 signal(SIGTERM, handler); 3395 signal(SIGHUP, handler); 3396 } 3397 3398 /** 3399 * Called as a result of getting a signal. 3400 * Depending on the current state of the test (and the role of this 3401 * process) compute and report one more set of ending statistics 3402 * before cleaning up and exiting. 3403 */ 3404 void 3405 iperf_got_sigend(struct iperf_test *test) 3406 { 3407 /* 3408 * If we're the client, or if we're a server and running a test, 3409 * then dump out the accumulated stats so far. 3410 */ 3411 if (test->role == 'c' || 3412 (test->role == 's' && test->state == TEST_RUNNING)) { 3413 3414 test->done = 1; 3415 cpu_util(test->cpu_util); 3416 test->stats_callback(test); 3417 test->state = DISPLAY_RESULTS; /* change local state only */ 3418 if (test->on_test_finish) 3419 test->on_test_finish(test); 3420 test->reporter_callback(test); 3421 } 3422 3423 if (test->ctrl_sck >= 0) { 3424 test->state = (test->role == 'c') ? CLIENT_TERMINATE : SERVER_TERMINATE; 3425 (void) Nwrite(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp); 3426 } 3427 i_errno = (test->role == 'c') ? IECLIENTTERM : IESERVERTERM; 3428 iperf_errexit(test, "interrupt - %s", iperf_strerror(i_errno)); 3429 } 3430 3431 /* Try to write a PID file if requested, return -1 on an error. */ 3432 int 3433 iperf_create_pidfile(struct iperf_test *test) 3434 { 3435 if (test->pidfile) { 3436 int fd; 3437 char buf[8]; 3438 fd = open(test->pidfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR|S_IWUSR); 3439 if (fd < 0) { 3440 return -1; 3441 } 3442 snprintf(buf, sizeof(buf), "%d", getpid()); /* no trailing newline */ 3443 if (write(fd, buf, strlen(buf) + 1) < 0) { 3444 return -1; 3445 } 3446 if (close(fd) < 0) { 3447 return -1; 3448 }; 3449 } 3450 return 0; 3451 } 3452 3453 /* Get rid of a PID file, return -1 on error. */ 3454 int 3455 iperf_delete_pidfile(struct iperf_test *test) 3456 { 3457 if (test->pidfile) { 3458 if (unlink(test->pidfile) < 0) { 3459 return -1; 3460 } 3461 } 3462 return 0; 3463 } 3464 3465 int 3466 iperf_json_start(struct iperf_test *test) 3467 { 3468 test->json_top = cJSON_CreateObject(); 3469 if (test->json_top == NULL) 3470 return -1; 3471 test->json_start = cJSON_CreateObject(); 3472 if (test->json_start == NULL) 3473 return -1; 3474 cJSON_AddItemToObject(test->json_top, "start", test->json_start); 3475 test->json_connected = cJSON_CreateArray(); 3476 if (test->json_connected == NULL) 3477 return -1; 3478 cJSON_AddItemToObject(test->json_start, "connected", test->json_connected); 3479 test->json_intervals = cJSON_CreateArray(); 3480 if (test->json_intervals == NULL) 3481 return -1; 3482 cJSON_AddItemToObject(test->json_top, "intervals", test->json_intervals); 3483 test->json_end = cJSON_CreateObject(); 3484 if (test->json_end == NULL) 3485 return -1; 3486 cJSON_AddItemToObject(test->json_top, "end", test->json_end); 3487 return 0; 3488 } 3489 3490 int 3491 iperf_json_finish(struct iperf_test *test) 3492 { 3493 if (test->title) 3494 cJSON_AddStringToObject(test->json_top, "title", test->title); 3495 /* Include server output */ 3496 if (test->json_server_output) { 3497 cJSON_AddItemToObject(test->json_top, "server_output_json", test->json_server_output); 3498 } 3499 if (test->server_output_text) { 3500 cJSON_AddStringToObject(test->json_top, "server_output_text", test->server_output_text); 3501 } 3502 test->json_output_string = cJSON_Print(test->json_top); 3503 if (test->json_output_string == NULL) 3504 return -1; 3505 fprintf(test->outfile, "%s\n", test->json_output_string); 3506 iflush(test); 3507 cJSON_Delete(test->json_top); 3508 test->json_top = test->json_start = test->json_connected = test->json_intervals = test->json_server_output = test->json_end = NULL; 3509 return 0; 3510 } 3511 3512 3513 /* CPU affinity stuff - Linux and FreeBSD only. */ 3514 3515 int 3516 iperf_setaffinity(struct iperf_test *test, int affinity) 3517 { 3518 #if defined(HAVE_SCHED_SETAFFINITY) 3519 cpu_set_t cpu_set; 3520 3521 CPU_ZERO(&cpu_set); 3522 CPU_SET(affinity, &cpu_set); 3523 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 3524 i_errno = IEAFFINITY; 3525 return -1; 3526 } 3527 return 0; 3528 #elif defined(HAVE_CPUSET_SETAFFINITY) 3529 cpuset_t cpumask; 3530 3531 if(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 3532 sizeof(cpuset_t), &test->cpumask) != 0) { 3533 i_errno = IEAFFINITY; 3534 return -1; 3535 } 3536 3537 CPU_ZERO(&cpumask); 3538 CPU_SET(affinity, &cpumask); 3539 3540 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 3541 sizeof(cpuset_t), &cpumask) != 0) { 3542 i_errno = IEAFFINITY; 3543 return -1; 3544 } 3545 return 0; 3546 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 3547 i_errno = IEAFFINITY; 3548 return -1; 3549 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 3550 } 3551 3552 int 3553 iperf_clearaffinity(struct iperf_test *test) 3554 { 3555 #if defined(HAVE_SCHED_SETAFFINITY) 3556 cpu_set_t cpu_set; 3557 int i; 3558 3559 CPU_ZERO(&cpu_set); 3560 for (i = 0; i < CPU_SETSIZE; ++i) 3561 CPU_SET(i, &cpu_set); 3562 if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) != 0) { 3563 i_errno = IEAFFINITY; 3564 return -1; 3565 } 3566 return 0; 3567 #elif defined(HAVE_CPUSET_SETAFFINITY) 3568 if(cpuset_setaffinity(CPU_LEVEL_WHICH,CPU_WHICH_PID, -1, 3569 sizeof(cpuset_t), &test->cpumask) != 0) { 3570 i_errno = IEAFFINITY; 3571 return -1; 3572 } 3573 return 0; 3574 #else /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 3575 i_errno = IEAFFINITY; 3576 return -1; 3577 #endif /* neither HAVE_SCHED_SETAFFINITY nor HAVE_CPUSET_SETAFFINITY */ 3578 } 3579 3580 int 3581 iperf_printf(struct iperf_test *test, const char* format, ...) 3582 { 3583 va_list argp; 3584 int r = -1; 3585 3586 /* 3587 * There are roughly two use cases here. If we're the client, 3588 * want to print stuff directly to the output stream. 3589 * If we're the sender we might need to buffer up output to send 3590 * to the client. 3591 * 3592 * This doesn't make a whole lot of difference except there are 3593 * some chunks of output on the client (on particular the whole 3594 * of the server output with --get-server-output) that could 3595 * easily exceed the size of the line buffer, but which don't need 3596 * to be buffered up anyway. 3597 */ 3598 if (test->role == 'c') { 3599 if (test->title) 3600 fprintf(test->outfile, "%s: ", test->title); 3601 va_start(argp, format); 3602 r = vfprintf(test->outfile, format, argp); 3603 va_end(argp); 3604 } 3605 else if (test->role == 's') { 3606 char linebuffer[1024]; 3607 va_start(argp, format); 3608 r = vsnprintf(linebuffer, sizeof(linebuffer), format, argp); 3609 va_end(argp); 3610 fprintf(test->outfile, "%s", linebuffer); 3611 3612 if (test->role == 's' && iperf_get_test_get_server_output(test)) { 3613 struct iperf_textline *l = (struct iperf_textline *) malloc(sizeof(struct iperf_textline)); 3614 l->line = strdup(linebuffer); 3615 TAILQ_INSERT_TAIL(&(test->server_output_list), l, textlineentries); 3616 } 3617 } 3618 return r; 3619 } 3620 3621 int 3622 iflush(struct iperf_test *test) 3623 { 3624 return fflush(test->outfile); 3625 } 3626