aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE12
-rw-r--r--src/iperf.h5
-rw-r--r--src/iperf_api.c25
-rw-r--r--src/iperf_api.h3
-rw-r--r--src/iperf_udp.c76
-rw-r--r--src/locale.c1
-rw-r--r--src/portable_endian.h115
7 files changed, 215 insertions, 22 deletions
diff --git a/LICENSE b/LICENSE
index adb1d16..e5fc4c8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -255,3 +255,15 @@ This software contains source code (src/units.{c.h}) that is:
* -------------------------------------------------------------------
* input and output numbers, converting with kilo, mega, giga
* ------------------------------------------------------------------- */
+
+=====
+
+This software contains source code (src/portable_endian.h) that is:
+
+// "License": Public Domain
+// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
+
+=====
+
+
+
diff --git a/src/iperf.h b/src/iperf.h
index 9f3f8f2..07ce9a2 100644
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -91,7 +91,7 @@ struct iperf_settings
int tos; /* type of service bit */
int flowlabel; /* IPv6 flow label */
iperf_size_t bytes; /* number of bytes to send */
- int blocks; /* number of blocks (packets) to send */
+ iperf_size_t blocks; /* number of blocks (packets) to send */
char unit_format; /* -f */
};
@@ -200,6 +200,7 @@ struct iperf_test
int zerocopy; /* -Z option - use sendfile */
int debug; /* -d option - enable debug */
int get_server_output; /* --get-server-output */
+ int udp_counters_64bit; /* --use-64-bit-udp-counters */
int multisend;
@@ -227,7 +228,7 @@ struct iperf_test
int num_streams; /* total streams in the test (-P) */
iperf_size_t bytes_sent;
- int blocks_sent;
+ iperf_size_t blocks_sent;
char cookie[COOKIE_SIZE];
// struct iperf_stream *streams; /* pointer to list of struct stream */
SLIST_HEAD(slisthead, iperf_stream) streams;
diff --git a/src/iperf_api.c b/src/iperf_api.c
index acc1366..068930f 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -59,7 +59,7 @@
#include "tcp_window_size.h"
#include "iperf_util.h"
#include "locale.h"
-
+#include "version.h"
/* Forwards. */
static int send_parameters(struct iperf_test *test);
@@ -235,6 +235,12 @@ iperf_get_test_bind_address(struct iperf_test *ipt)
return ipt->bind_address;
}
+int
+iperf_get_test_udp_counters_64bit(struct iperf_test *ipt)
+{
+ return ipt->udp_counters_64bit;
+}
+
/************** Setter routines for some fields inside iperf_test *************/
void
@@ -388,6 +394,12 @@ iperf_set_test_bind_address(struct iperf_test *ipt, char *bind_address)
ipt->bind_address = strdup(bind_address);
}
+void
+iperf_set_test_udp_counters_64bit(struct iperf_test *ipt, int udp_counters_64bit)
+{
+ ipt->udp_counters_64bit = udp_counters_64bit;
+}
+
/********************** Get/set test protocol structure ***********************/
struct protocol *
@@ -597,6 +609,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"pidfile", required_argument, NULL, 'I'},
{"logfile", required_argument, NULL, OPT_LOGFILE},
{"get-server-output", no_argument, NULL, OPT_GET_SERVER_OUTPUT},
+ {"udp-counters-64bit", no_argument, NULL, OPT_UDP_COUNTERS_64BIT},
{"debug", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
@@ -834,6 +847,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->get_server_output = 1;
client_flag = 1;
break;
+ case OPT_UDP_COUNTERS_64BIT:
+ test->udp_counters_64bit = 1;
+ break;
case 'h':
default:
usage_long();
@@ -1197,6 +1213,10 @@ send_parameters(struct iperf_test *test)
cJSON_AddStringToObject(j, "congestion", test->congestion);
if (test->get_server_output)
cJSON_AddIntToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
+ if (test->udp_counters_64bit)
+ cJSON_AddIntToObject(j, "udp_counters_64bit", iperf_get_test_udp_counters_64bit(test));
+
+ cJSON_AddStringToObject(j, "client_version", IPERF_VERSION);
if (test->debug) {
printf("send_parameters:\n%s\n", cJSON_Print(j));
@@ -1271,6 +1291,8 @@ get_parameters(struct iperf_test *test)
test->congestion = strdup(j_p->valuestring);
if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
iperf_set_test_get_server_output(test, 1);
+ if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
+ iperf_set_test_udp_counters_64bit(test, 1);
if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
test->sender_has_retransmits = 1;
cJSON_Delete(j);
@@ -1883,6 +1905,7 @@ iperf_reset_test(struct iperf_test *test)
test->settings->mss = 0;
memset(test->cookie, 0, COOKIE_SIZE);
test->multisend = 10; /* arbitrary */
+ test->udp_counters_64bit = 0;
/* Free output line buffers, if any (on the server only) */
struct iperf_textline *t;
diff --git a/src/iperf_api.h b/src/iperf_api.h
index 37504f6..ecac575 100644
--- a/src/iperf_api.h
+++ b/src/iperf_api.h
@@ -29,6 +29,7 @@ struct iperf_stream;
#define OPT_SCTP 1
#define OPT_LOGFILE 2
#define OPT_GET_SERVER_OUTPUT 3
+#define OPT_UDP_COUNTERS_64BIT 4
/* states */
#define TEST_START 1
@@ -73,6 +74,7 @@ char* iperf_get_test_json_output_string ( struct iperf_test* ipt );
int iperf_get_test_zerocopy( struct iperf_test* ipt );
int iperf_get_test_get_server_output( struct iperf_test* ipt );
char* iperf_get_test_bind_address ( struct iperf_test* ipt );
+int iperf_get_test_udp_counters_64bit( struct iperf_test* ipt );
/* Setter routines for some fields inside iperf_test. */
void iperf_set_verbose( struct iperf_test* ipt, int verbose );
@@ -96,6 +98,7 @@ int iperf_has_zerocopy( void );
void iperf_set_test_zerocopy( struct iperf_test* ipt, int zerocopy );
void iperf_set_test_get_server_output( struct iperf_test* ipt, int get_server_output );
void iperf_set_test_bind_address( struct iperf_test* ipt, char *bind_address );
+void iperf_set_test_udp_counters_64bit( struct iperf_test* ipt, int udp_counters_64bit );
/**
* exchange_parameters - handles the param_Exchange part for client
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);
diff --git a/src/locale.c b/src/locale.c
index f51ac8b..9e4c647 100644
--- a/src/locale.c
+++ b/src/locale.c
@@ -126,6 +126,7 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
" -O, --omit N omit the first n seconds\n"
" -T, --title str prefix every output line with this string\n"
" --get-server-output get results from server\n"
+ " --udp-counters-64bit use 64-bit counters in UDP test packets\n"
#ifdef NOT_YET_SUPPORTED /* still working on these */
#endif
diff --git a/src/portable_endian.h b/src/portable_endian.h
new file mode 100644
index 0000000..42d40be
--- /dev/null
+++ b/src/portable_endian.h
@@ -0,0 +1,115 @@
+// "License": Public Domain
+// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
+
+#ifndef PORTABLE_ENDIAN_H__
+#define PORTABLE_ENDIAN_H__
+
+#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
+
+# define __WINDOWS__
+
+#endif
+
+#if defined(__linux__) || defined(__CYGWIN__)
+
+# include <endian.h>
+
+#elif defined(__APPLE__)
+
+# include <libkern/OSByteOrder.h>
+
+# define htobe16(x) OSSwapHostToBigInt16(x)
+# define htole16(x) OSSwapHostToLittleInt16(x)
+# define be16toh(x) OSSwapBigToHostInt16(x)
+# define le16toh(x) OSSwapLittleToHostInt16(x)
+
+# define htobe32(x) OSSwapHostToBigInt32(x)
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define be32toh(x) OSSwapBigToHostInt32(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+
+# define htobe64(x) OSSwapHostToBigInt64(x)
+# define htole64(x) OSSwapHostToLittleInt64(x)
+# define be64toh(x) OSSwapBigToHostInt64(x)
+# define le64toh(x) OSSwapLittleToHostInt64(x)
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#elif defined(__OpenBSD__)
+
+# include <sys/endian.h>
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+
+# include <sys/endian.h>
+
+# define be16toh(x) betoh16(x)
+# define le16toh(x) letoh16(x)
+
+# define be32toh(x) betoh32(x)
+# define le32toh(x) letoh32(x)
+
+# define be64toh(x) betoh64(x)
+# define le64toh(x) letoh64(x)
+
+#elif defined(__WINDOWS__)
+
+# include <winsock2.h>
+# include <sys/param.h>
+
+# if BYTE_ORDER == LITTLE_ENDIAN
+
+# define htobe16(x) htons(x)
+# define htole16(x) (x)
+# define be16toh(x) ntohs(x)
+# define le16toh(x) (x)
+
+# define htobe32(x) htonl(x)
+# define htole32(x) (x)
+# define be32toh(x) ntohl(x)
+# define le32toh(x) (x)
+
+# define htobe64(x) htonll(x)
+# define htole64(x) (x)
+# define be64toh(x) ntohll(x)
+# define le64toh(x) (x)
+
+# elif BYTE_ORDER == BIG_ENDIAN
+
+ /* that would be xbox 360 */
+# define htobe16(x) (x)
+# define htole16(x) __builtin_bswap16(x)
+# define be16toh(x) (x)
+# define le16toh(x) __builtin_bswap16(x)
+
+# define htobe32(x) (x)
+# define htole32(x) __builtin_bswap32(x)
+# define be32toh(x) (x)
+# define le32toh(x) __builtin_bswap32(x)
+
+# define htobe64(x) (x)
+# define htole64(x) __builtin_bswap64(x)
+# define be64toh(x) (x)
+# define le64toh(x) __builtin_bswap64(x)
+
+# else
+
+# error byte order not supported
+
+# endif
+
+# define __BYTE_ORDER BYTE_ORDER
+# define __BIG_ENDIAN BIG_ENDIAN
+# define __LITTLE_ENDIAN LITTLE_ENDIAN
+# define __PDP_ENDIAN PDP_ENDIAN
+
+#else
+
+# error platform not supported
+
+#endif
+
+#endif \ No newline at end of file