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