xref: /iperf/src/iperf_server_api.c (revision 02a35f07)
1a951c980SBrian Tierney 
2a951c980SBrian Tierney /*
3a951c980SBrian Tierney  * Copyright (c) 2009, The Regents of the University of California, through
4a951c980SBrian Tierney  * Lawrence Berkeley National Laboratory (subject to receipt of any required
5a951c980SBrian Tierney  * approvals from the U.S. Dept. of Energy).  All rights reserved.
6a951c980SBrian Tierney  */
7a951c980SBrian Tierney 
8a951c980SBrian Tierney /* iperf_server_api.c: Functions to be used by an iperf server
9a951c980SBrian Tierney */
10a951c980SBrian Tierney 
11a951c980SBrian Tierney #include <stdio.h>
12a951c980SBrian Tierney #include <stdlib.h>
13a951c980SBrian Tierney #include <string.h>
14a951c980SBrian Tierney #include <getopt.h>
15a951c980SBrian Tierney #include <errno.h>
16a951c980SBrian Tierney #include <unistd.h>
17a951c980SBrian Tierney #include <assert.h>
18a951c980SBrian Tierney #include <fcntl.h>
198a0b5a5dSsethdelliott #include <sys/queue.h>
20a951c980SBrian Tierney #include <sys/socket.h>
21a951c980SBrian Tierney #include <sys/types.h>
22a951c980SBrian Tierney #include <netinet/in.h>
23a951c980SBrian Tierney #include <arpa/inet.h>
24a951c980SBrian Tierney #include <netdb.h>
25a951c980SBrian Tierney #include <pthread.h>
26a951c980SBrian Tierney #include <stdint.h>
27a951c980SBrian Tierney #include <netinet/tcp.h>
28a951c980SBrian Tierney #include <sys/time.h>
29a951c980SBrian Tierney #include <sys/resource.h>
30a951c980SBrian Tierney #include <sched.h>
31a951c980SBrian Tierney #include <setjmp.h>
32a951c980SBrian Tierney 
33a951c980SBrian Tierney #include "iperf.h"
34a951c980SBrian Tierney #include "iperf_server_api.h"
35a951c980SBrian Tierney #include "iperf_api.h"
36a951c980SBrian Tierney #include "iperf_udp.h"
37a951c980SBrian Tierney #include "iperf_tcp.h"
38b60a49ddSsethdelliott #include "iperf_error.h"
398a0b5a5dSsethdelliott #include "iperf_util.h"
40a951c980SBrian Tierney #include "timer.h"
41a951c980SBrian Tierney #include "net.h"
42a951c980SBrian Tierney #include "units.h"
43a951c980SBrian Tierney #include "tcp_window_size.h"
44b0b16b86SJon Dugan #include "iperf_util.h"
45a951c980SBrian Tierney #include "locale.h"
46a951c980SBrian Tierney 
47a3281a3dSBrian Tierney 
48982c704aSsethdelliott int
49982c704aSsethdelliott iperf_server_listen(struct iperf_test *test)
50982c704aSsethdelliott {
51982c704aSsethdelliott     char ubuf[UNIT_LEN];
52982c704aSsethdelliott     int x;
53982c704aSsethdelliott 
54f99bd3b2Ssethdelliott     if((test->listener = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
55b60a49ddSsethdelliott         i_errno = IELISTEN;
56b60a49ddSsethdelliott         return (-1);
57982c704aSsethdelliott     }
58982c704aSsethdelliott 
59982c704aSsethdelliott     printf("-----------------------------------------------------------\n");
60982c704aSsethdelliott     printf("Server listening on %d\n", test->server_port);
61982c704aSsethdelliott 
62982c704aSsethdelliott     // This needs to be changed to reflect if client has different window size
63982c704aSsethdelliott     // make sure we got what we asked for
64ba2672a2Ssethdelliott     /* XXX: This needs to be moved to the stream listener
6566ce7ad4Ssethdelliott     if ((x = get_tcp_windowsize(test->listener, SO_RCVBUF)) < 0) {
66982c704aSsethdelliott         // Needs to set some sort of error number/message
67982c704aSsethdelliott         perror("SO_RCVBUF");
68982c704aSsethdelliott         return -1;
69982c704aSsethdelliott     }
70ba2672a2Ssethdelliott     */
71982c704aSsethdelliott 
72ba2672a2Ssethdelliott     // XXX: This code needs to be moved to after parameter exhange
73c81883bfSsethdelliott     /*
7466ce7ad4Ssethdelliott     if (test->protocol->id == Ptcp) {
75112a907cSsethdelliott         if (test->settings->socket_bufsize > 0) {
76982c704aSsethdelliott             unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
77982c704aSsethdelliott             printf("TCP window size: %s\n", ubuf);
78982c704aSsethdelliott         } else {
79982c704aSsethdelliott             printf("Using TCP Autotuning\n");
80982c704aSsethdelliott         }
81982c704aSsethdelliott     }
82c81883bfSsethdelliott     */
83982c704aSsethdelliott     printf("-----------------------------------------------------------\n");
84982c704aSsethdelliott 
85982c704aSsethdelliott     FD_ZERO(&test->read_set);
86efdc02f7Ssethdelliott     FD_ZERO(&test->write_set);
8766ce7ad4Ssethdelliott     FD_SET(test->listener, &test->read_set);
8866ce7ad4Ssethdelliott     test->max_fd = (test->listener > test->max_fd) ? test->listener : test->max_fd;
89982c704aSsethdelliott 
90982c704aSsethdelliott     return 0;
91982c704aSsethdelliott }
92982c704aSsethdelliott 
93982c704aSsethdelliott int
94982c704aSsethdelliott iperf_accept(struct iperf_test *test)
95982c704aSsethdelliott {
96982c704aSsethdelliott     int s;
97465b565cSsethdelliott     int rbuf = ACCESS_DENIED;
98af70b448Ssethdelliott     char cookie[COOKIE_SIZE];
99982c704aSsethdelliott     socklen_t len;
100982c704aSsethdelliott     struct sockaddr_in addr;
101982c704aSsethdelliott 
102b68ac00eSsethdelliott     len = sizeof(addr);
10366ce7ad4Ssethdelliott     if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) {
104b60a49ddSsethdelliott         i_errno = IEACCEPT;
105b60a49ddSsethdelliott         return (-1);
106982c704aSsethdelliott     }
107af70b448Ssethdelliott 
108af70b448Ssethdelliott     if (test->ctrl_sck == -1) {
109af70b448Ssethdelliott         /* Server free, accept new client */
110112a907cSsethdelliott         if (Nread(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
111b60a49ddSsethdelliott             i_errno = IERECVCOOKIE;
112b60a49ddSsethdelliott             return (-1);
113af70b448Ssethdelliott         }
114af70b448Ssethdelliott 
115465b565cSsethdelliott         FD_SET(s, &test->read_set);
116465b565cSsethdelliott         FD_SET(s, &test->write_set);
117465b565cSsethdelliott         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
118465b565cSsethdelliott         test->ctrl_sck = s;
119982c704aSsethdelliott 
120af70b448Ssethdelliott         test->state = PARAM_EXCHANGE;
121af70b448Ssethdelliott         if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
122b60a49ddSsethdelliott             i_errno = IESENDMESSAGE;
123b60a49ddSsethdelliott             return (-1);
124af70b448Ssethdelliott         }
125b60a49ddSsethdelliott         if (iperf_exchange_parameters(test) < 0) {
126b60a49ddSsethdelliott             return (-1);
127b60a49ddSsethdelliott         }
1284df383f6Ssethdelliott         if (test->on_connect) {
1294df383f6Ssethdelliott             test->on_connect(test);
1304df383f6Ssethdelliott         }
131982c704aSsethdelliott     } else {
132b60a49ddSsethdelliott         // XXX: Do we even need to receive cookie if we're just going to deny anyways?
133af70b448Ssethdelliott         if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) {
134b60a49ddSsethdelliott             i_errno = IERECVCOOKIE;
135b60a49ddSsethdelliott             return (-1);
136465b565cSsethdelliott         }
137efb7bbe4Ssethdelliott         if (Nwrite(s, &rbuf, sizeof(int), Ptcp) < 0) {
138b60a49ddSsethdelliott             i_errno = IESENDMESSAGE;
139b60a49ddSsethdelliott             return (-1);
140465b565cSsethdelliott         }
141465b565cSsethdelliott         close(s);
142982c704aSsethdelliott     }
143982c704aSsethdelliott 
144b60a49ddSsethdelliott     return (0);
145af70b448Ssethdelliott }
146af70b448Ssethdelliott 
147b68ac00eSsethdelliott 
148a951c980SBrian Tierney /**************************************************************************/
149982c704aSsethdelliott int
150465b565cSsethdelliott iperf_handle_message_server(struct iperf_test *test)
151982c704aSsethdelliott {
152b68ac00eSsethdelliott     int rval;
153efdc02f7Ssethdelliott     struct iperf_stream *sp;
154efdc02f7Ssethdelliott 
155b60a49ddSsethdelliott     // XXX: Need to rethink how this behaves to fit API
156b60a49ddSsethdelliott     if ((rval = Nread(test->ctrl_sck, &test->state, sizeof(char), Ptcp)) <= 0) {
157b68ac00eSsethdelliott         if (rval == 0) {
158b68ac00eSsethdelliott             fprintf(stderr, "The client has unexpectedly closed the connection.\n");
159b60a49ddSsethdelliott             i_errno = IECTRLCLOSE;
160b68ac00eSsethdelliott             test->state = IPERF_DONE;
161b60a49ddSsethdelliott             return (0);
162b68ac00eSsethdelliott         } else {
163b60a49ddSsethdelliott             i_errno = IERECVMESSAGE;
164b60a49ddSsethdelliott             return (-1);
165982c704aSsethdelliott         }
166b68ac00eSsethdelliott     }
167982c704aSsethdelliott 
168982c704aSsethdelliott     switch(test->state) {
169ba2672a2Ssethdelliott         case TEST_START:
170ba2672a2Ssethdelliott             break;
171465b565cSsethdelliott         case TEST_END:
172f1b3bd81Ssethdelliott             test->stats_callback(test);
173dd4bc008Ssethdelliott             SLIST_FOREACH(sp, &test->streams, streams) {
174efdc02f7Ssethdelliott                 FD_CLR(sp->socket, &test->read_set);
175efdc02f7Ssethdelliott                 FD_CLR(sp->socket, &test->write_set);
176efdc02f7Ssethdelliott                 close(sp->socket);
177efdc02f7Ssethdelliott             }
178181d61afSsethdelliott             test->state = EXCHANGE_RESULTS;
179efb7bbe4Ssethdelliott             if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
180b60a49ddSsethdelliott                 i_errno = IESENDMESSAGE;
181b60a49ddSsethdelliott                 return (-1);
182181d61afSsethdelliott             }
183b60a49ddSsethdelliott             if (iperf_exchange_results(test) < 0)
184b60a49ddSsethdelliott                 return (-1);
185873952e3Ssethdelliott             test->state = DISPLAY_RESULTS;
186efb7bbe4Ssethdelliott             if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
187b60a49ddSsethdelliott                 i_errno = IESENDMESSAGE;
188b60a49ddSsethdelliott                 return (-1);
189465b565cSsethdelliott             }
1904df383f6Ssethdelliott             if (test->on_test_finish)
1914df383f6Ssethdelliott                 test->on_test_finish(test);
192181d61afSsethdelliott             test->reporter_callback(test);
193465b565cSsethdelliott             break;
194873952e3Ssethdelliott         case IPERF_DONE:
195873952e3Ssethdelliott             break;
196465b565cSsethdelliott         case CLIENT_TERMINATE:
197ffdcc7d4Ssethdelliott             i_errno = IECLIENTTERM;
198ffdcc7d4Ssethdelliott 
199ffdcc7d4Ssethdelliott             // XXX: Remove this line below!
2001ac522ecSsethdelliott             fprintf(stderr, "The client has terminated.\n");
201dd4bc008Ssethdelliott             SLIST_FOREACH(sp, &test->streams, streams) {
2021ac522ecSsethdelliott                 FD_CLR(sp->socket, &test->read_set);
2031ac522ecSsethdelliott                 FD_CLR(sp->socket, &test->write_set);
2041ac522ecSsethdelliott                 close(sp->socket);
2051ac522ecSsethdelliott             }
2061ac522ecSsethdelliott             test->state = IPERF_DONE;
2071ac522ecSsethdelliott             break;
208ba2672a2Ssethdelliott         default:
209b60a49ddSsethdelliott             i_errno = IEMESSAGE;
210b60a49ddSsethdelliott             return (-1);
211982c704aSsethdelliott     }
212982c704aSsethdelliott 
213b60a49ddSsethdelliott     return (0);
214982c704aSsethdelliott }
215982c704aSsethdelliott 
2160bd8d9daSsethdelliott /* XXX: This function is not used anymore */
217efdc02f7Ssethdelliott void
218efdc02f7Ssethdelliott iperf_test_reset(struct iperf_test *test)
219efdc02f7Ssethdelliott {
2200bd8d9daSsethdelliott     struct iperf_stream *sp;
221efdc02f7Ssethdelliott 
222efdc02f7Ssethdelliott     close(test->ctrl_sck);
223efdc02f7Ssethdelliott 
224efdc02f7Ssethdelliott     /* Free streams */
225dd4bc008Ssethdelliott     while (!SLIST_EMPTY(&test->streams)) {
226dd4bc008Ssethdelliott         sp = SLIST_FIRST(&test->streams);
227dd4bc008Ssethdelliott         SLIST_REMOVE_HEAD(&test->streams, streams);
228dd4bc008Ssethdelliott         iperf_free_stream(sp);
229dd4bc008Ssethdelliott     }
230f1b3bd81Ssethdelliott     free_timer(test->timer);
231f1b3bd81Ssethdelliott     free_timer(test->stats_timer);
232f1b3bd81Ssethdelliott     free_timer(test->reporter_timer);
233f1b3bd81Ssethdelliott     test->timer = NULL;
234f1b3bd81Ssethdelliott     test->stats_timer = NULL;
235f1b3bd81Ssethdelliott     test->reporter_timer = NULL;
236efdc02f7Ssethdelliott 
237dd4bc008Ssethdelliott     SLIST_INIT(&test->streams);
23832885561Ssethdelliott 
239efdc02f7Ssethdelliott     test->role = 's';
24066ce7ad4Ssethdelliott     set_protocol(test, Ptcp);
24132885561Ssethdelliott     test->duration = DURATION;
24232885561Ssethdelliott     test->state = 0;
24332885561Ssethdelliott     test->server_hostname = NULL;
24432885561Ssethdelliott 
24532885561Ssethdelliott     test->ctrl_sck = -1;
24666ce7ad4Ssethdelliott     test->prot_listener = -1;
24732885561Ssethdelliott 
248f1b3bd81Ssethdelliott     test->bytes_sent = 0;
249f1b3bd81Ssethdelliott 
25032885561Ssethdelliott     test->reverse = 0;
251b68ac00eSsethdelliott     test->no_delay = 0;
25232885561Ssethdelliott 
253efdc02f7Ssethdelliott     FD_ZERO(&test->read_set);
254efdc02f7Ssethdelliott     FD_ZERO(&test->write_set);
25566ce7ad4Ssethdelliott     FD_SET(test->listener, &test->read_set);
25666ce7ad4Ssethdelliott     test->max_fd = test->listener;
25732885561Ssethdelliott 
25832885561Ssethdelliott     test->num_streams = 1;
259112a907cSsethdelliott     test->settings->socket_bufsize = 0;
260112a907cSsethdelliott     test->settings->blksize = DEFAULT_TCP_BLKSIZE;
261112a907cSsethdelliott     test->settings->rate = RATE;   /* UDP only */
262112a907cSsethdelliott     test->settings->mss = 0;
263112a907cSsethdelliott     memset(test->cookie, 0, COOKIE_SIZE);
264efdc02f7Ssethdelliott }
265efdc02f7Ssethdelliott 
2667fa9f68fSsethdelliott int
267a951c980SBrian Tierney iperf_run_server(struct iperf_test *test)
268a951c980SBrian Tierney {
269112a907cSsethdelliott     int result, s, streams_accepted;
270efdc02f7Ssethdelliott     fd_set temp_read_set, temp_write_set;
2718a0b5a5dSsethdelliott     struct iperf_stream *sp;
2727fa9f68fSsethdelliott     struct timeval tv;
2730bd8d9daSsethdelliott     time_t sec, usec;
274a951c980SBrian Tierney 
275982c704aSsethdelliott     // Open socket and listen
276982c704aSsethdelliott     if (iperf_server_listen(test) < 0) {
277b60a49ddSsethdelliott         return (-1);
278e99faeaeSBrian Tierney     }
279a951c980SBrian Tierney 
280efdc02f7Ssethdelliott     test->state = IPERF_START;
281112a907cSsethdelliott     streams_accepted = 0;
282a951c980SBrian Tierney 
283873952e3Ssethdelliott     while (test->state != IPERF_DONE) {
284982c704aSsethdelliott 
285efdc02f7Ssethdelliott         memcpy(&temp_read_set, &test->read_set, sizeof(fd_set));
286efdc02f7Ssethdelliott         memcpy(&temp_write_set, &test->write_set, sizeof(fd_set));
287982c704aSsethdelliott         tv.tv_sec = 15;
288982c704aSsethdelliott         tv.tv_usec = 0;
289982c704aSsethdelliott 
290efdc02f7Ssethdelliott         result = select(test->max_fd + 1, &temp_read_set, &temp_write_set, NULL, &tv);
291982c704aSsethdelliott         if (result < 0 && errno != EINTR) {
292b60a49ddSsethdelliott             i_errno = IESELECT;
293b60a49ddSsethdelliott             return (-1);
294982c704aSsethdelliott         } else if (result > 0) {
29566ce7ad4Ssethdelliott             if (FD_ISSET(test->listener, &temp_read_set)) {
296b68ac00eSsethdelliott                 if (test->state != CREATE_STREAMS) {
297465b565cSsethdelliott                     if (iperf_accept(test) < 0) {
298b60a49ddSsethdelliott                         return (-1);
299982c704aSsethdelliott                     }
30066ce7ad4Ssethdelliott                     FD_CLR(test->listener, &temp_read_set);
301982c704aSsethdelliott                 }
302b68ac00eSsethdelliott             }
303efdc02f7Ssethdelliott             if (FD_ISSET(test->ctrl_sck, &temp_read_set)) {
304b60a49ddSsethdelliott                 if (iperf_handle_message_server(test) < 0)
305b60a49ddSsethdelliott                     return (-1);
306efdc02f7Ssethdelliott                 FD_CLR(test->ctrl_sck, &temp_read_set);
307982c704aSsethdelliott             }
308465b565cSsethdelliott 
309465b565cSsethdelliott             if (test->state == CREATE_STREAMS) {
3108a0b5a5dSsethdelliott                 if (FD_ISSET(test->prot_listener, &temp_read_set)) {
3118a0b5a5dSsethdelliott 
31266ce7ad4Ssethdelliott                     if ((s = test->protocol->accept(test)) < 0)
313b60a49ddSsethdelliott                         return (-1);
3148a0b5a5dSsethdelliott 
3158a0b5a5dSsethdelliott                     if (!is_closed(s)) {
31666ce7ad4Ssethdelliott                         sp = iperf_new_stream(test, s);
3178a0b5a5dSsethdelliott                         if (!sp)
318b60a49ddSsethdelliott                             return (-1);
31966ce7ad4Ssethdelliott 
3208a0b5a5dSsethdelliott                         FD_SET(s, &test->read_set);
3218a0b5a5dSsethdelliott                         FD_SET(s, &test->write_set);
3228a0b5a5dSsethdelliott                         test->max_fd = (s > test->max_fd) ? s : test->max_fd;
32366ce7ad4Ssethdelliott 
324112a907cSsethdelliott                         streams_accepted++;
3254df383f6Ssethdelliott                         if (test->on_new_stream)
3264df383f6Ssethdelliott                             test->on_new_stream(sp);
327b68ac00eSsethdelliott                     }
3288a0b5a5dSsethdelliott                     FD_CLR(test->prot_listener, &temp_read_set);
329b68ac00eSsethdelliott                 }
3308a0b5a5dSsethdelliott 
331112a907cSsethdelliott                 if (streams_accepted == test->num_streams) {
33266ce7ad4Ssethdelliott                     if (test->protocol->id != Ptcp) {
3338a0b5a5dSsethdelliott                         FD_CLR(test->prot_listener, &test->read_set);
3348a0b5a5dSsethdelliott                         close(test->prot_listener);
33566ce7ad4Ssethdelliott                     } else {
3360bd8d9daSsethdelliott                         if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
33766ce7ad4Ssethdelliott                             FD_CLR(test->listener, &test->read_set);
33866ce7ad4Ssethdelliott                             close(test->listener);
339f99bd3b2Ssethdelliott                             if ((s = netannounce(test->settings->domain, Ptcp, test->bind_address, test->server_port)) < 0) {
340b60a49ddSsethdelliott                                 i_errno = IELISTEN;
341c81883bfSsethdelliott                                 return (-1);
342c81883bfSsethdelliott                             }
34366ce7ad4Ssethdelliott                             test->listener = s;
344c81883bfSsethdelliott                             test->max_fd = (s > test->max_fd ? s : test->max_fd);
34566ce7ad4Ssethdelliott                             FD_SET(test->listener, &test->read_set);
346c81883bfSsethdelliott                         }
3478556db5dSsethdelliott                     }
3488a0b5a5dSsethdelliott                     test->prot_listener = -1;
349465b565cSsethdelliott                     test->state = TEST_START;
350b68ac00eSsethdelliott                     if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
351b60a49ddSsethdelliott                         i_errno = IESENDMESSAGE;
352b60a49ddSsethdelliott                         return (-1);
353982c704aSsethdelliott                     }
354b60a49ddSsethdelliott                     if (iperf_init_test(test) < 0)
355b60a49ddSsethdelliott                         return (-1);
356f1b3bd81Ssethdelliott                     test->state = TEST_RUNNING;
357f1b3bd81Ssethdelliott                     if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
358b60a49ddSsethdelliott                         i_errno = IESENDMESSAGE;
359b60a49ddSsethdelliott                         return (-1);
360f1b3bd81Ssethdelliott                     }
361982c704aSsethdelliott                 }
362982c704aSsethdelliott             }
363982c704aSsethdelliott 
364f1b3bd81Ssethdelliott             if (test->state == TEST_RUNNING) {
365465b565cSsethdelliott                 if (test->reverse) {
366465b565cSsethdelliott                     // Reverse mode. Server sends.
367b60a49ddSsethdelliott                     if (iperf_send(test) < 0)
368b60a49ddSsethdelliott                         return (-1);
369982c704aSsethdelliott                 } else {
370465b565cSsethdelliott                     // Regular mode. Server receives.
371b60a49ddSsethdelliott                     if (iperf_recv(test) < 0)
372b60a49ddSsethdelliott                         return (-1);
373e99faeaeSBrian Tierney                 }
374f1b3bd81Ssethdelliott 
375f1b3bd81Ssethdelliott                 /* Perform callbacks */
376f1b3bd81Ssethdelliott                 if (timer_expired(test->stats_timer)) {
377f1b3bd81Ssethdelliott                     test->stats_callback(test);
3780bd8d9daSsethdelliott                     sec = (time_t) test->stats_interval;
3790bd8d9daSsethdelliott                     usec = (test->stats_interval - sec) * SEC_TO_US;
3800bd8d9daSsethdelliott                     if (update_timer(test->stats_timer, sec, usec) < 0)
381b60a49ddSsethdelliott                         return (-1);
382f1b3bd81Ssethdelliott                 }
383f1b3bd81Ssethdelliott                 if (timer_expired(test->reporter_timer)) {
384f1b3bd81Ssethdelliott                     test->reporter_callback(test);
3850bd8d9daSsethdelliott                     sec = (time_t) test->reporter_interval;
3860bd8d9daSsethdelliott                     usec = (test->reporter_interval - sec) * SEC_TO_US;
3870bd8d9daSsethdelliott                     if (update_timer(test->reporter_timer, sec, usec) < 0)
388b60a49ddSsethdelliott                         return (-1);
389f1b3bd81Ssethdelliott                 }
390f1b3bd81Ssethdelliott             }
391a951c980SBrian Tierney         }
392982c704aSsethdelliott     }
393e99faeaeSBrian Tierney 
394*02a35f07Ssethdelliott     /* Close open test sockets */
3950bd8d9daSsethdelliott     close(test->ctrl_sck);
3960bd8d9daSsethdelliott     close(test->listener);
397efdc02f7Ssethdelliott 
398b60a49ddSsethdelliott     return (0);
399a3281a3dSBrian Tierney }
400a3281a3dSBrian Tierney 
401