udp: Fold checking of splice flag into udp_mmh_splice_port()

udp_mmh_splice_port() is used to determine if a UDP datagram can be
"spliced" (forwarded via a socket instead of tap).  We only invoke it if
the origin socket has the 'splice' flag set.

Fold the checking of the flag into the helper itself, which makes the
caller simpler.  It does mean we have a loop looking for a batch of
spliceable or non-spliceable packets even in the case where the flag is
clear.  This shouldn't be that expensive though, since each call to
udp_mmh_splice_port() will return without accessing memory in that case.
In any case we're going to need a similar loop in more cases with upcoming
flow table work.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
David Gibson 2024-06-14 11:51:06 +10:00 committed by Stefano Brivio
parent 523fbc5af7
commit 63db7dcdbf

23
udp.c
View file

@ -466,21 +466,25 @@ static int udp_splice_new_ns(void *arg)
/** /**
* udp_mmh_splice_port() - Is source address of message suitable for splicing? * udp_mmh_splice_port() - Is source address of message suitable for splicing?
* @v6: Is @sa a sockaddr_in6 (otherwise sockaddr_in)? * @uref: UDP epoll reference for incoming message's origin socket
* @mmh: mmsghdr of incoming message * @mmh: mmsghdr of incoming message
* *
* Return: if @sa refers to localhost (127.0.0.1 or ::1) the port from * Return: if source address of message in @mmh refers to localhost (127.0.0.1
* @sa in host order, otherwise -1. * or ::1) its source port (host order), otherwise -1.
*/ */
static int udp_mmh_splice_port(bool v6, const struct mmsghdr *mmh) static int udp_mmh_splice_port(union udp_epoll_ref uref,
const struct mmsghdr *mmh)
{ {
const struct sockaddr_in6 *sa6 = mmh->msg_hdr.msg_name; const struct sockaddr_in6 *sa6 = mmh->msg_hdr.msg_name;
const struct sockaddr_in *sa4 = mmh->msg_hdr.msg_name; const struct sockaddr_in *sa4 = mmh->msg_hdr.msg_name;
if (v6 && IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) if (!uref.splice)
return -1;
if (uref.v6 && IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
return ntohs(sa6->sin6_port); return ntohs(sa6->sin6_port);
if (!v6 && IN4_IS_ADDR_LOOPBACK(&sa4->sin_addr)) if (!uref.v6 && IN4_IS_ADDR_LOOPBACK(&sa4->sin_addr))
return ntohs(sa4->sin_port); return ntohs(sa4->sin_port);
return -1; return -1;
@ -775,19 +779,16 @@ void udp_buf_sock_handler(const struct ctx *c, union epoll_ref ref, uint32_t eve
for (i = 0; i < n; i += m) { for (i = 0; i < n; i += m) {
int splicefrom = -1; int splicefrom = -1;
m = n;
if (ref.udp.splice) { splicefrom = udp_mmh_splice_port(ref.udp, mmh_recv + i);
splicefrom = udp_mmh_splice_port(v6, mmh_recv + i);
for (m = 1; i + m < n; m++) { for (m = 1; i + m < n; m++) {
int p; int p;
p = udp_mmh_splice_port(v6, mmh_recv + i + m); p = udp_mmh_splice_port(ref.udp, mmh_recv + i + m);
if (p != splicefrom) if (p != splicefrom)
break; break;
} }
}
if (splicefrom >= 0) if (splicefrom >= 0)
udp_splice_sendfrom(c, i, m, splicefrom, dstport, udp_splice_sendfrom(c, i, m, splicefrom, dstport,