Added -C / --linux-congestion.
Also a few other bugfixes I ran across.
Этот коммит содержится в:
родитель
adec7fe48b
Коммит
62bfa88ceb
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user