Skip to content

Commit

Permalink
Enable reading ECN on mvfst client on windows using recvmmsg wrapper …
Browse files Browse the repository at this point in the history
…path

Summary:
Previously, none of the read paths supported by QuicClienTransport had support for reaching the ToS field on Windows.

This change adds support for reading ToS fields in the `shouldUseWrapperRecvmmsgForBatchRecv` read path on Windows.

This facilitates running and testing ECN/L4S in a Windows-only environment.

Reviewed By: kvtsoy, sharmafb

Differential Revision: D66045131

fbshipit-source-id: 440cf99b5b97d852286630668abac906ea696950
  • Loading branch information
jbeshay authored and facebook-github-bot committed Nov 21, 2024
1 parent f72ceb8 commit 4569046
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 5 deletions.
32 changes: 31 additions & 1 deletion quic/common/udpsocket/QuicAsyncUDPSocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@

namespace quic {

#if _WIN32
// Folly netops exposes Windows control messages using the same struct field
// names used by Linux. This defines macros to use these field names on Windows.

#define FOLLY_CMSG_FIRSTHDR(msg) \
(((msg)->msg_controllen >= sizeof(WSACMSGHDR)) \
? (LPWSACMSGHDR)(msg)->msg_control \
: (LPWSACMSGHDR)NULL)

#define FOLLY_CMSG_NXTHDR(msg, cmsg) \
(((cmsg) == NULL) \
? FOLLY_CMSG_FIRSTHDR(msg) \
: ((((PUCHAR)(cmsg) + WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len) + \
sizeof(WSACMSGHDR)) > \
(PUCHAR)((msg)->msg_control) + (msg)->msg_controllen) \
? (LPWSACMSGHDR)NULL \
: (LPWSACMSGHDR)((PUCHAR)(cmsg) + \
WSA_CMSGHDR_ALIGN((cmsg)->cmsg_len))))
#endif

template <typename T, typename>
T* QuicAsyncUDPSocket::getTypedSocket() const {
auto sock = dynamic_cast<T*>(this);
Expand All @@ -25,7 +45,17 @@ T* QuicAsyncUDPSocket::getTypedSocket() const {
void QuicAsyncUDPSocket::fromMsg(
[[maybe_unused]] ReadCallback::OnDataAvailableParams& params,
[[maybe_unused]] struct msghdr& msg) {
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
#ifdef _WIN32
PCMSGHDR cmsg = FOLLY_CMSG_FIRSTHDR(&msg);
while (cmsg != NULL) {
if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TOS) ||
(cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_TCLASS)) {
params.tos = *(PINT)WSA_CMSG_DATA(cmsg);
break;
}
cmsg = FOLLY_CMSG_NXTHDR(&msg, cmsg);
}
#elif defined(FOLLY_HAVE_MSG_ERRQUEUE)
struct cmsghdr* cmsg;
uint16_t* grosizeptr;
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
Expand Down
6 changes: 5 additions & 1 deletion quic/common/udpsocket/QuicAsyncUDPSocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ class QuicAsyncUDPSocket {
using Timestamp = std::array<struct timespec, 3>;
std::optional<Timestamp> ts;
uint8_t tos = 0;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
#ifdef _WIN32
// Make control message space for ToS
static constexpr size_t kCmsgSpace = CMSG_SPACE(sizeof(INT));
#elif defined(FOLLY_HAVE_MSG_ERRQUEUE)
// Make control message space for GRO, timestamp, and ToS
static constexpr size_t kCmsgSpace = CMSG_SPACE(sizeof(uint16_t)) +
CMSG_SPACE(sizeof(Timestamp)) + CMSG_SPACE(sizeof(uint8_t));
#endif
Expand Down
6 changes: 3 additions & 3 deletions quic/common/udpsocket/QuicAsyncUDPSocketImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ QuicAsyncUDPSocket::RecvResult QuicAsyncUDPSocketImpl::recvmmsgNetworkData(
recvmmsgStorage_.resize(numPackets);
auto& msgs = recvmmsgStorage_.msgs;
int flags = 0;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
#if defined(FOLLY_HAVE_MSG_ERRQUEUE) || defined(_WIN32)
bool useGRO = getGRO() > 0;
bool checkCmsgs = useGRO || getTimestamping() > 0 || getRecvTos();
std::vector<std::array<
Expand Down Expand Up @@ -59,7 +59,7 @@ QuicAsyncUDPSocket::RecvResult QuicAsyncUDPSocketImpl::recvmmsgNetworkData(
rawAddr->sa_family = address().getFamily();
msg->msg_name = rawAddr;
msg->msg_namelen = kAddrLen;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
#if defined(FOLLY_HAVE_MSG_ERRQUEUE) || defined(_WIN32)
if (checkCmsgs) {
::memset(controlVec[i].data(), 0, controlVec[i].size());
msg->msg_control = controlVec[i].data();
Expand Down Expand Up @@ -95,7 +95,7 @@ QuicAsyncUDPSocket::RecvResult QuicAsyncUDPSocketImpl::recvmmsgNetworkData(
continue;
}
QuicAsyncUDPSocket::ReadCallback::OnDataAvailableParams params;
#ifdef FOLLY_HAVE_MSG_ERRQUEUE
#if defined(FOLLY_HAVE_MSG_ERRQUEUE) || defined(_WIN32)
if (checkCmsgs) {
QuicAsyncUDPSocket::fromMsg(params, msg.msg_hdr);

Expand Down

0 comments on commit 4569046

Please sign in to comment.