xref: /iperf/src/iperf_server_api.c (revision b1bc12a2)
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_timer_proc(TimerClientData client_data, struct timeval *nowP)
320 {
321     struct iperf_test *test = client_data.p;
322     struct iperf_stream *sp;
323 
324     test->timer = NULL;
325     if (test->done)
326         return;
327     test->done = 1;
328     /* Free streams */
329     while (!SLIST_EMPTY(&test->streams)) {
330         sp = SLIST_FIRST(&test->streams);
331         SLIST_REMOVE_HEAD(&test->streams, streams);
332         close(sp->socket);
333         iperf_free_stream(sp);
334     }
335     close(test->ctrl_sck);
336 }
337 
338 static void
339 server_stats_timer_proc(TimerClientData client_data, struct timeval *nowP)
340 {
341     struct iperf_test *test = client_data.p;
342 
343     if (test->done)
344         return;
345     if (test->stats_callback)
346 	test->stats_callback(test);
347 }
348 
349 static void
350 server_reporter_timer_proc(TimerClientData client_data, struct timeval *nowP)
351 {
352     struct iperf_test *test = client_data.p;
353 
354     if (test->done)
355         return;
356     if (test->reporter_callback)
357 	test->reporter_callback(test);
358 }
359 
360 static int
361 create_server_timers(struct iperf_test * test)
362 {
363     struct timeval now;
364     TimerClientData cd;
365 
366     if (gettimeofday(&now, NULL) < 0) {
367 	i_errno = IEINITTEST;
368 	return -1;
369     }
370     cd.p = test;
371     test->timer = test->stats_timer = test->reporter_timer = NULL;
372     if (test->duration != 0 ) {
373         test->done = 0;
374         test->timer = tmr_create(&now, server_timer_proc, cd, (test->duration + test->omit + 5) * SEC_TO_US, 0);
375         if (test->timer == NULL) {
376             i_errno = IEINITTEST;
377             return -1;
378         }
379     }
380 
381     test->stats_timer = test->reporter_timer = NULL;
382     if (test->stats_interval != 0) {
383         test->stats_timer = tmr_create(&now, server_stats_timer_proc, cd, test->stats_interval * SEC_TO_US, 1);
384         if (test->stats_timer == NULL) {
385             i_errno = IEINITTEST;
386             return -1;
387 	}
388     }
389     if (test->reporter_interval != 0) {
390         test->reporter_timer = tmr_create(&now, server_reporter_timer_proc, cd, test->reporter_interval * SEC_TO_US, 1);
391         if (test->reporter_timer == NULL) {
392             i_errno = IEINITTEST;
393             return -1;
394 	}
395     }
396     return 0;
397 }
398 
399 static void
400 server_omit_timer_proc(TimerClientData client_data, struct timeval *nowP)
401 {
402     struct iperf_test *test = client_data.p;
403 
404     test->omit_timer = NULL;
405     test->omitting = 0;
406     iperf_reset_stats(test);
407     if (test->verbose && !test->json_output && test->reporter_interval == 0)
408 	iperf_printf(test, "%s", report_omit_done);
409 
410     /* Reset the timers. */
411     if (test->stats_timer != NULL)
412 	tmr_reset(nowP, test->stats_timer);
413     if (test->reporter_timer != NULL)
414 	tmr_reset(nowP, test->reporter_timer);
415 }
416 
417 static int
418 create_server_omit_timer(struct iperf_test * test)
419 {
420     struct timeval now;
421     TimerClientData cd;
422 
423     if (test->omit == 0) {
424 	test->omit_timer = NULL;
425 	test->omitting = 0;
426     } else {
427 	if (gettimeofday(&now, NULL) < 0) {
428 	    i_errno = IEINITTEST;
429 	    return -1;
430 	}
431 	test->omitting = 1;
432 	cd.p = test;
433 	test->omit_timer = tmr_create(&now, server_omit_timer_proc, cd, test->omit * SEC_TO_US, 0);
434 	if (test->omit_timer == NULL) {
435 	    i_errno = IEINITTEST;
436 	    return -1;
437 	}
438     }
439 
440     return 0;
441 }
442 
443 static void
444 cleanup_server(struct iperf_test *test)
445 {
446     /* Close open test sockets */
447     if (test->ctrl_sck) {
448 	close(test->ctrl_sck);
449     }
450     if (test->listener) {
451 	close(test->listener);
452     }
453 
454     /* Cancel any remaining timers. */
455     if (test->stats_timer != NULL) {
456 	tmr_cancel(test->stats_timer);
457 	test->stats_timer = NULL;
458     }
459     if (test->reporter_timer != NULL) {
460 	tmr_cancel(test->reporter_timer);
461 	test->reporter_timer = NULL;
462     }
463     if (test->omit_timer != NULL) {
464 	tmr_cancel(test->omit_timer);
465 	test->omit_timer = NULL;
466     }
467     if (test->congestion_used != NULL) {
468         free(test->congestion_used);
469     }
470     if (test->timer != NULL) {
471         tmr_cancel(test->timer);
472         test->timer = NULL;
473     }
474 }
475 
476 
477 int
478 iperf_run_server(struct iperf_test *test)
479 {
480     int result, s, streams_accepted;
481     fd_set read_set, write_set;
482     struct iperf_stream *sp;
483     struct timeval now;
484     struct timeval* timeout;
485 
486     if (test->affinity != -1)
487 	if (iperf_setaffinity(test, test->affinity) != 0)
488 	    return -2;
489 
490     if (test->json_output)
491 	if (iperf_json_start(test) < 0)
492 	    return -2;
493 
494     if (test->json_output) {
495 	cJSON_AddItemToObject(test->json_start, "version", cJSON_CreateString(version));
496 	cJSON_AddItemToObject(test->json_start, "system_info", cJSON_CreateString(get_system_info()));
497     } else if (test->verbose) {
498 	iperf_printf(test, "%s\n", version);
499 	iperf_printf(test, "%s", "");
500 	iperf_printf(test, "%s\n", get_system_info());
501 	iflush(test);
502     }
503 
504     // Open socket and listen
505     if (iperf_server_listen(test) < 0) {
506         return -2;
507     }
508 
509     // Begin calculating CPU utilization
510     cpu_util(NULL);
511 
512     test->state = IPERF_START;
513     streams_accepted = 0;
514 
515     while (test->state != IPERF_DONE) {
516 
517         memcpy(&read_set, &test->read_set, sizeof(fd_set));
518         memcpy(&write_set, &test->write_set, sizeof(fd_set));
519 
520 	(void) gettimeofday(&now, NULL);
521 	timeout = tmr_timeout(&now);
522         result = select(test->max_fd + 1, &read_set, &write_set, NULL, timeout);
523         if (result < 0 && errno != EINTR) {
524 	    cleanup_server(test);
525             i_errno = IESELECT;
526             return -1;
527         }
528 	if (result > 0) {
529             if (FD_ISSET(test->listener, &read_set)) {
530                 if (test->state != CREATE_STREAMS) {
531                     if (iperf_accept(test) < 0) {
532 			cleanup_server(test);
533                         return -1;
534                     }
535                     FD_CLR(test->listener, &read_set);
536                 }
537             }
538             if (FD_ISSET(test->ctrl_sck, &read_set)) {
539                 if (iperf_handle_message_server(test) < 0) {
540 		    cleanup_server(test);
541                     return -1;
542 		}
543                 FD_CLR(test->ctrl_sck, &read_set);
544             }
545 
546             if (test->state == CREATE_STREAMS) {
547                 if (FD_ISSET(test->prot_listener, &read_set)) {
548 
549                     if ((s = test->protocol->accept(test)) < 0) {
550 			cleanup_server(test);
551                         return -1;
552 		    }
553 
554 #if defined(HAVE_TCP_CONGESTION)
555 		    if (test->protocol->id == Ptcp) {
556 			if (test->congestion) {
557 			    if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
558 				/*
559 				 * ENOENT means we tried to set the
560 				 * congestion algorithm but the algorithm
561 				 * specified doesn't exist.  This can happen
562 				 * if the client and server have different
563 				 * congestion algorithms available.  In this
564 				 * case, print a warning, but otherwise
565 				 * continue.
566 				 */
567 				if (errno == ENOENT) {
568 				    warning("TCP congestion control algorithm not supported");
569 				}
570 				else {
571 				    close(s);
572 				    cleanup_server(test);
573 				    i_errno = IESETCONGESTION;
574 				    return -1;
575 				}
576 			    }
577 			}
578 			{
579 			    socklen_t len = TCP_CA_NAME_MAX;
580 			    char ca[TCP_CA_NAME_MAX + 1];
581 			    if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) {
582 				close(s);
583 				cleanup_server(test);
584 				i_errno = IESETCONGESTION;
585 				return -1;
586 			    }
587 			    test->congestion_used = strdup(ca);
588 			    if (test->debug) {
589 				printf("Congestion algorithm is %s\n", test->congestion_used);
590 			    }
591 			}
592 		    }
593 #endif /* HAVE_TCP_CONGESTION */
594 
595                     if (!is_closed(s)) {
596                         sp = iperf_new_stream(test, s);
597                         if (!sp) {
598 			    cleanup_server(test);
599                             return -1;
600 			}
601 
602 			if (test->sender)
603 			    FD_SET(s, &test->write_set);
604 			else
605 			    FD_SET(s, &test->read_set);
606 			if (s > test->max_fd) test->max_fd = s;
607 
608 			/*
609 			 * If the protocol isn't UDP, or even if it is but
610 			 * we're the receiver, set nonblocking sockets.
611 			 * We need this to allow a server receiver to
612 			 * maintain interactivity with the control channel.
613 			 */
614 			if (test->protocol->id != Pudp ||
615 			    !test->sender) {
616 			    setnonblocking(s, 1);
617 			}
618 
619                         streams_accepted++;
620                         if (test->on_new_stream)
621                             test->on_new_stream(sp);
622                     }
623                     FD_CLR(test->prot_listener, &read_set);
624                 }
625 
626                 if (streams_accepted == test->num_streams) {
627                     if (test->protocol->id != Ptcp) {
628                         FD_CLR(test->prot_listener, &test->read_set);
629                         close(test->prot_listener);
630                     } else {
631                         if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
632                             FD_CLR(test->listener, &test->read_set);
633                             close(test->listener);
634 			    test->listener = 0;
635                             if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
636 				cleanup_server(test);
637                                 i_errno = IELISTEN;
638                                 return -1;
639                             }
640                             test->listener = s;
641                             FD_SET(test->listener, &test->read_set);
642 			    if (test->listener > test->max_fd) test->max_fd = test->listener;
643                         }
644                     }
645                     test->prot_listener = -1;
646 		    if (iperf_set_send_state(test, TEST_START) != 0) {
647 			cleanup_server(test);
648                         return -1;
649 		    }
650                     if (iperf_init_test(test) < 0) {
651 			cleanup_server(test);
652                         return -1;
653 		    }
654 		    if (create_server_timers(test) < 0) {
655 			cleanup_server(test);
656                         return -1;
657 		    }
658 		    if (create_server_omit_timer(test) < 0) {
659 			cleanup_server(test);
660                         return -1;
661 		    }
662 		    if (test->reverse)
663 			if (iperf_create_send_timers(test) < 0) {
664 			    cleanup_server(test);
665 			    return -1;
666 			}
667 		    if (iperf_set_send_state(test, TEST_RUNNING) != 0) {
668 			cleanup_server(test);
669                         return -1;
670 		    }
671                 }
672             }
673 
674             if (test->state == TEST_RUNNING) {
675                 if (test->reverse) {
676                     // Reverse mode. Server sends.
677                     if (iperf_send(test, &write_set) < 0) {
678 			cleanup_server(test);
679                         return -1;
680 		    }
681                 } else {
682                     // Regular mode. Server receives.
683                     if (iperf_recv(test, &read_set) < 0) {
684 			cleanup_server(test);
685                         return -1;
686 		    }
687                 }
688             }
689         }
690 
691 	if (result == 0 ||
692 	    (timeout != NULL && timeout->tv_sec == 0 && timeout->tv_usec == 0)) {
693 	    /* Run the timers. */
694 	    (void) gettimeofday(&now, NULL);
695 	    tmr_run(&now);
696 	}
697     }
698 
699     cleanup_server(test);
700 
701     if (test->json_output) {
702 	if (iperf_json_finish(test) < 0)
703 	    return -1;
704     }
705 
706     iflush(test);
707 
708     if (test->server_affinity != -1)
709 	if (iperf_clearaffinity(test) != 0)
710 	    return -1;
711 
712     return 0;
713 }
714