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