1
0
mirror of https://passt.top/passt synced 2024-06-30 15:02:40 +00:00

udp: Always use sendto() rather than send() for forwarding spliced packets

udp_sock_handler_splice() has two different ways of sending out packets
once it has determined the correct destination socket.  For the originating
sockets (which are not connected) it uses sendto() to specify a specific
address.  For the forward socket (which is connected) we use send().

However we know the correct destination address even for the forward socket
we do also know the correct destination address.  We can use this to use
sendto() instead of send(), removing the need for two different paths and
some staging data structures.

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 2022-11-30 15:13:03 +11:00 committed by Stefano Brivio
parent 729edc241d
commit 9ef31b7619

40
udp.c
View File

@ -48,7 +48,8 @@
* - forward direction: 127.0.0.1:5000 -> 127.0.0.1:80 in init from bound
* socket s, with epoll reference: index = 80, splice = UDP_TO_NS
* - if udp_splice_to_ns[V4][5000].target_sock:
* - send packet to udp_splice_to_ns[V4][5000].target_sock
* - send packet to udp_splice_to_ns[V4][5000].target_sock, with
* destination port 80
* - otherwise:
* - create new socket udp_splice_to_ns[V4][5000].target_sock
* - bind in namespace to 127.0.0.1:5000
@ -71,7 +72,8 @@
* - forward direction: 127.0.0.1:2000 -> 127.0.0.1:22 in namespace from bound
* socket s, with epoll reference: index = 22, splice = UDP_TO_INIT
* - if udp4_splice_to_init[V4][2000].target_sock:
* - send packet to udp_splice_to_init[V4][2000].target_sock
* - send packet to udp_splice_to_init[V4][2000].target_sock, with
* destination port 22
* - otherwise:
* - create new socket udp_splice_to_init[V4][2000].target_sock
* - bind in init to 127.0.0.1:2000
@ -244,9 +246,6 @@ static struct mmsghdr udp6_l2_mh_tap [UDP_TAP_FRAMES_MEM];
static struct iovec udp_iov_recv [UDP_SPLICE_FRAMES];
static struct mmsghdr udp_mmh_recv [UDP_SPLICE_FRAMES];
static struct iovec udp_iov_send [UDP_SPLICE_FRAMES];
static struct mmsghdr udp_mmh_send [UDP_SPLICE_FRAMES];
static struct iovec udp_iov_sendto [UDP_SPLICE_FRAMES];
static struct mmsghdr udp_mmh_sendto [UDP_SPLICE_FRAMES];
@ -529,7 +528,7 @@ static int udp_splice_connect_ns(void *arg)
static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
uint32_t events, const struct timespec *now)
{
in_port_t src, dst = ref.r.p.udp.udp.port, send_dst = 0;
in_port_t src, dst = ref.r.p.udp.udp.port;
struct msghdr *mh = &udp_mmh_recv[0].msg_hdr;
struct sockaddr_storage *sa_s = mh->msg_name;
int s, v6 = ref.r.p.udp.udp.v6, n, i;
@ -570,8 +569,6 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
case UDP_BACK_TO_INIT:
if (!(s = udp_splice_to_ns[v6][dst].orig_sock))
return;
send_dst = dst;
break;
case UDP_TO_INIT:
src += c->udp.fwd_in.rdelta[src];
@ -587,25 +584,11 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
case UDP_BACK_TO_NS:
if (!(s = udp_splice_to_init[v6][dst].orig_sock))
return;
send_dst = dst;
break;
default:
return;
}
if (ref.r.p.udp.udp.splice == UDP_TO_NS ||
ref.r.p.udp.udp.splice == UDP_TO_INIT) {
for (i = 0; i < n; i++) {
struct msghdr *mh_s = &udp_mmh_send[i].msg_hdr;
mh_s->msg_iov->iov_len = udp_mmh_recv[i].msg_len;
}
sendmmsg(s, udp_mmh_send, n, MSG_NOSIGNAL);
return;
}
for (i = 0; i < n; i++) {
struct msghdr *mh_s = &udp_mmh_sendto[i].msg_hdr;
@ -617,7 +600,7 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
((struct sockaddr_in6) {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_LOOPBACK_INIT,
.sin6_port = htons(send_dst),
.sin6_port = htons(dst),
.sin6_scope_id = 0,
});
} else {
@ -625,7 +608,7 @@ static void udp_sock_handler_splice(const struct ctx *c, union epoll_ref ref,
((struct sockaddr_in) {
.sin_family = AF_INET,
.sin_addr = { .s_addr = htonl(INADDR_LOOPBACK) },
.sin_port = htons(send_dst),
.sin_port = htons(dst),
.sin_zero = { 0 },
});
}
@ -1228,15 +1211,6 @@ static void udp_splice_iov_init(void)
iov->iov_len = sizeof(udp_splice_buf[i]);
}
for (i = 0, h = udp_mmh_send; i < UDP_SPLICE_FRAMES; i++, h++) {
struct msghdr *mh = &h->msg_hdr;
mh->msg_iov = &udp_iov_send[i];
mh->msg_iovlen = 1;
}
for (i = 0, iov = udp_iov_send; i < UDP_SPLICE_FRAMES; i++, iov++)
iov->iov_base = udp_splice_buf[i];
for (i = 0, h = udp_mmh_sendto; i < UDP_SPLICE_FRAMES; i++, h++) {
struct msghdr *mh = &h->msg_hdr;