From 3b60f09017c1733882e9245d13922310c0a83c9f Mon Sep 17 00:00:00 2001 From: "Bruce A. Mah" Date: Tue, 6 Jan 2015 10:22:00 -0800 Subject: [PATCH] Unbreak (partially) SCTP on Solaris. Solaris implements an (older?) version of the API for SCTP_MAXSEG, which takes an integer argument rather than a struct sctp_assoc_val. We need to test for that and handle it appropriately. There are some signs it doesn't even work correctly if we do this, so quietly ignore errors that happen if the OS complains it's unsupported. Also, Solaris doesn't support SCTP_DISABLE_FRAGMENTS even though it defines the preprocessor symbol for this. Rather than aborting when we try to unsuccessfully unset this option, just ignore the error. Lightly tested with SCTP over IPv6 on localhost. --- configure.ac | 2 ++ src/iperf_sctp.c | 40 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 6f1f110..31361b9 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ # Initialize the autoconf system for the specified tool, version and mailing list AC_INIT(iperf, 3-CURRENT, https://github.com/esnet/iperf, iperf, http://software.es.net/iperf/) +AC_LANG(C) # Specify where the auxiliary files created by configure should go. The config # directory is picked so that they don't clutter up more useful directories. @@ -88,6 +89,7 @@ AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([netinet/sctp.h], AC_DEFINE([HAVE_SCTP], [1], [Have SCTP support.]) AC_SEARCH_LIBS(sctp_bindx, [sctp]), + AC_CHECK_TYPES([struct sctp_assoc_value]) [], [#ifdef HAVE_SYS_SOCKET_H #include diff --git a/src/iperf_sctp.c b/src/iperf_sctp.c index 4ce21bf..89be76a 100644 --- a/src/iperf_sctp.c +++ b/src/iperf_sctp.c @@ -1,5 +1,5 @@ /* - * iperf, Copyright (c) 2014, The Regents of the University of + * iperf, Copyright (c) 2014, 2015, 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. @@ -280,8 +280,21 @@ iperf_sctp_connect(struct iperf_test *test) } if ((test->settings->mss >= 512 && test->settings->mss <= 131072)) { + + /* + * Some platforms use a struct sctp_assoc_value as the + * argument to SCTP_MAXSEG. Other (older API implementations) + * take an int. FreeBSD 10 and CentOS 6 support SCTP_MAXSEG, + * but OpenSolaris 11 doesn't. + */ +#ifdef HAVE_STRUCT_SCTP_ASSOC_VALUE struct sctp_assoc_value av; + /* + * Some platforms support SCTP_FUTURE_ASSOC, others need to + * (equivalently) do 0 here. FreeBSD 10 is an example of the + * former, CentOS 6 Linux is an example of the latter. + */ #ifdef SCTP_FUTURE_ASSOC av.assoc_id = SCTP_FUTURE_ASSOC; #else @@ -295,6 +308,21 @@ iperf_sctp_connect(struct iperf_test *test) i_errno = IESETMSS; return -1; } +#else + opt = test->settings->mss; + + /* + * Solaris might not support this option. If it doesn't work, + * ignore the error (at least for now). + */ + if (setsockopt(s, IPPROTO_SCTP, SCTP_MAXSEG, &opt, sizeof(opt)) < 0 && + errno != ENOPROTOOPT) { + close(s); + freeaddrinfo(server_res); + i_errno = IESETMSS; + return -1; + } +#endif HAVE_STRUCT_SCTP_ASSOC_VALUE } if (test->settings->num_ostreams > 0) { @@ -333,8 +361,16 @@ iperf_sctp_connect(struct iperf_test *test) return -1; } + /* + * We want to allow fragmentation. But there's at least one + * implementation (Solaris) that doesn't support this option, + * even though it defines SCTP_DISABLE_FRAGMENTS. So we have to + * try setting the option and ignore the error, if it doesn't + * work. + */ opt = 0; - if(setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &opt, sizeof(opt)) < 0) { + if (setsockopt(s, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, &opt, sizeof(opt)) < 0 && + errno != ENOPROTOOPT) { close(s); freeaddrinfo(server_res); i_errno = IESETSCTPDISABLEFRAG;