diff --git a/folly/io/async/AsyncUDPSocket.cpp b/folly/io/async/AsyncUDPSocket.cpp index 5ed0204de84..614679068d2 100644 --- a/folly/io/async/AsyncUDPSocket.cpp +++ b/folly/io/async/AsyncUDPSocket.cpp @@ -132,6 +132,32 @@ void AsyncUDPSocket::bind(const folly::SocketAddress& address) { } } +void AsyncUDPSocket::dontFragment(bool df) { +#ifdef IP_MTU_DISCOVER + if (address().getFamily() == AF_INET) { + int v4 = df ? IP_PMTUDISC_DO : IP_PMTUDISC_WANT; + if (fsp::setsockopt(fd_, IPPROTO_IP, IP_MTU_DISCOVER, &v4, sizeof(v4))) { + throw AsyncSocketException( + AsyncSocketException::NOT_OPEN, + "Failed to set DF with IP_MTU_DISCOVER", + errno); + } + } +#endif +#ifdef IPV6_MTU_DISCOVER + if (address().getFamily() == AF_INET6) { + int v6 = df ? IPV6_PMTUDISC_DO : IPV6_PMTUDISC_WANT; + if (fsp::setsockopt( + fd_, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &v6, sizeof(v6))) { + throw AsyncSocketException( + AsyncSocketException::NOT_OPEN, + "Failed to set DF with IPV6_MTU_DISCOVER", + errno); + } + } +#endif +} + void AsyncUDPSocket::setFD(int fd, FDOwnership ownership) { CHECK_EQ(-1, fd_) << "Already bound to another FD"; diff --git a/folly/io/async/AsyncUDPSocket.h b/folly/io/async/AsyncUDPSocket.h index 0f390384f97..6e953efc9ea 100644 --- a/folly/io/async/AsyncUDPSocket.h +++ b/folly/io/async/AsyncUDPSocket.h @@ -162,6 +162,18 @@ class AsyncUDPSocket : public EventHandler { return eventBase_; } + /** + * Enable or disable fragmentation on the socket. + * + * On Linux, this sets IP(V6)_MTU_DISCOVER to IP(V6)_PMTUDISC_DO when enabled, + * and to IP(V6)_PMTUDISC_WANT when disabled. IP(V6)_PMTUDISC_WANT will use + * per-route setting to set DF bit. It may be more desirable to use + * IP(V6)_PMTUDISC_PROBE as opposed to IP(V6)_PMTUDISC_DO for apps that has + * its own PMTU Discovery mechanism. + * Note this doesn't work on Apple. + */ + virtual void dontFragment(bool df); + protected: virtual ssize_t sendmsg(int socket, const struct msghdr* message, int flags) { return ::sendmsg(socket, message, flags); diff --git a/folly/io/async/test/MockAsyncUDPSocket.h b/folly/io/async/test/MockAsyncUDPSocket.h index 847a0ca209f..c82a5620932 100644 --- a/folly/io/async/test/MockAsyncUDPSocket.h +++ b/folly/io/async/test/MockAsyncUDPSocket.h @@ -39,6 +39,7 @@ struct MockAsyncUDPSocket : public AsyncUDPSocket { MOCK_CONST_METHOD0(getFD, int()); MOCK_METHOD1(setReusePort, void(bool)); MOCK_METHOD1(setReuseAddr, void(bool)); + MOCK_METHOD1(dontFragment, void(bool)); }; }}