File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / iperf / src / iperf_server_api.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:36:46 2021 UTC (3 years, 4 months ago) by misho
Branches: iperf, MAIN
CVS tags: v3_3_9, HEAD
iperf 3.3.9

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>