Skip to content

Commit

Permalink
Add -X to restrict SCTP binding to a subset of interfaces.
Browse files Browse the repository at this point in the history
Contains an alternate implementation of previously-submitted patches
to set the maximum segment size and no-delay options.

As a result of this change, SCTP functionality on Linux will generally
require the libsctp library (on CentOS and similar distributions this
is provided by the lksctp-tools RPM).

Part of esnet#131.

Submitted by:	Bruce Simpson <[email protected]>
  • Loading branch information
bmah888 committed Jan 5, 2015
1 parent eb9a2c0 commit e142062
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 15 deletions.
5 changes: 3 additions & 2 deletions configure.ac
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# iperf, Copyright (c) 2014, The Regents of the University of
# iperf, Copyright (c) 2014, 2015, 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.
Expand Down Expand Up @@ -86,7 +86,8 @@ AC_C_CONST
# Check for SCTP support
AC_CHECK_HEADERS([sys/socket.h])
AC_CHECK_HEADERS([netinet/sctp.h],
AC_DEFINE([HAVE_SCTP], [1], [Have SCTP support.]),
AC_DEFINE([HAVE_SCTP], [1], [Have SCTP support.])
AC_SEARCH_LIBS(sctp_bindx, [sctp]),
[],
[#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
Expand Down
4 changes: 2 additions & 2 deletions docs/dev.rst
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ Code Authors
The main authors of iperf3 are (in alphabetical order): Jon Dugan,
Seth Elliott, Bruce A. Mah, Jeff Poskanzer, Kaustubh Prabhu.
Additional code contributions have come from (also in alphabetical
order): Mark Ashley, Aaron Brown, Aeneas Jaißle, Susant Sahani, Brian
Tierney.
order): Mark Ashley, Aaron Brown, Aeneas Jaißle, Susant Sahani,
Bruce Simpson, Brian Tierney.

iperf3 contains some original code from iperf2. The authors of iperf2
are (in alphabetical order): Jon Dugan, John Estabrook, Jim Ferbuson,
Expand Down
10 changes: 9 additions & 1 deletion src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ struct iperf_settings
iperf_size_t bytes; /* number of bytes to send */
iperf_size_t blocks; /* number of blocks (packets) to send */
char unit_format; /* -f */
int num_ostreams; /* SCTP initmsg settings */
};

struct iperf_test;
Expand Down Expand Up @@ -186,6 +187,12 @@ struct iperf_textline {
TAILQ_ENTRY(iperf_textline) textlineentries;
};

struct xbind_entry {
char *name;
struct addrinfo *ai;
TAILQ_ENTRY(xbind_entry) link;
};

struct iperf_test
{
char role; /* 'c' lient or 's' erver */
Expand All @@ -194,7 +201,8 @@ struct iperf_test
struct protocol *protocol;
signed char state;
char *server_hostname; /* -c option */
char *bind_address; /* -B option */
char *bind_address; /* first -B option */
TAILQ_HEAD(xbind_addrhead, xbind_entry) xbind_addrs; /* all -X opts */
int bind_port; /* --cport option */
int server_port;
int omit; /* duration of omit period (-O flag) */
Expand Down
22 changes: 20 additions & 2 deletions src/iperf3.1
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ run in reverse mode (server sends, client receives)
window size / socket buffer size (this gets sent to the server and used on that side too)
.TP
.BR -M ", " --set-mss " \fIn\fR"
set TCP maximum segment size (MTU - 40 bytes)
set TCP/SCTP maximum segment size (MTU - 40 bytes)
.TP
.BR -N ", " --no-delay " "
set TCP no delay, disabling Nagle's Algorithm
set TCP/SCTP no delay, disabling Nagle's Algorithm
.TP
.BR -4 ", " --version4 " "
only use IPv4
Expand All @@ -147,6 +147,24 @@ set the IP 'type of service'
.BR -L ", " --flowlabel " \fIn\fR"
set the IPv6 flow label (currently only supported on Linux)
.TP
.BR -X ", " --xbind " \fIname\fR"
Bind SCTP associations to a specific subset of links using sctp_bindx(3).
The \fB--B\fR flag will be ignored if this flag is specified.
Normally SCTP will include the protocol addresses of all active links
on the local host when setting up an association. Specifying at least
one \fB--X\fR name will disable this behaviour.
This flag must be specified for each link to be included in the
association, and is supported for both iperf servers and clients
(the latter are supported by passing the first \fB--X\fR argument to bind(2)).
Hostnames are accepted as arguments and are resolved using
getaddrinfo(3).
If the \fB--4\fR or \fB--6\fR flags are specified, names
which do not resolve to addresses within the
specified protocol family will be ignored.
.TP
.BR --nstreams " \fIn\fR"
Set number of SCTP streams.
.TP
.BR -Z ", " --zerocopy " "
Use a "zero copy" method of sending data, such as sendfile(2),
instead of the usual write(2).
Expand Down
52 changes: 51 additions & 1 deletion src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,8 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
#endif /* HAVE_TCP_CONGESTION */
#if defined(HAVE_SCTP)
{"sctp", no_argument, NULL, OPT_SCTP},
{"nstreams", required_argument, NULL, OPT_NUMSTREAMS},
{"xbind", required_argument, NULL, 'X'},
#endif
{"pidfile", required_argument, NULL, 'I'},
{"logfile", required_argument, NULL, OPT_LOGFILE},
Expand All @@ -652,10 +654,11 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
char* comma;
#endif /* HAVE_CPU_AFFINITY */
char* slash;
struct xbind_entry *xbe;

blksize = 0;
server_flag = client_flag = rate_flag = duration_flag = 0;
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:h", longopts, NULL)) != -1) {
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
test->server_port = atoi(optarg);
Expand Down Expand Up @@ -719,6 +722,14 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
#endif /* HAVE_SCTP */
break;

case OPT_NUMSTREAMS:
#if defined(linux) || defined(__FreeBSD__)
test->settings->num_ostreams = unit_atoi(optarg);
client_flag = 1;
#else /* linux */
i_errno = IEUNIMP;
return -1;
#endif /* linux */
case 'b':
slash = strchr(optarg, '/');
if (slash) {
Expand Down Expand Up @@ -818,6 +829,20 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
return -1;
#endif /* HAVE_FLOWLABEL */
break;
case 'X':
xbe = (struct xbind_entry *)malloc(sizeof(struct xbind_entry));
if (!xbe) {
i_errno = IESETSCTPBINDX;
return -1;
}
memset(xbe, 0, sizeof(*xbe));
xbe->name = strdup(optarg);
if (!xbe->name) {
i_errno = IESETSCTPBINDX;
return -1;
}
TAILQ_INSERT_TAIL(&test->xbind_addrs, xbe, link);
break;
case 'Z':
if (!has_sendfile()) {
i_errno = IENOSENDFILE;
Expand Down Expand Up @@ -1732,6 +1757,7 @@ iperf_defaults(struct iperf_test *testp)
testp->diskfile_name = (char*) 0;
testp->affinity = -1;
testp->server_affinity = -1;
TAILQ_INIT(&testp->xbind_addrs);
#if defined(HAVE_CPUSET_SETAFFINITY)
CPU_ZERO(&testp->cpumask);
#endif /* HAVE_CPUSET_SETAFFINITY */
Expand Down Expand Up @@ -1845,6 +1871,18 @@ iperf_free_test(struct iperf_test *test)
free(test->server_hostname);
if (test->bind_address)
free(test->bind_address);
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
struct xbind_entry *xbe;

while (!TAILQ_EMPTY(&test->xbind_addrs)) {
xbe = TAILQ_FIRST(&test->xbind_addrs);
TAILQ_REMOVE(&test->xbind_addrs, xbe, link);
if (xbe->ai)
freeaddrinfo(xbe->ai);
free(xbe->name);
free(xbe);
}
}
free(test->settings);
if (test->title)
free(test->title);
Expand Down Expand Up @@ -1885,6 +1923,18 @@ iperf_free_test(struct iperf_test *test)
free(t);
}

/* sctp_bindx: do not free the arguments, only the resolver results */
if (!TAILQ_EMPTY(&test->xbind_addrs)) {
struct xbind_entry *xbe;

TAILQ_FOREACH(xbe, &test->xbind_addrs, link) {
if (xbe->ai) {
freeaddrinfo(xbe->ai);
xbe->ai = NULL;
}
}
}

/* XXX: Why are we setting these values to NULL? */
// test->streams = NULL;
test->stats_callback = NULL;
Expand Down
7 changes: 5 additions & 2 deletions src/iperf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct iperf_stream;
#define OPT_GET_SERVER_OUTPUT 3
#define OPT_UDP_COUNTERS_64BIT 4
#define OPT_CLIENT_PORT 5
#define OPT_NUMSTREAMS 6

/* states */
#define TEST_START 1
Expand Down Expand Up @@ -308,8 +309,8 @@ enum {
IECLIENTTERM = 119, // The client has terminated
IESERVERTERM = 120, // The server has terminated
IEACCESSDENIED = 121, // The server is busy running a test. Try again later.
IESETNODELAY = 122, // Unable to set TCP NODELAY (check perror)
IESETMSS = 123, // Unable to set TCP MSS (check perror)
IESETNODELAY = 122, // Unable to set TCP/SCTP NODELAY (check perror)
IESETMSS = 123, // Unable to set TCP/SCTP MSS (check perror)
IESETBUF = 124, // Unable to set socket buffer size (check perror)
IESETTOS = 125, // Unable to set IP TOS (check perror)
IESETCOS = 126, // Unable to set IPv6 traffic class (check perror)
Expand All @@ -324,6 +325,8 @@ enum {
IEPIDFILE = 135, // Unable to write PID file
IEV6ONLY = 136, // Unable to set/unset IPV6_V6ONLY (check perror)
IESETSCTPDISABLEFRAG = 137, // Unable to set SCTP Fragmentation (check perror)
IESETSCTPNSTREAM= 138, // Unable to set SCTP number of streams (check perror)
IESETSCTPBINDX= 139, // Unable to process sctp_bindx() parameters
/* Stream errors */
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)
Expand Down
8 changes: 6 additions & 2 deletions src/iperf_error.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,11 @@ iperf_strerror(int i_errno)
snprintf(errstr, len, "the server is busy running a test. try again later");
break;
case IESETNODELAY:
snprintf(errstr, len, "unable to set TCP NODELAY");
snprintf(errstr, len, "unable to set TCP/SCTP NODELAY");
perr = 1;
break;
case IESETMSS:
snprintf(errstr, len, "unable to set TCP MSS");
snprintf(errstr, len, "unable to set TCP/SCTP MSS");
perr = 1;
break;
case IESETBUF:
Expand Down Expand Up @@ -347,6 +347,10 @@ iperf_strerror(int i_errno)
snprintf(errstr, len, "unable to set SCTP_DISABLE_FRAGMENTS");
perr = 1;
break;
case IESETSCTPNSTREAM:
snprintf(errstr, len, "unable to set SCTP_INIT num of SCTP streams\n");
perr = 1;
break;
}

if (herr || perr)
Expand Down
6 changes: 4 additions & 2 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
" -c, --client <host> run in client mode, connecting to <host>\n"
#if defined(HAVE_SCTP)
" --sctp use SCTP rather than TCP\n"
" -X, --xbind <name> bind SCTP association to links\n"
" --nstreams # number of SCTP streams\n"
#endif /* HAVE_SCTP */
" -u, --udp use UDP rather than TCP\n"
" -b, --bandwidth #[KMG][/#] target bandwidth in bits/sec (0 for unlimited)\n"
Expand All @@ -137,8 +139,8 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
#if defined(HAVE_TCP_CONGESTION)
" -C, --congestion <algo> set TCP congestion control algorithm (Linux and FreeBSD only)\n"
#endif /* HAVE_TCP_CONGESTION */
" -M, --set-mss # set TCP maximum segment size (MTU - 40 bytes)\n"
" -N, --nodelay set TCP no delay, disabling Nagle's Algorithm\n"
" -M, --set-mss # set TCP/SCTP maximum segment size (MTU - 40 bytes)\n"
" -N, --no-delay set TCP/SCTP no delay, disabling Nagle's Algorithm\n"
" -4, --version4 only use IPv4\n"
" -6, --version6 only use IPv6\n"
" -S, --tos N set the IP 'type of service'\n"
Expand Down
Loading

0 comments on commit e142062

Please sign in to comment.