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;
|
||||
int64_t dtargus;
|
||||
|
||||
|
||||
/* XXX: These variables were used in the old UDP code
|
||||
int64_t delayus, adjustus, dtargus;
|
||||
*/
|
||||
|
||||
if (test->protocol == Pudp) {
|
||||
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 /= test->default_settings->rate;
|
||||
|
||||
@ -236,6 +217,11 @@ package_parameters(struct iperf_test *test)
|
||||
strncat(pstring, optbuf, sizeof(pstring));
|
||||
}
|
||||
|
||||
if (test->no_delay) {
|
||||
snprintf(optbuf, sizeof(optbuf), "-N ");
|
||||
strncat(pstring, optbuf, sizeof(pstring));
|
||||
}
|
||||
|
||||
if (test->default_settings->bytes) {
|
||||
snprintf(optbuf, sizeof(optbuf), "-n %llu ", test->default_settings->bytes);
|
||||
strncat(pstring, optbuf, sizeof(pstring));
|
||||
@ -296,7 +282,7 @@ parse_parameters(struct iperf_test *test)
|
||||
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) {
|
||||
case 'p':
|
||||
test->protocol = Ptcp;
|
||||
@ -314,6 +300,9 @@ parse_parameters(struct iperf_test *test)
|
||||
test->protocol = Pudp;
|
||||
test->new_stream = iperf_new_udp_stream;
|
||||
break;
|
||||
case 'N':
|
||||
test->no_delay = 1;
|
||||
break;
|
||||
case 'P':
|
||||
test->num_streams = atoi(optarg);
|
||||
break;
|
||||
@ -349,6 +338,9 @@ parse_parameters(struct iperf_test *test)
|
||||
int
|
||||
iperf_exchange_parameters(struct iperf_test * test)
|
||||
{
|
||||
int s, opt, len;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
if (test->role == 'c') {
|
||||
|
||||
package_parameters(test);
|
||||
@ -362,6 +354,52 @@ iperf_exchange_parameters(struct iperf_test * test)
|
||||
test->listener_udp = netannounce(test->protocol, NULL, test->server_port);
|
||||
FD_SET(test->listener_udp, &test->read_set);
|
||||
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
|
||||
@ -674,13 +712,48 @@ int
|
||||
iperf_create_streams(struct iperf_test *test)
|
||||
{
|
||||
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) {
|
||||
s = netdial(test->protocol, test->server_hostname, test->server_port);
|
||||
if (s < 0) {
|
||||
perror("netdial stream");
|
||||
return -1;
|
||||
if (test->protocol == Ptcp && (test->no_delay || test->default_settings->mss)) {
|
||||
if ((hent = gethostbyname(test->server_hostname)) == 0) {
|
||||
perror("gethostbyname");
|
||||
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) {
|
||||
@ -693,6 +766,7 @@ iperf_create_streams(struct iperf_test *test)
|
||||
perror("write data");
|
||||
return -1;
|
||||
}
|
||||
// XXX: Should this read be TCP instead?
|
||||
if (read(s, &buf, sizeof(i)) < 0) {
|
||||
perror("read data");
|
||||
return -1;
|
||||
|
@ -70,6 +70,7 @@ iperf_server_listen(struct iperf_test *test)
|
||||
*/
|
||||
|
||||
// XXX: This code needs to be moved to after parameter exhange
|
||||
/*
|
||||
if (test->protocol == Ptcp) {
|
||||
if (test->default_settings->socket_bufsize > 0) {
|
||||
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("-----------------------------------------------------------\n");
|
||||
|
||||
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->blksize = DEFAULT_TCP_BLKSIZE;
|
||||
test->default_settings->rate = RATE; /* UDP only */
|
||||
test->default_settings->mss = 0;
|
||||
memset(test->default_settings->cookie, 0, COOKIE_SIZE);
|
||||
}
|
||||
|
||||
int
|
||||
iperf_run_server(struct iperf_test *test)
|
||||
{
|
||||
int result;
|
||||
int result, s;
|
||||
fd_set temp_read_set, temp_write_set;
|
||||
struct timeval tv;
|
||||
|
||||
@ -412,6 +415,18 @@ iperf_run_server(struct iperf_test *test)
|
||||
FD_CLR(test->listener_udp, &test->read_set);
|
||||
close(test->listener_udp);
|
||||
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;
|
||||
if (Nwrite(test->ctrl_sck, &test->state, sizeof(char), Ptcp) < 0) {
|
||||
|
Загрузка…
Ссылка в новой задаче
Block a user