xref: /iperf/src/iperf_client_api.c (revision cde81d76)
1 /*
2  * iperf, Copyright (c) 2014-2018, 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 <netinet/in.h>
36 #include <sys/select.h>
37 #include <sys/uio.h>
38 #include <arpa/inet.h>
39 
40 #include "iperf.h"
41 #include "iperf_api.h"
42 #include "iperf_util.h"
43 #include "iperf_locale.h"
44 #include "iperf_time.h"
45 #include "net.h"
46 #include "timer.h"
47 
48 #if defined(HAVE_TCP_CONGESTION)
49 #if !defined(TCP_CA_NAME_MAX)
50 #define TCP_CA_NAME_MAX 16
51 #endif /* TCP_CA_NAME_MAX */
52 #endif /* HAVE_TCP_CONGESTION */
53 
54 int
55 iperf_create_streams(struct iperf_test *test)
56 {
57     int i, s;
58 #if defined(HAVE_TCP_CONGESTION)
59     int saved_errno;
60 #endif /* HAVE_TCP_CONGESTION */
61     struct iperf_stream *sp;
62 
63     int orig_bind_port = test->bind_port;
64     for (i = 0; i < test->num_streams; ++i) {
65 
66         test->bind_port = orig_bind_port;
67 	if (orig_bind_port)
68 	    test->bind_port += i;
69         if ((s = test->protocol->connect(test)) < 0)
70             return -1;
71 
72 #if defined(HAVE_TCP_CONGESTION)
73 	if (test->protocol->id == Ptcp) {
74 	    if (test->congestion) {
75 		if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
76 		    saved_errno = errno;
77 		    close(s);
78 		    errno = saved_errno;
79 		    i_errno = IESETCONGESTION;
80 		    return -1;
81 		}
82 	    }
83 	    {
84 		socklen_t len = TCP_CA_NAME_MAX;
85 		char ca[TCP_CA_NAME_MAX + 1];
86 		if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) {
87 		    saved_errno = errno;
88 		    close(s);
89 		    errno = saved_errno;
90 		    i_errno = IESETCONGESTION;
91 		    return -1;
92 		}
93 		test->congestion_used = strdup(ca);
94 		if (test->debug) {
95 		    printf("Congestion algorithm is %s\n", test->congestion_used);
96 		}
97 	    }
98 	}
99 #endif /* HAVE_TCP_CONGESTION */
100 
101 	if (test->sender)
102 	    FD_SET(s, &test->write_set);
103 	else
104 	    FD_SET(s, &test->read_set);
105 	if (s > test->max_fd) test->max_fd = s;
106 
107         sp = iperf_new_stream(test, s);
108         if (!sp)
109             return -1;
110 
111         /* Perform the new stream callback */
112         if (test->on_new_stream)
113             test->on_new_stream(sp);
114     }
115 
116     return 0;
117 }
118 
119 static void
120 test_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
121 {
122     struct iperf_test *test = client_data.p;
123 
124     test->timer = NULL;
125     test->done = 1;
126 }
127 
128 static void
129 client_stats_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
130 {
131     struct iperf_test *test = client_data.p;
132 
133     if (test->done)
134         return;
135     if (test->stats_callback)
136 	test->stats_callback(test);
137 }
138 
139 static void
140 client_reporter_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
141 {
142     struct iperf_test *test = client_data.p;
143 
144     if (test->done)
145         return;
146     if (test->reporter_callback)
147 	test->reporter_callback(test);
148 }
149 
150 static int
151 create_client_timers(struct iperf_test * test)
152 {
153     struct iperf_time now;
154     TimerClientData cd;
155 
156     if (iperf_time_now(&now) < 0) {
157 	i_errno = IEINITTEST;
158 	return -1;
159     }
160     cd.p = test;
161     test->timer = test->stats_timer = test->reporter_timer = NULL;
162     if (test->duration != 0) {
163 	test->done = 0;
164         test->timer = tmr_create(&now, test_timer_proc, cd, ( test->duration + test->omit ) * SEC_TO_US, 0);
165         if (test->timer == NULL) {
166             i_errno = IEINITTEST;
167             return -1;
168 	}
169     }
170     if (test->stats_interval != 0) {
171         test->stats_timer = tmr_create(&now, client_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1);
172         if (test->stats_timer == NULL) {
173             i_errno = IEINITTEST;
174             return -1;
175 	}
176     }
177     if (test->reporter_interval != 0) {
178         test->reporter_timer = tmr_create(&now, client_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1);
179         if (test->reporter_timer == NULL) {
180             i_errno = IEINITTEST;
181             return -1;
182 	}
183     }
184     return 0;
185 }
186 
187 static void
188 client_omit_timer_proc(TimerClientData client_data, struct iperf_time *nowP)
189 {
190     struct iperf_test *test = client_data.p;
191 
192     test->omit_timer = NULL;
193     test->omitting = 0;
194     iperf_reset_stats(test);
195     if (test->verbose && !test->json_output && test->reporter_interval == 0)
196         iperf_printf(test, "%s", report_omit_done);
197 
198     /* Reset the timers. */
199     if (test->stats_timer != NULL)
200         tmr_reset(nowP, test->stats_timer);
201     if (test->reporter_timer != NULL)
202         tmr_reset(nowP, test->reporter_timer);
203 }
204 
205 static int
206 create_client_omit_timer(struct iperf_test * test)
207 {
208     struct iperf_time now;
209     TimerClientData cd;
210 
211     if (test->omit == 0) {
212 	test->omit_timer = NULL;
213         test->omitting = 0;
214     } else {
215 	if (iperf_time_now(&now) < 0) {
216 	    i_errno = IEINITTEST;
217 	    return -1;
218 	}
219 	test->omitting = 1;
220 	cd.p = test;
221 	test->omit_timer = tmr_create(&now, client_omit_timer_proc, cd, test->omit * SEC_TO_US, 0);
222 	if (test->omit_timer == NULL) {
223 	    i_errno = IEINITTEST;
224 	    return -1;
225 	}
226     }
227     return 0;
228 }
229 
230 int
231 iperf_handle_message_client(struct iperf_test *test)
232 {
233     int rval;
234     int32_t err;
235 
236     /*!!! Why is this read() and not Nread()? */
237     if ((rval = read(test->ctrl_sck, (char*) &test->state, sizeof(signed char))) <= 0) {
238         if (rval == 0) {
239             i_errno = IECTRLCLOSE;
240             return -1;
241         } else {
242             i_errno = IERECVMESSAGE;
243             return -1;
244         }
245     }
246 
247     switch (test->state) {
248         case PARAM_EXCHANGE:
249             if (iperf_exchange_parameters(test) < 0)
250                 return -1;
251             if (test->on_connect)
252                 test->on_connect(test);
253             break;
254         case CREATE_STREAMS:
255             if (iperf_create_streams(test) < 0)
256                 return -1;
257             break;
258         case TEST_START:
259             if (iperf_init_test(test) < 0)
260                 return -1;
261             if (create_client_timers(test) < 0)
262                 return -1;
263             if (create_client_omit_timer(test) < 0)
264                 return -1;
265 	    if (!test->reverse)
266 		if (iperf_create_send_timers(test) < 0)
267 		    return -1;
268             break;
269         case TEST_RUNNING:
270             break;
271         case EXCHANGE_RESULTS:
272             if (iperf_exchange_results(test) < 0)
273                 return -1;
274             break;
275         case DISPLAY_RESULTS:
276             if (test->on_test_finish)
277                 test->on_test_finish(test);
278             iperf_client_end(test);
279             break;
280         case IPERF_DONE:
281             break;
282         case SERVER_TERMINATE:
283             i_errno = IESERVERTERM;
284 
285 	    /*
286 	     * Temporarily be in DISPLAY_RESULTS phase so we can get
287 	     * ending summary statistics.
288 	     */
289 	    signed char oldstate = test->state;
290 	    cpu_util(test->cpu_util);
291 	    test->state = DISPLAY_RESULTS;
292 	    test->reporter_callback(test);
293 	    test->state = oldstate;
294             return -1;
295         case ACCESS_DENIED:
296             i_errno = IEACCESSDENIED;
297             return -1;
298         case SERVER_ERROR:
299             if (Nread(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
300                 i_errno = IECTRLREAD;
301                 return -1;
302             }
303 	    i_errno = ntohl(err);
304             if (Nread(test->ctrl_sck, (char*) &err, sizeof(err), Ptcp) < 0) {
305                 i_errno = IECTRLREAD;
306                 return -1;
307             }
308             errno = ntohl(err);
309             return -1;
310         default:
311             i_errno = IEMESSAGE;
312             return -1;
313     }
314 
315     return 0;
316 }
317 
318 
319 
320 /* iperf_connect -- client to server connection function */
321 int
322 iperf_connect(struct iperf_test *test)
323 {
324     FD_ZERO(&test->read_set);
325     FD_ZERO(&test->write_set);
326 
327     make_cookie(test->cookie);
328 
329     /* Create and connect the control channel */
330     if (test->ctrl_sck < 0)
331 	// Create the control channel using an ephemeral port
332 	test->ctrl_sck = netdial(test->settings->domain, Ptcp, test->bind_address, 0, test->server_hostname, test->server_port, test->settings->connect_timeout);
333     if (test->ctrl_sck < 0) {
334         i_errno = IECONNECT;
335         return -1;
336     }
337 
338     if (Nwrite(test->ctrl_sck, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
339         i_errno = IESENDCOOKIE;
340         return -1;
341     }
342 
343     FD_SET(test->ctrl_sck, &test->read_set);
344     if (test->ctrl_sck > test->max_fd) test->max_fd = test->ctrl_sck;
345 
346     int opt;
347     socklen_t len;
348 
349     len = sizeof(opt);
350 	if (getsockopt(test->ctrl_sck, IPPROTO_TCP, TCP_MAXSEG, &opt, &len) < 0) {
351 		test->ctrl_sck_mss = 0;
352 	}
353 	else {
354 		if (opt > 0 && opt <= MAX_UDP_BLOCKSIZE) {
355 			test->ctrl_sck_mss = opt;
356 		}
357 		else {
358 			char str[128];
359 			snprintf(str, sizeof(str),
360 				"Ignoring nonsense TCP MSS %d", opt);
361 			warning(str);
362 
363 			test->ctrl_sck_mss = 0;
364 		}
365 	}
366 
367     if (test->verbose) {
368 	printf("Control connection MSS %d\n", test->ctrl_sck_mss);
369     }
370 
371     /*
372      * If we're doing a UDP test and the block size wasn't explicitly
373      * set, then use the known MSS of the control connection to pick
374      * an appropriate default.  If we weren't able to get the
375      * MSS for some reason, then default to something that should
376      * work on non-jumbo-frame Ethernet networks.  The goal is to
377      * pick a reasonable default that is large but should get from
378      * sender to receiver without any IP fragmentation.
379      *
380      * We assume that the control connection is routed the same as the
381      * data packets (thus has the same PMTU).  Also in the case of
382      * --reverse tests, we assume that the MTU is the same in both
383      * directions.  Note that even if the algorithm guesses wrong,
384      * the user always has the option to override.
385      */
386     if (test->protocol->id == Pudp) {
387 	if (test->settings->blksize == 0) {
388 	    if (test->ctrl_sck_mss) {
389 		test->settings->blksize = test->ctrl_sck_mss;
390 	    }
391 	    else {
392 		test->settings->blksize = DEFAULT_UDP_BLKSIZE;
393 	    }
394 	    if (test->verbose) {
395 		printf("Setting UDP block size to %d\n", test->settings->blksize);
396 	    }
397 	}
398 
399 	/*
400 	 * Regardless of whether explicitly or implicitly set, if the
401 	 * block size is larger than the MSS, print a warning.
402 	 */
403 	if (test->ctrl_sck_mss > 0 &&
404 	    test->settings->blksize > test->ctrl_sck_mss) {
405 	    char str[128];
406 	    snprintf(str, sizeof(str),
407 		     "UDP block size %d exceeds TCP MSS %d, may result in fragmentation / drops", test->settings->blksize, test->ctrl_sck_mss);
408 	    warning(str);
409 	}
410     }
411 
412     return 0;
413 }
414 
415 
416 int
417 iperf_client_end(struct iperf_test *test)
418 {
419     struct iperf_stream *sp;
420 
421     /* Close all stream sockets */
422     SLIST_FOREACH(sp, &test->streams, streams) {
423         close(sp->socket);
424     }
425 
426     /* show final summary */
427     test->reporter_callback(test);
428 
429     if (iperf_set_send_state(test, IPERF_DONE) != 0)
430         return -1;
431 
432     /* Close control socket */
433     if (test->ctrl_sck)
434         close(test->ctrl_sck);
435 
436     return 0;
437 }
438 
439 
440 int
441 iperf_run_client(struct iperf_test * test)
442 {
443     int startup;
444     int result = 0;
445     fd_set read_set, write_set;
446     struct iperf_time now;
447     struct timeval* timeout = NULL;
448     struct iperf_stream *sp;
449 
450     if (test->affinity != -1)
451 	if (iperf_setaffinity(test, test->affinity) != 0)
452 	    return -1;
453 
454     if (test->json_output)
455 	if (iperf_json_start(test) < 0)
456 	    return -1;
457 
458     if (test->json_output) {
459 	cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
460 	cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
461     } else if (test->verbose) {
462 	iperf_printf(test, "%s\n", version);
463 	iperf_printf(test, "%s", "");
464 	iperf_printf(test, "%s\n", get_system_info());
465 	iflush(test);
466     }
467 
468     /* Start the client and connect to the server */
469     if (iperf_connect(test) < 0)
470         return -1;
471 
472     /* Begin calculating CPU utilization */
473     cpu_util(NULL);
474 
475     startup = 1;
476     while (test->state != IPERF_DONE) {
477 	memcpy(&read_set, &test->read_set, sizeof(fd_set));
478 	memcpy(&write_set, &test->write_set, sizeof(fd_set));
479 	iperf_time_now(&now);
480 	timeout = tmr_timeout(&now);
481 	result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
482 	if (result < 0 && errno != EINTR) {
483   	    i_errno = IESELECT;
484 	    return -1;
485 	}
486 	if (result > 0) {
487 	    if (FD_ISSET(test->ctrl_sck, &read_set)) {
488  	        if (iperf_handle_message_client(test) < 0) {
489 		    return -1;
490 		}
491 		FD_CLR(test->ctrl_sck, &read_set);
492 	    }
493 	}
494 
495 	if (test->state == TEST_RUNNING) {
496 
497 	    /* Is this our first time really running? */
498 	    if (startup) {
499 	        startup = 0;
500 
501 		// Set non-blocking for non-UDP tests
502 		if (test->protocol->id != Pudp) {
503 		    SLIST_FOREACH(sp, &test->streams, streams) {
504 			setnonblocking(sp->socket, 1);
505 		    }
506 		}
507 	    }
508 
509 	    if (test->reverse) {
510 		// Reverse mode. Client receives.
511 		if (iperf_recv(test, &read_set) < 0)
512 		    return -1;
513 	    } else {
514 		// Regular mode. Client sends.
515 		if (iperf_send(test, &write_set) < 0)
516 		    return -1;
517 	    }
518 
519             /* Run the timers. */
520             iperf_time_now(&now);
521             tmr_run(&now);
522 
523 	    /* Is the test done yet? */
524 	    if ((!test->omitting) &&
525 	        ((test->duration != 0 && test->done) ||
526 	         (test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes) ||
527 	         (test->settings->blocks != 0 && test->blocks_sent >= test->settings->blocks))) {
528 
529 		// Unset non-blocking for non-UDP tests
530 		if (test->protocol->id != Pudp) {
531 		    SLIST_FOREACH(sp, &test->streams, streams) {
532 			setnonblocking(sp->socket, 0);
533 		    }
534 		}
535 
536 		/* Yes, done!  Send TEST_END. */
537 		test->done = 1;
538 		cpu_util(test->cpu_util);
539 		test->stats_callback(test);
540 		if (iperf_set_send_state(test, TEST_END) != 0)
541 		    return -1;
542 	    }
543 	}
544 	// If we're in reverse mode, continue draining the data
545 	// connection(s) even if test is over.  This prevents a
546 	// deadlock where the server side fills up its pipe(s)
547 	// and gets blocked, so it can't receive state changes
548 	// from the client side.
549 	else if (test->reverse && test->state == TEST_END) {
550 	    if (iperf_recv(test, &read_set) < 0)
551 		return -1;
552 	}
553     }
554 
555     if (test->json_output) {
556 	if (iperf_json_finish(test) < 0)
557 	    return -1;
558     } else {
559 	iperf_printf(test, "\n");
560 	iperf_printf(test, "%s", report_done);
561     }
562 
563     iflush(test);
564 
565     return 0;
566 }
567