Added support for setting the MAXSEG (MSS) and NODELAY TCP options. Setting MSS is still a little buggy.
Этот коммит содержится в:
родитель
aa89cda29f
Коммит
c81883bf08
124
src/iperf_api.c
124
src/iperf_api.c
@ -145,27 +145,8 @@ iperf_init_test(struct iperf_test *test)
|
|||||||
struct iperf_stream *sp;
|
struct iperf_stream *sp;
|
||||||
int64_t dtargus;
|
int64_t dtargus;
|
||||||
|
|
||||||
|
|
||||||
/* XXX: These variables were used in the old UDP code
|
|
||||||
int64_t delayus, adjustus, dtargus;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (test->protocol == Pudp) {
|
if (test->protocol == Pudp) {
|
||||||
prot = "UDP";
|
prot = "UDP";
|
||||||
/* XXX: Trying my own implementation
|
|
||||||
dtargus = (int64_t) (test->default_settings->blksize) * SEC_TO_US * 8;
|
|
||||||
dtargus /= test->default_settings->rate;
|
|
||||||
|
|
||||||
assert(dtargus != 0);
|
|
||||||
|
|
||||||
delayus = dtargus;
|
|
||||||
adjustus = 0;
|
|
||||||
|
|
||||||
printf("iperf_run_client: adjustus: %lld, delayus %lld \n", adjustus, delayus);
|
|
||||||
|
|
||||||
for (sp = test->streams; sp != NULL; sp = sp->next)
|
|
||||||
sp->send_timer = new_timer(0, dtargus);
|
|
||||||
*/
|
|
||||||
dtargus = (int64_t) test->default_settings->blksize * SEC_TO_US * 8;
|
dtargus = (int64_t) test->default_settings->blksize * SEC_TO_US * 8;
|
||||||
dtargus /= test->default_settings->rate;
|
dtargus /= test->default_settings->rate;
|
||||||
|
|
||||||
@ -236,6 +217,11 @@ package_parameters(struct iperf_test *test)
|
|||||||
strncat(pstring, optbuf, sizeof(pstring));
|
strncat(pstring, optbuf, sizeof(pstring));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (test->no_delay) {
|
||||||
|
snprintf(optbuf, sizeof(optbuf), "-N ");
|
||||||
|
strncat(pstring, optbuf, sizeof(pstring));
|
||||||
|
}
|
||||||
|
|
||||||
if (test->default_settings->bytes) {
|
if (test->default_settings->bytes) {
|
||||||
snprintf(optbuf, sizeof(optbuf), "-n %llu ", test->default_settings->bytes);
|
snprintf(optbuf, sizeof(optbuf), "-n %llu ", test->default_settings->bytes);
|
||||||
strncat(pstring, optbuf, sizeof(pstring));
|
strncat(pstring, optbuf, sizeof(pstring));
|
||||||
@ -296,7 +282,7 @@ parse_parameters(struct iperf_test *test)
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ch = getopt(n, params, "pt:n:m:uP:Rw:l:b:")) != -1) {
|
while ((ch = getopt(n, params, "pt:n:m:uNP:Rw:l:b:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'p':
|
case 'p':
|
||||||
test->protocol = Ptcp;
|
test->protocol = Ptcp;
|
||||||
@ -314,6 +300,9 @@ parse_parameters(struct iperf_test *test)
|
|||||||
test->protocol = Pudp;
|
test->protocol = Pudp;
|
||||||
test->new_stream = iperf_new_udp_stream;
|
test->new_stream = iperf_new_udp_stream;
|
||||||
break;
|
break;
|
||||||
|
case 'N':
|
||||||
|
test->no_delay = 1;
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
test->num_streams = atoi(optarg);
|
test->num_streams = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
@ -349,6 +338,9 @@ parse_parameters(struct iperf_test *test)
|
|||||||
int
|
int
|
||||||
iperf_exchange_parameters(struct iperf_test * test)
|
iperf_exchange_parameters(struct iperf_test * test)
|
||||||
{
|
{
|
||||||
|
int s, opt, len;
|
||||||
|
struct sockaddr_in sa;
|
||||||
|
|
||||||
if (test->role == 'c') {
|
if (test->role == 'c') {
|
||||||
|
|
||||||
package_parameters(test);
|
package_parameters(test);
|
||||||
@ -362,6 +354,52 @@ iperf_exchange_parameters(struct iperf_test * test)
|
|||||||
test->listener_udp = netannounce(test->protocol, NULL, test->server_port);
|
test->listener_udp = netannounce(test->protocol, NULL, test->server_port);
|
||||||
FD_SET(test->listener_udp, &test->read_set);
|
FD_SET(test->listener_udp, &test->read_set);
|
||||||
test->max_fd = (test->listener_udp > test->max_fd) ? test->listener_udp : test->max_fd;
|
test->max_fd = (test->listener_udp > test->max_fd) ? test->listener_udp : test->max_fd;
|
||||||
|
} else if (test->protocol == Ptcp) {
|
||||||
|
if (test->no_delay || test->default_settings->mss) {
|
||||||
|
FD_CLR(test->listener_tcp, &test->read_set);
|
||||||
|
close(test->listener_tcp);
|
||||||
|
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
perror("socket tcp listener mss");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (test->no_delay) {
|
||||||
|
opt = 1;
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt TCP_NODELAY");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
printf(" TCP NODELAY: on\n");
|
||||||
|
}
|
||||||
|
// XXX: Setting MSS is very buggy!
|
||||||
|
if (opt = test->default_settings->mss) {
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt TCP_MAXSEG");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
printf(" TCP MSS: %d\n", opt);
|
||||||
|
}
|
||||||
|
opt = 1;
|
||||||
|
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt SO_REUSEADDR");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sin_family = AF_INET;
|
||||||
|
sa.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
sa.sin_port = htons(test->server_port);
|
||||||
|
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
|
||||||
|
close(s);
|
||||||
|
perror("bind tcp mss/nodelay listener");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
listen(s, 5);
|
||||||
|
|
||||||
|
test->listener_tcp = s;
|
||||||
|
test->max_fd = (s > test->max_fd) ? s : test->max_fd;
|
||||||
|
FD_SET(test->listener_tcp, &test->read_set);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the control message to create streams and start the test
|
// Send the control message to create streams and start the test
|
||||||
@ -674,13 +712,48 @@ int
|
|||||||
iperf_create_streams(struct iperf_test *test)
|
iperf_create_streams(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
struct iperf_stream *sp;
|
struct iperf_stream *sp;
|
||||||
int i, s, buf;
|
struct sockaddr_in sa;
|
||||||
|
struct hostent *hent;
|
||||||
|
int i, s, buf, opt;
|
||||||
|
|
||||||
for (i = 0; i < test->num_streams; ++i) {
|
for (i = 0; i < test->num_streams; ++i) {
|
||||||
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
if (test->protocol == Ptcp && (test->no_delay || test->default_settings->mss)) {
|
||||||
if (s < 0) {
|
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
||||||
perror("netdial stream");
|
perror("gethostbyname");
|
||||||
return -1;
|
return (-1);
|
||||||
|
}
|
||||||
|
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||||
|
perror("socket");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sin_family = AF_INET;
|
||||||
|
memcpy(&sa.sin_addr.s_addr, hent->h_addr, sizeof(sa.sin_addr.s_addr));
|
||||||
|
sa.sin_port = htons(test->server_port);
|
||||||
|
|
||||||
|
if (test->no_delay) {
|
||||||
|
opt = 1;
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opt = test->default_settings->mss) {
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
|
||||||
|
perror("setsockopt");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0 && errno != EINPROGRESS) {
|
||||||
|
perror("connect tcp stream");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("netdial stream");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->protocol == Ptcp) {
|
if (test->protocol == Ptcp) {
|
||||||
@ -693,6 +766,7 @@ iperf_create_streams(struct iperf_test *test)
|
|||||||
perror("write data");
|
perror("write data");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// XXX: Should this read be TCP instead?
|
||||||
if (read(s, &buf, sizeof(i)) < 0) {
|
if (read(s, &buf, sizeof(i)) < 0) {
|
||||||
perror("read data");
|
perror("read data");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -70,6 +70,7 @@ iperf_server_listen(struct iperf_test *test)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// XXX: This code needs to be moved to after parameter exhange
|
// XXX: This code needs to be moved to after parameter exhange
|
||||||
|
/*
|
||||||
if (test->protocol == Ptcp) {
|
if (test->protocol == Ptcp) {
|
||||||
if (test->default_settings->socket_bufsize > 0) {
|
if (test->default_settings->socket_bufsize > 0) {
|
||||||
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
|
unit_snprintf(ubuf, UNIT_LEN, (double) x, 'A');
|
||||||
@ -78,6 +79,7 @@ iperf_server_listen(struct iperf_test *test)
|
|||||||
printf("Using TCP Autotuning\n");
|
printf("Using TCP Autotuning\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
printf("-----------------------------------------------------------\n");
|
printf("-----------------------------------------------------------\n");
|
||||||
|
|
||||||
FD_ZERO(&test->read_set);
|
FD_ZERO(&test->read_set);
|
||||||
@ -329,13 +331,14 @@ iperf_test_reset(struct iperf_test *test)
|
|||||||
test->default_settings->socket_bufsize = 0;
|
test->default_settings->socket_bufsize = 0;
|
||||||
test->default_settings->blksize = DEFAULT_TCP_BLKSIZE;
|
test->default_settings->blksize = DEFAULT_TCP_BLKSIZE;
|
||||||
test->default_settings->rate = RATE; /* UDP only */
|
test->default_settings->rate = RATE; /* UDP only */
|
||||||
|
test->default_settings->mss = 0;
|
||||||
memset(test->default_settings->cookie, 0, COOKIE_SIZE);
|
memset(test->default_settings->cookie, 0, COOKIE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_run_server(struct iperf_test *test)
|
iperf_run_server(struct iperf_test *test)
|
||||||
{
|
{
|
||||||
int result;
|
int result, s;
|
||||||
fd_set temp_read_set, temp_write_set;
|
fd_set temp_read_set, temp_write_set;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
@ -412,6 +415,18 @@ iperf_run_server(struct iperf_test *test)
|
|||||||
FD_CLR(test->listener_udp, &test->read_set);
|
FD_CLR(test->listener_udp, &test->read_set);
|
||||||
close(test->listener_udp);
|
close(test->listener_udp);
|
||||||
test->listener_udp = -1;
|
test->listener_udp = -1;
|
||||||
|
} else if (test->protocol == Ptcp) {
|
||||||
|
if (test->no_delay || test->default_settings->mss) {
|
||||||
|
FD_CLR(test->listener_tcp, &test->read_set);
|
||||||
|
close(test->listener_tcp);
|
||||||
|
if ((s = netannounce(Ptcp, NULL, test->server_port)) < 0) {
|
||||||
|
perror("reconnect tcp listener");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
test->listener_tcp = s;
|
||||||
|
test->max_fd = (s > test->max_fd ? s : test->max_fd);
|
||||||
|
FD_SET(test->listener_tcp, &test->read_set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
test->state = TEST_START;
|
test->state = TEST_START;
|
||||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user