From 329523a5574bafe387241261c06919296d00a105 Mon Sep 17 00:00:00 2001 From: "Bruce A. Mah" Date: Thu, 28 Aug 2014 08:59:32 -0700 Subject: Add a --udp-counters-64bit feature to support very long UDP tests. UDP tests store a packet sequence number in the packets to detect loss and ordering issues. This sequence number is a 32-bit signed integer, which can wrap during very long-running UDP tests. This change adds an option (defaulting to off) which uses a 64-bit unsigned integer to store this quantity in the packet. The option is specified on the client side; the server must support this feature for proper functioning (older servers will interoperate with newer clients, as long as --udp-counters-64-bit is not used). The default might be changed in a future version of iperf3. As a part of this change, the client sends its version string to the server in the parameter block. Uses a public-domain compatibility shim for 64-bit byte order conversions. There are probably some additional platforms that need to be supported, in particular Solaris. We might add some configure-time checks to only enable this feature on platforms where we can support the byte-order conversions. This change is not well-tested. Towards issue #191. --- src/iperf_udp.c | 76 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'src/iperf_udp.c') diff --git a/src/iperf_udp.c b/src/iperf_udp.c index bc7a8f1..38d0cc7 100644 --- a/src/iperf_udp.c +++ b/src/iperf_udp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2011, The Regents of the University of California, + * Copyright (c) 2009-2011, 2014, The Regents of the University of California, * through Lawrence Berkeley National Laboratory (subject to receipt of any * required approvals from the U.S. Dept. of Energy). All rights reserved. * @@ -28,7 +28,7 @@ #include "iperf_udp.h" #include "timer.h" #include "net.h" - +#include "portable_endian.h" /* iperf_udp_recv * @@ -37,9 +37,10 @@ int iperf_udp_recv(struct iperf_stream *sp) { + uint32_t sec, usec; + uint64_t pcount; int r; int size = sp->settings->blksize; - uint32_t sec, usec, pcount; double transit = 0, d = 0; struct timeval sent_time, arrival_time; @@ -51,14 +52,27 @@ iperf_udp_recv(struct iperf_stream *sp) sp->result->bytes_received += r; sp->result->bytes_received_this_interval += r; - memcpy(&sec, sp->buffer, sizeof(sec)); - memcpy(&usec, sp->buffer+4, sizeof(usec)); - memcpy(&pcount, sp->buffer+8, sizeof(pcount)); - sec = ntohl(sec); - usec = ntohl(usec); - pcount = ntohl(pcount); - sent_time.tv_sec = sec; - sent_time.tv_usec = usec; + if (sp->test->udp_counters_64bit) { + memcpy(&sec, sp->buffer, sizeof(sec)); + memcpy(&usec, sp->buffer+4, sizeof(usec)); + memcpy(&pcount, sp->buffer+8, sizeof(pcount)); + sec = ntohl(sec); + usec = ntohl(usec); + pcount = be64toh(pcount); + sent_time.tv_sec = sec; + sent_time.tv_usec = usec; + } + else { + uint32_t pc; + memcpy(&sec, sp->buffer, sizeof(sec)); + memcpy(&usec, sp->buffer+4, sizeof(usec)); + memcpy(&pc, sp->buffer+8, sizeof(pc)); + sec = ntohl(sec); + usec = ntohl(usec); + pcount = ntohl(pc); + sent_time.tv_sec = sec; + sent_time.tv_usec = usec; + } /* Out of order packets */ if (pcount >= sp->packet_count + 1) { @@ -68,7 +82,7 @@ iperf_udp_recv(struct iperf_stream *sp) sp->packet_count = pcount; } else { sp->outoforder_packets++; - iperf_err(sp->test, "OUT OF ORDER - incoming packet = %d and received packet = %d AND SP = %d", pcount, sp->packet_count, sp->socket); + iperf_err(sp->test, "OUT OF ORDER - incoming packet = %llu and received packet = %d AND SP = %d", pcount, sp->packet_count, sp->socket); } /* jitter measurement */ @@ -83,6 +97,10 @@ iperf_udp_recv(struct iperf_stream *sp) // J = |(R1 - S1) - (R0 - S0)| [/ number of packets, for average] sp->jitter += (d - sp->jitter) / 16.0; + if (sp->test->debug) { + fprintf(stderr, "packet_count %llu\n", sp->packet_count); + } + return r; } @@ -95,20 +113,40 @@ int iperf_udp_send(struct iperf_stream *sp) { int r; - uint32_t sec, usec, pcount; int size = sp->settings->blksize; struct timeval before; gettimeofday(&before, 0); ++sp->packet_count; - sec = htonl(before.tv_sec); - usec = htonl(before.tv_usec); - pcount = htonl(sp->packet_count); - memcpy(sp->buffer, &sec, sizeof(sec)); - memcpy(sp->buffer+4, &usec, sizeof(usec)); - memcpy(sp->buffer+8, &pcount, sizeof(pcount)); + if (sp->test->udp_counters_64bit) { + + uint32_t sec, usec; + uint64_t pcount; + + sec = htonl(before.tv_sec); + usec = htonl(before.tv_usec); + pcount = htobe64(sp->packet_count); + + memcpy(sp->buffer, &sec, sizeof(sec)); + memcpy(sp->buffer+4, &usec, sizeof(usec)); + memcpy(sp->buffer+8, &pcount, sizeof(pcount)); + + } + else { + + uint32_t sec, usec, pcount; + + sec = htonl(before.tv_sec); + usec = htonl(before.tv_usec); + pcount = htonl(sp->packet_count); + + memcpy(sp->buffer, &sec, sizeof(sec)); + memcpy(sp->buffer+4, &usec, sizeof(usec)); + memcpy(sp->buffer+8, &pcount, sizeof(pcount)); + + } r = Nwrite(sp->socket, sp->buffer, size, Pudp); -- cgit v1.2.3