* [PATCH 0/4] UDP flow socket preliminaries
@ 2025-03-25 3:00 David Gibson
2025-03-25 3:00 ` [PATCH 1/4] udp: Common invocation of udp_sock_errs() for vhost-user and "buf" paths David Gibson
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: David Gibson @ 2025-03-25 3:00 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
As discussed on our recent call, I'm working towards using connected
sockets on both sides of UDP flows. This series makes some
preliminary reworks that simplify things and make that easier.
David Gibson (4):
udp: Common invocation of udp_sock_errs() for vhost-user and "buf"
paths
udp: Simplify checking of epoll event bits
udp_vu: Factor things out of udp_vu_reply_sock_data() loop
udp: Share more logic between vu and non-vu reply socket paths
udp.c | 120 +++++++++++++++++++++++++------------------------
udp_internal.h | 2 +-
udp_vu.c | 68 +++++++++-------------------
udp_vu.h | 9 ++--
4 files changed, 88 insertions(+), 111 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] udp: Common invocation of udp_sock_errs() for vhost-user and "buf" paths
2025-03-25 3:00 [PATCH 0/4] UDP flow socket preliminaries David Gibson
@ 2025-03-25 3:00 ` David Gibson
2025-03-25 3:00 ` [PATCH 2/4] udp: Simplify checking of epoll event bits David Gibson
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2025-03-25 3:00 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
The vhost-user and non-vhost-user paths for both udp_listen_sock_handler()
and udp_reply_sock_handler() are more or less completely separate. Both,
however, start with essentially the same invocation of udp_sock_errs(), so
that can be made common.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp.c | 37 ++++++++++++++++++++-----------------
udp_internal.h | 2 +-
udp_vu.c | 15 ---------------
3 files changed, 21 insertions(+), 33 deletions(-)
diff --git a/udp.c b/udp.c
index 80520cbd..4a06b162 100644
--- a/udp.c
+++ b/udp.c
@@ -585,7 +585,8 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
*
* Return: Number of errors handled, or < 0 if we have an unrecoverable error
*/
-int udp_sock_errs(const struct ctx *c, union epoll_ref ref, uint32_t events)
+static int udp_sock_errs(const struct ctx *c, union epoll_ref ref,
+ uint32_t events)
{
unsigned n_err = 0;
socklen_t errlen;
@@ -678,13 +679,6 @@ static void udp_buf_listen_sock_handler(const struct ctx *c,
const socklen_t sasize = sizeof(udp_meta[0].s_in);
int n, i;
- if (udp_sock_errs(c, ref, events) < 0) {
- err("UDP: Unrecoverable error on listening socket:"
- " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
- /* FIXME: what now? close/re-open socket? */
- return;
- }
-
if ((n = udp_sock_recv(c, ref.fd, events, udp_mh_recv)) <= 0)
return;
@@ -750,6 +744,13 @@ void udp_listen_sock_handler(const struct ctx *c,
union epoll_ref ref, uint32_t events,
const struct timespec *now)
{
+ if (udp_sock_errs(c, ref, events) < 0) {
+ err("UDP: Unrecoverable error on listening socket:"
+ " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
+ /* FIXME: what now? close/re-open socket? */
+ return;
+ }
+
if (c->mode == MODE_VU) {
udp_vu_listen_sock_handler(c, ref, events, now);
return;
@@ -777,17 +778,8 @@ static void udp_buf_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
uint8_t topif = pif_at_sidx(tosidx);
int n, i, from_s;
- ASSERT(!c->no_udp && uflow);
-
from_s = uflow->s[ref.flowside.sidei];
- if (udp_sock_errs(c, ref, events) < 0) {
- flow_err(uflow, "Unrecoverable error on reply socket");
- flow_err_details(uflow);
- udp_flow_close(c, uflow);
- return;
- }
-
if ((n = udp_sock_recv(c, from_s, events, udp_mh_recv)) <= 0)
return;
@@ -825,6 +817,17 @@ static void udp_buf_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
void udp_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
uint32_t events, const struct timespec *now)
{
+ struct udp_flow *uflow = udp_at_sidx(ref.flowside);
+
+ ASSERT(!c->no_udp && uflow);
+
+ if (udp_sock_errs(c, ref, events) < 0) {
+ flow_err(uflow, "Unrecoverable error on reply socket");
+ flow_err_details(uflow);
+ udp_flow_close(c, uflow);
+ return;
+ }
+
if (c->mode == MODE_VU) {
udp_vu_reply_sock_handler(c, ref, events, now);
return;
diff --git a/udp_internal.h b/udp_internal.h
index 3b081f54..02724e59 100644
--- a/udp_internal.h
+++ b/udp_internal.h
@@ -30,5 +30,5 @@ size_t udp_update_hdr4(struct iphdr *ip4h, struct udp_payload_t *bp,
size_t udp_update_hdr6(struct ipv6hdr *ip6h, struct udp_payload_t *bp,
const struct flowside *toside, size_t dlen,
bool no_udp_csum);
-int udp_sock_errs(const struct ctx *c, union epoll_ref ref, uint32_t events);
+
#endif /* UDP_INTERNAL_H */
diff --git a/udp_vu.c b/udp_vu.c
index c26a223d..84f52aff 100644
--- a/udp_vu.c
+++ b/udp_vu.c
@@ -227,12 +227,6 @@ void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
int i;
- if (udp_sock_errs(c, ref, events) < 0) {
- err("UDP: Unrecoverable error on listening socket:"
- " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
- return;
- }
-
for (i = 0; i < UDP_MAX_FRAMES; i++) {
const struct flowside *toside;
union sockaddr_inany s_in;
@@ -300,15 +294,6 @@ void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
int i;
- ASSERT(!c->no_udp);
-
- if (udp_sock_errs(c, ref, events) < 0) {
- flow_err(uflow, "Unrecoverable error on reply socket");
- flow_err_details(uflow);
- udp_flow_close(c, uflow);
- return;
- }
-
for (i = 0; i < UDP_MAX_FRAMES; i++) {
uint8_t topif = pif_at_sidx(tosidx);
ssize_t dlen;
--
@@ -227,12 +227,6 @@ void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
int i;
- if (udp_sock_errs(c, ref, events) < 0) {
- err("UDP: Unrecoverable error on listening socket:"
- " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
- return;
- }
-
for (i = 0; i < UDP_MAX_FRAMES; i++) {
const struct flowside *toside;
union sockaddr_inany s_in;
@@ -300,15 +294,6 @@ void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
int i;
- ASSERT(!c->no_udp);
-
- if (udp_sock_errs(c, ref, events) < 0) {
- flow_err(uflow, "Unrecoverable error on reply socket");
- flow_err_details(uflow);
- udp_flow_close(c, uflow);
- return;
- }
-
for (i = 0; i < UDP_MAX_FRAMES; i++) {
uint8_t topif = pif_at_sidx(tosidx);
ssize_t dlen;
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] udp: Simplify checking of epoll event bits
2025-03-25 3:00 [PATCH 0/4] UDP flow socket preliminaries David Gibson
2025-03-25 3:00 ` [PATCH 1/4] udp: Common invocation of udp_sock_errs() for vhost-user and "buf" paths David Gibson
@ 2025-03-25 3:00 ` David Gibson
2025-03-25 3:00 ` [PATCH 3/4] udp_vu: Factor things out of udp_vu_reply_sock_data() loop David Gibson
2025-03-25 3:00 ` [PATCH 4/4] udp: Share more logic between vu and non-vu reply socket paths David Gibson
3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2025-03-25 3:00 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
udp_{listen,reply}_sock_handler() can accept both EPOLLERR and EPOLLIN
events. However, unlike most epoll event handlers we don't check the
event bits right there. EPOLLERR is checked within udp_sock_errs() which
we call unconditionally. Checking EPOLLIN is still more buried: it is
checked within both udp_sock_recv() and udp_vu_sock_recv().
We can simplify the logic and pass less extraneous parameters around by
moving the checking of the event bits to the top level event handlers.
This makes udp_{buf,vu}_{listen,reply}_sock_handler() no longer general
event handlers, but specific to EPOLLIN events, meaning new data. So,
rename those functions to udp_{buf,vu}_{listen,reply}_sock_data() to better
reflect their function.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp.c | 78 ++++++++++++++++++++++++--------------------------------
udp_vu.c | 25 +++++++-----------
udp_vu.h | 8 +++---
3 files changed, 47 insertions(+), 64 deletions(-)
diff --git a/udp.c b/udp.c
index 4a06b162..26a91c9c 100644
--- a/udp.c
+++ b/udp.c
@@ -581,12 +581,10 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
* udp_sock_errs() - Process errors on a socket
* @c: Execution context
* @ref: epoll reference
- * @events: epoll events bitmap
*
* Return: Number of errors handled, or < 0 if we have an unrecoverable error
*/
-static int udp_sock_errs(const struct ctx *c, union epoll_ref ref,
- uint32_t events)
+static int udp_sock_errs(const struct ctx *c, union epoll_ref ref)
{
unsigned n_err = 0;
socklen_t errlen;
@@ -595,9 +593,6 @@ static int udp_sock_errs(const struct ctx *c, union epoll_ref ref,
ASSERT(!c->no_udp);
- if (!(events & EPOLLERR))
- return 0; /* Nothing to do */
-
/* Empty the error queue */
while ((rc = udp_sock_recverr(c, ref)) > 0)
n_err += rc;
@@ -630,15 +625,13 @@ static int udp_sock_errs(const struct ctx *c, union epoll_ref ref,
* udp_sock_recv() - Receive datagrams from a socket
* @c: Execution context
* @s: Socket to receive from
- * @events: epoll events bitmap
* @mmh mmsghdr array to receive into
*
* Return: Number of datagrams received
*
* #syscalls recvmmsg arm:recvmmsg_time64 i686:recvmmsg_time64
*/
-static int udp_sock_recv(const struct ctx *c, int s, uint32_t events,
- struct mmsghdr *mmh)
+static int udp_sock_recv(const struct ctx *c, int s, struct mmsghdr *mmh)
{
/* For not entirely clear reasons (data locality?) pasta gets better
* throughput if we receive tap datagrams one at a atime. For small
@@ -651,9 +644,6 @@ static int udp_sock_recv(const struct ctx *c, int s, uint32_t events,
ASSERT(!c->no_udp);
- if (!(events & EPOLLIN))
- return 0;
-
n = recvmmsg(s, mmh, n, 0, NULL);
if (n < 0) {
err_perror("Error receiving datagrams");
@@ -664,22 +654,20 @@ static int udp_sock_recv(const struct ctx *c, int s, uint32_t events,
}
/**
- * udp_buf_listen_sock_handler() - Handle new data from socket
+ * udp_buf_listen_sock_data() - Handle new data from socket
* @c: Execution context
* @ref: epoll reference
- * @events: epoll events bitmap
* @now: Current timestamp
*
* #syscalls recvmmsg
*/
-static void udp_buf_listen_sock_handler(const struct ctx *c,
- union epoll_ref ref, uint32_t events,
- const struct timespec *now)
+static void udp_buf_listen_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now)
{
const socklen_t sasize = sizeof(udp_meta[0].s_in);
int n, i;
- if ((n = udp_sock_recv(c, ref.fd, events, udp_mh_recv)) <= 0)
+ if ((n = udp_sock_recv(c, ref.fd, udp_mh_recv)) <= 0)
return;
/* We divide datagrams into batches based on how we need to send them,
@@ -744,33 +732,33 @@ void udp_listen_sock_handler(const struct ctx *c,
union epoll_ref ref, uint32_t events,
const struct timespec *now)
{
- if (udp_sock_errs(c, ref, events) < 0) {
- err("UDP: Unrecoverable error on listening socket:"
- " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
- /* FIXME: what now? close/re-open socket? */
- return;
+ if (events & EPOLLERR) {
+ if (udp_sock_errs(c, ref) < 0) {
+ err("UDP: Unrecoverable error on listening socket:"
+ " (%s port %hu)", pif_name(ref.udp.pif), ref.udp.port);
+ /* FIXME: what now? close/re-open socket? */
+ return;
+ }
}
- if (c->mode == MODE_VU) {
- udp_vu_listen_sock_handler(c, ref, events, now);
- return;
+ if (events & EPOLLIN) {
+ if (c->mode == MODE_VU)
+ udp_vu_listen_sock_data(c, ref, now);
+ else
+ udp_buf_listen_sock_data(c, ref, now);
}
-
- udp_buf_listen_sock_handler(c, ref, events, now);
}
/**
- * udp_buf_reply_sock_handler() - Handle new data from flow specific socket
+ * udp_buf_reply_sock_data() - Handle new data from flow specific socket
* @c: Execution context
* @ref: epoll reference
- * @events: epoll events bitmap
* @now: Current timestamp
*
* #syscalls recvmmsg
*/
-static void udp_buf_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events,
- const struct timespec *now)
+static void udp_buf_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now)
{
flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
@@ -780,7 +768,7 @@ static void udp_buf_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
from_s = uflow->s[ref.flowside.sidei];
- if ((n = udp_sock_recv(c, from_s, events, udp_mh_recv)) <= 0)
+ if ((n = udp_sock_recv(c, from_s, udp_mh_recv)) <= 0)
return;
flow_trace(uflow, "Received %d datagrams on reply socket", n);
@@ -821,19 +809,21 @@ void udp_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
ASSERT(!c->no_udp && uflow);
- if (udp_sock_errs(c, ref, events) < 0) {
- flow_err(uflow, "Unrecoverable error on reply socket");
- flow_err_details(uflow);
- udp_flow_close(c, uflow);
- return;
+ if (events & EPOLLERR) {
+ if (udp_sock_errs(c, ref) < 0) {
+ flow_err(uflow, "Unrecoverable error on reply socket");
+ flow_err_details(uflow);
+ udp_flow_close(c, uflow);
+ return;
+ }
}
- if (c->mode == MODE_VU) {
- udp_vu_reply_sock_handler(c, ref, events, now);
- return;
+ if (events & EPOLLIN) {
+ if (c->mode == MODE_VU)
+ udp_vu_reply_sock_data(c, ref, now);
+ else
+ udp_buf_reply_sock_data(c, ref, now);
}
-
- udp_buf_reply_sock_handler(c, ref, events, now);
}
/**
diff --git a/udp_vu.c b/udp_vu.c
index 84f52aff..698667f6 100644
--- a/udp_vu.c
+++ b/udp_vu.c
@@ -78,14 +78,12 @@ static int udp_vu_sock_info(int s, union sockaddr_inany *s_in)
* udp_vu_sock_recv() - Receive datagrams from socket into vhost-user buffers
* @c: Execution context
* @s: Socket to receive from
- * @events: epoll events bitmap
* @v6: Set for IPv6 connections
* @dlen: Size of received data (output)
*
* Return: Number of iov entries used to store the datagram
*/
-static int udp_vu_sock_recv(const struct ctx *c, int s, uint32_t events,
- bool v6, ssize_t *dlen)
+static int udp_vu_sock_recv(const struct ctx *c, int s, bool v6, ssize_t *dlen)
{
struct vu_dev *vdev = c->vdev;
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
@@ -95,9 +93,6 @@ static int udp_vu_sock_recv(const struct ctx *c, int s, uint32_t events,
ASSERT(!c->no_udp);
- if (!(events & EPOLLIN))
- return 0;
-
/* compute L2 header length */
hdrlen = udp_vu_hdrlen(v6);
@@ -214,14 +209,13 @@ static void udp_vu_csum(const struct flowside *toside, int iov_used)
}
/**
- * udp_vu_listen_sock_handler() - Handle new data from socket
+ * udp_vu_listen_sock_data() - Handle new data from socket
* @c: Execution context
* @ref: epoll reference
- * @events: epoll events bitmap
* @now: Current timestamp
*/
-void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now)
+void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now)
{
struct vu_dev *vdev = c->vdev;
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
@@ -262,7 +256,7 @@ void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
- iov_used = udp_vu_sock_recv(c, ref.fd, events, v6, &dlen);
+ iov_used = udp_vu_sock_recv(c, ref.fd, v6, &dlen);
if (iov_used <= 0)
break;
@@ -277,14 +271,13 @@ void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
}
/**
- * udp_vu_reply_sock_handler() - Handle new data from flow specific socket
+ * udp_vu_reply_sock_data() - Handle new data from flow specific socket
* @c: Execution context
* @ref: epoll reference
- * @events: epoll events bitmap
* @now: Current timestamp
*/
-void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now)
+void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now)
{
flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
@@ -313,7 +306,7 @@ void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
- iov_used = udp_vu_sock_recv(c, from_s, events, v6, &dlen);
+ iov_used = udp_vu_sock_recv(c, from_s, v6, &dlen);
if (iov_used <= 0)
break;
flow_trace(uflow, "Received 1 datagram on reply socket");
diff --git a/udp_vu.h b/udp_vu.h
index ba7018d3..4f2262d0 100644
--- a/udp_vu.h
+++ b/udp_vu.h
@@ -6,8 +6,8 @@
#ifndef UDP_VU_H
#define UDP_VU_H
-void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now);
-void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now);
+void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now);
+void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now);
#endif /* UDP_VU_H */
--
@@ -6,8 +6,8 @@
#ifndef UDP_VU_H
#define UDP_VU_H
-void udp_vu_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now);
-void udp_vu_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
- uint32_t events, const struct timespec *now);
+void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now);
+void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+ const struct timespec *now);
#endif /* UDP_VU_H */
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] udp_vu: Factor things out of udp_vu_reply_sock_data() loop
2025-03-25 3:00 [PATCH 0/4] UDP flow socket preliminaries David Gibson
2025-03-25 3:00 ` [PATCH 1/4] udp: Common invocation of udp_sock_errs() for vhost-user and "buf" paths David Gibson
2025-03-25 3:00 ` [PATCH 2/4] udp: Simplify checking of epoll event bits David Gibson
@ 2025-03-25 3:00 ` David Gibson
2025-03-25 3:00 ` [PATCH 4/4] udp: Share more logic between vu and non-vu reply socket paths David Gibson
3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2025-03-25 3:00 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
At the start of every cycle of the loop in udp_vu_reply_sock_data() we:
- ASSERT that uflow is not NULL
- Check if the target pif is PIF_TAP
- Initialize the v6 boolean
However, all of these depend only on the flow, which doesn't change across
the loop. This is probably a duplication from udp_vu_listen_sock_data(),
where the flow can be different for each packet. For the reply socket
case, however, factor that logic out of the loop.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp_vu.c | 28 +++++++++++++---------------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/udp_vu.c b/udp_vu.c
index 698667f6..6e1823a9 100644
--- a/udp_vu.c
+++ b/udp_vu.c
@@ -281,30 +281,28 @@ void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
{
flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
+ bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
struct udp_flow *uflow = udp_at_sidx(ref.flowside);
int from_s = uflow->s[ref.flowside.sidei];
struct vu_dev *vdev = c->vdev;
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
+ uint8_t topif = pif_at_sidx(tosidx);
int i;
- for (i = 0; i < UDP_MAX_FRAMES; i++) {
- uint8_t topif = pif_at_sidx(tosidx);
- ssize_t dlen;
- int iov_used;
- bool v6;
-
- ASSERT(uflow);
+ ASSERT(uflow);
- if (topif != PIF_TAP) {
- uint8_t frompif = pif_at_sidx(ref.flowside);
+ if (topif != PIF_TAP) {
+ uint8_t frompif = pif_at_sidx(ref.flowside);
- flow_err(uflow,
- "No support for forwarding UDP from %s to %s",
- pif_name(frompif), pif_name(topif));
- continue;
- }
+ flow_err(uflow,
+ "No support for forwarding UDP from %s to %s",
+ pif_name(frompif), pif_name(topif));
+ return;
+ }
- v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
+ for (i = 0; i < UDP_MAX_FRAMES; i++) {
+ ssize_t dlen;
+ int iov_used;
iov_used = udp_vu_sock_recv(c, from_s, v6, &dlen);
if (iov_used <= 0)
--
@@ -281,30 +281,28 @@ void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
{
flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
+ bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
struct udp_flow *uflow = udp_at_sidx(ref.flowside);
int from_s = uflow->s[ref.flowside.sidei];
struct vu_dev *vdev = c->vdev;
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
+ uint8_t topif = pif_at_sidx(tosidx);
int i;
- for (i = 0; i < UDP_MAX_FRAMES; i++) {
- uint8_t topif = pif_at_sidx(tosidx);
- ssize_t dlen;
- int iov_used;
- bool v6;
-
- ASSERT(uflow);
+ ASSERT(uflow);
- if (topif != PIF_TAP) {
- uint8_t frompif = pif_at_sidx(ref.flowside);
+ if (topif != PIF_TAP) {
+ uint8_t frompif = pif_at_sidx(ref.flowside);
- flow_err(uflow,
- "No support for forwarding UDP from %s to %s",
- pif_name(frompif), pif_name(topif));
- continue;
- }
+ flow_err(uflow,
+ "No support for forwarding UDP from %s to %s",
+ pif_name(frompif), pif_name(topif));
+ return;
+ }
- v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
+ for (i = 0; i < UDP_MAX_FRAMES; i++) {
+ ssize_t dlen;
+ int iov_used;
iov_used = udp_vu_sock_recv(c, from_s, v6, &dlen);
if (iov_used <= 0)
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] udp: Share more logic between vu and non-vu reply socket paths
2025-03-25 3:00 [PATCH 0/4] UDP flow socket preliminaries David Gibson
` (2 preceding siblings ...)
2025-03-25 3:00 ` [PATCH 3/4] udp_vu: Factor things out of udp_vu_reply_sock_data() loop David Gibson
@ 2025-03-25 3:00 ` David Gibson
3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2025-03-25 3:00 UTC (permalink / raw)
To: passt-dev, Stefano Brivio; +Cc: David Gibson
Share some additional miscellaneous logic between the vhost-user and "buf"
paths for data on udp reply sockets. The biggest piece is error handling
of cases where we can't forward between the two pifs of the flow. We also
make common some more simple logic locating the correct flow and its
parameters.
This adds some lines of code due to extra comment lines, but nonetheless
reduces logic duplication.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp.c | 41 ++++++++++++++++++++++++++---------------
udp_vu.c | 26 +++++++++++---------------
udp_vu.h | 3 ++-
3 files changed, 39 insertions(+), 31 deletions(-)
diff --git a/udp.c b/udp.c
index 26a91c9c..f417cea1 100644
--- a/udp.c
+++ b/udp.c
@@ -752,24 +752,25 @@ void udp_listen_sock_handler(const struct ctx *c,
/**
* udp_buf_reply_sock_data() - Handle new data from flow specific socket
* @c: Execution context
- * @ref: epoll reference
+ * @s: Socket to read data from
+ * @tosidx: Flow & side to forward data from @s to
* @now: Current timestamp
*
+ * Return: true on success, false if can't forward from socket to flow's pif
+ *
* #syscalls recvmmsg
*/
-static void udp_buf_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+static bool udp_buf_reply_sock_data(const struct ctx *c,
+ int s, flow_sidx_t tosidx,
const struct timespec *now)
{
- flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
- struct udp_flow *uflow = udp_at_sidx(ref.flowside);
+ struct udp_flow *uflow = udp_at_sidx(tosidx);
uint8_t topif = pif_at_sidx(tosidx);
- int n, i, from_s;
-
- from_s = uflow->s[ref.flowside.sidei];
+ int n, i;
- if ((n = udp_sock_recv(c, from_s, udp_mh_recv)) <= 0)
- return;
+ if ((n = udp_sock_recv(c, s, udp_mh_recv)) <= 0)
+ return true;
flow_trace(uflow, "Received %d datagrams on reply socket", n);
uflow->ts = now->tv_sec;
@@ -788,11 +789,10 @@ static void udp_buf_reply_sock_data(const struct ctx *c, union epoll_ref ref,
} else if (topif == PIF_TAP) {
tap_send_frames(c, &udp_l2_iov[0][0], UDP_NUM_IOVS, n);
} else {
- uint8_t frompif = pif_at_sidx(ref.flowside);
-
- flow_err(uflow, "No support for forwarding UDP from %s to %s",
- pif_name(frompif), pif_name(topif));
+ return false;
}
+
+ return true;
}
/**
@@ -819,10 +819,21 @@ void udp_reply_sock_handler(const struct ctx *c, union epoll_ref ref,
}
if (events & EPOLLIN) {
+ flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
+ int s = ref.fd;
+ bool ret;
+
if (c->mode == MODE_VU)
- udp_vu_reply_sock_data(c, ref, now);
+ ret = udp_vu_reply_sock_data(c, s, tosidx, now);
else
- udp_buf_reply_sock_data(c, ref, now);
+ ret = udp_buf_reply_sock_data(c, s, tosidx, now);
+
+ if (!ret) {
+ flow_err(uflow,
+ "No support for forwarding UDP from %s to %s",
+ pif_name(pif_at_sidx(ref.flowside)),
+ pif_name(pif_at_sidx(tosidx)));
+ }
}
}
diff --git a/udp_vu.c b/udp_vu.c
index 6e1823a9..06bdeae6 100644
--- a/udp_vu.c
+++ b/udp_vu.c
@@ -273,38 +273,32 @@ void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
/**
* udp_vu_reply_sock_data() - Handle new data from flow specific socket
* @c: Execution context
- * @ref: epoll reference
+ * @s: Socket to read data from
+ * @tosidx: Flow & side to forward data from @s to
* @now: Current timestamp
+ *
+ * Return: true on success, false if can't forward from socket to flow's pif
*/
-void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx,
const struct timespec *now)
{
- flow_sidx_t tosidx = flow_sidx_opposite(ref.flowside);
const struct flowside *toside = flowside_at_sidx(tosidx);
bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
- struct udp_flow *uflow = udp_at_sidx(ref.flowside);
- int from_s = uflow->s[ref.flowside.sidei];
+ struct udp_flow *uflow = udp_at_sidx(tosidx);
struct vu_dev *vdev = c->vdev;
struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
- uint8_t topif = pif_at_sidx(tosidx);
int i;
ASSERT(uflow);
- if (topif != PIF_TAP) {
- uint8_t frompif = pif_at_sidx(ref.flowside);
-
- flow_err(uflow,
- "No support for forwarding UDP from %s to %s",
- pif_name(frompif), pif_name(topif));
- return;
- }
+ if (pif_at_sidx(tosidx) != PIF_TAP)
+ return false;
for (i = 0; i < UDP_MAX_FRAMES; i++) {
ssize_t dlen;
int iov_used;
- iov_used = udp_vu_sock_recv(c, from_s, v6, &dlen);
+ iov_used = udp_vu_sock_recv(c, s, v6, &dlen);
if (iov_used <= 0)
break;
flow_trace(uflow, "Received 1 datagram on reply socket");
@@ -318,4 +312,6 @@ void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
}
vu_flush(vdev, vq, elem, iov_used);
}
+
+ return true;
}
diff --git a/udp_vu.h b/udp_vu.h
index 4f2262d0..2299b51f 100644
--- a/udp_vu.h
+++ b/udp_vu.h
@@ -8,6 +8,7 @@
void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
const struct timespec *now);
-void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx,
const struct timespec *now);
+
#endif /* UDP_VU_H */
--
@@ -8,6 +8,7 @@
void udp_vu_listen_sock_data(const struct ctx *c, union epoll_ref ref,
const struct timespec *now);
-void udp_vu_reply_sock_data(const struct ctx *c, union epoll_ref ref,
+bool udp_vu_reply_sock_data(const struct ctx *c, int s, flow_sidx_t tosidx,
const struct timespec *now);
+
#endif /* UDP_VU_H */
--
2.49.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-03-25 3:00 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-25 3:00 [PATCH 0/4] UDP flow socket preliminaries David Gibson
2025-03-25 3:00 ` [PATCH 1/4] udp: Common invocation of udp_sock_errs() for vhost-user and "buf" paths David Gibson
2025-03-25 3:00 ` [PATCH 2/4] udp: Simplify checking of epoll event bits David Gibson
2025-03-25 3:00 ` [PATCH 3/4] udp_vu: Factor things out of udp_vu_reply_sock_data() loop David Gibson
2025-03-25 3:00 ` [PATCH 4/4] udp: Share more logic between vu and non-vu reply socket paths David Gibson
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).