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