Commit 1902d0ff authored by Dan Melnic's avatar Dan Melnic Committed by Facebook GitHub Bot

Add support for UDP RX timestamps

Summary: Add support for UDP RX timestamps

Reviewed By: mjoras

Differential Revision: D24146914

fbshipit-source-id: 381839fc5402f13e428364c47c5752473acda6af
parent 343a70ae
...@@ -737,8 +737,21 @@ void AsyncUDPSocket::handleRead() noexcept { ...@@ -737,8 +737,21 @@ void AsyncUDPSocket::handleRead() noexcept {
ReadCallback::OnDataAvailableParams params; ReadCallback::OnDataAvailableParams params;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE #ifdef FOLLY_HAVE_MSG_ERRQUEUE
if (gro_.has_value() && (gro_.value() > 0)) { bool use_gro = gro_.has_value() && (gro_.value() > 0);
char control[CMSG_SPACE(sizeof(uint16_t))] = {}; bool use_ts = ts_.has_value() && (ts_.value() > 0);
if (use_gro || use_ts) {
char control
[CMSG_SPACE(sizeof(uint16_t)) +
CMSG_SPACE(sizeof(ReadCallback::OnDataAvailableParams::Timestamp))];
::memset(
control,
0,
(use_gro ? CMSG_SPACE(sizeof(uint16_t)) : 0) +
(use_ts ? CMSG_SPACE(sizeof(
ReadCallback::OnDataAvailableParams::Timestamp))
: 0));
struct msghdr msg = {}; struct msghdr msg = {};
struct iovec iov = {}; struct iovec iov = {};
struct cmsghdr* cmsg; struct cmsghdr* cmsg;
...@@ -762,10 +775,23 @@ void AsyncUDPSocket::handleRead() noexcept { ...@@ -762,10 +775,23 @@ void AsyncUDPSocket::handleRead() noexcept {
addrLen = msg.msg_namelen; addrLen = msg.msg_namelen;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
cmsg = CMSG_NXTHDR(&msg, cmsg)) { cmsg = CMSG_NXTHDR(&msg, cmsg)) {
if (cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) { if (cmsg->cmsg_level == SOL_UDP) {
grosizeptr = (uint16_t*)CMSG_DATA(cmsg); if (cmsg->cmsg_type == UDP_GRO) {
params.gro_ = *grosizeptr; grosizeptr = (uint16_t*)CMSG_DATA(cmsg);
break; params.gro_ = *grosizeptr;
}
} else {
if (cmsg->cmsg_level == SOL_SOCKET) {
if (cmsg->cmsg_type == SO_TIMESTAMPING ||
cmsg->cmsg_type == SO_TIMESTAMPNS) {
ReadCallback::OnDataAvailableParams::Timestamp ts;
memcpy(
&ts,
reinterpret_cast<struct timespec*>(CMSG_DATA(cmsg)),
sizeof(ts));
params.ts_ = ts;
}
}
} }
} }
} }
...@@ -867,6 +893,40 @@ bool AsyncUDPSocket::setGRO(bool bVal) { ...@@ -867,6 +893,40 @@ bool AsyncUDPSocket::setGRO(bool bVal) {
#endif #endif
} }
// packet timestamping
int AsyncUDPSocket::getTimestamping() {
// check if we can return the cached value
if (FOLLY_UNLIKELY(!ts_.has_value())) {
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
int ts = -1;
socklen_t optlen = sizeof(ts);
if (!netops::getsockopt(fd_, SOL_SOCKET, SO_TIMESTAMPING, &ts, &optlen)) {
ts_ = ts;
} else {
ts_ = -1;
}
#else
ts_ = -1;
#endif
}
return ts_.value();
}
bool AsyncUDPSocket::setTimestamping(int val) {
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
int ret =
netops::setsockopt(fd_, SOL_SOCKET, SO_TIMESTAMPING, &val, sizeof(val));
ts_ = ret ? -1 : val;
return !ret;
#else
(void)val;
return false;
#endif
}
int AsyncUDPSocket::getGRO() { int AsyncUDPSocket::getGRO() {
// check if we can return the cached value // check if we can return the cached value
if (FOLLY_UNLIKELY(!gro_.has_value())) { if (FOLLY_UNLIKELY(!gro_.has_value())) {
......
...@@ -42,6 +42,18 @@ class AsyncUDPSocket : public EventHandler { ...@@ -42,6 +42,18 @@ class AsyncUDPSocket : public EventHandler {
public: public:
struct OnDataAvailableParams { struct OnDataAvailableParams {
int gro_ = -1; int gro_ = -1;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
// RX timestamp if available
using Timestamp = std::array<struct timespec, 3>;
folly::Optional<Timestamp> ts_;
static std::chrono::nanoseconds to(const struct timespec& ts) {
auto duration = std::chrono::seconds(ts.tv_sec) +
std::chrono::nanoseconds(ts.tv_nsec);
return std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
}
#endif
}; };
/** /**
* Invoked when the socket becomes readable and we want buffer * Invoked when the socket becomes readable and we want buffer
...@@ -383,6 +395,10 @@ class AsyncUDPSocket : public EventHandler { ...@@ -383,6 +395,10 @@ class AsyncUDPSocket : public EventHandler {
bool setGRO(bool bVal); bool setGRO(bool bVal);
// packet timestamping
int getTimestamping();
bool setTimestamping(int val);
// disable/enable RX zero checksum check for UDP over IPv6 // disable/enable RX zero checksum check for UDP over IPv6
bool setRxZeroChksum6(bool bVal); bool setRxZeroChksum6(bool bVal);
...@@ -482,6 +498,9 @@ class AsyncUDPSocket : public EventHandler { ...@@ -482,6 +498,9 @@ class AsyncUDPSocket : public EventHandler {
// See https://lwn.net/Articles/770978/ for more details // See https://lwn.net/Articles/770978/ for more details
folly::Optional<int> gro_; folly::Optional<int> gro_;
// packet timestamping
folly::Optional<int> ts_;
ErrMessageCallback* errMessageCallback_{nullptr}; ErrMessageCallback* errMessageCallback_{nullptr};
}; };
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment