diff --git a/src/iperf_api.h b/src/iperf_api.h index e032877..66617df 100755 --- a/src/iperf_api.h +++ b/src/iperf_api.h @@ -334,6 +334,7 @@ enum { IESETSCTPNSTREAM= 138, // Unable to set SCTP number of streams (check perror) IESETSCTPBINDX= 139, // Unable to process sctp_bindx() parameters IESETPACING= 140, // Unable to set socket pacing rate + IESETBUF2= 141, // Socket buffer size incorrect (written value != read value) /* Stream errors */ IECREATESTREAM = 200, // Unable to create a new stream (check herror/perror) IEINITSTREAM = 201, // Unable to initialize stream (check herror/perror) diff --git a/src/iperf_error.c b/src/iperf_error.c index a64c212..1cfceeb 100644 --- a/src/iperf_error.c +++ b/src/iperf_error.c @@ -359,6 +359,10 @@ iperf_strerror(int i_errno) snprintf(errstr, len, "unable to set socket pacing"); perr = 1; break; + case IESETBUF2: + snprintf(errstr, len, "socket buffer size not set correctly"); + break; + } if (herr || perr) diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c index a2eb85b..b7ec0ff 100644 --- a/src/iperf_tcp.c +++ b/src/iperf_tcp.c @@ -317,6 +317,7 @@ iperf_tcp_connect(struct iperf_test *test) struct addrinfo hints, *local_res, *server_res; char portstr[6]; int s, opt; + socklen_t optlen; int saved_errno; if (test->bind_address) { @@ -406,18 +407,43 @@ iperf_tcp_connect(struct iperf_test *test) return -1; } } + + /* Read back and verify the sender socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, &optlen) < 0) { + saved_errno = errno; + close(s); + freeaddrinfo(server_res); + errno = saved_errno; + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } if (test->debug) { - socklen_t optlen = sizeof(opt); - if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, &optlen) < 0) { - saved_errno = errno; - close(s); - freeaddrinfo(server_res); - errno = saved_errno; - i_errno = IESETBUF; - return -1; - } printf("SO_SNDBUF is %u\n", opt); } + + /* Read back and verify the receiver socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, &optlen) < 0) { + saved_errno = errno; + close(s); + freeaddrinfo(server_res); + errno = saved_errno; + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } + if (test->debug) { + printf("SO_RCVBUF is %u\n", opt); + } + #if defined(HAVE_FLOWLABEL) if (test->settings->flowlabel) { if (server_res->ai_addr->sa_family != AF_INET6) { diff --git a/src/iperf_udp.c b/src/iperf_udp.c index fd426e1..ae4796a 100644 --- a/src/iperf_udp.c +++ b/src/iperf_udp.c @@ -233,6 +233,8 @@ iperf_udp_accept(struct iperf_test *test) * receiving so that we can cover both normal and --reverse operation. */ int opt; + socklen_t optlen; + if ((opt = test->settings->socket_bufsize)) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) { i_errno = IESETBUF; @@ -244,6 +246,34 @@ iperf_udp_accept(struct iperf_test *test) } } + /* Read back and verify the sender socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, &optlen) < 0) { + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } + if (test->debug) { + printf("SO_SNDBUF is %u\n", opt); + } + + /* Read back and verify the receiver socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, &optlen) < 0) { + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } + if (test->debug) { + printf("SO_RCVBUF is %u\n", opt); + } + #if defined(HAVE_SO_MAX_PACING_RATE) /* If socket pacing is available and not disabled, try it. */ if (! test->no_fq_socket_pacing) { @@ -332,6 +362,8 @@ iperf_udp_connect(struct iperf_test *test) * receiving so that we can cover both normal and --reverse operation. */ int opt; + socklen_t optlen; + if ((opt = test->settings->socket_bufsize)) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) { i_errno = IESETBUF; @@ -342,6 +374,33 @@ iperf_udp_connect(struct iperf_test *test) return -1; } } + /* Read back and verify the sender socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, &optlen) < 0) { + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } + if (test->debug) { + printf("SO_SNDBUF is %u\n", opt); + } + + /* Read back and verify the receiver socket buffer size */ + optlen = sizeof(opt); + if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, &optlen) < 0) { + i_errno = IESETBUF; + return -1; + } + if (test->settings->socket_bufsize && test->settings->socket_bufsize != opt) { + i_errno = IESETBUF2; + return -1; + } + if (test->debug) { + printf("SO_RCVBUF is %u\n", opt); + } #if defined(HAVE_SO_MAX_PACING_RATE) /* If socket pacing is available and not disabled, try it. */