Added -C / --linux-congestion.

Also a few other bugfixes I ran across.
This commit is contained in:
Jef Poskanzer 2013-12-13 19:57:52 -08:00
parent adec7fe48b
commit 62bfa88ceb
8 changed files with 99 additions and 12 deletions

View File

@ -156,6 +156,7 @@ struct iperf_test
char *diskfile_name; /* -F option */
int affinity, server_affinity; /* -A option */
char *title; /* -T option */
char *congestion; /* -C option */
int ctrl_sck;
int listener;

View File

@ -123,6 +123,9 @@ period.
.TP
.BR -T ", " --title " \fIstr\fR"
Prefix every output line with this string.
.TP
.BR -C ", " --linux-congestion " \fIalgo\fR"
Set the congestion control algorithm (linux only).
.SH AUTHORS
Iperf was originally written by Mark Gates and Alex Warshavsky.

View File

@ -519,14 +519,10 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{"file", required_argument, NULL, 'F'},
{"affinity", required_argument, NULL, 'A'},
{"title", required_argument, NULL, 'T'},
{"help", no_argument, NULL, 'h'},
/* XXX: The following ifdef needs to be split up. linux-congestion is not
* necessarily supported by systems that support tos.
*/
#ifdef ADD_WHEN_SUPPORTED
{"linux-congestion", required_argument, NULL, 'L'},
#if defined(linux)
{"linux-congestion", required_argument, NULL, 'C'},
#endif
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
int flag;
@ -536,7 +532,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
blksize = 0;
server_flag = client_flag = rate_flag = 0;
while ((flag = getopt_long(argc, argv, "p:f:i:DVJvsc:ub:t:n:l:P:Rw:B:M:N46S:L:ZO:F:A:T:h", longopts, NULL)) != -1) {
while ((flag = getopt_long(argc, argv, "p:f:i:DVJvsc:ub:t:n:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:h", longopts, NULL)) != -1) {
switch (flag) {
case 'p':
test->server_port = atoi(optarg);
@ -629,8 +625,7 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
client_flag = 1;
break;
case 'B':
test->bind_address = (char *) malloc(strlen(optarg)+1);
strncpy(test->bind_address, optarg, strlen(optarg)+1);
test->bind_address = strdup(optarg);
break;
case 'M':
test->settings->mss = atoi(optarg);
@ -707,6 +702,15 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
sprintf(test->title, "%s: ", optarg);
client_flag = 1;
break;
case 'C':
#if defined(linux)
test->congestion = strdup(optarg);
client_flag = 1;
#else /* linux */
i_errno = IEUNIMP;
return -1;
#endif /* linux */
break;
case 'h':
default:
usage_long();
@ -1023,6 +1027,8 @@ send_parameters(struct iperf_test *test)
cJSON_AddIntToObject(j, "flowlabel", test->settings->flowlabel);
if (test->title)
cJSON_AddStringToObject(j, "title", test->title);
if (test->congestion)
cJSON_AddStringToObject(j, "congestion", test->congestion);
if (JSON_write(test->ctrl_sck, j) < 0) {
i_errno = IESENDPARAMS;
r = -1;
@ -1078,6 +1084,8 @@ get_parameters(struct iperf_test *test)
test->settings->flowlabel = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "title")) != NULL)
test->title = strdup(j_p->valuestring);
if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
test->congestion = strdup(j_p->valuestring);
if (test->sender && test->protocol->id == Ptcp && has_tcpinfo_retransmits())
test->sender_has_retransmits = 1;
cJSON_Delete(j);
@ -1385,6 +1393,7 @@ iperf_defaults(struct iperf_test *testp)
testp->affinity = -1;
testp->server_affinity = -1;
testp->title = NULL;
testp->congestion = NULL;
testp->server_port = PORT;
testp->ctrl_sck = -1;
testp->prot_listener = -1;
@ -1465,11 +1474,15 @@ iperf_free_test(struct iperf_test *test)
iperf_free_stream(sp);
}
free(test->server_hostname);
free(test->bind_address);
if (test->server_hostname)
free(test->server_hostname);
if (test->bind_address)
free(test->bind_address);
free(test->settings);
if (test->title)
free(test->title);
if (test->congestion)
free(test->congestion);
if (test->omit_timer != NULL)
tmr_cancel(test->omit_timer);
if (test->timer != NULL)
@ -1533,8 +1546,10 @@ iperf_reset_test(struct iperf_test *test)
test->duration = DURATION;
test->server_affinity = -1;
test->title = NULL;
test->congestion = NULL;
test->state = 0;
test->server_hostname = NULL;
test->bind_address = NULL;
test->ctrl_sck = -1;
test->prot_listener = -1;

View File

@ -274,6 +274,7 @@ enum {
IEPROTOCOL = 131, // Protocol does not exist
IEAFFINITY = 132, // Unable to set CPU affinity (check perror)
IEDAEMON = 133, // Unable to become a daemon process
IESETCONGESTION = 134, // Unable to set TCP_CONGESTION
/* Stream errors */
IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror)
IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror)

View File

@ -284,6 +284,10 @@ iperf_strerror(int i_errno)
snprintf(errstr, len, "unable to update timer");
perr = 1;
break;
case IESETCONGESTION:
snprintf(errstr, len, "unable to set TCP_CONGESTION");
perr = 1;
break;
}
if (herr || perr)

View File

@ -259,6 +259,7 @@ iperf_test_reset(struct iperf_test *test)
test->affinity = -1;
test->server_affinity = -1;
test->title = NULL;
test->congestion = NULL;
test->state = 0;
test->server_hostname = NULL;

View File

@ -120,6 +120,7 @@ iperf_tcp_listen(struct iperf_test *test)
struct addrinfo hints, *res;
char portstr[6];
int s, opt;
int saved_errno;
s = test->listener;
@ -146,8 +147,10 @@ iperf_tcp_listen(struct iperf_test *test)
if (test->no_delay) {
opt = 1;
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESETNODELAY;
return -1;
}
@ -155,30 +158,50 @@ iperf_tcp_listen(struct iperf_test *test)
// XXX: Setting MSS is very buggy!
if ((opt = test->settings->mss)) {
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESETMSS;
return -1;
}
}
if ((opt = test->settings->socket_bufsize)) {
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESETBUF;
return -1;
}
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESETBUF;
return -1;
}
}
#if defined(linux)
if (test->congestion) {
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESETCONGESTION;
return -1;
}
}
#endif
opt = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IEREUSEADDR;
return -1;
}
@ -191,8 +214,10 @@ iperf_tcp_listen(struct iperf_test *test)
}
if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(res);
errno = saved_errno;
i_errno = IESTREAMLISTEN;
return -1;
}
@ -221,6 +246,7 @@ iperf_tcp_connect(struct iperf_test *test)
struct addrinfo hints, *local_res, *server_res;
char portstr[6];
int s, opt;
int saved_errno;
if (test->bind_address) {
memset(&hints, 0, sizeof(hints));
@ -253,9 +279,11 @@ iperf_tcp_connect(struct iperf_test *test)
if (test->bind_address) {
if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(local_res);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESTREAMCONNECT;
return -1;
}
@ -266,30 +294,38 @@ iperf_tcp_connect(struct iperf_test *test)
if (test->no_delay) {
opt = 1;
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETNODELAY;
return -1;
}
}
if ((opt = test->settings->mss)) {
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETMSS;
return -1;
}
}
if ((opt = test->settings->socket_bufsize)) {
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETBUF;
return -1;
}
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETBUF;
return -1;
}
@ -297,8 +333,10 @@ iperf_tcp_connect(struct iperf_test *test)
#if defined(linux)
if (test->settings->flowlabel) {
if (server_res->ai_addr->sa_family != AF_INET6) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETFLOW;
return -1;
} else {
@ -315,8 +353,10 @@ iperf_tcp_connect(struct iperf_test *test)
memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETFLOW;
return -1;
}
@ -324,8 +364,10 @@ iperf_tcp_connect(struct iperf_test *test)
opt = 1;
if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETFLOW;
return -1;
}
@ -333,9 +375,24 @@ iperf_tcp_connect(struct iperf_test *test)
}
#endif
#if defined(linux)
if (test->congestion) {
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESETCONGESTION;
return -1;
}
}
#endif
if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
saved_errno = errno;
close(s);
freeaddrinfo(server_res);
errno = saved_errno;
i_errno = IESTREAMCONNECT;
return -1;
}
@ -344,7 +401,9 @@ iperf_tcp_connect(struct iperf_test *test)
/* Send cookie for verification */
if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
saved_errno = errno;
close(s);
errno = saved_errno;
i_errno = IESENDCOOKIE;
return -1;
}

View File

@ -94,6 +94,9 @@ const char usage_longstr[] = "Usage: iperf [-s|-c host] [options]\n"
" -R, --reverse run in reverse mode (server sends, client receives)\n"
" -w, --window #[KMG] TCP window size (socket buffer size)\n"
" -B, --bind <host> bind to a specific interface or multicast address\n"
#if defined(linux)
" -C, --linux-congestion <algo> set TCP congestion control algorithm (Linux only)\n"
#endif
" -M, --set-mss # set TCP maximum segment size (MTU - 40 bytes)\n"
" -N, --nodelay set TCP no delay, disabling Nagle's Algorithm\n"
" -4, --version4 only use IPv4\n"