aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce A. Mah <bmah@es.net>2016-09-22 13:34:52 -0700
committerBruce A. Mah <bmah@es.net>2016-09-22 13:34:52 -0700
commit7eeaa1cb070de41ff41d2d881ddb094db7f43352 (patch)
tree86b4ce72d41417cf1908413de23b0c8f6ee9d6e4
parent353615b772201eb77786b25485bf20f4a50ce413 (diff)
downloadiperf3-7eeaa1cb070de41ff41d2d881ddb094db7f43352.tar.gz
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.
-rwxr-xr-xsrc/iperf.h2
-rwxr-xr-xsrc/iperf_api.c35
-rw-r--r--src/iperf_client_api.c32
-rw-r--r--src/iperf_server_api.c32
-rw-r--r--src/iperf_tcp.c21
5 files changed, 99 insertions, 23 deletions
diff --git a/src/iperf.h b/src/iperf.h
index 5e56e48..235065c 100755
--- a/src/iperf.h
+++ b/src/iperf.h
@@ -220,6 +220,8 @@ struct iperf_test
#endif /* HAVE_CPUSET_SETAFFINITY */
char *title; /* -T 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 *logfile; /* --logfile option */
diff --git a/src/iperf_api.c b/src/iperf_api.c
index ee751a2..b364835 100755
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -1334,6 +1334,8 @@ send_parameters(struct iperf_test *test)
cJSON_AddStringToObject(j, "title", test->title);
if (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)
cJSON_AddNumberToObject(j, "get_server_output", iperf_get_test_get_server_output(test));
if (test->udp_counters_64bit)
@@ -1414,6 +1416,8 @@ get_parameters(struct iperf_test *test)
test->title = strdup(j_p->valuestring);
if ((j_p = cJSON_GetObjectItem(j, "congestion")) != NULL)
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)
iperf_set_test_get_server_output(test, 1);
if ((j_p = cJSON_GetObjectItem(j, "udp_counters_64bit")) != NULL)
@@ -1455,6 +1459,9 @@ send_results(struct iperf_test *test)
else
sender_has_retransmits = test->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 (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_user;
cJSON *j_cpu_util_system;
+ cJSON *j_remote_congestion_used;
cJSON *j_sender_has_retransmits;
int result_has_retransmits;
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);
}
return r;
@@ -1833,6 +1847,8 @@ iperf_defaults(struct iperf_test *testp)
#endif /* HAVE_CPUSET_SETAFFINITY */
testp->title = NULL;
testp->congestion = NULL;
+ testp->congestion_used = NULL;
+ testp->remote_congestion_used = NULL;
testp->server_port = PORT;
testp->ctrl_sck = -1;
testp->prot_listener = -1;
@@ -1965,6 +1981,10 @@ iperf_free_test(struct iperf_test *test)
free(test->title);
if (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)
tmr_cancel(test->omit_timer);
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]));
+ 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 {
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]);
+ 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 */
diff --git a/src/iperf_client_api.c b/src/iperf_client_api.c
index f19f6f1..9df7ee8 100644
--- a/src/iperf_client_api.c
+++ b/src/iperf_client_api.c
@@ -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
* to receipt of any required approvals from the U.S. Dept. of
* Energy). All rights reserved.
@@ -43,6 +43,11 @@
#include "net.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
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)
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)
FD_SET(s, &test->write_set);
else
diff --git a/src/iperf_server_api.c b/src/iperf_server_api.c
index 65661d7..10adc07 100644
--- a/src/iperf_server_api.c
+++ b/src/iperf_server_api.c
@@ -62,6 +62,11 @@
#include "iperf_util.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
iperf_server_listen(struct iperf_test *test)
@@ -510,6 +515,33 @@ iperf_run_server(struct iperf_test *test)
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)) {
sp = iperf_new_stream(test, s);
if (!sp) {
diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c
index ac3b392..a2eb85b 100644
--- a/src/iperf_tcp.c
+++ b/src/iperf_tcp.c
@@ -235,16 +235,6 @@ iperf_tcp_listen(struct iperf_test *test)
}
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 socket pacing is available and not disabled, try it. */
if (! test->no_fq_socket_pacing) {
@@ -473,17 +463,6 @@ iperf_tcp_connect(struct iperf_test *test)
}
#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 socket pacing is available and not disabled, try it. */
if (! test->no_fq_socket_pacing) {