Skip to content

Commit 92c9155

Browse files
authored
Add SCTP information to --json output (#1731)
* Add SCTP information to --json output * Fix compile error when SCTP is not supported
1 parent ac4205b commit 92c9155

File tree

4 files changed

+101
-6
lines changed

4 files changed

+101
-6
lines changed

src/iperf.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
8383
typedef unsigned int uint
8484
#endif // __vxworks or __VXWORKS__
8585

86+
struct iperf_sctp_info
87+
{
88+
long rtt;
89+
long pmtu;
90+
uint32_t wnd;
91+
uint32_t cwnd;
92+
};
93+
8694
struct iperf_interval_results
8795
{
8896
atomic_iperf_size_t bytes_transferred; /* bytes transferred in this interval */
@@ -107,6 +115,9 @@ struct iperf_interval_results
107115
/* Just placeholders, never accessed. */
108116
char *tcpInfo;
109117
#endif
118+
#if defined(HAVE_SCTP_H)
119+
struct iperf_sctp_info sctp_info;
120+
#endif /* HAVE_SCTP_H */
110121
long interval_retrans;
111122
long snd_cwnd;
112123
long snd_wnd;

src/iperf_api.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3362,8 +3362,14 @@ iperf_stats_callback(struct iperf_test *test)
33623362
struct iperf_interval_results *irp, temp;
33633363
struct iperf_time temp_time;
33643364
iperf_size_t total_interval_bytes_transferred = 0;
3365+
#if defined(HAVE_SCTP_H)
3366+
struct iperf_sctp_info sctp_info;
3367+
#endif /* HAVE_SCTP_H */
33653368

33663369
temp.omitted = test->omitting;
3370+
temp.rtt = 0;
3371+
temp.rttvar = 0;
3372+
temp.pmtu = 0;
33673373
SLIST_FOREACH(sp, &test->streams, streams) {
33683374
rp = sp->result;
33693375
temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
@@ -3431,6 +3437,36 @@ iperf_stats_callback(struct iperf_test *test)
34313437
temp.outoforder_packets = sp->outoforder_packets;
34323438
temp.cnt_error = sp->cnt_error;
34333439
}
3440+
3441+
#if defined(HAVE_SCTP_H)
3442+
if (test->protocol->id == Psctp) {
3443+
if (iperf_sctp_get_info(sp, &sctp_info) >= 0) {;
3444+
temp.pmtu = sctp_info.pmtu;
3445+
temp.rtt = sctp_info.rtt;
3446+
temp.snd_cwnd = sctp_info.cwnd;
3447+
temp.snd_wnd = sctp_info.wnd;
3448+
if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
3449+
rp->stream_max_snd_cwnd = temp.snd_cwnd;
3450+
}
3451+
if (temp.snd_wnd > rp->stream_max_snd_wnd) {
3452+
rp->stream_max_snd_wnd = temp.snd_wnd;
3453+
}
3454+
if (temp.rtt >= 0) {
3455+
temp.rtt = sctp_info.rtt;
3456+
if (temp.rtt > rp->stream_max_rtt) {
3457+
rp->stream_max_rtt = temp.rtt;
3458+
}
3459+
if (rp->stream_min_rtt == 0 ||
3460+
temp.rtt < rp->stream_min_rtt) {
3461+
rp->stream_min_rtt = temp.rtt;
3462+
}
3463+
rp->stream_sum_rtt += temp.rtt;
3464+
rp->stream_count_rtt++;
3465+
}
3466+
}
3467+
}
3468+
#endif /* HAVE_SCTP_H */
3469+
34343470
add_to_interval_list(rp, &temp);
34353471
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
34363472
}
@@ -3871,7 +3907,7 @@ iperf_print_results(struct iperf_test *test)
38713907
}
38723908
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
38733909
if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
3874-
if (test->sender_has_retransmits) {
3910+
if (test->sender_has_retransmits || test->protocol->id == Psctp) {
38753911
/* Sender summary, TCP and SCTP with retransmits. */
38763912
if (test->json_output)
38773913
cJSON_AddItemToObject(json_summary_stream, report_sender, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d max_snd_cwnd: %d max_snd_wnd: %d max_rtt: %d min_rtt: %d mean_rtt: %d sender: %b", (int64_t) sp->socket, (double) start_time, (double) sender_time, (double) sender_time, (int64_t) bytes_sent, bandwidth * 8, (int64_t) sp->result->stream_retrans, (int64_t) sp->result->stream_max_snd_cwnd, (int64_t) sp->result->stream_max_snd_wnd, (int64_t) sp->result->stream_max_rtt, (int64_t) sp->result->stream_min_rtt, (int64_t) ((sp->result->stream_count_rtt == 0) ? 0 : sp->result->stream_sum_rtt / sp->result->stream_count_rtt), stream_must_be_sender));
@@ -4322,7 +4358,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
43224358
et = iperf_time_in_secs(&temp_time);
43234359

43244360
if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
4325-
if (test->sender_has_retransmits == 1 && sp->sender) {
4361+
if ((test->sender_has_retransmits == 1 || test->protocol->id == Psctp) && sp->sender) {
43264362
/* Interval, TCP with retransmits. */
43274363
if (test->json_output)
43284364
cJSON_AddItemToArray(json_interval_streams, iperf_json_printf("socket: %d start: %f end: %f seconds: %f bytes: %d bits_per_second: %f retransmits: %d snd_cwnd: %d snd_wnd: %d rtt: %d rttvar: %d pmtu: %d omitted: %b sender: %b", (int64_t) sp->socket, (double) st, (double) et, (double) irp->interval_duration, (int64_t) irp->bytes_transferred, bandwidth * 8, (int64_t) irp->interval_retrans, (int64_t) irp->snd_cwnd, (int64_t) irp->snd_wnd, (int64_t) irp->rtt, (int64_t) irp->rttvar, (int64_t) irp->pmtu, irp->omitted, sp->sender));

src/iperf_sctp.c

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@
3939
#include <sys/select.h>
4040
#include <limits.h>
4141

42-
#ifdef HAVE_NETINET_SCTP_H
43-
#include <netinet/sctp.h>
44-
#endif /* HAVE_NETINET_SCTP_H */
45-
4642
#include "iperf.h"
4743
#include "iperf_api.h"
4844
#include "iperf_sctp.h"
@@ -734,3 +730,49 @@ iperf_sctp_bindx(struct iperf_test *test, int s, int is_server)
734730
return -1;
735731
#endif /* HAVE_SCTP_H */
736732
}
733+
734+
735+
/* iperf_sctp_get_rtt
736+
*
737+
* Get SCTP stream RTT.
738+
* Assuming that iperf3 supports only one-toone SCTP associassion, and not one-to-many associassion.
739+
*
740+
* Main resouses used are RFC-6458, man pages for SCTP,
741+
* https://docs.oracle.com/cd/E19253-01/817-4415/sockets-199/index.html.
742+
*
743+
*/
744+
int
745+
iperf_sctp_get_info(struct iperf_stream *sp, struct iperf_sctp_info *sctp_info)
746+
{
747+
#if defined(HAVE_SCTP_H)
748+
struct sctp_status status;
749+
socklen_t len;
750+
sctp_assoc_t assoc_id;
751+
int rc = 0;
752+
753+
if (sp->test->protocol->id != Psctp) {
754+
rc = -1;
755+
} else {
756+
#ifdef SCTP_FUTURE_ASSOC
757+
assoc_id = SCTP_FUTURE_ASSOC;
758+
#else
759+
assoc_id = 0;
760+
#endif
761+
len = sizeof(status);
762+
rc = sctp_opt_info(sp->socket, assoc_id, SCTP_STATUS, &status, &len);
763+
if (rc < 0) {
764+
if (sp->test->debug_level >= DEBUG_LEVEL_ERROR)
765+
iperf_err(sp->test, "sctp_opt_info get SCTP_STATUS for socket %d failed with errno %d - %s", sp->socket, errno, strerror(errno));
766+
} else {
767+
sctp_info->wnd = status.sstat_rwnd;
768+
sctp_info->rtt = status.sstat_primary.spinfo_srtt;
769+
sctp_info->pmtu = status.sstat_primary.spinfo_mtu;
770+
sctp_info->cwnd = status.sstat_primary.spinfo_cwnd;
771+
}
772+
}
773+
774+
return rc;
775+
#else
776+
return -1;
777+
#endif /* HAVE_SCTP_H */
778+
}

src/iperf_sctp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#ifndef IPERF_SCTP_H
2828
#define IPERF_SCTP_H
2929

30+
#ifdef HAVE_NETINET_SCTP_H
31+
#include <netinet/sctp.h>
32+
#endif /* HAVE_NETINET_SCTP_H */
33+
3034
/**
3135
* iperf_sctp_accept -- accepts a new SCTP connection
3236
* on sctp_listener_socket for SCTP data and param/result
@@ -65,4 +69,6 @@ int iperf_sctp_init(struct iperf_test *test);
6569

6670
int iperf_sctp_bindx(struct iperf_test *test, int s, int is_server);
6771

72+
int iperf_sctp_get_info(struct iperf_stream *sp, struct iperf_sctp_info *sctp_info);
73+
6874
#endif

0 commit comments

Comments
 (0)