First try at issue #461.
First, realize that we've been setting the congestion control (CC) algorithm unnecessarily; rather than doing it for all listening or connecting sockets, do it just for those sockets that are being used for TCP test streams. Record the CC algorithm in use (this handles the case where a CC algorithm hasn't been specified), and have the client and server exchange this information. Report the CC algorithms that were used (note that it's theoretically possible for the two ends of the test to be using different algorithms, if no algorithm was explicitly specified and the two end hosts have different defaults, or if one side allows setting the CC algorithm and the other doesn't). Committing to a branch to make it easier to test this code on a wider combination of systems.
Этот коммит содержится в:
родитель
353615b772
Коммит
7eeaa1cb07
@ -220,6 +220,8 @@ struct iperf_test
|
|||||||
#endif /* HAVE_CPUSET_SETAFFINITY */
|
#endif /* HAVE_CPUSET_SETAFFINITY */
|
||||||
char *title; /* -T option */
|
char *title; /* -T option */
|
||||||
char *congestion; /* -C option */
|
char *congestion; /* -C option */
|
||||||
|
char *congestion_used; /* what was actually used */
|
||||||
|
char *remote_congestion_used; /* what the other side used */
|
||||||
char *pidfile; /* -P option */
|
char *pidfile; /* -P option */
|
||||||
|
|
||||||
char *logfile; /* --logfile option */
|
char *logfile; /* --logfile option */
|
||||||
|
@ -1334,6 +1334,8 @@ send_parameters(struct iperf_test *test)
|
|||||||
cJSON_AddStringToObject(j, "title", test->title);
|
cJSON_AddStringToObject(j, "title", test->title);
|
||||||
if (test->congestion)
|
if (test->congestion)
|
||||||
cJSON_AddStringToObject(j, "congestion", test->congestion);
|
cJSON_AddStringToObject(j, "congestion", test->congestion);
|
||||||
|
if (test->congestion_used)
|
||||||
|
cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
|
||||||
if (test->get_server_output)
|
if (test->get_server_output)
|
||||||
cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
|
cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
|
||||||
if (test->udp_counters_64bit)
|
if (test->udp_counters_64bit)
|
||||||
@ -1414,6 +1416,8 @@ get_parameters(struct iperf_test *test)
|
|||||||
test->title = strdup(j_p->valuestring);
|
test->title = strdup(j_p->valuestring);
|
||||||
if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
|
if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
|
||||||
test->congestion = strdup(j_p->valuestring);
|
test->congestion = strdup(j_p->valuestring);
|
||||||
|
if ((j_p = cJSON_GetObjectItem(j, "congestion_used")) != NULL)
|
||||||
|
test->congestion_used = strdup(j_p->valuestring);
|
||||||
if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
|
if ((j_p = cJSON_GetObjectItem(j, "get_server_output")) != NULL)
|
||||||
iperf_set_test_get_server_output(test, 1);
|
iperf_set_test_get_server_output(test, 1);
|
||||||
if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
|
if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
|
||||||
@ -1455,6 +1459,9 @@ send_results(struct iperf_test *test)
|
|||||||
else
|
else
|
||||||
sender_has_retransmits = test->sender_has_retransmits;
|
sender_has_retransmits = test->sender_has_retransmits;
|
||||||
cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
|
cJSON_AddNumberToObject(j, "sender_has_retransmits", sender_has_retransmits);
|
||||||
|
if ( test->congestion_used ) {
|
||||||
|
cJSON_AddStringToObject(j, "congestion_used", test->congestion_used);
|
||||||
|
}
|
||||||
|
|
||||||
/* If on the server and sending server output, then do this */
|
/* If on the server and sending server output, then do this */
|
||||||
if (test->role == 's' && test->get_server_output) {
|
if (test->role == 's' && test->get_server_output) {
|
||||||
@ -1529,6 +1536,7 @@ get_results(struct iperf_test *test)
|
|||||||
cJSON *j_cpu_util_total;
|
cJSON *j_cpu_util_total;
|
||||||
cJSON *j_cpu_util_user;
|
cJSON *j_cpu_util_user;
|
||||||
cJSON *j_cpu_util_system;
|
cJSON *j_cpu_util_system;
|
||||||
|
cJSON *j_remote_congestion_used;
|
||||||
cJSON *j_sender_has_retransmits;
|
cJSON *j_sender_has_retransmits;
|
||||||
int result_has_retransmits;
|
int result_has_retransmits;
|
||||||
cJSON *j_streams;
|
cJSON *j_streams;
|
||||||
@ -1637,6 +1645,12 @@ get_results(struct iperf_test *test)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
j_remote_congestion_used = cJSON_GetObjectItem(j, "congestion_used");
|
||||||
|
if (j_remote_congestion_used != NULL) {
|
||||||
|
test->remote_congestion_used = strdup(j_remote_congestion_used->valuestring);
|
||||||
|
}
|
||||||
|
|
||||||
cJSON_Delete(j);
|
cJSON_Delete(j);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@ -1833,6 +1847,8 @@ iperf_defaults(struct iperf_test *testp)
|
|||||||
#endif /* HAVE_CPUSET_SETAFFINITY */
|
#endif /* HAVE_CPUSET_SETAFFINITY */
|
||||||
testp->title = NULL;
|
testp->title = NULL;
|
||||||
testp->congestion = NULL;
|
testp->congestion = NULL;
|
||||||
|
testp->congestion_used = NULL;
|
||||||
|
testp->remote_congestion_used = NULL;
|
||||||
testp->server_port = PORT;
|
testp->server_port = PORT;
|
||||||
testp->ctrl_sck = -1;
|
testp->ctrl_sck = -1;
|
||||||
testp->prot_listener = -1;
|
testp->prot_listener = -1;
|
||||||
@ -1965,6 +1981,10 @@ iperf_free_test(struct iperf_test *test)
|
|||||||
free(test->title);
|
free(test->title);
|
||||||
if (test->congestion)
|
if (test->congestion)
|
||||||
free(test->congestion);
|
free(test->congestion);
|
||||||
|
if (test->congestion_used)
|
||||||
|
free(test->congestion_used);
|
||||||
|
if (test->remote_congestion_used)
|
||||||
|
free(test->remote_congestion_used);
|
||||||
if (test->omit_timer != NULL)
|
if (test->omit_timer != NULL)
|
||||||
tmr_cancel(test->omit_timer);
|
tmr_cancel(test->omit_timer);
|
||||||
if (test->timer != NULL)
|
if (test->timer != NULL)
|
||||||
@ -2500,11 +2520,24 @@ iperf_print_results(struct iperf_test *test)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test->json_output)
|
if (test->json_output) {
|
||||||
cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f host_user: %f host_system: %f remote_total: %f remote_user: %f remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2]));
|
cJSON_AddItemToObject(test->json_end, "cpu_utilization_percent", iperf_json_printf("host_total: %f host_user: %f host_system: %f remote_total: %f remote_user: %f remote_system: %f", (double) test->cpu_util[0], (double) test->cpu_util[1], (double) test->cpu_util[2], (double) test->remote_cpu_util[0], (double) test->remote_cpu_util[1], (double) test->remote_cpu_util[2]));
|
||||||
|
if (test->congestion_used) {
|
||||||
|
cJSON_AddStringToObject(test->json_end, "local_tcp_congestion", test->congestion_used);
|
||||||
|
}
|
||||||
|
if (test->remote_congestion_used) {
|
||||||
|
cJSON_AddStringToObject(test->json_end, "remote_tcp_congestion", test->remote_congestion_used);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (test->verbose) {
|
if (test->verbose) {
|
||||||
iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
|
iprintf(test, report_cpu, report_local, test->sender?report_sender:report_receiver, test->cpu_util[0], test->cpu_util[1], test->cpu_util[2], report_remote, test->sender?report_receiver:report_sender, test->remote_cpu_util[0], test->remote_cpu_util[1], test->remote_cpu_util[2]);
|
||||||
|
if (test->congestion_used) {
|
||||||
|
iprintf(test, "local_tcp_congestion %s\n", test->congestion_used);
|
||||||
|
}
|
||||||
|
if (test->remote_congestion_used) {
|
||||||
|
iprintf(test, "remote_tcp_congestion %s\n", test->remote_congestion_used);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print server output if we're on the client and it was requested/provided */
|
/* Print server output if we're on the client and it was requested/provided */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* iperf, Copyright (c) 2014, 2015, The Regents of the University of
|
* iperf, Copyright (c) 2014, 2015, 2016, The Regents of the University of
|
||||||
* California, through Lawrence Berkeley National Laboratory (subject
|
* California, through Lawrence Berkeley National Laboratory (subject
|
||||||
* to receipt of any required approvals from the U.S. Dept. of
|
* to receipt of any required approvals from the U.S. Dept. of
|
||||||
* Energy). All rights reserved.
|
* Energy). All rights reserved.
|
||||||
@ -43,6 +43,11 @@
|
|||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_TCP_CONGESTION)
|
||||||
|
#if !defined(TCP_CA_NAME_MAX)
|
||||||
|
#define TCP_CA_NAME_MAX 16
|
||||||
|
#endif /* TCP_CA_NAME_MAX */
|
||||||
|
#endif /* HAVE_TCP_CONGESTION */
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_create_streams(struct iperf_test *test)
|
iperf_create_streams(struct iperf_test *test)
|
||||||
@ -59,6 +64,31 @@ iperf_create_streams(struct iperf_test *test)
|
|||||||
if ((s = test->protocol->connect(test)) < 0)
|
if ((s = test->protocol->connect(test)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#if defined(HAVE_TCP_CONGESTION)
|
||||||
|
if (test->protocol->id == Ptcp) {
|
||||||
|
if (test->congestion) {
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
|
||||||
|
close(s);
|
||||||
|
i_errno = IESETCONGESTION;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int len = TCP_CA_NAME_MAX;
|
||||||
|
char ca[TCP_CA_NAME_MAX + 1];
|
||||||
|
if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) {
|
||||||
|
close(s);
|
||||||
|
i_errno = IESETCONGESTION;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
test->congestion_used = strdup(ca);
|
||||||
|
if (test->debug) {
|
||||||
|
printf("Congestion algorithm is %s\n", test->congestion_used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_TCP_CONGESTION */
|
||||||
|
|
||||||
if (test->sender)
|
if (test->sender)
|
||||||
FD_SET(s, &test->write_set);
|
FD_SET(s, &test->write_set);
|
||||||
else
|
else
|
||||||
|
@ -62,6 +62,11 @@
|
|||||||
#include "iperf_util.h"
|
#include "iperf_util.h"
|
||||||
#include "iperf_locale.h"
|
#include "iperf_locale.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_TCP_CONGESTION)
|
||||||
|
#if !defined(TCP_CA_NAME_MAX)
|
||||||
|
#define TCP_CA_NAME_MAX 16
|
||||||
|
#endif /* TCP_CA_NAME_MAX */
|
||||||
|
#endif /* HAVE_TCP_CONGESTION */
|
||||||
|
|
||||||
int
|
int
|
||||||
iperf_server_listen(struct iperf_test *test)
|
iperf_server_listen(struct iperf_test *test)
|
||||||
@ -510,6 +515,33 @@ iperf_run_server(struct iperf_test *test)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_TCP_CONGESTION)
|
||||||
|
if (test->protocol->id == Ptcp) {
|
||||||
|
if (test->congestion) {
|
||||||
|
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
|
||||||
|
close(s);
|
||||||
|
cleanup_server(test);
|
||||||
|
i_errno = IESETCONGESTION;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int len = TCP_CA_NAME_MAX;
|
||||||
|
char ca[TCP_CA_NAME_MAX + 1];
|
||||||
|
if (getsockopt(s, IPPROTO_TCP, TCP_CONGESTION, ca, &len) < 0) {
|
||||||
|
close(s);
|
||||||
|
cleanup_server(test);
|
||||||
|
i_errno = IESETCONGESTION;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
test->congestion_used = strdup(ca);
|
||||||
|
if (test->debug) {
|
||||||
|
printf("Congestion algorithm is %s\n", test->congestion_used);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_TCP_CONGESTION */
|
||||||
|
|
||||||
if (!is_closed(s)) {
|
if (!is_closed(s)) {
|
||||||
sp = iperf_new_stream(test, s);
|
sp = iperf_new_stream(test, s);
|
||||||
if (!sp) {
|
if (!sp) {
|
||||||
|
@ -235,16 +235,6 @@ iperf_tcp_listen(struct iperf_test *test)
|
|||||||
}
|
}
|
||||||
printf("SO_SNDBUF is %u\n", opt);
|
printf("SO_SNDBUF is %u\n", opt);
|
||||||
}
|
}
|
||||||
#if defined(HAVE_TCP_CONGESTION)
|
|
||||||
if (test->congestion) {
|
|
||||||
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
|
|
||||||
close(s);
|
|
||||||
freeaddrinfo(res);
|
|
||||||
i_errno = IESETCONGESTION;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HAVE_TCP_CONGESTION */
|
|
||||||
#if defined(HAVE_SO_MAX_PACING_RATE)
|
#if defined(HAVE_SO_MAX_PACING_RATE)
|
||||||
/* If socket pacing is available and not disabled, try it. */
|
/* If socket pacing is available and not disabled, try it. */
|
||||||
if (! test->no_fq_socket_pacing) {
|
if (! test->no_fq_socket_pacing) {
|
||||||
@ -473,17 +463,6 @@ iperf_tcp_connect(struct iperf_test *test)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_FLOWLABEL */
|
#endif /* HAVE_FLOWLABEL */
|
||||||
|
|
||||||
#if defined(HAVE_TCP_CONGESTION)
|
|
||||||
if (test->congestion) {
|
|
||||||
if (setsockopt(s, IPPROTO_TCP, TCP_CONGESTION, test->congestion, strlen(test->congestion)) < 0) {
|
|
||||||
close(s);
|
|
||||||
freeaddrinfo(server_res);
|
|
||||||
i_errno = IESETCONGESTION;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* HAVE_TCP_CONGESTION */
|
|
||||||
|
|
||||||
#if defined(HAVE_SO_MAX_PACING_RATE)
|
#if defined(HAVE_SO_MAX_PACING_RATE)
|
||||||
/* If socket pacing is available and not disabled, try it. */
|
/* If socket pacing is available and not disabled, try it. */
|
||||||
if (! test->no_fq_socket_pacing) {
|
if (! test->no_fq_socket_pacing) {
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user