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