From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: Jon Maloy <jmaloy@redhat.com>,
David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 3/7] udp: Pass socket & flow information direction to error handling functions
Date: Tue, 15 Apr 2025 17:16:20 +1000 [thread overview]
Message-ID: <20250415071624.2618589-4-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20250415071624.2618589-1-david@gibson.dropbear.id.au>
udp_sock_recverr() and udp_sock_errs() take an epoll reference from which
they obtain both the socket fd to receive errors from, and - for flow
specific sockets - the flow and side the socket is associated with.
We have some upcoming cases where we want to clear errors when we're not
directly associated with receiving an epoll event, so it's not natural to
have an epoll reference. Therefore, make these functions take the socket
and flow from explicit parameters.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
udp.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/udp.c b/udp.c
index 154f99b5..c51ac955 100644
--- a/udp.c
+++ b/udp.c
@@ -467,14 +467,15 @@ static void udp_send_tap_icmp6(const struct ctx *c,
/**
* udp_sock_recverr() - Receive and clear an error from a socket
* @c: Execution context
- * @ref: epoll reference
+ * @s: Socket to receive errors from
+ * @sidx: Flow and side of @s, or FLOW_SIDX_NONE if unknown
*
* Return: 1 if error received and processed, 0 if no more errors in queue, < 0
* if there was an error reading the queue
*
* #syscalls recvmsg
*/
-static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
+static int udp_sock_recverr(const struct ctx *c, int s, flow_sidx_t sidx)
{
struct errhdr {
struct sock_extended_err ee;
@@ -484,7 +485,6 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
char data[ICMP6_MAX_DLEN];
const struct errhdr *eh;
struct cmsghdr *hdr;
- int s = ref.fd;
struct iovec iov = {
.iov_base = data,
.iov_len = sizeof(data)
@@ -525,12 +525,12 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
}
eh = (const struct errhdr *)CMSG_DATA(hdr);
- if (ref.type == EPOLL_TYPE_UDP) {
- flow_sidx_t sidx = flow_sidx_opposite(ref.flowside);
- const struct flowside *toside = flowside_at_sidx(sidx);
+ if (flow_sidx_valid(sidx)) {
+ flow_sidx_t tosidx = flow_sidx_opposite(sidx);
+ const struct flowside *toside = flowside_at_sidx(tosidx);
size_t dlen = rc;
- if (pif_is_socket(pif_at_sidx(sidx))) {
+ if (pif_is_socket(pif_at_sidx(tosidx))) {
/* XXX Is there any way to propagate ICMPs from socket
* to socket? */
} else if (hdr->cmsg_level == IPPROTO_IP) {
@@ -554,21 +554,21 @@ 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
+ * @s: Socket to receive errors from
+ * @sidx: Flow and side of @s, or FLOW_SIDX_NONE if unknown
*
* 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)
+static int udp_sock_errs(const struct ctx *c, int s, flow_sidx_t sidx)
{
unsigned n_err = 0;
socklen_t errlen;
- int s = ref.fd;
int rc, err;
ASSERT(!c->no_udp);
/* Empty the error queue */
- while ((rc = udp_sock_recverr(c, ref)) > 0)
+ while ((rc = udp_sock_recverr(c, s, sidx)) > 0)
n_err += rc;
if (rc < 0)
@@ -777,7 +777,7 @@ void udp_listen_sock_handler(const struct ctx *c,
const struct timespec *now)
{
if (events & EPOLLERR) {
- if (udp_sock_errs(c, ref) < 0) {
+ if (udp_sock_errs(c, ref.fd, FLOW_SIDX_NONE) < 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? */
@@ -804,7 +804,7 @@ void udp_sock_handler(const struct ctx *c, union epoll_ref ref,
ASSERT(!c->no_udp && uflow);
if (events & EPOLLERR) {
- if (udp_sock_errs(c, ref) < 0) {
+ if (udp_sock_errs(c, ref.fd, ref.flowside) < 0) {
flow_err(uflow, "Unrecoverable error on flow socket");
goto fail;
}
--
@@ -467,14 +467,15 @@ static void udp_send_tap_icmp6(const struct ctx *c,
/**
* udp_sock_recverr() - Receive and clear an error from a socket
* @c: Execution context
- * @ref: epoll reference
+ * @s: Socket to receive errors from
+ * @sidx: Flow and side of @s, or FLOW_SIDX_NONE if unknown
*
* Return: 1 if error received and processed, 0 if no more errors in queue, < 0
* if there was an error reading the queue
*
* #syscalls recvmsg
*/
-static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
+static int udp_sock_recverr(const struct ctx *c, int s, flow_sidx_t sidx)
{
struct errhdr {
struct sock_extended_err ee;
@@ -484,7 +485,6 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
char data[ICMP6_MAX_DLEN];
const struct errhdr *eh;
struct cmsghdr *hdr;
- int s = ref.fd;
struct iovec iov = {
.iov_base = data,
.iov_len = sizeof(data)
@@ -525,12 +525,12 @@ static int udp_sock_recverr(const struct ctx *c, union epoll_ref ref)
}
eh = (const struct errhdr *)CMSG_DATA(hdr);
- if (ref.type == EPOLL_TYPE_UDP) {
- flow_sidx_t sidx = flow_sidx_opposite(ref.flowside);
- const struct flowside *toside = flowside_at_sidx(sidx);
+ if (flow_sidx_valid(sidx)) {
+ flow_sidx_t tosidx = flow_sidx_opposite(sidx);
+ const struct flowside *toside = flowside_at_sidx(tosidx);
size_t dlen = rc;
- if (pif_is_socket(pif_at_sidx(sidx))) {
+ if (pif_is_socket(pif_at_sidx(tosidx))) {
/* XXX Is there any way to propagate ICMPs from socket
* to socket? */
} else if (hdr->cmsg_level == IPPROTO_IP) {
@@ -554,21 +554,21 @@ 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
+ * @s: Socket to receive errors from
+ * @sidx: Flow and side of @s, or FLOW_SIDX_NONE if unknown
*
* 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)
+static int udp_sock_errs(const struct ctx *c, int s, flow_sidx_t sidx)
{
unsigned n_err = 0;
socklen_t errlen;
- int s = ref.fd;
int rc, err;
ASSERT(!c->no_udp);
/* Empty the error queue */
- while ((rc = udp_sock_recverr(c, ref)) > 0)
+ while ((rc = udp_sock_recverr(c, s, sidx)) > 0)
n_err += rc;
if (rc < 0)
@@ -777,7 +777,7 @@ void udp_listen_sock_handler(const struct ctx *c,
const struct timespec *now)
{
if (events & EPOLLERR) {
- if (udp_sock_errs(c, ref) < 0) {
+ if (udp_sock_errs(c, ref.fd, FLOW_SIDX_NONE) < 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? */
@@ -804,7 +804,7 @@ void udp_sock_handler(const struct ctx *c, union epoll_ref ref,
ASSERT(!c->no_udp && uflow);
if (events & EPOLLERR) {
- if (udp_sock_errs(c, ref) < 0) {
+ if (udp_sock_errs(c, ref.fd, ref.flowside) < 0) {
flow_err(uflow, "Unrecoverable error on flow socket");
goto fail;
}
--
2.49.0
next prev parent reply other threads:[~2025-04-15 7:16 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-15 7:16 [PATCH 0/7] Assorted fixes for UDP socket and error handling problems David Gibson
2025-04-15 7:16 ` [PATCH 1/7] udp: Fix breakage of UDP error handling by PKTINFO support David Gibson
2025-04-15 7:16 ` [PATCH 2/7] udp: Be quieter about errors on UDP receive David Gibson
2025-04-15 7:16 ` David Gibson [this message]
2025-04-15 7:16 ` [PATCH 4/7] udp: Deal with errors as we go in udp_sock_fwd() David Gibson
2025-04-15 7:16 ` [PATCH 5/7] udp: Add udp_pktinfo() helper David Gibson
2025-04-15 18:54 ` Stefano Brivio
2025-04-16 0:37 ` David Gibson
2025-04-15 7:16 ` [PATCH 6/7] udp: Minor re-organisation of udp_sock_recverr() David Gibson
2025-04-15 7:16 ` [PATCH 7/7] udp: Propagate errors on listening and brand new sockets David Gibson
2025-04-15 18:54 ` Stefano Brivio
2025-04-16 0:38 ` David Gibson
2025-04-15 19:10 ` [PATCH 0/7] Assorted fixes for UDP socket and error handling problems Stefano Brivio
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250415071624.2618589-4-david@gibson.dropbear.id.au \
--to=david@gibson.dropbear.id.au \
--cc=jmaloy@redhat.com \
--cc=passt-dev@passt.top \
--cc=sbrivio@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).