aboutsummaryrefslogtreecommitdiff
path: root/src/iperf_api.c
diff options
context:
space:
mode:
authorBruce A. Mah <bmah@es.net>2014-02-14 11:52:16 -0800
committerBruce A. Mah <bmah@es.net>2014-02-14 11:52:16 -0800
commit60bd98a538808e58eb18c259ebe3678bb19c3a2a (patch)
treecd2f32103a65e93e72b1f7c4a49512e605a39e32 /src/iperf_api.c
parentd076653bd4a92a1587c8214a6e0603e25eda2307 (diff)
downloadiperf3-60bd98a538808e58eb18c259ebe3678bb19c3a2a.tar.gz
Add SCTP support with the --sctp flag (Linux and FreeBSD only).
Note this option only has a long option flag; we're running out of letters for short options. Based heavily on a patch submitted in Issue 131 (SCTP support for iperf); I added support for FreeBSD and did some other packaging and documentation improvements. We probably shouldn't tie SCTP support to looking specifically for Linux or FreeBSD; we probably leave support enabled all the time if possible, possibly with some configure-time checks.
Diffstat (limited to 'src/iperf_api.c')
-rw-r--r--src/iperf_api.c91
1 files changed, 74 insertions, 17 deletions
diff --git a/src/iperf_api.c b/src/iperf_api.c
index f8822cd..593f019 100644
--- a/src/iperf_api.c
+++ b/src/iperf_api.c
@@ -45,6 +45,7 @@
#include "iperf_api.h"
#include "iperf_udp.h"
#include "iperf_tcp.h"
+#include "iperf_sctp.h"
#include "timer.h"
#include "cjson.h"
@@ -545,6 +546,9 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
#if defined(linux) && defined(TCP_CONGESTION)
{"linux-congestion", required_argument, NULL, 'C'},
#endif
+#if defined(linux) || defined(__FreeBSD__)
+ {"sctp", no_argument, NULL, OPT_SCTP},
+#endif
{"pidfile", required_argument, NULL, 'I'},
{"debug", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
@@ -609,6 +613,16 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
set_protocol(test, Pudp);
client_flag = 1;
break;
+ case OPT_SCTP:
+#if defined(linux) || defined(__FreeBSD__)
+ set_protocol(test, Psctp);
+ client_flag = 1;
+#else /* linux */
+ i_errno = IEUNIMP;
+ return -1;
+#endif /* linux */
+ break;
+
case 'b':
slash = strchr(optarg, '/');
if (slash) {
@@ -1082,6 +1096,8 @@ send_parameters(struct iperf_test *test)
cJSON_AddTrueToObject(j, "tcp");
else if (test->protocol->id == Pudp)
cJSON_AddTrueToObject(j, "udp");
+ else if (test->protocol->id == Psctp)
+ cJSON_AddTrueToObject(j, "sctp");
cJSON_AddIntToObject(j, "omit", test->omit);
if (test->server_affinity != -1)
cJSON_AddIntToObject(j, "server_affinity", test->server_affinity);
@@ -1141,6 +1157,8 @@ get_parameters(struct iperf_test *test)
set_protocol(test, Ptcp);
if ((j_p = cJSON_GetObjectItem(j, "udp")) != NULL)
set_protocol(test, Pudp);
+ if ((j_p = cJSON_GetObjectItem(j, "sctp")) != NULL)
+ set_protocol(test, Psctp);
if ((j_p = cJSON_GetObjectItem(j, "omit")) != NULL)
test->omit = j_p->valueint;
if ((j_p = cJSON_GetObjectItem(j, "server_affinity")) != NULL)
@@ -1471,10 +1489,32 @@ iperf_new_test()
}
/**************************************************************************/
+
+struct protocol *
+protocol_new(void)
+{
+ struct protocol *proto;
+
+ proto = malloc(sizeof(struct protocol));
+ if(!proto) {
+ return NULL;
+ }
+ memset(proto, 0, sizeof(struct protocol));
+
+ return proto;
+}
+
+void
+protocol_free(struct protocol *proto)
+{
+ free(proto);
+}
+
+/**************************************************************************/
int
iperf_defaults(struct iperf_test *testp)
{
- struct protocol *tcp, *udp;
+ struct protocol *tcp, *udp, *sctp;
testp->omit = OMIT;
testp->duration = DURATION;
@@ -1514,16 +1554,9 @@ iperf_defaults(struct iperf_test *testp)
SLIST_INIT(&testp->streams);
SLIST_INIT(&testp->protocols);
- tcp = (struct protocol *) malloc(sizeof(struct protocol));
+ tcp = protocol_new();
if (!tcp)
return -1;
- memset(tcp, 0, sizeof(struct protocol));
- udp = (struct protocol *) malloc(sizeof(struct protocol));
- if (!udp) {
- free(tcp);
- return -1;
- }
- memset(udp, 0, sizeof(struct protocol));
tcp->id = Ptcp;
tcp->name = "TCP";
@@ -1535,6 +1568,12 @@ iperf_defaults(struct iperf_test *testp)
tcp->init = NULL;
SLIST_INSERT_HEAD(&testp->protocols, tcp, protocols);
+ udp = protocol_new();
+ if (!udp) {
+ protocol_free(tcp);
+ return -1;
+ }
+
udp->id = Pudp;
udp->name = "UDP";
udp->accept = iperf_udp_accept;
@@ -1547,6 +1586,24 @@ iperf_defaults(struct iperf_test *testp)
set_protocol(testp, Ptcp);
+ sctp = protocol_new();
+ if (!sctp) {
+ protocol_free(tcp);
+ protocol_free(udp);
+ return -1;
+ }
+
+ sctp->id = Psctp;
+ sctp->name = "SCTP";
+ sctp->accept = iperf_sctp_accept;
+ sctp->listen = iperf_sctp_listen;
+ sctp->connect = iperf_sctp_connect;
+ sctp->send = iperf_sctp_send;
+ sctp->recv = iperf_sctp_recv;
+ sctp->init = iperf_sctp_init;
+
+ SLIST_INSERT_AFTER(udp, sctp, protocols);
+
testp->on_new_stream = iperf_on_new_stream;
testp->on_test_start = iperf_on_test_start;
testp->on_connect = iperf_on_connect;
@@ -1844,7 +1901,7 @@ iperf_print_intermediate(struct iperf_test *test)
start_time = timeval_diff(&sp->result->start_time,&irp->interval_start_time);
end_time = timeval_diff(&sp->result->start_time,&irp->interval_end_time);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender && test->sender_has_retransmits) {
/* Interval sum, TCP with retransmits. */
if (test->json_output)
@@ -1906,7 +1963,7 @@ iperf_print_results(struct iperf_test *test)
iprintf(test, "%s", report_bw_separator);
if (test->verbose)
iprintf(test, "%s", report_summary);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits)
iprintf(test, "%s", report_bw_retrans_header);
else
@@ -1931,7 +1988,7 @@ iperf_print_results(struct iperf_test *test)
total_sent += bytes_sent;
total_received += bytes_received;
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits) {
total_retransmits += sp->result->stream_retrans;
}
@@ -1944,7 +2001,7 @@ iperf_print_results(struct iperf_test *test)
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_sent, 'A');
bandwidth = (double) bytes_sent / (double) end_time;
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits) {
/* Summary, TCP with retransmits. */
if (test->json_output)
@@ -1986,7 +2043,7 @@ iperf_print_results(struct iperf_test *test)
unit_snprintf(ubuf, UNIT_LEN, (double) bytes_received, 'A');
bandwidth = (double) bytes_received / (double) end_time;
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->json_output)
cJSON_AddItemToObject(json_summary_stream, "receiver", iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f", (int64_t) sp->socket, (double) start_time, (double) end_time, (double) end_time, (int64_t) bytes_received, bandwidth * 8));
else
@@ -1998,7 +2055,7 @@ iperf_print_results(struct iperf_test *test)
unit_snprintf(ubuf, UNIT_LEN, (double) total_sent, 'A');
bandwidth = (double) total_sent / (double) end_time;
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits) {
/* Summary sum, TCP with retransmits. */
if (test->json_output)
@@ -2084,7 +2141,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
** else nothing.
*/
if (timeval_equals(&sp->result->start_time, &irp->interval_start_time)) {
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender && test->sender_has_retransmits)
iprintf(test, "%s", report_bw_retrans_cwnd_header);
else
@@ -2107,7 +2164,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
st = timeval_diff(&sp->result->start_time, &irp->interval_start_time);
et = timeval_diff(&sp->result->start_time, &irp->interval_end_time);
- if (test->protocol->id == Ptcp) {
+ if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender && test->sender_has_retransmits) {
/* Interval, TCP with retransmits. */
if (test->json_output)