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 #include <errno.h> 11 #include <setjmp.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <signal.h> 17 #include <sys/types.h> 18 #include <sys/select.h> 19 #include <sys/uio.h> 20 #include <arpa/inet.h> 21 22 #include "iperf.h" 23 #include "iperf_api.h" 24 #include "iperf_util.h" 25 #include "locale.h" 26 #include "net.h" 27 #include "timer.h" 28 29 30 int 31 iperf_create_streams(struct iperf_test *test) 32 { 33 int i, s; 34 struct iperf_stream *sp; 35 36 for (i = 0; i < test->num_streams; ++i) { 37 38 if ((s = test->protocol->connect(test)) < 0) 39 return -1; 40 41 if (test->sender) 42 FD_SET(s, &test->write_set); 43 else 44 FD_SET(s, &test->read_set); 45 if (s > test->max_fd) test->max_fd = s; 46 47 sp = iperf_new_stream(test, s); 48 if (!sp) 49 return -1; 50 51 /* Perform the new stream callback */ 52 if (test->on_new_stream) 53 test->on_new_stream(sp); 54 } 55 56 return 0; 57 } 58 59 static void 60 test_timer_proc(TimerClientData client_data, struct timeval *nowP) 61 { 62 struct iperf_test *test = client_data.p; 63 64 test->timer = NULL; 65 test->done = 1; 66 } 67 68 static void 69 client_stats_timer_proc(TimerClientData client_data, struct timeval *nowP) 70 { 71 struct iperf_test *test = client_data.p; 72 73 if (test->done) 74 return; 75 if (test->stats_callback) 76 test->stats_callback(test); 77 } 78 79 static void 80 client_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP) 81 { 82 struct iperf_test *test = client_data.p; 83 84 if (test->done) 85 return; 86 if (test->reporter_callback) 87 test->reporter_callback(test); 88 } 89 90 static int 91 create_client_timers(struct iperf_test * test) 92 { 93 struct timeval now; 94 TimerClientData cd; 95 96 if (gettimeofday(&now, NULL) < 0) { 97 i_errno = IEINITTEST; 98 return -1; 99 } 100 cd.p = test; 101 test->timer = test->stats_timer = test->reporter_timer = NULL; 102 if (test->duration != 0) { 103 test->done = 0; 104 test->timer = tmr_create(&now, test_timer_proc, cd, ( test->duration + test->omit ) * SEC_TO_US, 0); 105 if (test->timer == NULL) { 106 i_errno = IEINITTEST; 107 return -1; 108 } 109 } 110 if (test->stats_interval != 0) { 111 test->stats_timer = tmr_create(&now, client_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1); 112 if (test->stats_timer == NULL) { 113 i_errno = IEINITTEST; 114 return -1; 115 } 116 } 117 if (test->reporter_interval != 0) { 118 test->reporter_timer = tmr_create(&now, client_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1); 119 if (test->reporter_timer == NULL) { 120 i_errno = IEINITTEST; 121 return -1; 122 } 123 } 124 return 0; 125 } 126 127 static void 128 client_omit_timer_proc(TimerClientData client_data, struct timeval *nowP) 129 { 130 struct iperf_test *test = client_data.p; 131 132 test->omit_timer = NULL; 133 test->omitting = 0; 134 iperf_reset_stats(test); 135 if (test->verbose && !test->json_output && test->reporter_interval == 0) 136 iprintf(test, "%s", report_omit_done); 137 138 /* Reset the timers. */ 139 if (test->stats_timer != NULL) 140 tmr_reset(nowP, test->stats_timer); 141 if (test->reporter_timer != NULL) 142 tmr_reset(nowP, test->reporter_timer); 143 } 144 145 static int 146 create_client_omit_timer(struct iperf_test * test) 147 { 148 struct timeval now; 149 TimerClientData cd; 150 151 if (test->omit == 0) { 152 test->omit_timer = NULL; 153 test->omitting = 0; 154 } else { 155 if (gettimeofday(&now, NULL) < 0) { 156 i_errno = IEINITTEST; 157 return -1; 158 } 159 test->omitting = 1; 160 cd.p = test; 161 test->omit_timer = tmr_create(&now, client_omit_timer_proc, cd, test->omit * SEC_TO_US, 0); 162 if (test->omit_timer == NULL) { 163 i_errno = IEINITTEST; 164 return -1; 165 } 166 } 167 return 0; 168 } 169 170 int 171 iperf_handle_message_client(struct iperf_test *test) 172 { 173 int rval; 174 int32_t err; 175 176 /*!!! Why is this read() and not Nread()? */ 177 if ((rval = read(test->ctrl_sck, (char*) &test->state, sizeof(signed char))) <= 0) { 178 if (rval == 0) { 179 i_errno = IECTRLCLOSE; 180 return -1; 181 } else { 182 i_errno = IERECVMESSAGE; 183 return -1; 184 } 185 } 186 187 switch (test->state) { 188 case PARAM_EXCHANGE: 189 if (iperf_exchange_parameters(test) < 0) 190 return -1; 191 if (test->on_connect) 192 test->on_connect(test); 193 break; 194 case CREATE_STREAMS: 195 if (iperf_create_streams(test) < 0) 196 return -1; 197 break; 198 case TEST_START: 199 if (iperf_init_test(test) < 0) 200 return -1; 201 if (create_client_timers(test) < 0) 202 return -1; 203 if (create_client_omit_timer(test) < 0) 204 return -1; 205 if (!test->reverse) 206 if (iperf_create_send_timers(test) < 0) 207 return -1; 208 break; 209 case TEST_RUNNING: 210 break; 211 case EXCHANGE_RESULTS: 212 if (iperf_exchange_results(test) < 0) 213 return -1; 214 break; 215 case DISPLAY_RESULTS: 216 if (test->on_test_finish) 217 test->on_test_finish(test); 218 iperf_client_end(test); 219 break; 220 case IPERF_DONE: 221 break; 222 case SERVER_TERMINATE: 223 i_errno = IESERVERTERM; 224 225 /* 226 * Temporarily be in DISPLAY_RESULTS phase so we can get 227 * ending summary statistics. 228 */ 229 signed char oldstate = test->state; 230 cpu_util(test->cpu_util); 231 test->state = DISPLAY_RESULTS; 232 test->reporter_callback(test); 233 test->state = oldstate; 234 return -1; 235 case ACCESS_DENIED: 236 i_errno = IEACCESSDENIED; 237 return -1; 238 case SERVER_ERROR: 239 if (Nread(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 240 i_errno = IECTRLREAD; 241 return -1; 242 } 243 i_errno = ntohl(err); 244 if (Nread(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) { 245 i_errno = IECTRLREAD; 246 return -1; 247 } 248 errno = ntohl(err); 249 return -1; 250 default: 251 i_errno = IEMESSAGE; 252 return -1; 253 } 254 255 return 0; 256 } 257 258 259 260 /* iperf_connect -- client to server connection function */ 261 int 262 iperf_connect(struct iperf_test *test) 263 { 264 FD_ZERO(&test->read_set); 265 FD_ZERO(&test->write_set); 266 267 make_cookie(test->cookie); 268 269 /* Create and connect the control channel */ 270 if (test->ctrl_sck < 0) 271 test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, test->server_hostname, test->server_port); 272 if (test->ctrl_sck < 0) { 273 i_errno = IECONNECT; 274 return -1; 275 } 276 277 if (Nwrite(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) { 278 i_errno = IESENDCOOKIE; 279 return -1; 280 } 281 282 FD_SET(test->ctrl_sck, &test->read_set); 283 if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck; 284 285 return 0; 286 } 287 288 289 int 290 iperf_client_end(struct iperf_test *test) 291 { 292 struct iperf_stream *sp; 293 294 /* Close all stream sockets */ 295 SLIST_FOREACH(sp, &test->streams, streams) { 296 close(sp->socket); 297 } 298 299 /* show final summary */ 300 test->reporter_callback(test); 301 302 if (iperf_set_send_state(test, IPERF_DONE) != 0) 303 return -1; 304 305 return 0; 306 } 307 308 309 static jmp_buf sigend_jmp_buf; 310 311 static void 312 sigend_handler(int sig) 313 { 314 longjmp(sigend_jmp_buf, 1); 315 } 316 317 318 typedef enum { cm_select, cm_itimer } cm_t; 319 320 static int sigalrm_triggered; 321 322 static void 323 sigalrm_handler(int sig) 324 { 325 sigalrm_triggered = 1; 326 } 327 328 int 329 iperf_run_client(struct iperf_test * test) 330 { 331 cm_t concurrency_model; 332 int startup; 333 int result = 0; 334 fd_set read_set, write_set; 335 struct timeval now; 336 struct timeval* timeout = NULL; 337 struct itimerval itv; 338 339 /* Termination signals. */ 340 iperf_catch_sigend(sigend_handler); 341 if (setjmp(sigend_jmp_buf)) 342 iperf_got_sigend(test); 343 344 if (test->affinity != -1) 345 if (iperf_setaffinity(test, test->affinity) != 0) 346 return -1; 347 348 if (test->json_output) 349 if (iperf_json_start(test) < 0) 350 return -1; 351 352 if (test->json_output) { 353 cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version)); 354 cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info())); 355 } else if (test->verbose) { 356 iprintf(test, "%s\n", version); 357 iprintf(test, "%s", ""); 358 fflush(stdout); 359 printf("%s\n", get_system_info()); 360 } 361 362 /* Start the client and connect to the server */ 363 if (iperf_connect(test) < 0) 364 return -1; 365 366 /* Begin calculating CPU utilization */ 367 cpu_util(NULL); 368 369 startup = 1; 370 concurrency_model = cm_select; /* always start in select mode */ 371 while (test->state != IPERF_DONE) { 372 373 if (concurrency_model == cm_select) { 374 memcpy(&read_set, &test->read_set, sizeof(fd_set)); 375 memcpy(&write_set, &test->write_set, sizeof(fd_set)); 376 (void) gettimeofday(&now, NULL); 377 timeout = tmr_timeout(&now); 378 result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout); 379 if (result < 0 && errno != EINTR) { 380 i_errno = IESELECT; 381 return -1; 382 } 383 if (result > 0) { 384 if (FD_ISSET(test->ctrl_sck, &read_set)) { 385 if (iperf_handle_message_client(test) < 0) { 386 return -1; 387 } 388 FD_CLR(test->ctrl_sck, &read_set); 389 } 390 } 391 } 392 393 if (test->state == TEST_RUNNING) { 394 395 /* Is this our first time really running? */ 396 if (startup) { 397 startup = 0; 398 /* Decide which concurrency model to use for the real test. 399 ** SIGALRM is less overhead but there are a bunch of cases 400 ** where it either won't work or is ill-advised. 401 */ 402 if (test->may_use_sigalrm && test->settings->rate == 0 && 403 (test->stats_interval == 0 || test->stats_interval > 0.2) && 404 (test->reporter_interval == 0 || test->reporter_interval > 0.2) && 405 (test->omit == 0 || test->omit > 0.2) && 406 ! test->reverse) { 407 concurrency_model = cm_itimer; 408 test->multisend = 1; 409 signal(SIGALRM, sigalrm_handler); 410 sigalrm_triggered = 0; 411 itv.it_interval.tv_sec = 0; 412 itv.it_interval.tv_usec = 100000; 413 itv.it_value.tv_sec = 0; 414 itv.it_value.tv_usec = 100000; 415 (void) setitimer(ITIMER_REAL, &itv, NULL); 416 } 417 418 } 419 420 if (test->reverse) { 421 // Reverse mode. Client receives. 422 if (iperf_recv(test, &read_set) < 0) 423 return -1; 424 } else { 425 // Regular mode. Client sends. 426 if (iperf_send(test, concurrency_model == cm_itimer ? NULL : &write_set) < 0) 427 return -1; 428 } 429 430 if ((concurrency_model == cm_select && 431 (result == 0 || 432 (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0))) || 433 (concurrency_model == cm_itimer && sigalrm_triggered)) { 434 /* Run the timers. */ 435 (void) gettimeofday(&now, NULL); 436 tmr_run(&now); 437 if (concurrency_model == cm_itimer) 438 sigalrm_triggered = 0; 439 } 440 441 /* Is the test done yet? */ 442 if ((!test->omitting) && 443 ((test->duration != 0 && test->done) || 444 (test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) || 445 (test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks))) { 446 /* Yes, done! Send TEST_END. */ 447 test->done = 1; 448 cpu_util(test->cpu_util); 449 test->stats_callback(test); 450 if (iperf_set_send_state(test, TEST_END) != 0) 451 return -1; 452 /* If we were doing setitimer(), go back to select() for the end. */ 453 if (concurrency_model == cm_itimer) { 454 itv.it_interval.tv_sec = 0; 455 itv.it_interval.tv_usec = 0; 456 itv.it_value.tv_sec = 0; 457 itv.it_value.tv_usec = 0; 458 (void) setitimer(ITIMER_REAL, &itv, NULL); 459 concurrency_model = cm_select; 460 } 461 } 462 } 463 // If we're in reverse mode, continue draining the data 464 // connection(s) even if test is over. This prevents a 465 // deadlock where the server side fills up its pipe(s) 466 // and gets blocked, so it can't receive state changes 467 // from the client side. 468 else if (test->reverse && test->state == TEST_END) { 469 if (iperf_recv(test, &read_set) < 0) 470 return -1; 471 } 472 } 473 474 if (test->json_output) { 475 if (iperf_json_finish(test) < 0) 476 return -1; 477 } else { 478 iprintf(test, "\n"); 479 iprintf(test, "%s", report_done); 480 } 481 482 return 0; 483 } 484