1 /* 2 * Copyright (c) 2009-2014, The Regents of the University of California, 3 * through Lawrence Berkeley National Laboratory (subject to receipt of any 4 * required approvals from the U.S. Dept. of Energy). All rights reserved. 5 * 6 * This code is distributed under a BSD style license, see the LICENSE file 7 * for complete information. 8 */ 9 10 /* iperf_server_api.c: Functions to be used by an iperf server 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <getopt.h> 17 #include <errno.h> 18 #include <unistd.h> 19 #include <assert.h> 20 #include <fcntl.h> 21 #include <sys/socket.h> 22 #include <sys/types.h> 23 #include <netinet/in.h> 24 #include <arpa/inet.h> 25 #include <netdb.h> 26 #include <pthread.h> 27 #include <stdint.h> 28 #include <netinet/tcp.h> 29 #include <sys/time.h> 30 #include <sys/resource.h> 31 #include <sched.h> 32 #include <setjmp.h> 33 34 #include "iperf.h" 35 #include "iperf_api.h" 36 #include "iperf_udp.h" 37 #include "iperf_tcp.h" 38 #include "iperf_util.h" 39 #include "timer.h" 40 #include "net.h" 41 #include "units.h" 42 #include "tcp_window_size.h" 43 #include "iperf_util.h" 44 #include "locale.h" 45 46 47 int 48 iperf_server_listen(struct iperf_test *test) 49 { 50 retry: 51 if((test->listener = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) { 52 if (errno == EAFNOSUPPORT && (test->settings->domain == AF_INET6 || test->settings->domain == AF_UNSPEC)) { 53 /* If we get "Address family not supported by protocol", that 54 ** probably means we were compiled with IPv6 but the running 55 ** kernel does not actually do IPv6. This is not too unusual, 56 ** v6 support is and perhaps always will be spotty. 57 */ 58 warning("this system does not seem to support IPv6 - trying IPv4"); 59 test->settings->domain = AF_INET; 60 goto retry; 61 } else { 62 i_errno = IELISTEN; 63 return -1; 64 } 65 } 66 67 if (!test->json_output) { 68 iprintf(test, "-----------------------------------------------------------\n"); 69 iprintf(test, "Server listening on %d\n", test->server_port); 70 } 71 72 // This needs to be changed to reflect if client has different window size 73 // make sure we got what we asked for 74 /* XXX: This needs to be moved to the stream listener 75 if ((x = get_tcp_windowsize(test->listener, SO_RCVBUF)) < 0) { 76 // Needs to set some sort of error number/message 77 perror("SO_RCVBUF"); 78 return -1; 79 } 80 */ 81 82 // XXX: This code needs to be moved to after parameter exhange 83 /* 84 char ubuf[UNIT_LEN]; 85 int x; 86 87 if (test->protocol->id == Ptcp) { 88 if (test->settings->socket_bufsize > 0) { 89 unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A'); 90 if (!test->json_output) 91 iprintf(test, report_window, ubuf); 92 } else { 93 if (!test->json_output) 94 iprintf(test, "%s", report_autotune); 95 } 96 } 97 */ 98 if (!test->json_output) 99 iprintf(test, "-----------------------------------------------------------\n"); 100 101 FD_ZERO(&test->read_set); 102 FD_ZERO(&test->write_set); 103 FD_SET(test->listener, &test->read_set); 104 if (test->listener > test->max_fd) test->max_fd = test->listener; 105 106 return 0; 107 } 108 109 int 110 iperf_accept(struct iperf_test *test) 111 { 112 int s; 113 signed char rbuf = ACCESS_DENIED; 114 char cookie[COOKIE_SIZE]; 115 socklen_t len; 116 struct sockaddr_storage addr; 117 118 len = sizeof(addr); 119 if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) { 120 i_errno = IEACCEPT; 121 return -1; 122 } 123 124 if (test->ctrl_sck == -1) { 125 /* Server free, accept new client */ 126 test->ctrl_sck = s; 127 if (Nread(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) { 128 i_errno = IERECVCOOKIE; 129 return -1; 130 } 131 FD_SET(test->ctrl_sck, &test->read_set); 132 if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck; 133 134 if (iperf_set_send_state(test, PARAM_EXCHANGE) != 0) 135 return -1; 136 if (iperf_exchange_parameters(test) < 0) 137 return -1; 138 if (test->server_affinity != -1) 139 if (iperf_setaffinity(test, test->server_affinity) != 0) 140 return -1; 141 if (test->on_connect) 142 test->on_connect(test); 143 } else { 144 /* XXX: Do we even need to receive cookie if we're just going to deny anyways? */ 145 if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) { 146 i_errno = IERECVCOOKIE; 147 return -1; 148 } 149 if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) { 150 i_errno = IESENDMESSAGE; 151 return -1; 152 } 153 close(s); 154 } 155 156 return 0; 157 } 158 159 160 /**************************************************************************/ 161 int 162 iperf_handle_message_server(struct iperf_test *test) 163 { 164 int rval; 165 struct iperf_stream *sp; 166 167 // XXX: Need to rethink how this behaves to fit API 168 if ((rval = Nread(test->ctrl_sck, (char*) &test->state, sizeof(signed char), Ptcp)) <= 0) { 169 if (rval == 0) { 170 iperf_err(test, "the client has unexpectedly closed the connection"); 171 i_errno = IECTRLCLOSE; 172 test->state = IPERF_DONE; 173 return 0; 174 } else { 175 i_errno = IERECVMESSAGE; 176 return -1; 177 } 178 } 179 180 switch(test->state) { 181 case TEST_START: 182 break; 183 case TEST_END: 184 test->done = 1; 185 cpu_util(test->cpu_util); 186 test->stats_callback(test); 187 SLIST_FOREACH(sp, &test->streams, streams) { 188 FD_CLR(sp->socket, &test->read_set); 189 FD_CLR(sp->socket, &test->write_set); 190 close(sp->socket); 191 } 192 if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0) 193 return -1; 194 if (iperf_exchange_results(test) < 0) 195 return -1; 196 if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0) 197 return -1; 198 if (test->on_test_finish) 199 test->on_test_finish(test); 200 test->reporter_callback(test); 201 break; 202 case IPERF_DONE: 203 break; 204 case CLIENT_TERMINATE: 205 i_errno = IECLIENTTERM; 206 207 // Temporarily be in DISPLAY_RESULTS phase so we can get 208 // ending summary statistics. 209 signed char oldstate = test->state; 210 cpu_util(test->cpu_util); 211 test->state = DISPLAY_RESULTS; 212 test->reporter_callback(test); 213 test->state = oldstate; 214 215 // XXX: Remove this line below! 216 iperf_err(test, "the client has terminated"); 217 SLIST_FOREACH(sp, &test->streams, streams) { 218 FD_CLR(sp->socket, &test->read_set); 219 FD_CLR(sp->socket, &test->write_set); 220 close(sp->socket); 221 } 222 test->state = IPERF_DONE; 223 break; 224 default: 225 i_errno = IEMESSAGE; 226 return -1; 227 } 228 229 return 0; 230 } 231 232 /* XXX: This function is not used anymore */ 233 void 234 iperf_test_reset(struct iperf_test *test) 235 { 236 struct iperf_stream *sp; 237 238 close(test->ctrl_sck); 239 240 /* Free streams */ 241 while (!SLIST_EMPTY(&test->streams)) { 242 sp = SLIST_FIRST(&test->streams); 243 SLIST_REMOVE_HEAD(&test->streams, streams); 244 iperf_free_stream(sp); 245 } 246 if (test->timer != NULL) { 247 tmr_cancel(test->timer); 248 test->timer = NULL; 249 } 250 if (test->stats_timer != NULL) { 251 tmr_cancel(test->stats_timer); 252 test->stats_timer = NULL; 253 } 254 if (test->reporter_timer != NULL) { 255 tmr_cancel(test->reporter_timer); 256 test->reporter_timer = NULL; 257 } 258 test->done = 0; 259 260 SLIST_INIT(&test->streams); 261 262 test->role = 's'; 263 set_protocol(test, Ptcp); 264 test->omit = OMIT; 265 test->duration = DURATION; 266 test->diskfile_name = (char*) 0; 267 test->affinity = -1; 268 test->server_affinity = -1; 269 test->title = NULL; 270 test->congestion = NULL; 271 test->state = 0; 272 test->server_hostname = NULL; 273 274 test->ctrl_sck = -1; 275 test->prot_listener = -1; 276 277 test->bytes_sent = 0; 278 279 test->reverse = 0; 280 test->sender = 0; 281 test->sender_has_retransmits = 0; 282 test->no_delay = 0; 283 284 FD_ZERO(&test->read_set); 285 FD_ZERO(&test->write_set); 286 FD_SET(test->listener, &test->read_set); 287 test->max_fd = test->listener; 288 289 test->num_streams = 1; 290 test->settings->socket_bufsize = 0; 291 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 292 test->settings->rate = 0; 293 test->settings->mss = 0; 294 memset(test->cookie, 0, COOKIE_SIZE); 295 } 296 297 static void 298 server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) 299 { 300 struct iperf_test *test = client_data.p; 301 302 if (test->done) 303 return; 304 if (test->stats_callback) 305 test->stats_callback(test); 306 } 307 308 static void 309 server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) 310 { 311 struct iperf_test *test = client_data.p; 312 313 if (test->done) 314 return; 315 if (test->reporter_callback) 316 test->reporter_callback(test); 317 } 318 319 static int 320 create_server_timers(struct iperf_test * test) 321 { 322 struct timeval now; 323 TimerClientData cd; 324 325 if (gettimeofday(&now, NULL) < 0) { 326 i_errno = IEINITTEST; 327 return -1; 328 } 329 cd.p = test; 330 test->stats_timer = test->reporter_timer = NULL; 331 if (test->stats_interval != 0) { 332 test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1); 333 if (test->stats_timer == NULL) { 334 i_errno = IEINITTEST; 335 return -1; 336 } 337 } 338 if (test->reporter_interval != 0) { 339 test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1); 340 if (test->reporter_timer == NULL) { 341 i_errno = IEINITTEST; 342 return -1; 343 } 344 } 345 return 0; 346 } 347 348 static void 349 server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) 350 { 351 struct iperf_test *test = client_data.p; 352 353 test->omit_timer = NULL; 354 test->omitting = 0; 355 iperf_reset_stats(test); 356 if (test->verbose && !test->json_output && test->reporter_interval == 0) 357 iprintf(test, "%s", report_omit_done); 358 359 /* Reset the timers. */ 360 if (test->stats_timer != NULL) 361 tmr_reset(nowP, test->stats_timer); 362 if (test->reporter_timer != NULL) 363 tmr_reset(nowP, test->reporter_timer); 364 } 365 366 static int 367 create_server_omit_timer(struct iperf_test * test) 368 { 369 struct timeval now; 370 TimerClientData cd; 371 372 if (test->omit == 0) { 373 test->omit_timer = NULL; 374 test->omitting = 0; 375 } else { 376 if (gettimeofday(&now, NULL) < 0) { 377 i_errno = IEINITTEST; 378 return -1; 379 } 380 test->omitting = 1; 381 cd.p = test; 382 test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0); 383 if (test->omit_timer == NULL) { 384 i_errno = IEINITTEST; 385 return -1; 386 } 387 } 388 389 return 0; 390 } 391 392 static void 393 cleanup_server(struct iperf_test *test) 394 { 395 /* Close open test sockets */ 396 close(test->ctrl_sck); 397 close(test->listener); 398 399 /* Cancel any remaining timers. */ 400 if (test->stats_timer != NULL) { 401 tmr_cancel(test->stats_timer); 402 test->stats_timer = NULL; 403 } 404 if (test->reporter_timer != NULL) { 405 tmr_cancel(test->reporter_timer); 406 test->reporter_timer = NULL; 407 } 408 if (test->omit_timer != NULL) { 409 tmr_cancel(test->omit_timer); 410 test->omit_timer = NULL; 411 } 412 } 413 414 415 static jmp_buf sigend_jmp_buf; 416 417 static void 418 sigend_handler(int sig) 419 { 420 longjmp(sigend_jmp_buf, 1); 421 } 422 423 424 int 425 iperf_run_server(struct iperf_test *test) 426 { 427 int result, s, streams_accepted; 428 fd_set read_set, write_set; 429 struct iperf_stream *sp; 430 struct timeval now; 431 struct timeval* timeout; 432 433 /* Termination signals. */ 434 iperf_catch_sigend(sigend_handler); 435 if (setjmp(sigend_jmp_buf)) 436 iperf_got_sigend(test); 437 438 if (test->affinity != -1) 439 if (iperf_setaffinity(test, test->affinity) != 0) 440 return -1; 441 442 if (test->json_output) 443 if (iperf_json_start(test) < 0) 444 return -1; 445 446 if (test->json_output) { 447 cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version)); 448 cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info())); 449 } else if (test->verbose) { 450 iprintf(test, "%s\n", version); 451 iprintf(test, "%s", ""); 452 iprintf(test, "%s\n", get_system_info()); 453 iflush(test); 454 } 455 456 // Open socket and listen 457 if (iperf_server_listen(test) < 0) { 458 return -1; 459 } 460 461 // Begin calculating CPU utilization 462 cpu_util(NULL); 463 464 test->state = IPERF_START; 465 streams_accepted = 0; 466 467 while (test->state != IPERF_DONE) { 468 469 memcpy(&read_set, &test->read_set, sizeof(fd_set)); 470 memcpy(&write_set, &test->write_set, sizeof(fd_set)); 471 472 (void) gettimeofday(&now, NULL); 473 timeout = tmr_timeout(&now); 474 result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); 475 if (result < 0 && errno != EINTR) { 476 cleanup_server(test); 477 i_errno = IESELECT; 478 return -1; 479 } 480 if (result > 0) { 481 if (FD_ISSET(test->listener, &read_set)) { 482 if (test->state != CREATE_STREAMS) { 483 if (iperf_accept(test) < 0) { 484 cleanup_server(test); 485 return -1; 486 } 487 FD_CLR(test->listener, &read_set); 488 } 489 } 490 if (FD_ISSET(test->ctrl_sck, &read_set)) { 491 if (iperf_handle_message_server(test) < 0) { 492 cleanup_server(test); 493 return -1; 494 } 495 FD_CLR(test->ctrl_sck, &read_set); 496 } 497 498 if (test->state == CREATE_STREAMS) { 499 if (FD_ISSET(test->prot_listener, &read_set)) { 500 501 if ((s = test->protocol->accept(test)) < 0) { 502 cleanup_server(test); 503 return -1; 504 } 505 506 if (!is_closed(s)) { 507 sp = iperf_new_stream(test, s); 508 if (!sp) { 509 cleanup_server(test); 510 return -1; 511 } 512 513 if (test->sender) 514 FD_SET(s, &test->write_set); 515 else 516 FD_SET(s, &test->read_set); 517 if (s > test->max_fd) test->max_fd = s; 518 519 streams_accepted++; 520 if (test->on_new_stream) 521 test->on_new_stream(sp); 522 } 523 FD_CLR(test->prot_listener, &read_set); 524 } 525 526 if (streams_accepted == test->num_streams) { 527 if (test->protocol->id != Ptcp) { 528 FD_CLR(test->prot_listener, &test->read_set); 529 close(test->prot_listener); 530 } else { 531 if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) { 532 FD_CLR(test->listener, &test->read_set); 533 close(test->listener); 534 if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) { 535 cleanup_server(test); 536 i_errno = IELISTEN; 537 return -1; 538 } 539 test->listener = s; 540 FD_SET(test->listener, &test->read_set); 541 if (test->listener > test->max_fd) test->max_fd = test->listener; 542 } 543 } 544 test->prot_listener = -1; 545 if (iperf_set_send_state(test, TEST_START) != 0) { 546 cleanup_server(test); 547 return -1; 548 } 549 if (iperf_init_test(test) < 0) { 550 cleanup_server(test); 551 return -1; 552 } 553 if (create_server_timers(test) < 0) { 554 cleanup_server(test); 555 return -1; 556 } 557 if (create_server_omit_timer(test) < 0) { 558 cleanup_server(test); 559 return -1; 560 } 561 if (test->reverse) 562 if (iperf_create_send_timers(test) < 0) { 563 cleanup_server(test); 564 return -1; 565 } 566 if (iperf_set_send_state(test, TEST_RUNNING) != 0) { 567 cleanup_server(test); 568 return -1; 569 } 570 } 571 } 572 573 if (test->state == TEST_RUNNING) { 574 if (test->reverse) { 575 // Reverse mode. Server sends. 576 if (iperf_send(test, &write_set) < 0) { 577 cleanup_server(test); 578 return -1; 579 } 580 } else { 581 // Regular mode. Server receives. 582 if (iperf_recv(test, &read_set) < 0) { 583 cleanup_server(test); 584 return -1; 585 } 586 } 587 } 588 } 589 590 if (result == 0 || 591 (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) { 592 /* Run the timers. */ 593 (void) gettimeofday(&now, NULL); 594 tmr_run(&now); 595 } 596 } 597 598 cleanup_server(test); 599 600 if (test->json_output) { 601 if (iperf_json_finish(test) < 0) 602 return -1; 603 } 604 605 iflush(test); 606 607 if (test->server_affinity != -1) 608 if (iperf_clearaffinity(test) != 0) 609 return -1; 610 611 return 0; 612 } 613