Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/iperf_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ typedef atomic_uint_fast64_t atomic_iperf_size_t;
#define DEFAULT_UDP_BLKSIZE 1460 /* default is dynamically set, else this */
#define DEFAULT_TCP_BLKSIZE (128 * 1024) /* default read/write block size */
#define DEFAULT_SCTP_BLKSIZE (64 * 1024)
#define DEFAULT_SCTP_SOCKBUF (512 * 1024) /* Linux SCTP has no rcvbuf auto-tune */
#define DEFAULT_PACING_TIMER 1000
#define DEFAULT_NO_MSG_RCVD_TIMEOUT 120000
#define MIN_NO_MSG_RCVD_TIMEOUT 100
Expand Down
34 changes: 34 additions & 0 deletions src/iperf_sctp.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ iperf_sctp_accept(struct iperf_test * test)
return -1;
}

{
/*
* Apply SO_RCVBUF/SO_SNDBUF on the accepted association. The
* listener-side setting does not reliably open the per-association
* receive window on Linux SCTP (see iperf_sctp_listen()), so repeat
* here. Honour --window if the user supplied it, otherwise apply
* DEFAULT_SCTP_SOCKBUF. Best-effort; failures are silently ignored
* to match the iperf_sctp_listen() / iperf_sctp_connect() default
* branches.
*/
int opt = test->settings->socket_bufsize;
if (opt == 0)
opt = DEFAULT_SCTP_SOCKBUF;
(void) setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
(void) setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
}

if (Nread(s, cookie, COOKIE_SIZE, Psctp) < 0) {
i_errno = IERECVCOOKIE;
close(s);
Expand Down Expand Up @@ -206,6 +223,18 @@ iperf_sctp_listen(struct iperf_test *test)
i_errno = IESETBUF;
return -1;
}
} else {
/*
* Linux SCTP does not auto-tune SO_RCVBUF/SO_SNDBUF the way TCP does
* (no equivalent of tcp_moderate_rcvbuf), so without an explicit
* setting the per-association rwnd collapses to a few tens of KB and
* gates single-stream throughput. Apply a sensible default; the
* kernel will silently cap at net.core.{r,w}mem_max where smaller.
* Failures are non-fatal -- this is best-effort, not user-requested.
*/
opt = DEFAULT_SCTP_SOCKBUF;
(void) setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
(void) setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
}

if (test->bind_dev) {
Expand Down Expand Up @@ -341,6 +370,11 @@ iperf_sctp_connect(struct iperf_test *test)
i_errno = IESETBUF;
return -1;
}
} else {
/* see iperf_sctp_listen() for rationale; best-effort, non-fatal. */
opt = DEFAULT_SCTP_SOCKBUF;
(void) setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
(void) setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
}

if (test->bind_dev) {
Expand Down