Skip to content

Commit

Permalink
Add SCTP information to --json output (#1731)
Browse files Browse the repository at this point in the history
* Add SCTP information to --json output

* Fix compile error when SCTP is not supported
  • Loading branch information
davidBar-On authored Aug 2, 2024
1 parent ac4205b commit 92c9155
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 6 deletions.
11 changes: 11 additions & 0 deletions src/iperf.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
typedef unsigned int uint
#endif // __vxworks or __VXWORKS__

struct iperf_sctp_info
{
long rtt;
long pmtu;
uint32_t wnd;
uint32_t cwnd;
};

struct iperf_interval_results
{
atomic_iperf_size_t bytes_transferred; /* bytes transferred in this interval */
Expand All @@ -107,6 +115,9 @@ struct iperf_interval_results
/* Just placeholders, never accessed. */
char *tcpInfo;
#endif
#if defined(HAVE_SCTP_H)
struct iperf_sctp_info sctp_info;
#endif /* HAVE_SCTP_H */
long interval_retrans;
long snd_cwnd;
long snd_wnd;
Expand Down
40 changes: 38 additions & 2 deletions src/iperf_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3362,8 +3362,14 @@ iperf_stats_callback(struct iperf_test *test)
struct iperf_interval_results *irp, temp;
struct iperf_time temp_time;
iperf_size_t total_interval_bytes_transferred = 0;
#if defined(HAVE_SCTP_H)
struct iperf_sctp_info sctp_info;
#endif /* HAVE_SCTP_H */

temp.omitted = test->omitting;
temp.rtt = 0;
temp.rttvar = 0;
temp.pmtu = 0;
SLIST_FOREACH(sp, &test->streams, streams) {
rp = sp->result;
temp.bytes_transferred = sp->sender ? rp->bytes_sent_this_interval : rp->bytes_received_this_interval;
Expand Down Expand Up @@ -3431,6 +3437,36 @@ iperf_stats_callback(struct iperf_test *test)
temp.outoforder_packets = sp->outoforder_packets;
temp.cnt_error = sp->cnt_error;
}

#if defined(HAVE_SCTP_H)
if (test->protocol->id == Psctp) {
if (iperf_sctp_get_info(sp, &sctp_info) >= 0) {;
temp.pmtu = sctp_info.pmtu;
temp.rtt = sctp_info.rtt;
temp.snd_cwnd = sctp_info.cwnd;
temp.snd_wnd = sctp_info.wnd;
if (temp.snd_cwnd > rp->stream_max_snd_cwnd) {
rp->stream_max_snd_cwnd = temp.snd_cwnd;
}
if (temp.snd_wnd > rp->stream_max_snd_wnd) {
rp->stream_max_snd_wnd = temp.snd_wnd;
}
if (temp.rtt >= 0) {
temp.rtt = sctp_info.rtt;
if (temp.rtt > rp->stream_max_rtt) {
rp->stream_max_rtt = temp.rtt;
}
if (rp->stream_min_rtt == 0 ||
temp.rtt < rp->stream_min_rtt) {
rp->stream_min_rtt = temp.rtt;
}
rp->stream_sum_rtt += temp.rtt;
rp->stream_count_rtt++;
}
}
}
#endif /* HAVE_SCTP_H */

add_to_interval_list(rp, &temp);
rp->bytes_sent_this_interval = rp->bytes_received_this_interval = 0;
}
Expand Down Expand Up @@ -3871,7 +3907,7 @@ iperf_print_results(struct iperf_test *test)
}
unit_snprintf(nbuf, UNIT_LEN, bandwidth, test->settings->unit_format);
if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits) {
if (test->sender_has_retransmits || test->protocol->id == Psctp) {
/* Sender summary, TCP and SCTP with retransmits. */
if (test->json_output)
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));
Expand Down Expand Up @@ -4322,7 +4358,7 @@ print_interval_results(struct iperf_test *test, struct iperf_stream *sp, cJSON *
et = iperf_time_in_secs(&temp_time);

if (test->protocol->id == Ptcp || test->protocol->id == Psctp) {
if (test->sender_has_retransmits == 1 && sp->sender) {
if ((test->sender_has_retransmits == 1 || test->protocol->id == Psctp) && sp->sender) {
/* Interval, TCP with retransmits. */
if (test->json_output)
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));
Expand Down
50 changes: 46 additions & 4 deletions src/iperf_sctp.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@
#include <sys/select.h>
#include <limits.h>

#ifdef HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif /* HAVE_NETINET_SCTP_H */

#include "iperf.h"
#include "iperf_api.h"
#include "iperf_sctp.h"
Expand Down Expand Up @@ -734,3 +730,49 @@ iperf_sctp_bindx(struct iperf_test *test, int s, int is_server)
return -1;
#endif /* HAVE_SCTP_H */
}


/* iperf_sctp_get_rtt
*
* Get SCTP stream RTT.
* Assuming that iperf3 supports only one-toone SCTP associassion, and not one-to-many associassion.
*
* Main resouses used are RFC-6458, man pages for SCTP,
* https://docs.oracle.com/cd/E19253-01/817-4415/sockets-199/index.html.
*
*/
int
iperf_sctp_get_info(struct iperf_stream *sp, struct iperf_sctp_info *sctp_info)
{
#if defined(HAVE_SCTP_H)
struct sctp_status status;
socklen_t len;
sctp_assoc_t assoc_id;
int rc = 0;

if (sp->test->protocol->id != Psctp) {
rc = -1;
} else {
#ifdef SCTP_FUTURE_ASSOC
assoc_id = SCTP_FUTURE_ASSOC;
#else
assoc_id = 0;
#endif
len = sizeof(status);
rc = sctp_opt_info(sp->socket, assoc_id, SCTP_STATUS, &status, &len);
if (rc < 0) {
if (sp->test->debug_level >= DEBUG_LEVEL_ERROR)
iperf_err(sp->test, "sctp_opt_info get SCTP_STATUS for socket %d failed with errno %d - %s", sp->socket, errno, strerror(errno));
} else {
sctp_info->wnd = status.sstat_rwnd;
sctp_info->rtt = status.sstat_primary.spinfo_srtt;
sctp_info->pmtu = status.sstat_primary.spinfo_mtu;
sctp_info->cwnd = status.sstat_primary.spinfo_cwnd;
}
}

return rc;
#else
return -1;
#endif /* HAVE_SCTP_H */
}
6 changes: 6 additions & 0 deletions src/iperf_sctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#ifndef IPERF_SCTP_H
#define IPERF_SCTP_H

#ifdef HAVE_NETINET_SCTP_H
#include <netinet/sctp.h>
#endif /* HAVE_NETINET_SCTP_H */

/**
* iperf_sctp_accept -- accepts a new SCTP connection
* on sctp_listener_socket for SCTP data and param/result
Expand Down Expand Up @@ -65,4 +69,6 @@ int iperf_sctp_init(struct iperf_test *test);

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

int iperf_sctp_get_info(struct iperf_stream *sp, struct iperf_sctp_info *sctp_info);

#endif

0 comments on commit 92c9155

Please sign in to comment.