Skip to content

Commit

Permalink
Add an API to AsyncUDPSocket to set DF bit
Browse files Browse the repository at this point in the history
Summary: Some application requires IP not to fragment the the datagram. Add an API to AsyncUDPSocket to set such option.

Reviewed By: siyengar

Differential Revision: D5421406

fbshipit-source-id: 6cd3ab262f1420e22eb0948e0e2bfef77b7b6e92
  • Loading branch information
Yang Chi authored and facebook-github-bot committed Feb 28, 2018
1 parent 2b5eff8 commit 2806dda
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 0 deletions.
26 changes: 26 additions & 0 deletions folly/io/async/AsyncUDPSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down
12 changes: 12 additions & 0 deletions folly/io/async/AsyncUDPSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions folly/io/async/test/MockAsyncUDPSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -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));
};

}}

0 comments on commit 2806dda

Please sign in to comment.