public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Laurent Vivier <lvivier@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: [PATCH v2 05/10] udp_vu: Pass iov explicitly to helpers instead of using file-scoped array
Date: Fri, 10 Apr 2026 16:59:54 +1000	[thread overview]
Message-ID: <adif6hw6lNUGxop9@zatzit> (raw)
In-Reply-To: <20260403163811.3209635-6-lvivier@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 7858 bytes --]

On Fri, Apr 03, 2026 at 06:38:06PM +0200, Laurent Vivier wrote:
> udp_vu_sock_recv(), udp_vu_prepare(), and udp_vu_csum() all operated on
> the file-scoped iov_vu[] array directly.  Pass iov and count as explicit
> parameters instead, and move iov_vu[] and elem[] to function-local
> statics in udp_vu_sock_to_tap(), the only function that needs them.
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>

One cosmetic nit noted.

> ---
>  udp_vu.c | 64 +++++++++++++++++++++++++++++---------------------------
>  1 file changed, 33 insertions(+), 31 deletions(-)
> 
> diff --git a/udp_vu.c b/udp_vu.c
> index 34f39e1256f8..9688fe1fdc5c 100644
> --- a/udp_vu.c
> +++ b/udp_vu.c
> @@ -33,9 +33,6 @@
>  #include "udp_vu.h"
>  #include "vu_common.h"
>  
> -static struct iovec     iov_vu		[VIRTQUEUE_MAX_SIZE];
> -static struct vu_virtq_element	elem		[VIRTQUEUE_MAX_SIZE];
> -
>  /**
>   * udp_vu_hdrlen() - Sum size of all headers, from UDP to virtio-net
>   * @v6:		Set for IPv6 packet
> @@ -58,14 +55,14 @@ static size_t udp_vu_hdrlen(bool v6)
>  
>  /**
>   * udp_vu_sock_recv() - Receive datagrams from socket into vhost-user buffers
> + * @iov:	IO vector for the frame (in/out)
> + * @cnt:	Number of IO vector entries (in/out)

Nit: this new description loses some details about the value of *@cnt
on output.

>   * @s:		Socket to receive from
>   * @v6:		Set for IPv6 connections
> - * @iov_cnt:	Number of collected iov in iov_vu (input)
> - * 		Number of iov entries used to store the datagram (output)
>   *
>   * Return: size of received data, -1 on error
>   */
> -static ssize_t udp_vu_sock_recv(int s, bool v6, size_t *iov_cnt)
> +static ssize_t udp_vu_sock_recv(struct iovec *iov, size_t *cnt, int s, bool v6)
>  {
>  	struct msghdr msg  = { 0 };
>  	size_t hdrlen, l2len;
> @@ -75,27 +72,27 @@ static ssize_t udp_vu_sock_recv(int s, bool v6, size_t *iov_cnt)
>  	hdrlen = udp_vu_hdrlen(v6);
>  
>  	/* reserve space for the headers */
> -	assert(iov_vu[0].iov_len >= MAX(hdrlen, ETH_ZLEN + VNET_HLEN));
> -	iov_vu[0].iov_base = (char *)iov_vu[0].iov_base + hdrlen;
> -	iov_vu[0].iov_len -= hdrlen;
> +	assert(iov[0].iov_len >= MAX(hdrlen, ETH_ZLEN + VNET_HLEN));
> +	iov[0].iov_base = (char *)iov[0].iov_base + hdrlen;
> +	iov[0].iov_len -= hdrlen;
>  
>  	/* read data from the socket */
> -	msg.msg_iov = iov_vu;
> -	msg.msg_iovlen = *iov_cnt;
> +	msg.msg_iov = iov;
> +	msg.msg_iovlen = *cnt;
>  
>  	dlen = recvmsg(s, &msg, 0);
>  	if (dlen < 0)
>  		return -1;
>  
>  	/* restore the pointer to the headers address */
> -	iov_vu[0].iov_base = (char *)iov_vu[0].iov_base - hdrlen;
> -	iov_vu[0].iov_len += hdrlen;
> +	iov[0].iov_base = (char *)iov[0].iov_base - hdrlen;
> +	iov[0].iov_len += hdrlen;
>  
> -	*iov_cnt = iov_truncate(iov_vu, *iov_cnt, dlen + hdrlen);
> +	*cnt = iov_truncate(iov, *cnt, dlen + hdrlen);
>  
>  	/* pad frame to 60 bytes: first buffer is at least ETH_ZLEN long */
>  	l2len = dlen + hdrlen - VNET_HLEN;
> -	vu_pad(&iov_vu[0], l2len);
> +	vu_pad(&iov[0], l2len);
>  
>  	return dlen;
>  }
> @@ -103,27 +100,28 @@ static ssize_t udp_vu_sock_recv(int s, bool v6, size_t *iov_cnt)
>  /**
>   * udp_vu_prepare() - Prepare the packet header
>   * @c:		Execution context
> + * @iov:	IO vector for the frame (including vnet header)
>   * @toside:	Address information for one side of the flow
>   * @dlen:	Packet data length
>   *
>   * Return: Layer-4 length
>   */
> -static size_t udp_vu_prepare(const struct ctx *c,
> +static size_t udp_vu_prepare(const struct ctx *c, const struct iovec *iov,
>  			     const struct flowside *toside, ssize_t dlen)
>  {
>  	struct ethhdr *eh;
>  	size_t l4len;
>  
>  	/* ethernet header */
> -	eh = vu_eth(iov_vu[0].iov_base);
> +	eh = vu_eth(iov[0].iov_base);
>  
>  	memcpy(eh->h_dest, c->guest_mac, sizeof(eh->h_dest));
>  	memcpy(eh->h_source, c->our_tap_mac, sizeof(eh->h_source));
>  
>  	/* initialize header */
>  	if (inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr)) {
> -		struct iphdr *iph = vu_ip(iov_vu[0].iov_base);
> -		struct udp_payload_t *bp = vu_payloadv4(iov_vu[0].iov_base);
> +		struct iphdr *iph = vu_ip(iov[0].iov_base);
> +		struct udp_payload_t *bp = vu_payloadv4(iov[0].iov_base);
>  
>  		eh->h_proto = htons(ETH_P_IP);
>  
> @@ -131,8 +129,8 @@ static size_t udp_vu_prepare(const struct ctx *c,
>  
>  		l4len = udp_update_hdr4(iph, bp, toside, dlen, true);
>  	} else {
> -		struct ipv6hdr *ip6h = vu_ip(iov_vu[0].iov_base);
> -		struct udp_payload_t *bp = vu_payloadv6(iov_vu[0].iov_base);
> +		struct ipv6hdr *ip6h = vu_ip(iov[0].iov_base);
> +		struct udp_payload_t *bp = vu_payloadv6(iov[0].iov_base);
>  
>  		eh->h_proto = htons(ETH_P_IPV6);
>  
> @@ -147,23 +145,25 @@ static size_t udp_vu_prepare(const struct ctx *c,
>  /**
>   * udp_vu_csum() - Calculate and set checksum for a UDP packet
>   * @toside:	Address information for one side of the flow
> - * @iov_used:	Number of used iov_vu items
> + * @iov:	IO vector for the frame
> + * @cnt:	Number of IO vector entries
>   */
> -static void udp_vu_csum(const struct flowside *toside, int iov_used)
> +static void udp_vu_csum(const struct flowside *toside, const struct iovec *iov,
> +			size_t cnt)
>  {
>  	const struct in_addr *src4 = inany_v4(&toside->oaddr);
>  	const struct in_addr *dst4 = inany_v4(&toside->eaddr);
> -	char *base = iov_vu[0].iov_base;
> +	char *base = iov[0].iov_base;
>  	struct udp_payload_t *bp;
>  	struct iov_tail data;
>  
>  	if (src4 && dst4) {
>  		bp = vu_payloadv4(base);
> -		data = IOV_TAIL(iov_vu, iov_used, (char *)&bp->data - base);
> +		data = IOV_TAIL(iov, cnt, (char *)&bp->data - base);
>  		csum_udp4(&bp->uh, *src4, *dst4, &data);
>  	} else {
>  		bp = vu_payloadv6(base);
> -		data = IOV_TAIL(iov_vu, iov_used, (char *)&bp->data - base);
> +		data = IOV_TAIL(iov, cnt, (char *)&bp->data - base);
>  		csum_udp6(&bp->uh, &toside->oaddr.a6, &toside->eaddr.a6, &data);
>  	}
>  }
> @@ -178,7 +178,9 @@ static void udp_vu_csum(const struct flowside *toside, int iov_used)
>  void udp_vu_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx)
>  {
>  	const struct flowside *toside = flowside_at_sidx(tosidx);
> +	static struct vu_virtq_element elem[VIRTQUEUE_MAX_SIZE];
>  	bool v6 = !(inany_v4(&toside->eaddr) && inany_v4(&toside->oaddr));
> +	static struct iovec iov_vu[VIRTQUEUE_MAX_SIZE];
>  	struct vu_dev *vdev = c->vdev;
>  	struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE];
>  	int i;
> @@ -211,9 +213,9 @@ void udp_vu_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx)
>  
>  		assert((size_t)elem_cnt == iov_cnt);	/* one iovec per element */
>  
> -		dlen = udp_vu_sock_recv(s, v6, &iov_cnt);
> +		dlen = udp_vu_sock_recv(iov_vu, &iov_cnt, s, v6);
>  		if (dlen < 0) {
> -			vu_queue_rewind(vq, iov_cnt);
> +			vu_queue_rewind(vq, elem_cnt);
>  			break;
>  		}
>  
> @@ -223,12 +225,12 @@ void udp_vu_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx)
>  		vu_queue_rewind(vq, elem_cnt - elem_used);
>  
>  		if (iov_cnt > 0) {
> -			udp_vu_prepare(c, toside, dlen);
> +			udp_vu_prepare(c, iov_vu, toside, dlen);
>  			if (*c->pcap) {
> -				udp_vu_csum(toside, iov_cnt);
> +				udp_vu_csum(toside, iov_vu, iov_cnt);
>  				pcap_iov(iov_vu, iov_cnt, VNET_HLEN);
>  			}
<> -			vu_flush(vdev, vq, elem, iov_cnt);
> +			vu_flush(vdev, vq, elem, elem_used);
>  			vu_queue_notify(vdev, vq);
>  		}
>  	}
> -- 
> 2.53.0
> 

-- 
David Gibson (he or they)	| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you, not the other way
				| around.
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-04-10  7:00 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-03 16:38 [PATCH v2 00/10] vhost-user: Preparatory series for multiple iovec entries per virtqueue element Laurent Vivier
2026-04-03 16:38 ` [PATCH v2 01/10] iov: Introduce iov_memset() Laurent Vivier
2026-04-03 16:38 ` [PATCH v2 02/10] iov: Add iov_memcpy() to copy data between iovec arrays Laurent Vivier
2026-04-10  6:44   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 03/10] vu_common: Move vnethdr setup into vu_flush() Laurent Vivier
2026-04-10  6:47   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 04/10] udp_vu: Move virtqueue management from udp_vu_sock_recv() to its caller Laurent Vivier
2026-04-10  6:56   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 05/10] udp_vu: Pass iov explicitly to helpers instead of using file-scoped array Laurent Vivier
2026-04-10  6:59   ` David Gibson [this message]
2026-04-03 16:38 ` [PATCH v2 06/10] checksum: Pass explicit L4 length to checksum functions Laurent Vivier
2026-04-10  7:12   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 07/10] pcap: Pass explicit L2 length to pcap_iov() Laurent Vivier
2026-04-10  7:17   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 08/10] vu_common: Pass explicit frame length to vu_flush() Laurent Vivier
2026-04-10  7:21   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 09/10] tcp: Pass explicit data length to tcp_fill_headers() Laurent Vivier
2026-04-10  7:23   ` David Gibson
2026-04-03 16:38 ` [PATCH v2 10/10] vhost-user: Centralise Ethernet frame padding in vu_collect() and vu_pad() Laurent Vivier
2026-04-10  7:28   ` David Gibson

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=adif6hw6lNUGxop9@zatzit \
    --to=david@gibson.dropbear.id.au \
    --cc=lvivier@redhat.com \
    --cc=passt-dev@passt.top \
    /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).