udp: Pre-populate msg_names with local address

udp_splice_namebuf is now used only for spliced sending, and so it is
only ever populated with the localhost address, either IPv4 or IPv6.
So, replace the awkward initialization in udp_sock_handler_splice()
with statically initialized versions for IPv4 and IPv6.  We then just
need to update the port number in udp_sock_handler_splice().

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 2023-01-05 15:26:22 +11:00 committed by Stefano Brivio
parent c9e193b5ae
commit f1ed8dbfa7
2 changed files with 25 additions and 22 deletions

40
udp.c
View file

@ -232,11 +232,18 @@ static struct mmsghdr udp4_l2_mh_tap [UDP_MAX_FRAMES];
static struct mmsghdr udp6_l2_mh_tap [UDP_MAX_FRAMES]; static struct mmsghdr udp6_l2_mh_tap [UDP_MAX_FRAMES];
/* recvmmsg()/sendmmsg() data for "spliced" connections */ /* recvmmsg()/sendmmsg() data for "spliced" connections */
static struct sockaddr_storage udp_splice_namebuf;
static struct iovec udp4_iov_splice [UDP_MAX_FRAMES]; static struct iovec udp4_iov_splice [UDP_MAX_FRAMES];
static struct iovec udp6_iov_splice [UDP_MAX_FRAMES]; static struct iovec udp6_iov_splice [UDP_MAX_FRAMES];
static struct sockaddr_in udp4_localname = {
.sin_family = AF_INET,
.sin_addr = IN4ADDR_LOOPBACK_INIT,
};
static struct sockaddr_in6 udp6_localname = {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_LOOPBACK_INIT,
};
static struct mmsghdr udp4_mh_splice [UDP_MAX_FRAMES]; static struct mmsghdr udp4_mh_splice [UDP_MAX_FRAMES];
static struct mmsghdr udp6_mh_splice [UDP_MAX_FRAMES]; static struct mmsghdr udp6_mh_splice [UDP_MAX_FRAMES];
@ -610,23 +617,10 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
if (n <= 0) if (n <= 0)
return; return;
if (v6) { if (v6)
*((struct sockaddr_in6 *)&udp_splice_namebuf) = udp6_localname.sin6_port = htons(dst);
((struct sockaddr_in6) { else
.sin6_family = AF_INET6, udp4_localname.sin_port = htons(dst);
.sin6_addr = IN6ADDR_LOOPBACK_INIT,
.sin6_port = htons(dst),
.sin6_scope_id = 0,
});
} else {
*((struct sockaddr_in *)&udp_splice_namebuf) =
((struct sockaddr_in) {
.sin_family = AF_INET,
.sin_addr = { .s_addr = htonl(INADDR_LOOPBACK) },
.sin_port = htons(dst),
.sin_zero = { 0 },
});
}
for (i = 0; i < n; i += m) { for (i = 0; i < n; i += m) {
in_port_t src = sa_port(v6, mmh_recv[i].msg_hdr.msg_name); in_port_t src = sa_port(v6, mmh_recv[i].msg_hdr.msg_name);
@ -1256,9 +1250,11 @@ static void udp_splice_iov_init(void)
struct msghdr *mh4 = &udp4_mh_splice[i].msg_hdr; struct msghdr *mh4 = &udp4_mh_splice[i].msg_hdr;
struct msghdr *mh6 = &udp6_mh_splice[i].msg_hdr; struct msghdr *mh6 = &udp6_mh_splice[i].msg_hdr;
mh4->msg_name = mh6->msg_name = &udp_splice_namebuf; mh4->msg_name = &udp4_localname;
mh4->msg_namelen = sizeof(udp_splice_namebuf); mh4->msg_namelen = sizeof(udp4_localname);
mh6->msg_namelen = sizeof(udp_splice_namebuf);
mh6->msg_name = &udp6_localname;
mh6->msg_namelen = sizeof(udp6_localname);
udp4_iov_splice[i].iov_base = udp4_l2_buf[i].data; udp4_iov_splice[i].iov_base = udp4_l2_buf[i].data;
udp6_iov_splice[i].iov_base = udp6_l2_buf[i].data; udp6_iov_splice[i].iov_base = udp6_l2_buf[i].data;

7
util.h
View file

@ -79,6 +79,13 @@
(IN_MULTICAST(ntohl((a)->s_addr))) (IN_MULTICAST(ntohl((a)->s_addr)))
#define IN4_ARE_ADDR_EQUAL(a, b) \ #define IN4_ARE_ADDR_EQUAL(a, b) \
(((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr) (((struct in_addr *)(a))->s_addr == ((struct in_addr *)b)->s_addr)
#if __BYTE_ORDER == __BIG_ENDIAN
#define IN4ADDR_LOOPBACK_INIT \
{ .s_addr = INADDR_LOOPBACK }
#else
#define IN4ADDR_LOOPBACK_INIT \
{ .s_addr = __bswap_constant_32(INADDR_LOOPBACK) }
#endif
#define NS_FN_STACK_SIZE (RLIMIT_STACK_VAL * 1024 / 8) #define NS_FN_STACK_SIZE (RLIMIT_STACK_VAL * 1024 / 8)
int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags, int do_clone(int (*fn)(void *), char *stack_area, size_t stack_size, int flags,