Skip to content

Commit

Permalink
quic: enable UDP GRO
Browse files Browse the repository at this point in the history
Closes #14012
  • Loading branch information
tatsuhiro-t authored and bagder committed Jun 26, 2024
1 parent 411af83 commit a571afc
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 11 deletions.
13 changes: 13 additions & 0 deletions lib/cf-socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
#elif defined(HAVE_NETINET_TCP_H)
#include <netinet/tcp.h>
#endif
#ifdef HAVE_NETINET_UDP_H
#include <netinet/udp.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
Expand Down Expand Up @@ -1852,6 +1855,9 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
{
struct cf_socket_ctx *ctx = cf->ctx;
int rc;
int one = 1;

(void)one;

/* QUIC needs a connected socket, nonblocking */
DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD);
Expand Down Expand Up @@ -1892,6 +1898,13 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
}
#endif
}

#if defined(UDP_GRO) && (defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)) && \
((defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_QUICHE))
(void)setsockopt(ctx->sock, IPPROTO_UDP, UDP_GRO, &one,
(socklen_t)sizeof(one));
#endif

return CURLE_OK;
}

Expand Down
100 changes: 89 additions & 11 deletions lib/vquic/vquic.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@

#include "curl_setup.h"

#ifdef HAVE_NETINET_UDP_H
#include <netinet/udp.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
Expand Down Expand Up @@ -329,6 +332,36 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
return vquic_flush(cf, data, qctx);
}

#if defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)
static size_t msghdr_get_udp_gro(struct msghdr *msg)
{
uint16_t gso_size = 0;
#ifdef UDP_GRO
struct cmsghdr *cmsg;

/* Workaround musl CMSG_NXTHDR issue */
#ifndef __GLIBC__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsign-compare"
#pragma clang diagnostic ignored "-Wcast-align"
#endif
for(cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
#ifndef __GLIBC__
#pragma clang diagnostic pop
#endif
if(cmsg->cmsg_level == SOL_UDP && cmsg->cmsg_type == UDP_GRO) {
memcpy(&gso_size, CMSG_DATA(cmsg), sizeof(gso_size));

break;
}
}
#endif
(void)msg;

return gso_size;
}
#endif

#ifdef HAVE_SENDMMSG
static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
struct Curl_easy *data,
Expand All @@ -339,12 +372,16 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
#define MMSG_NUM 64
struct iovec msg_iov[MMSG_NUM];
struct mmsghdr mmsg[MMSG_NUM];
uint8_t msg_ctrl[MMSG_NUM * CMSG_SPACE(sizeof(uint16_t))];
uint8_t bufs[MMSG_NUM][2*1024];
struct sockaddr_storage remote_addr[MMSG_NUM];
size_t total_nread, pkts;
int mcount, i, n;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
size_t gso_size;
size_t pktlen;
size_t offset, to;

DEBUGASSERT(max_pkts > 0);
pkts = 0;
Expand All @@ -359,6 +396,8 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
mmsg[i].msg_hdr.msg_iovlen = 1;
mmsg[i].msg_hdr.msg_name = &remote_addr[i];
mmsg[i].msg_hdr.msg_namelen = sizeof(remote_addr[i]);
mmsg[i].msg_hdr.msg_control = &msg_ctrl[i];
mmsg[i].msg_hdr.msg_controllen = CMSG_SPACE(sizeof(uint16_t));
}

while((mcount = recvmmsg(qctx->sockfd, mmsg, n, 0, NULL)) == -1 &&
Expand All @@ -385,14 +424,30 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf,
}

CURL_TRC_CF(data, cf, "recvmmsg() -> %d packets", mcount);
pkts += mcount;
for(i = 0; i < mcount; ++i) {
total_nread += mmsg[i].msg_len;
result = recv_cb(bufs[i], mmsg[i].msg_len,
mmsg[i].msg_hdr.msg_name, mmsg[i].msg_hdr.msg_namelen,
0, userp);
if(result)
goto out;

gso_size = msghdr_get_udp_gro(&mmsg[i].msg_hdr);
if(gso_size == 0) {
gso_size = mmsg[i].msg_len;
}

for(offset = 0; offset < mmsg[i].msg_len; offset = to) {
++pkts;

to = offset + gso_size;
if(to > mmsg[i].msg_len) {
pktlen = mmsg[i].msg_len - offset;
}
else {
pktlen = gso_size;
}

result = recv_cb(bufs[i] + offset, pktlen, mmsg[i].msg_hdr.msg_name,
mmsg[i].msg_hdr.msg_namelen, 0, userp);
if(result)
goto out;
}
}
}

Expand All @@ -418,18 +473,24 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
ssize_t nread;
char errstr[STRERROR_LEN];
CURLcode result = CURLE_OK;
uint8_t msg_ctrl[CMSG_SPACE(sizeof(uint16_t))];
size_t gso_size;
size_t pktlen;
size_t offset, to;

msg_iov.iov_base = buf;
msg_iov.iov_len = (int)sizeof(buf);

memset(&msg, 0, sizeof(msg));
msg.msg_iov = &msg_iov;
msg.msg_iovlen = 1;
msg.msg_control = msg_ctrl;

DEBUGASSERT(max_pkts > 0);
for(pkts = 0, total_nread = 0; pkts < max_pkts;) {
msg.msg_name = &remote_addr;
msg.msg_namelen = sizeof(remote_addr);
msg.msg_controllen = sizeof(msg_ctrl);
while((nread = recvmsg(qctx->sockfd, &msg, 0)) == -1 &&
SOCKERRNO == EINTR)
;
Expand All @@ -452,12 +513,29 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
goto out;
}

++pkts;
total_nread += (size_t)nread;
result = recv_cb(buf, (size_t)nread, msg.msg_name, msg.msg_namelen,
0, userp);
if(result)
goto out;

gso_size = msghdr_get_udp_gro(&msg);
if(gso_size == 0) {
gso_size = (size_t)nread;
}

for(offset = 0; offset < (size_t)nread; offset = to) {
++pkts;

to = offset + gso_size;
if(to > (size_t)nread) {
pktlen = (size_t)nread - offset;
}
else {
pktlen = gso_size;
}

result =
recv_cb(buf + offset, pktlen, msg.msg_name, msg.msg_namelen, 0, userp);
if(result)
goto out;
}
}

out:
Expand Down

0 comments on commit a571afc

Please sign in to comment.