From: JINMEI Tatuya Date: Fri, 16 Dec 2011 22:11:59 +0000 (+0000) Subject: [1452] use a larger number of send attempts for pushTooFast. Linux doubles the X-Git-Tag: perftcpdns_before_epoll~5^2~6^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8fda3f02eafeb955b965d9cc04f5a703dbab5f02;p=thirdparty%2Fkea.git [1452] use a larger number of send attempts for pushTooFast. Linux doubles the SO_SNDBUF value so 3 didn't work. also make sure bufsize is adjusted only when the default size is too small. --- diff --git a/src/lib/util/io/socketsession.cc b/src/lib/util/io/socketsession.cc index 32e63d0950..758a6e7d62 100644 --- a/src/lib/util/io/socketsession.cc +++ b/src/lib/util/io/socketsession.cc @@ -144,10 +144,18 @@ SocketSessionForwarder::connectToReceiver() { "Failed to make UNIX domain socket non blocking: " << strerror(errno)); } - if (setsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE, - sizeof(SOCKSESSION_BUFSIZE)) == -1) { - close(); - isc_throw(SocketSessionError, "Failed to set send buffer size"); + // Ensure the socket send buffer is large enough. If we can't get the + // current size, simply set the sufficient size. + int sndbuf_size; + socklen_t sndbuf_size_len = sizeof(sndbuf_size); + if (getsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &sndbuf_size, + &sndbuf_size_len) == -1 || + sndbuf_size < SOCKSESSION_BUFSIZE) { + if (setsockopt(impl_->fd_, SOL_SOCKET, SO_SNDBUF, &SOCKSESSION_BUFSIZE, + sizeof(SOCKSESSION_BUFSIZE)) == -1) { + close(); + isc_throw(SocketSessionError, "Failed to set send buffer size"); + } } if (connect(impl_->fd_, convertSockAddr(&impl_->sock_un_), impl_->sock_un_len_) == -1) { diff --git a/src/lib/util/tests/socketsession_unittest.cc b/src/lib/util/tests/socketsession_unittest.cc index 83cf493435..8f0cf40e1c 100644 --- a/src/lib/util/tests/socketsession_unittest.cc +++ b/src/lib/util/tests/socketsession_unittest.cc @@ -662,15 +662,22 @@ TEST_F(ForwardTest, badPush) { SocketSessionError); } -// A subroutine for pushTooFast. Due to the fixed configuration of the -// send buffer size, we shouldn't be able to forward 3 full-size DNS messages -// without receiving them. Exactly how many we can forward depends on the -// internal system implementation, so we'll at least confirm we can't do for 3. +// A subroutine for pushTooFast, continuously pushing socket sessions +// with full-size DNS messages (65535 bytes) without receiving them. +// the push attempts will eventually fill the socket send buffer and trigger +// an exception. Unfortunately exactly how many we can forward depends on +// the internal system implementation; it should be close to 3, because +// in our current implementation it sets the send buffer to a size that +// is sufficiently large to hold 2 sessions (but not much larger than that), +// but (for example) Linux internally doubles the specified upper limit. +// Experimentally we know 10 is enough to produce a reliable result, but +// if it turns out to be not the case, we should do it a bit harder, e.g., +// by probing the actual buffer size by getsockopt(SO_SNDBUF). void multiPush(SocketSessionForwarder& forwarder, const struct sockaddr& sa, const void* data, size_t data_len) { - for (int i = 0; i < 3; ++i) { + for (int i = 0; i < 10; ++i) { forwarder.push(1, AF_INET, SOCK_DGRAM, IPPROTO_UDP, sa, sa, data, data_len); }