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