1 /* 2 * Copyright (c) 2009-2011, 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 printf("-----------------------------------------------------------\n"); 69 printf("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->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 cpu_util(&test->cpu_util); 185 test->stats_callback(test); 186 SLIST_FOREACH(sp, &test->streams, streams) { 187 FD_CLR(sp->socket, &test->read_set); 188 FD_CLR(sp->socket, &test->write_set); 189 close(sp->socket); 190 } 191 if (iperf_set_send_state(test, EXCHANGE_RESULTS) != 0) 192 return -1; 193 if (iperf_exchange_results(test) < 0) 194 return -1; 195 if (iperf_set_send_state(test, DISPLAY_RESULTS) != 0) 196 return -1; 197 if (test->on_test_finish) 198 test->on_test_finish(test); 199 test->reporter_callback(test); 200 break; 201 case IPERF_DONE: 202 break; 203 case CLIENT_TERMINATE: 204 i_errno = IECLIENTTERM; 205 206 // XXX: Remove this line below! 207 iperf_err(test, "the client has terminated"); 208 SLIST_FOREACH(sp, &test->streams, streams) { 209 FD_CLR(sp->socket, &test->read_set); 210 FD_CLR(sp->socket, &test->write_set); 211 close(sp->socket); 212 } 213 test->state = IPERF_DONE; 214 break; 215 default: 216 i_errno = IEMESSAGE; 217 return -1; 218 } 219 220 return 0; 221 } 222 223 /* XXX: This function is not used anymore */ 224 void 225 iperf_test_reset(struct iperf_test *test) 226 { 227 struct iperf_stream *sp; 228 229 close(test->ctrl_sck); 230 231 /* Free streams */ 232 while (!SLIST_EMPTY(&test->streams)) { 233 sp = SLIST_FIRST(&test->streams); 234 SLIST_REMOVE_HEAD(&test->streams, streams); 235 iperf_free_stream(sp); 236 } 237 if (test->timer != NULL) { 238 tmr_cancel(test->timer); 239 test->timer = NULL; 240 } 241 if (test->stats_timer != NULL) { 242 tmr_cancel(test->stats_timer); 243 test->stats_timer = NULL; 244 } 245 if (test->reporter_timer != NULL) { 246 tmr_cancel(test->reporter_timer); 247 test->reporter_timer = NULL; 248 } 249 250 SLIST_INIT(&test->streams); 251 252 test->role = 's'; 253 set_protocol(test, Ptcp); 254 test->omit = OMIT; 255 test->duration = DURATION; 256 test->diskfile_name = (char*) 0; 257 test->affinity = -1; 258 test->server_affinity = -1; 259 test->title = NULL; 260 test->state = 0; 261 test->server_hostname = NULL; 262 263 test->ctrl_sck = -1; 264 test->prot_listener = -1; 265 266 test->bytes_sent = 0; 267 268 test->reverse = 0; 269 test->sender = 0; 270 test->sender_has_retransmits = 0; 271 test->no_delay = 0; 272 273 FD_ZERO(&test->read_set); 274 FD_ZERO(&test->write_set); 275 FD_SET(test->listener, &test->read_set); 276 test->max_fd = test->listener; 277 278 test->num_streams = 1; 279 test->settings->socket_bufsize = 0; 280 test->settings->blksize = DEFAULT_TCP_BLKSIZE; 281 test->settings->rate = 0; 282 test->settings->mss = 0; 283 memset(test->cookie, 0, COOKIE_SIZE); 284 } 285 286 static void 287 server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) 288 { 289 struct iperf_test *test = client_data.p; 290 291 if (test->done) 292 return; 293 if (test->stats_callback) 294 test->stats_callback(test); 295 } 296 297 static void 298 server_reporter_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->reporter_callback) 305 test->reporter_callback(test); 306 } 307 308 static int 309 create_server_timers(struct iperf_test * test) 310 { 311 struct timeval now; 312 TimerClientData cd; 313 314 if (gettimeofday(&now, NULL) < 0) { 315 i_errno = IEINITTEST; 316 return -1; 317 } 318 cd.p = test; 319 test->stats_timer = test->reporter_timer = NULL; 320 if (test->stats_interval != 0) { 321 test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1); 322 if (test->stats_timer == NULL) { 323 i_errno = IEINITTEST; 324 return -1; 325 } 326 } 327 if (test->reporter_interval != 0) { 328 test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1); 329 if (test->reporter_timer == NULL) { 330 i_errno = IEINITTEST; 331 return -1; 332 } 333 } 334 return 0; 335 } 336 337 static void 338 server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) 339 { 340 struct iperf_test *test = client_data.p; 341 342 test->omit_timer = NULL; 343 test->omitting = 0; 344 iperf_reset_stats(test); 345 if (test->verbose && !test->json_output && test->reporter_interval == 0) 346 iprintf(test, "%s", report_omit_done); 347 348 /* Reset the timers. */ 349 if (test->stats_timer != NULL) 350 tmr_reset(nowP, test->stats_timer); 351 if (test->reporter_timer != NULL) 352 tmr_reset(nowP, test->reporter_timer); 353 } 354 355 static int 356 create_server_omit_timer(struct iperf_test * test) 357 { 358 struct timeval now; 359 TimerClientData cd; 360 361 if (test->omit == 0) { 362 test->omit_timer = NULL; 363 test->omitting = 0; 364 } else { 365 if (gettimeofday(&now, NULL) < 0) { 366 i_errno = IEINITTEST; 367 return -1; 368 } 369 test->omitting = 1; 370 cd.p = test; 371 test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0); 372 if (test->omit_timer == NULL) { 373 i_errno = IEINITTEST; 374 return -1; 375 } 376 } 377 378 return 0; 379 } 380 381 static void 382 cleanup_server(struct iperf_test *test) 383 { 384 /* Close open test sockets */ 385 close(test->ctrl_sck); 386 close(test->listener); 387 388 /* Cancel any remaining timers. */ 389 if (test->stats_timer != NULL) { 390 tmr_cancel(test->stats_timer); 391 test->stats_timer = NULL; 392 } 393 if (test->reporter_timer != NULL) { 394 tmr_cancel(test->reporter_timer); 395 test->reporter_timer = NULL; 396 } 397 if (test->omit_timer != NULL) { 398 tmr_cancel(test->omit_timer); 399 test->omit_timer = NULL; 400 } 401 } 402 403 404 static jmp_buf sigend_jmp_buf; 405 406 static void 407 sigend_handler(int sig) 408 { 409 longjmp(sigend_jmp_buf, 1); 410 } 411 412 413 int 414 iperf_run_server(struct iperf_test *test) 415 { 416 int result, s, streams_accepted; 417 fd_set read_set, write_set; 418 struct iperf_stream *sp; 419 struct timeval now; 420 struct timeval* timeout; 421 422 /* Termination signals. */ 423 iperf_catch_sigend(sigend_handler); 424 if (setjmp(sigend_jmp_buf)) 425 iperf_got_sigend(test); 426 427 if (test->affinity != -1) 428 if (iperf_setaffinity(test->affinity) != 0) 429 return -1; 430 431 if (test->json_output) 432 if (iperf_json_start(test) < 0) 433 return -1; 434 435 if (test->json_output) { 436 cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version)); 437 cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info())); 438 } else if (test->verbose) { 439 iprintf(test, "%s\n", version); 440 iprintf(test, "%s", ""); 441 fflush(stdout); 442 system("uname -a"); 443 } 444 445 // Open socket and listen 446 if (iperf_server_listen(test) < 0) { 447 return -1; 448 } 449 450 // Begin calculating CPU utilization 451 cpu_util(NULL); 452 453 test->state = IPERF_START; 454 streams_accepted = 0; 455 456 while (test->state != IPERF_DONE) { 457 458 memcpy(&read_set, &test->read_set, sizeof(fd_set)); 459 memcpy(&write_set, &test->write_set, sizeof(fd_set)); 460 461 (void) gettimeofday(&now, NULL); 462 timeout = tmr_timeout(&now); 463 result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); 464 if (result < 0 && errno != EINTR) { 465 cleanup_server(test); 466 i_errno = IESELECT; 467 return -1; 468 } 469 if (result > 0) { 470 if (FD_ISSET(test->listener, &read_set)) { 471 if (test->state != CREATE_STREAMS) { 472 if (iperf_accept(test) < 0) { 473 cleanup_server(test); 474 return -1; 475 } 476 FD_CLR(test->listener, &read_set); 477 } 478 } 479 if (FD_ISSET(test->ctrl_sck, &read_set)) { 480 if (iperf_handle_message_server(test) < 0) { 481 cleanup_server(test); 482 return -1; 483 } 484 FD_CLR(test->ctrl_sck, &read_set); 485 } 486 487 if (test->state == CREATE_STREAMS) { 488 if (FD_ISSET(test->prot_listener, &read_set)) { 489 490 if ((s = test->protocol->accept(test)) < 0) { 491 cleanup_server(test); 492 return -1; 493 } 494 495 if (!is_closed(s)) { 496 sp = iperf_new_stream(test, s); 497 if (!sp) { 498 cleanup_server(test); 499 return -1; 500 } 501 502 if (test->sender) 503 FD_SET(s, &test->write_set); 504 else 505 FD_SET(s, &test->read_set); 506 if (s > test->max_fd) test->max_fd = s; 507 508 streams_accepted++; 509 if (test->on_new_stream) 510 test->on_new_stream(sp); 511 } 512 FD_CLR(test->prot_listener, &read_set); 513 } 514 515 if (streams_accepted == test->num_streams) { 516 if (test->protocol->id != Ptcp) { 517 FD_CLR(test->prot_listener, &test->read_set); 518 close(test->prot_listener); 519 } else { 520 if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) { 521 FD_CLR(test->listener, &test->read_set); 522 close(test->listener); 523 if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) { 524 cleanup_server(test); 525 i_errno = IELISTEN; 526 return -1; 527 } 528 test->listener = s; 529 FD_SET(test->listener, &test->read_set); 530 if (test->listener > test->max_fd) test->max_fd = test->listener; 531 } 532 } 533 test->prot_listener = -1; 534 if (iperf_set_send_state(test, TEST_START) != 0) { 535 cleanup_server(test); 536 return -1; 537 } 538 if (iperf_init_test(test) < 0) { 539 cleanup_server(test); 540 return -1; 541 } 542 if (create_server_timers(test) < 0) { 543 cleanup_server(test); 544 return -1; 545 } 546 if (create_server_omit_timer(test) < 0) { 547 cleanup_server(test); 548 return -1; 549 } 550 if (test->reverse) 551 if (iperf_create_send_timers(test) < 0) { 552 cleanup_server(test); 553 return -1; 554 } 555 if (iperf_set_send_state(test, TEST_RUNNING) != 0) { 556 cleanup_server(test); 557 return -1; 558 } 559 } 560 } 561 562 if (test->state == TEST_RUNNING) { 563 if (test->reverse) { 564 // Reverse mode. Server sends. 565 if (iperf_send(test, &write_set) < 0) { 566 cleanup_server(test); 567 return -1; 568 } 569 } else { 570 // Regular mode. Server receives. 571 if (iperf_recv(test, &read_set) < 0) { 572 cleanup_server(test); 573 return -1; 574 } 575 } 576 577 if (result == 0 || 578 (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) { 579 /* Run the timers. */ 580 (void) gettimeofday(&now, NULL); 581 tmr_run(&now); 582 } 583 } 584 } 585 } 586 587 cleanup_server(test); 588 589 if (test->json_output) { 590 if (iperf_json_finish(test) < 0) 591 return -1; 592 } 593 594 if (test->server_affinity != -1) 595 if (iperf_clearaffinity() != 0) 596 return -1; 597 598 return 0; 599 } 600