• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <assert.h>
33 #include <arpa/inet.h>
34 #include <sys/socket.h>
35 #include <sys/types.h>
36 #include <netinet/in.h>
37 #ifdef HAVE_STDINT_H
38 #include <stdint.h>
39 #endif
40 #include <sys/time.h>
41 #include <sys/select.h>
42 
43 #include "iperf.h"
44 #include "iperf_api.h"
45 #include "iperf_util.h"
46 #include "iperf_udp.h"
47 #include "timer.h"
48 #include "net.h"
49 #include "cjson.h"
50 #include "portable_endian.h"
51 
52 #if defined(HAVE_INTTYPES_H)
53 # include <inttypes.h>
54 #else
55 # ifndef PRIu64
56 #  if sizeof(long) == 8
57 #   define PRIu64		"lu"
58 #  else
59 #   define PRIu64		"llu"
60 #  endif
61 # endif
62 #endif
63 
64 /* iperf_udp_recv
65  *
66  * receives the data for UDP
67  */
68 int
iperf_udp_recv(struct iperf_stream * sp)69 iperf_udp_recv(struct iperf_stream *sp)
70 {
71     uint32_t  sec, usec;
72     uint64_t  pcount;
73     int       r;
74     int       size = sp->settings->blksize;
75     int       first_packet = 0;
76     double    transit = 0, d = 0;
77     struct iperf_time sent_time, arrival_time, temp_time;
78 
79     r = Nread(sp->socket, sp->buffer, size, Pudp);
80 
81     /*
82      * If we got an error in the read, or if we didn't read anything
83      * because the underlying read(2) got a EAGAIN, then skip packet
84      * processing.
85      */
86     if (r <= 0)
87         return r;
88 
89     /* Only count bytes received while we're in the correct state. */
90     if (sp->test->state == TEST_RUNNING) {
91 
92 	/*
93 	 * For jitter computation below, it's important to know if this
94 	 * packet is the first packet received.
95 	 */
96 	if (sp->result->bytes_received == 0) {
97 	    first_packet = 1;
98 	}
99 
100 	sp->result->bytes_received += r;
101 	sp->result->bytes_received_this_interval += r;
102 
103 	/* Dig the various counters out of the incoming UDP packet */
104 	if (sp->test->udp_counters_64bit) {
105 	    memcpy(&sec, sp->buffer, sizeof(sec));
106 	    memcpy(&usec, sp->buffer+4, sizeof(usec));
107 	    memcpy(&pcount, sp->buffer+8, sizeof(pcount));
108 	    sec = ntohl(sec);
109 	    usec = ntohl(usec);
110 	    pcount = be64toh(pcount);
111 	    sent_time.secs = sec;
112 	    sent_time.usecs = usec;
113 	}
114 	else {
115 	    uint32_t pc;
116 	    memcpy(&sec, sp->buffer, sizeof(sec));
117 	    memcpy(&usec, sp->buffer+4, sizeof(usec));
118 	    memcpy(&pc, sp->buffer+8, sizeof(pc));
119 	    sec = ntohl(sec);
120 	    usec = ntohl(usec);
121 	    pcount = ntohl(pc);
122 	    sent_time.secs = sec;
123 	    sent_time.usecs = usec;
124 	}
125 
126 	if (sp->test->debug)
127 	    fprintf(stderr, "pcount %" PRIu64 " packet_count %d\n", pcount, sp->packet_count);
128 
129 	/*
130 	 * Try to handle out of order packets.  The way we do this
131 	 * uses a constant amount of storage but might not be
132 	 * correct in all cases.  In particular we seem to have the
133 	 * assumption that packets can't be duplicated in the network,
134 	 * because duplicate packets will possibly cause some problems here.
135 	 *
136 	 * First figure out if the sequence numbers are going forward.
137 	 * Note that pcount is the sequence number read from the packet,
138 	 * and sp->packet_count is the highest sequence number seen so
139 	 * far (so we're expecting to see the packet with sequence number
140 	 * sp->packet_count + 1 arrive next).
141 	 */
142 	if (pcount >= sp->packet_count + 1) {
143 
144 	    /* Forward, but is there a gap in sequence numbers? */
145 	    if (pcount > sp->packet_count + 1) {
146 		/* There's a gap so count that as a loss. */
147 		sp->cnt_error += (pcount - 1) - sp->packet_count;
148 	    }
149 	    /* Update the highest sequence number seen so far. */
150 	    sp->packet_count = pcount;
151 	} else {
152 
153 	    /*
154 	     * Sequence number went backward (or was stationary?!?).
155 	     * This counts as an out-of-order packet.
156 	     */
157 	    sp->outoforder_packets++;
158 
159 	    /*
160 	     * If we have lost packets, then the fact that we are now
161 	     * seeing an out-of-order packet offsets a prior sequence
162 	     * number gap that was counted as a loss.  So we can take
163 	     * away a loss.
164 	     */
165 	    if (sp->cnt_error > 0)
166 		sp->cnt_error--;
167 
168 	    /* Log the out-of-order packet */
169 	    if (sp->test->debug)
170 		fprintf(stderr, "OUT OF ORDER - incoming packet sequence %" PRIu64 " but expected sequence %d on stream %d", pcount, sp->packet_count + 1, sp->socket);
171 	}
172 
173 	/*
174 	 * jitter measurement
175 	 *
176 	 * This computation is based on RFC 1889 (specifically
177 	 * sections 6.3.1 and A.8).
178 	 *
179 	 * Note that synchronized clocks are not required since
180 	 * the source packet delta times are known.  Also this
181 	 * computation does not require knowing the round-trip
182 	 * time.
183 	 */
184 	iperf_time_now(&arrival_time);
185 
186 	iperf_time_diff(&arrival_time, &sent_time, &temp_time);
187 	transit = iperf_time_in_secs(&temp_time);
188 
189 	/* Hack to handle the first packet by initializing prev_transit. */
190 	if (first_packet)
191 	    sp->prev_transit = transit;
192 
193 	d = transit - sp->prev_transit;
194 	if (d < 0)
195 	    d = -d;
196 	sp->prev_transit = transit;
197 	sp->jitter += (d - sp->jitter) / 16.0;
198     }
199     else {
200 	if (sp->test->debug)
201 	    printf("Late receive, state = %d\n", sp->test->state);
202     }
203 
204     return r;
205 }
206 
207 
208 /* iperf_udp_send
209  *
210  * sends the data for UDP
211  */
212 int
iperf_udp_send(struct iperf_stream * sp)213 iperf_udp_send(struct iperf_stream *sp)
214 {
215     int r;
216     int       size = sp->settings->blksize;
217     struct iperf_time before;
218 
219     iperf_time_now(&before);
220 
221     ++sp->packet_count;
222 
223     if (sp->test->udp_counters_64bit) {
224 
225 	uint32_t  sec, usec;
226 	uint64_t  pcount;
227 
228 	sec = htonl(before.secs);
229 	usec = htonl(before.usecs);
230 	pcount = htobe64(sp->packet_count);
231 
232 	memcpy(sp->buffer, &sec, sizeof(sec));
233 	memcpy(sp->buffer+4, &usec, sizeof(usec));
234 	memcpy(sp->buffer+8, &pcount, sizeof(pcount));
235 
236     }
237     else {
238 
239 	uint32_t  sec, usec, pcount;
240 
241 	sec = htonl(before.secs);
242 	usec = htonl(before.usecs);
243 	pcount = htonl(sp->packet_count);
244 
245 	memcpy(sp->buffer, &sec, sizeof(sec));
246 	memcpy(sp->buffer+4, &usec, sizeof(usec));
247 	memcpy(sp->buffer+8, &pcount, sizeof(pcount));
248 
249     }
250 
251     r = Nwrite(sp->socket, sp->buffer, size, Pudp);
252 
253     if (r < 0)
254 	return r;
255 
256     sp->result->bytes_sent += r;
257     sp->result->bytes_sent_this_interval += r;
258 
259     if (sp->test->debug)
260 	printf("sent %d bytes of %d, total %" PRIu64 "\n", r, sp->settings->blksize, sp->result->bytes_sent);
261 
262     return r;
263 }
264 
265 
266 /**************************************************************************/
267 
268 /*
269  * The following functions all have to do with managing UDP data sockets.
270  * UDP of course is connectionless, so there isn't really a concept of
271  * setting up a connection, although connect(2) can (and is) used to
272  * bind the remote end of sockets.  We need to simulate some of the
273  * connection management that is built-in to TCP so that each side of the
274  * connection knows about each other before the real data transfers begin.
275  */
276 
277 /*
278  * Set and verify socket buffer sizes.
279  * Return 0 if no error, -1 if an error, +1 if socket buffers are
280  * potentially too small to hold a message.
281  */
282 int
iperf_udp_buffercheck(struct iperf_test * test,int s)283 iperf_udp_buffercheck(struct iperf_test *test, int s)
284 {
285     int rc = 0;
286     int sndbuf_actual, rcvbuf_actual;
287 
288     /*
289      * Set socket buffer size if requested.  Do this for both sending and
290      * receiving so that we can cover both normal and --reverse operation.
291      */
292     int opt;
293     socklen_t optlen;
294 
295     if ((opt = test->settings->socket_bufsize)) {
296         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
297             i_errno = IESETBUF;
298             return -1;
299         }
300         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
301             i_errno = IESETBUF;
302             return -1;
303         }
304     }
305 
306     /* Read back and verify the sender socket buffer size */
307     optlen = sizeof(sndbuf_actual);
308     if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
309 	i_errno = IESETBUF;
310 	return -1;
311     }
312     if (test->debug) {
313 	printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
314     }
315     if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
316 	i_errno = IESETBUF2;
317 	return -1;
318     }
319     if (test->settings->blksize > sndbuf_actual) {
320 	char str[80];
321 	snprintf(str, sizeof(str),
322 		 "Block size %d > sending socket buffer size %d",
323 		 test->settings->blksize, sndbuf_actual);
324 	warning(str);
325 	rc = 1;
326     }
327 
328     /* Read back and verify the receiver socket buffer size */
329     optlen = sizeof(rcvbuf_actual);
330     if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
331 	i_errno = IESETBUF;
332 	return -1;
333     }
334     if (test->debug) {
335 	printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
336     }
337     if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
338 	i_errno = IESETBUF2;
339 	return -1;
340     }
341     if (test->settings->blksize > rcvbuf_actual) {
342 	char str[80];
343 	snprintf(str, sizeof(str),
344 		 "Block size %d > receiving socket buffer size %d",
345 		 test->settings->blksize, rcvbuf_actual);
346 	warning(str);
347 	rc = 1;
348     }
349 
350     if (test->json_output) {
351 	cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
352 	cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
353 	cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
354     }
355 
356     return rc;
357 }
358 
359 /*
360  * iperf_udp_accept
361  *
362  * Accepts a new UDP "connection"
363  */
364 int
iperf_udp_accept(struct iperf_test * test)365 iperf_udp_accept(struct iperf_test *test)
366 {
367     struct sockaddr_storage sa_peer;
368     int       buf;
369     socklen_t len;
370     int       sz, s;
371     int	      rc;
372 
373     /*
374      * Get the current outstanding socket.  This socket will be used to handle
375      * data transfers and a new "listening" socket will be created.
376      */
377     s = test->prot_listener;
378 
379     /*
380      * Grab the UDP packet sent by the client.  From that we can extract the
381      * client's address, and then use that information to bind the remote side
382      * of the socket to the client.
383      */
384     len = sizeof(sa_peer);
385     if ((sz = recvfrom(test->prot_listener, &buf, sizeof(buf), 0, (struct sockaddr *) &sa_peer, &len)) < 0) {
386         i_errno = IESTREAMACCEPT;
387         return -1;
388     }
389 
390     if (connect(s, (struct sockaddr *) &sa_peer, len) < 0) {
391         i_errno = IESTREAMACCEPT;
392         return -1;
393     }
394 
395     /* Check and set socket buffer sizes */
396     rc = iperf_udp_buffercheck(test, s);
397     if (rc < 0)
398 	/* error */
399 	return rc;
400     /*
401      * If the socket buffer was too small, but it was the default
402      * size, then try explicitly setting it to something larger.
403      */
404     if (rc > 0) {
405 	if (test->settings->socket_bufsize == 0) {
406 	    int bufsize = test->settings->blksize + UDP_BUFFER_EXTRA;
407 	    printf("Increasing socket buffer size to %d\n",
408 		bufsize);
409 	    test->settings->socket_bufsize = bufsize;
410 	    rc = iperf_udp_buffercheck(test, s);
411 	    if (rc < 0)
412 		return rc;
413 	}
414     }
415 
416 #if defined(HAVE_SO_MAX_PACING_RATE)
417     /* If socket pacing is specified, try it. */
418     if (test->settings->fqrate) {
419 	/* Convert bits per second to bytes per second */
420 	unsigned int fqrate = test->settings->fqrate / 8;
421 	if (fqrate > 0) {
422 	    if (test->debug) {
423 		printf("Setting fair-queue socket pacing to %u\n", fqrate);
424 	    }
425 	    if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
426 		warning("Unable to set socket pacing");
427 	    }
428 	}
429     }
430 #endif /* HAVE_SO_MAX_PACING_RATE */
431     {
432 	unsigned int rate = test->settings->rate / 8;
433 	if (rate > 0) {
434 	    if (test->debug) {
435 		printf("Setting application pacing to %u\n", rate);
436 	    }
437 	}
438     }
439 
440     /*
441      * Create a new "listening" socket to replace the one we were using before.
442      */
443     test->prot_listener = netannounce(test->settings->domain, Pudp, test->bind_address, test->server_port);
444     if (test->prot_listener < 0) {
445         i_errno = IESTREAMLISTEN;
446         return -1;
447     }
448 
449     FD_SET(test->prot_listener, &test->read_set);
450     test->max_fd = (test->max_fd < test->prot_listener) ? test->prot_listener : test->max_fd;
451 
452     /* Let the client know we're ready "accept" another UDP "stream" */
453     buf = 987654321;		/* any content will work here */
454     if (write(s, &buf, sizeof(buf)) < 0) {
455         i_errno = IESTREAMWRITE;
456         return -1;
457     }
458 
459     return s;
460 }
461 
462 
463 /*
464  * iperf_udp_listen
465  *
466  * Start up a listener for UDP stream connections.  Unlike for TCP,
467  * there is no listen(2) for UDP.  This socket will however accept
468  * a UDP datagram from a client (indicating the client's presence).
469  */
470 int
iperf_udp_listen(struct iperf_test * test)471 iperf_udp_listen(struct iperf_test *test)
472 {
473     int s;
474 
475     if ((s = netannounce(test->settings->domain, Pudp, test->bind_address, test->server_port)) < 0) {
476         i_errno = IESTREAMLISTEN;
477         return -1;
478     }
479 
480     /*
481      * The caller will put this value into test->prot_listener.
482      */
483     return s;
484 }
485 
486 
487 /*
488  * iperf_udp_connect
489  *
490  * "Connect" to a UDP stream listener.
491  */
492 int
iperf_udp_connect(struct iperf_test * test)493 iperf_udp_connect(struct iperf_test *test)
494 {
495     int s, buf, sz;
496 #ifdef SO_RCVTIMEO
497     struct timeval tv;
498 #endif
499     int rc;
500 
501     /* Create and bind our local socket. */
502     if ((s = netdial(test->settings->domain, Pudp, test->bind_address, test->bind_port, test->server_hostname, test->server_port, -1)) < 0) {
503         i_errno = IESTREAMCONNECT;
504         return -1;
505     }
506 
507     /* Check and set socket buffer sizes */
508     rc = iperf_udp_buffercheck(test, s);
509     if (rc < 0)
510 	/* error */
511 	return rc;
512     /*
513      * If the socket buffer was too small, but it was the default
514      * size, then try explicitly setting it to something larger.
515      */
516     if (rc > 0) {
517 	if (test->settings->socket_bufsize == 0) {
518 	    int bufsize = test->settings->blksize + UDP_BUFFER_EXTRA;
519 	    printf("Increasing socket buffer size to %d\n",
520 		bufsize);
521 	    test->settings->socket_bufsize = bufsize;
522 	    rc = iperf_udp_buffercheck(test, s);
523 	    if (rc < 0)
524 		return rc;
525 	}
526     }
527 
528 #if defined(HAVE_SO_MAX_PACING_RATE)
529     /* If socket pacing is available and not disabled, try it. */
530     if (test->settings->fqrate) {
531 	/* Convert bits per second to bytes per second */
532 	unsigned int fqrate = test->settings->fqrate / 8;
533 	if (fqrate > 0) {
534 	    if (test->debug) {
535 		printf("Setting fair-queue socket pacing to %u\n", fqrate);
536 	    }
537 	    if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
538 		warning("Unable to set socket pacing");
539 	    }
540 	}
541     }
542 #endif /* HAVE_SO_MAX_PACING_RATE */
543     {
544 	unsigned int rate = test->settings->rate / 8;
545 	if (rate > 0) {
546 	    if (test->debug) {
547 		printf("Setting application pacing to %u\n", rate);
548 	    }
549 	}
550     }
551 
552 #ifdef SO_RCVTIMEO
553     /* 30 sec timeout for a case when there is a network problem. */
554     tv.tv_sec = 30;
555     tv.tv_usec = 0;
556     setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv, sizeof(struct timeval));
557 #endif
558 
559     /*
560      * Write a datagram to the UDP stream to let the server know we're here.
561      * The server learns our address by obtaining its peer's address.
562      */
563     buf = 123456789;		/* this can be pretty much anything */
564     if (write(s, &buf, sizeof(buf)) < 0) {
565         // XXX: Should this be changed to IESTREAMCONNECT?
566         i_errno = IESTREAMWRITE;
567         return -1;
568     }
569 
570     /*
571      * Wait until the server replies back to us.
572      */
573     if ((sz = recv(s, &buf, sizeof(buf), 0)) < 0) {
574         i_errno = IESTREAMREAD;
575         return -1;
576     }
577 
578     return s;
579 }
580 
581 
582 /* iperf_udp_init
583  *
584  * initializer for UDP streams in TEST_START
585  */
586 int
iperf_udp_init(struct iperf_test * test)587 iperf_udp_init(struct iperf_test *test)
588 {
589     return 0;
590 }
591