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

Add MPTCP support with the --multipath flag #1166

Closed
wants to merge 1 commit into from
Closed
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 @@ -315,6 +315,7 @@ struct iperf_test
int udp_counters_64bit; /* --use-64-bit-udp-counters */
int forceflush; /* --forceflush - flushing output at every interval */
int multisend;
int multipath; /* -m option - multi-path variant */
int repeating_payload; /* --repeating-payload */
int timestamps; /* --timestamps */
char *timestamp_format;
Expand Down
4 changes: 4 additions & 0 deletions src/iperf3.1
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ run in client mode, connecting to the specified server.
By default, a test consists of sending data from the client to the
server, unless the \-R flag is specified.
.TP
.BR -m ", " --multipath " "
use multipath variant for the current protocol. This only applies to
TCP and enables MPTCP usage.
.TP
.BR --sctp
use SCTP rather than TCP (FreeBSD and Linux)
.TP
Expand Down
11 changes: 10 additions & 1 deletion src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"connect-timeout", required_argument, NULL, OPT_CONNECT_TIMEOUT},
{"idle-timeout", required_argument, NULL, OPT_IDLE_TIMEOUT},
{"rcv-timeout", required_argument, NULL, OPT_RCV_TIMEOUT},
{"multipath", no_argument, NULL, 'm'},
{"debug", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
Expand All @@ -1030,7 +1031,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
char *client_username = NULL, *client_rsa_public_key = NULL, *server_rsa_private_key = NULL;
#endif /* HAVE_SSL */

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) {
while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:mM:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
portno = atoi(optarg);
Expand Down Expand Up @@ -1103,6 +1104,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
iperf_set_test_role(test, 'c');
iperf_set_test_server_hostname(test, optarg);
break;
case 'm':
set_protocol(test, Ptcp);
test->multipath = 1;
break;
case 'u':
set_protocol(test, Pudp);
client_flag = 1;
Expand Down Expand Up @@ -2000,6 +2005,8 @@ send_parameters(struct iperf_test *test)
cJSON_AddTrueToObject(j, "reverse");
if (test->bidirectional)
cJSON_AddTrueToObject(j, "bidirectional");
if (test->multipath)
cJSON_AddTrueToObject(j, "multipath");
if (test->settings->socket_bufsize)
cJSON_AddNumberToObject(j, "window", test->settings->socket_bufsize);
if (test->settings->blksize)
Expand Down Expand Up @@ -2112,6 +2119,8 @@ get_parameters(struct iperf_test *test)
iperf_set_test_reverse(test, 1);
if ((j_p = cJSON_GetObjectItem(j, "bidirectional")) != NULL)
iperf_set_test_bidirectional(test, 1);
if ((j_p = cJSON_GetObjectItem(j, "multipath")) != NULL)
test->multipath = 1;
if ((j_p = cJSON_GetObjectItem(j, "window")) != NULL)
test->settings->socket_bufsize = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "len")) != NULL)
Expand Down
1 change: 1 addition & 0 deletions src/iperf_locale.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const char usage_longstr[] = "Usage: iperf3 [-s|-c host] [options]\n"
" --nstreams # number of SCTP streams\n"
#endif /* HAVE_SCTP_H */
" -u, --udp use UDP rather than TCP\n"
" -m, --multipath use MPTCP rather than plain TCP\n"
" --connect-timeout # timeout for control connection setup (ms)\n"
" -b, --bitrate #[KMG][/#] target bitrate in bits/sec (0 for unlimited)\n"
" (default %d Mbit/sec for UDP, unlimited for TCP)\n"
Expand Down
18 changes: 15 additions & 3 deletions src/iperf_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
#include "net.h"
#include "cjson.h"

#ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262
#endif

#if defined(HAVE_FLOWLABEL)
#include "flowlabel.h"
#endif /* HAVE_FLOWLABEL */
Expand Down Expand Up @@ -154,6 +158,7 @@ iperf_tcp_listen(struct iperf_test *test)
socklen_t optlen;
int saved_errno;
int rcvbuf_actual, sndbuf_actual;
int protocol = 0;

s = test->listener;

Expand All @@ -166,7 +171,7 @@ iperf_tcp_listen(struct iperf_test *test)
*
* It's not clear whether this is a requirement or a convenience.
*/
if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
if (test->multipath || test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
struct addrinfo hints, *res;
char portstr[6];

Expand Down Expand Up @@ -194,7 +199,10 @@ iperf_tcp_listen(struct iperf_test *test)
return -1;
}

if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) {
if (test->multipath)
protocol = IPPROTO_MPTCP;

if ((s = socket(res->ai_family, SOCK_STREAM, protocol)) < 0) {
freeaddrinfo(res);
i_errno = IESTREAMLISTEN;
return -1;
Expand Down Expand Up @@ -375,6 +383,7 @@ iperf_tcp_connect(struct iperf_test *test)
socklen_t optlen;
int saved_errno;
int rcvbuf_actual, sndbuf_actual;
int protocol = 0;

if (test->bind_address) {
memset(&hints, 0, sizeof(hints));
Expand All @@ -397,7 +406,10 @@ iperf_tcp_connect(struct iperf_test *test)
return -1;
}

if ((s = socket(server_res->ai_family, SOCK_STREAM, 0)) < 0) {
if (test->multipath)
protocol = IPPROTO_MPTCP;

if ((s = socket(server_res->ai_family, SOCK_STREAM, protocol)) < 0) {
if (test->bind_address)
freeaddrinfo(local_res);
freeaddrinfo(server_res);
Expand Down