1 /* 2 * iperf, Copyright (c) 2014, 2015, 2016, 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 25 * file for complete information. 26 */ 27 /* iperf_server_api.c: Functions to be used by an iperf server 28 */ 29 30 #include <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <getopt.h> 34 #include <errno.h> 35 #include <unistd.h> 36 #include <assert.h> 37 #include <fcntl.h> 38 #include <sys/socket.h> 39 #include <sys/types.h> 40 #include <netinet/in.h> 41 #include <arpa/inet.h> 42 #include <netdb.h> 43 #ifdef HAVE_STDINT_H 44 #include <stdint.h> 45 #endif 46 #include <sys/time.h> 47 #include <sys/resource.h> 48 #include <sched.h> 49 #include <setjmp.h> 50 51 #include "iperf.h" 52 #include "iperf_api.h" 53 #include "iperf_udp.h" 54 #include "iperf_tcp.h" 55 #include "iperf_util.h" 56 #include "timer.h" 57 #include "net.h" 58 #include "units.h" 59 #include "iperf_util.h" 60 #include "iperf_locale.h" 61 62 #if defined(HAVE_TCP_CONGESTION) 63 #if !defined(TCP_CA_NAME_MAX) 64 #define TCP_CA_NAME_MAX 16 65 #endif /* TCP_CA_NAME_MAX */ 66 #endif /* HAVE_TCP_CONGESTION */ 67 68 int 69 iperf_server_listen(struct iperf_test *test) 70 { 71 retry: 72 if((test->listener = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) { 73 if (errno == EAFNOSUPPORT && (test->settings->domain == AF_INET6 || test->settings->domain == AF_UNSPEC)) { 74 /* If we get "Address family not supported by protocol", that 75 ** probably means we were compiled with IPv6 but the running 76 ** kernel does not actually do IPv6. This is not too unusual, 77 ** v6 support is and perhaps always will be spotty. 78 */ 79 warning("this system does not seem to support IPv6 - trying IPv4"); 80 test->settings->domain = AF_INET; 81 goto retry; 82 } else { 83 i_errno = IELISTEN; 84 return -1; 85 } 86 } 87 88 if (!test->json_output) { 89 iperf_printf(test, "-----------------------------------------------------------\n"); 90 iperf_printf(test, "Server listening on %d\n", test->server_port); 91 } 92 93 if (!test->json_output) 94 iperf_printf(test, "-----------------------------------------------------------\n"); 95 96 FD_ZERO(&test->read_set); 97 FD_ZERO(&test->write_set); 98 FD_SET(test->listener, &test->read_set); 99 if (test->listener > test->max_fd) test->max_fd = test->listener; 100 101 return 0; 102 } 103 104 int 105 iperf_accept(struct iperf_test *test) 106 { 107 int s; 108 signed char rbuf = ACCESS_DENIED; 109 socklen_t len; 110 struct sockaddr_storage addr; 111 112 len = sizeof(addr); 113 if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) { 114 i_errno = IEACCEPT; 115 return -1; 116 } 117 118 if (test->ctrl_sck == -1) { 119 /* Server free, accept new client */ 120 test->ctrl_sck = s; 121 if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) { 122 i_errno = IERECVCOOKIE; 123 return -1; 124 } 125 FD_SET(test->ctrl_sck, &test->read_set); 126 if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck; 127 128 if (iperf_set_send_state(test, PARAM_EXCHANGE) != 0) 129 return -1; 130 if (iperf_exchange_parameters(test) < 0) 131 return -1; 132 if (test->server_affinity != -1) 133 if (iperf_setaffinity(test, test->server_affinity) != 0) 134 return -1; 135 if (test->on_connect) 136 test->on_connect(test); 137 } else { 138 /* 139 * Don't try to read from the socket. It could block an ongoing test. 140 * Just send ACCESS_DENIED. 141 */ 142 if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) { 143 i_errno = IESENDMESSAGE; 144 return -1; 145 } 146 close(s); 147 } 148 149 return 0; 150 } 151 152 153 /**************************************************************************/ 154 int 155 iperf_handle_message_server(struct iperf_test *test) 156 { 157 int rval; 158 struct iperf_stream *sp; 159 160 // XXX: Need to rethink how this behaves to fit API 161 if ((rval = Nread(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp)) <= 0) { 162 if (rval == 0) { 163 iperf_err(test, "the client has unexpectedly closed the connection"); 164 i_errno = IECTRLCLOSE; 165 test->state = IPERF_DONE; 166 return 0; 167 } else { 168 i_errno = IERECVMESSAGE; 169 return -1; 170 } 171 } 172 173 switch(test->state) { 174 case TEST_START: 175 break; 176 case TEST_END: 177 test->done = 1; 178 cpu_util(test->cpu_util); 179 test->stats_callback(test); 180 SLIST_FOREACH(sp, &test->streams, streams) { 181 FD_CLR(sp->socket, &test->read_set); 182 FD_CLR(sp->socket, &test->write_set); 183 close(sp->socket); 184 } 185 test->reporter_callback(test); 186 if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0) 187 return -1; 188 if (iperf_exchange_results(test) < 0) 189 return -1; 190 if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0) 191 return -1; 192 if (test->on_test_finish) 193 test->on_test_finish(test); 194 break; 195 case IPERF_DONE: 196 break; 197 case CLIENT_TERMINATE: 198 i_errno = IECLIENTTERM; 199 200 // Temporarily be in DISPLAY_RESULTS phase so we can get 201 // ending summary statistics. 202 signed char oldstate = test->state; 203 cpu_util(test->cpu_util); 204 test->state = DISPLAY_RESULTS; 205 test->reporter_callback(test); 206 test->state = oldstate; 207 208 // XXX: Remove this line below! 209 iperf_err(test, "the client has terminated"); 210 SLIST_FOREACH(sp, &test->streams, streams) { 211 FD_CLR(sp->socket, &test->read_set); 212 FD_CLR(sp->socket, &test->write_set); 213 close(sp->socket); 214 } 215 test->state = IPERF_DONE; 216 break; 217 default: 218 i_errno = IEMESSAGE; 219 return -1; 220 } 221 222 return 0; 223 } 224 225 /* XXX: This function is not used anymore */ 226 void 227 iperf_test_reset(struct iperf_test *test) 228 { 229 struct iperf_stream *sp; 230 231 close(test->ctrl_sck); 232 233 /* Free streams */ 234 while (!SLIST_EMPTY(&test->streams)) { 235 sp = SLIST_FIRST(&test->streams); 236 SLIST_REMOVE_HEAD(&test->streams, streams); 237 iperf_free_stream(sp); 238 } 239 if (test->timer != NULL) { 240 tmr_cancel(test->timer); 241 test->timer = NULL; 242 } 243 if (test->stats_timer != NULL) { 244 tmr_cancel(test->stats_timer); 245 test->stats_timer = NULL; 246 } 247 if (test->reporter_timer != NULL) { 248 tmr_cancel(test->reporter_timer); 249 test->reporter_timer = NULL; 250 } 251 test->done = 0; 252 253 SLIST_INIT(&test->streams); 254 255 test->role = 's'; 256 set_protocol(test, Ptcp); 257 test->omit = OMIT; 258 test->duration = DURATION; 259 test->diskfile_name = (char*) 0; 260 test->affinity = -1; 261 test->server_affinity = -1; 262 test->title = NULL; 263 test->congestion = NULL; 264 test->state = 0; 265 test->server_hostname = NULL; 266 267 test->ctrl_sck = -1; 268 test->prot_listener = -1; 269 270 test->bytes_sent = 0; 271 272 test->reverse = 0; 273 test->sender = 0; 274 test->sender_has_retransmits = 0; 275 test->no_delay = 0; 276 277 FD_ZERO(&test->read_set); 278 FD_ZERO(&test->write_set); 279 FD_SET(test->listener, &test->read_set); 280 test->max_fd = test->listener; 281 282 test->num_streams = 1; 283 test->settings->socket_bufsize = 0; 284 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 285 test->settings->rate = 0; 286 test->settings->mss = 0; 287 memset(test->cookie, 0, COOKIE_SIZE); 288 } 289 290 static void 291 server_timer_proc(TimerClientData client_data, struct timeval *nowP) 292 { 293 struct iperf_test *test = client_data.p; 294 struct iperf_stream *sp; 295 296 test->timer = NULL; 297 if (test->done) 298 return; 299 test->done = 1; 300 /* Free streams */ 301 while (!SLIST_EMPTY(&test->streams)) { 302 sp = SLIST_FIRST(&test->streams); 303 SLIST_REMOVE_HEAD(&test->streams, streams); 304 close(sp->socket); 305 iperf_free_stream(sp); 306 } 307 close(test->ctrl_sck); 308 } 309 310 static void 311 server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) 312 { 313 struct iperf_test *test = client_data.p; 314 315 if (test->done) 316 return; 317 if (test->stats_callback) 318 test->stats_callback(test); 319 } 320 321 static void 322 server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) 323 { 324 struct iperf_test *test = client_data.p; 325 326 if (test->done) 327 return; 328 if (test->reporter_callback) 329 test->reporter_callback(test); 330 } 331 332 static int 333 create_server_timers(struct iperf_test * test) 334 { 335 struct timeval now; 336 TimerClientData cd; 337 338 if (gettimeofday(&now, NULL) < 0) { 339 i_errno = IEINITTEST; 340 return -1; 341 } 342 cd.p = test; 343 test->timer = test->stats_timer = test->reporter_timer = NULL; 344 if (test->duration != 0 ) { 345 test->done = 0; 346 test->timer = tmr_create(&now, server_timer_proc, cd, (test->duration + test->omit + 5) * SEC_TO_US, 0); 347 if (test->timer == NULL) { 348 i_errno = IEINITTEST; 349 return -1; 350 } 351 } 352 353 test->stats_timer = test->reporter_timer = NULL; 354 if (test->stats_interval != 0) { 355 test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1); 356 if (test->stats_timer == NULL) { 357 i_errno = IEINITTEST; 358 return -1; 359 } 360 } 361 if (test->reporter_interval != 0) { 362 test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1); 363 if (test->reporter_timer == NULL) { 364 i_errno = IEINITTEST; 365 return -1; 366 } 367 } 368 return 0; 369 } 370 371 static void 372 server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) 373 { 374 struct iperf_test *test = client_data.p; 375 376 test->omit_timer = NULL; 377 test->omitting = 0; 378 iperf_reset_stats(test); 379 if (test->verbose && !test->json_output && test->reporter_interval == 0) 380 iperf_printf(test, "%s", report_omit_done); 381 382 /* Reset the timers. */ 383 if (test->stats_timer != NULL) 384 tmr_reset(nowP, test->stats_timer); 385 if (test->reporter_timer != NULL) 386 tmr_reset(nowP, test->reporter_timer); 387 } 388 389 static int 390 create_server_omit_timer(struct iperf_test * test) 391 { 392 struct timeval now; 393 TimerClientData cd; 394 395 if (test->omit == 0) { 396 test->omit_timer = NULL; 397 test->omitting = 0; 398 } else { 399 if (gettimeofday(&now, NULL) < 0) { 400 i_errno = IEINITTEST; 401 return -1; 402 } 403 test->omitting = 1; 404 cd.p = test; 405 test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0); 406 if (test->omit_timer == NULL) { 407 i_errno = IEINITTEST; 408 return -1; 409 } 410 } 411 412 return 0; 413 } 414 415 static void 416 cleanup_server(struct iperf_test *test) 417 { 418 /* Close open test sockets */ 419 if (test->ctrl_sck) { 420 close(test->ctrl_sck); 421 } 422 if (test->listener) { 423 close(test->listener); 424 } 425 426 /* Cancel any remaining timers. */ 427 if (test->stats_timer != NULL) { 428 tmr_cancel(test->stats_timer); 429 test->stats_timer = NULL; 430 } 431 if (test->reporter_timer != NULL) { 432 tmr_cancel(test->reporter_timer); 433 test->reporter_timer = NULL; 434 } 435 if (test->omit_timer != NULL) { 436 tmr_cancel(test->omit_timer); 437 test->omit_timer = NULL; 438 } 439 if (test->congestion_used != NULL) { 440 free(test->congestion_used); 441 test->congestion_used = NULL; 442 } 443 if (test->timer != NULL) { 444 tmr_cancel(test->timer); 445 test->timer = NULL; 446 } 447 } 448 449 450 int 451 iperf_run_server(struct iperf_test *test) 452 { 453 int result, s, streams_accepted; 454 fd_set read_set, write_set; 455 struct iperf_stream *sp; 456 struct timeval now; 457 struct timeval* timeout; 458 459 if (test->affinity != -1) 460 if (iperf_setaffinity(test, test->affinity) != 0) 461 return -2; 462 463 if (test->json_output) 464 if (iperf_json_start(test) < 0) 465 return -2; 466 467 if (test->json_output) { 468 cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version)); 469 cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info())); 470 } else if (test->verbose) { 471 iperf_printf(test, "%s\n", version); 472 iperf_printf(test, "%s", ""); 473 iperf_printf(test, "%s\n", get_system_info()); 474 iflush(test); 475 } 476 477 // Open socket and listen 478 if (iperf_server_listen(test) < 0) { 479 return -2; 480 } 481 482 // Begin calculating CPU utilization 483 cpu_util(NULL); 484 485 test->state = IPERF_START; 486 streams_accepted = 0; 487 488 while (test->state != IPERF_DONE) { 489 490 memcpy(&read_set, &test->read_set, sizeof(fd_set)); 491 memcpy(&write_set, &test->write_set, sizeof(fd_set)); 492 493 (void) gettimeofday(&now, NULL); 494 timeout = tmr_timeout(&now); 495 result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); 496 if (result < 0 && errno != EINTR) { 497 cleanup_server(test); 498 i_errno = IESELECT; 499 return -1; 500 } 501 if (result > 0) { 502 if (FD_ISSET(test->listener, &read_set)) { 503 if (test->state != CREATE_STREAMS) { 504 if (iperf_accept(test) < 0) { 505 cleanup_server(test); 506 return -1; 507 } 508 FD_CLR(test->listener, &read_set); 509 } 510 } 511 if (FD_ISSET(test->ctrl_sck, &read_set)) { 512 if (iperf_handle_message_server(test) < 0) { 513 cleanup_server(test); 514 return -1; 515 } 516 FD_CLR(test->ctrl_sck, &read_set); 517 } 518 519 if (test->state == CREATE_STREAMS) { 520 if (FD_ISSET(test->prot_listener, &read_set)) { 521 522 if ((s = test->protocol->accept(test)) < 0) { 523 cleanup_server(test); 524 return -1; 525 } 526 527 #if defined(HAVE_TCP_CONGESTION) 528 if (test->protocol->id == Ptcp) { 529 if (test->congestion) { 530 if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) { 531 /* 532 * ENOENT means we tried to set the 533 * congestion algorithm but the algorithm 534 * specified doesn't exist. This can happen 535 * if the client and server have different 536 * congestion algorithms available. In this 537 * case, print a warning, but otherwise 538 * continue. 539 */ 540 if (errno == ENOENT) { 541 warning("TCP congestion control algorithm not supported"); 542 } 543 else { 544 close(s); 545 cleanup_server(test); 546 i_errno = IESETCONGESTION; 547 return -1; 548 } 549 } 550 } 551 { 552 socklen_t len = TCP_CA_NAME_MAX; 553 char ca[TCP_CA_NAME_MAX + 1]; 554 if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) { 555 close(s); 556 cleanup_server(test); 557 i_errno = IESETCONGESTION; 558 return -1; 559 } 560 test->congestion_used = strdup(ca); 561 if (test->debug) { 562 printf("Congestion algorithm is %s\n", test->congestion_used); 563 } 564 } 565 } 566 #endif /* HAVE_TCP_CONGESTION */ 567 568 if (!is_closed(s)) { 569 sp = iperf_new_stream(test, s); 570 if (!sp) { 571 cleanup_server(test); 572 return -1; 573 } 574 575 if (test->sender) 576 FD_SET(s, &test->write_set); 577 else 578 FD_SET(s, &test->read_set); 579 if (s > test->max_fd) test->max_fd = s; 580 581 /* 582 * If the protocol isn't UDP, or even if it is but 583 * we're the receiver, set nonblocking sockets. 584 * We need this to allow a server receiver to 585 * maintain interactivity with the control channel. 586 */ 587 if (test->protocol->id != Pudp || 588 !test->sender) { 589 setnonblocking(s, 1); 590 } 591 592 streams_accepted++; 593 if (test->on_new_stream) 594 test->on_new_stream(sp); 595 } 596 FD_CLR(test->prot_listener, &read_set); 597 } 598 599 if (streams_accepted == test->num_streams) { 600 if (test->protocol->id != Ptcp) { 601 FD_CLR(test->prot_listener, &test->read_set); 602 close(test->prot_listener); 603 } else { 604 if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) { 605 FD_CLR(test->listener, &test->read_set); 606 close(test->listener); 607 test->listener = 0; 608 if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) { 609 cleanup_server(test); 610 i_errno = IELISTEN; 611 return -1; 612 } 613 test->listener = s; 614 FD_SET(test->listener, &test->read_set); 615 if (test->listener > test->max_fd) test->max_fd = test->listener; 616 } 617 } 618 test->prot_listener = -1; 619 if (iperf_set_send_state(test, TEST_START) != 0) { 620 cleanup_server(test); 621 return -1; 622 } 623 if (iperf_init_test(test) < 0) { 624 cleanup_server(test); 625 return -1; 626 } 627 if (create_server_timers(test) < 0) { 628 cleanup_server(test); 629 return -1; 630 } 631 if (create_server_omit_timer(test) < 0) { 632 cleanup_server(test); 633 return -1; 634 } 635 if (test->reverse) 636 if (iperf_create_send_timers(test) < 0) { 637 cleanup_server(test); 638 return -1; 639 } 640 if (iperf_set_send_state(test, TEST_RUNNING) != 0) { 641 cleanup_server(test); 642 return -1; 643 } 644 } 645 } 646 647 if (test->state == TEST_RUNNING) { 648 if (test->reverse) { 649 // Reverse mode. Server sends. 650 if (iperf_send(test, &write_set) < 0) { 651 cleanup_server(test); 652 return -1; 653 } 654 } else { 655 // Regular mode. Server receives. 656 if (iperf_recv(test, &read_set) < 0) { 657 cleanup_server(test); 658 return -1; 659 } 660 } 661 } 662 } 663 664 if (result == 0 || 665 (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) { 666 /* Run the timers. */ 667 (void) gettimeofday(&now, NULL); 668 tmr_run(&now); 669 } 670 } 671 672 cleanup_server(test); 673 674 if (test->json_output) { 675 if (iperf_json_finish(test) < 0) 676 return -1; 677 } 678 679 iflush(test); 680 681 if (test->server_affinity != -1) 682 if (iperf_clearaffinity(test) != 0) 683 return -1; 684 685 return 0; 686 } 687