Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support sending IMIX traffic pattern #1576

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct iperf_settings
int idle_timeout; /* server idle time timeout */
unsigned int snd_timeout; /* Timeout for sending tcp messages in active mode, in us */
struct iperf_time rcv_timeout; /* Timeout for receiving messages in active mode, in us */
int imix; /* Whether to send internet mix traffic */
};

struct iperf_test;
Expand Down
4 changes: 4 additions & 0 deletions src/iperf3.1
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,10 @@ or high-bitrate UDP tests. Both client and server need to be running
at least version 3.1 for this option to work. It may become the
default behavior at some point in the future.
.TP
.BR --imix
Use internet mix traffic pattern instead of maximum possible payload size.
This is useful for testing middleboxes.
.TP
.BR --repeating-payload
Use repeating pattern in payload, instead of random bytes.
The same payload is used in iperf2 (ASCII '0..9' repeating).
Expand Down
22 changes: 22 additions & 0 deletions src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"bitrate", required_argument, NULL, 'b'},
{"bandwidth", required_argument, NULL, 'b'},
{"server-bitrate-limit", required_argument, NULL, OPT_SERVER_BITRATE_LIMIT},
{"imix", no_argument, NULL, OPT_IMIX},
{"time", required_argument, NULL, 't'},
{"bytes", required_argument, NULL, 'n'},
{"blockcount", required_argument, NULL, 'k'},
Expand Down Expand Up @@ -1618,6 +1619,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
test->settings->connect_timeout = unit_atoi(optarg);
client_flag = 1;
break;
case OPT_IMIX:
test->settings->imix = 1;
break;
case 'h':
usage_long(stdout);
exit(0);
Expand Down Expand Up @@ -1766,6 +1770,24 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
}

/* Using 64-bit counters goes over 40 byte (incl. ip and udp hdr) pkt size class */
if (test->udp_counters_64bit && test->settings->imix) {
i_errno = IEUDPCOUNTERIMIX;
return -1;
}

/* IPv6 header is too big to fit into smallest pkt size class */
if (test->settings->imix && test->settings->domain != AF_INET) {
i_errno = IEUDPINET6IMIX;
return -1;
}

/* Cannot easily control packet size on the wire unless it's UDP */
if (test->settings->imix && test->protocol->id != Pudp) {
i_errno = IEIMIXNOTUDP;
return -1;
}

/* For subsequent calls to getopt */
#ifdef __APPLE__
optreset = 1;
Expand Down
4 changes: 4 additions & 0 deletions src/iperf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef uint64_t iperf_size_t;
#define OPT_DONT_FRAGMENT 26
#define OPT_RCV_TIMEOUT 27
#define OPT_SND_TIMEOUT 28
#define OPT_IMIX 29

/* states */
#define TEST_START 1
Expand Down Expand Up @@ -406,6 +407,9 @@ enum {
IERVRSONLYRCVTIMEOUT = 32, // Client receive timeout is valid only in reverse mode
IESNDTIMEOUT = 33, // Illegal message send timeout
IEUDPFILETRANSFER = 34, // Cannot transfer file using UDP
IEUDPCOUNTERIMIX = 35, // 64 bit counter too big for imix
IEUDPINET6IMIX = 36, // IPv6 header too big for imix
IEIMIXNOTUDP = 37, // IMIX mode cannot be used for non UDP
/* Test errors */
IENEWTEST = 100, // Unable to create a new test (check perror)
IEINITTEST = 101, // Test initialization failed (check perror)
Expand Down
9 changes: 9 additions & 0 deletions src/iperf_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,15 @@ iperf_strerror(int int_errno)
case IEUDPFILETRANSFER:
snprintf(errstr, len, "cannot transfer file using UDP");
break;
case IEUDPCOUNTERIMIX:
snprintf(errstr, len, "64 bit counter makes small imix packet too large");
break;
case IEUDPINET6IMIX:
snprintf(errstr, len, "ipv6 header makes small imix packet too large");
break;
case IEIMIXNOTUDP:
snprintf(errstr, len, "imix can only be used for udp");
break;
case IERVRSONLYRCVTIMEOUT:
snprintf(errstr, len, "client receive timeout is valid only in receiving mode");
perr = 1;
Expand Down
1 change: 1 addition & 0 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" --extra-data str data string to include in client and server JSON\n"
" --get-server-output get results from server\n"
" --udp-counters-64bit use 64-bit counters in UDP test packets\n"
" --imix use IMIX traffic pattern\n"
" --repeating-payload use repeating pattern in payload, instead of\n"
" randomized payload (like in iperf2)\n"
#if defined(HAVE_DONT_FRAGMENT)
Expand Down
35 changes: 33 additions & 2 deletions src/iperf_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
# endif
#endif

/* 20B for ipv4 and 8B for udp */
#define HEADER_OVERHEAD (20 + 8)

/* iperf_udp_recv
*
* receives the data for UDP
Expand Down Expand Up @@ -204,6 +207,32 @@ iperf_udp_recv(struct iperf_stream *sp)
return r;
}

/* Determine send size for a single packet */
static int iperf_udp_send_size(struct iperf_stream *sp)
{
int class_sz;
int r;

if (!sp->settings->imix)
return sp->settings->blksize;

/* IMIX (according to wikipedia) says:
* Packet size (incl. IP header) # Packets Distribution (in packets)
* 40 7 58.333333%
* 576 4 33.333333%
* 1500 1 8.333333%
*/
r = random() % 1000;
Copy link

@mandarjog mandarjog Sep 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the Random seed set explicitly?
I am wondering what is the behaviour we want ?

if we set a static seed (or give control of setting a seed), then successive runs are identical and conform to the packet size mixture distribution.

Without that every run is different, giving seed explicit control to the user will enable both behaviors.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seed is set lower in file (srandom(0xDEADF00D);). Would prefer to avoid another config flag (already quite a few) but don't mind adding if necessary

if (r < 580)
class_sz = 40;
else if (r < 580 + 333)
class_sz = 576;
else
class_sz = 1500;

return class_sz - HEADER_OVERHEAD;
}


/* iperf_udp_send
*
Expand All @@ -213,9 +242,10 @@ int
iperf_udp_send(struct iperf_stream *sp)
{
int r;
int size = sp->settings->blksize;
int size;
struct iperf_time before;

size = iperf_udp_send_size(sp);
iperf_time_now(&before);

++sp->packet_count;
Expand Down Expand Up @@ -264,7 +294,7 @@ iperf_udp_send(struct iperf_stream *sp)
sp->result->bytes_sent_this_interval += r;

if (sp->test->debug_level >= DEBUG_LEVEL_DEBUG)
printf("sent %d bytes of %d, total %" PRIu64 "\n", r, sp->settings->blksize, sp->result->bytes_sent);
printf("sent %d bytes of %d, total %" PRIu64 "\n", r, size, sp->result->bytes_sent);

return r;
}
Expand Down Expand Up @@ -631,5 +661,6 @@ iperf_udp_connect(struct iperf_test *test)
int
iperf_udp_init(struct iperf_test *test)
{
srandom(0xDEADF00D);
return 0;
}
6 changes: 6 additions & 0 deletions src/net.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* file for complete information.
*/
#include "iperf_config.h"
#include "iperf_api.h"

#include <stdio.h>
#include <unistd.h>
Expand Down Expand Up @@ -415,6 +416,11 @@ Nread(int fd, char *buf, size_t count, int prot)
nleft -= r;
buf += r;

if (prot == Pudp) {
/* read() guarantees atomic datagram delivery for UDP */
break;
}

/*
* We need some more bytes but don't want to wait around
* forever for them. In the case of partial results, we need
Expand Down