From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202502 header.b=ErHsEhmo; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 462375A026F for <passt-dev@passt.top>; Wed, 26 Mar 2025 04:44:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202502; t=1742960649; bh=jUZ6kBnz1NAW8zsjyvB7MHktZzsNQQtQnMJRXonVsGs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ErHsEhmoCx4WgAZ5t/IOGBby7c4SVD4iDkxr+bqLI7N8RicgJaNKwUGryvr3J1QDO AIvcDlDUHf3hdPR9AOfKJkd3lwTNQI4h3o86uo7L++wj36Py+j8fO1Wqe3GYLip23p STdv+rz9YrBk+c6EUAU40hwMDehW4nDRsdOlVgVSntDsKOfnff2Jl1HdgJtf4I125u 32LDuA2pQ4VwvY0pPL9pcNnAbWciN4DzewL8sh5xLss4fLbXPSgoTlaHiGusAGDyRU PVTW4P0oawHi3uxRVyfgmovmDZpsxRmFN2N/JS5MKia3B6rbn6B9LeKiJCiev1a3K5 zy8hjbDea8yGQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4ZMt215KxCz4x4d; Wed, 26 Mar 2025 14:44:09 +1100 (AEDT) From: David Gibson <david@gibson.dropbear.id.au> To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com> Subject: [PATCH v2 2/7] udp: Simplify checking of epoll event bits Date: Wed, 26 Mar 2025 14:44:02 +1100 Message-ID: <20250326034407.2240846-3-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250326034407.2240846-1-david@gibson.dropbear.id.au> References: <20250326034407.2240846-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 2ADYRUHMCESMSOMNUK2VSYFS5XYY32KE X-Message-ID-Hash: 2ADYRUHMCESMSOMNUK2VSYFS5XYY32KE X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson <david@gibson.dropbear.id.au> X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt <passt-dev.passt.top> Archived-At: <https://archives.passt.top/passt-dev/20250326034407.2240846-3-david@gibson.dropbear.id.au/> Archived-At: <https://passt.top/hyperkitty/list/passt-dev@passt.top/message/2ADYRUHMCESMSOMNUK2VSYFS5XYY32KE/> List-Archive: <https://archives.passt.top/passt-dev/> List-Archive: <https://passt.top/hyperkitty/list/passt-dev@passt.top/> List-Help: <mailto:passt-dev-request@passt.top?subject=help> List-Owner: <mailto:passt-dev-owner@passt.top> List-Post: <mailto:passt-dev@passt.top> List-Subscribe: <mailto:passt-dev-join@passt.top> List-Unsubscribe: <mailto:passt-dev-leave@passt.top> 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 ca101fec..55021ac4 100644 --- a/udp.c +++ b/udp.c @@ -583,12 +583,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; @@ -597,9 +595,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; @@ -632,15 +627,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 @@ -653,9 +646,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"); @@ -666,22 +656,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, @@ -746,33 +734,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); @@ -782,7 +770,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); @@ -823,19 +811,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 */ -- 2.49.0