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=202602 header.b=nkwGtwzm; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 4C2A55A0262 for ; Mon, 09 Mar 2026 10:50:41 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1773049838; bh=JVRVpck0FGulbkD9w8lol10HwSLCacfxKLLxLtTvnMU=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=nkwGtwzmyuQp9tFYfXFHRmYs3C2qZ1dkYNMufPHP2dqAjoGrPNETK/AtM2CLGh6YS n3n5USMZJTu/1PR1qRuLTPeSJkSZxQqj/HnWN+5z1uxXMZOcrC+6SqhDyS1W1ZyTvj e6m9ZMcKqNK18STM3ZsshzH5l486XPwxW3nKviz6dsJPhb1GV0Ih20dQMtwXz2mltp 4WBgZZozDSJxJr67AHyCnHjHUuvfaISB+BczWphOcnuL44m54Pi6S+aFxE/Zr8EG1u 4AR4bssFfdAf7SSsJ8nWoaCFtMBwShZvVqinRVRU3tSqFfJeCqMWx4X2CweQHRneJj lL/HsYloOOYyQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fTshG0KMmz4wRH; Mon, 09 Mar 2026 20:50:38 +1100 (AEDT) Date: Mon, 9 Mar 2026 20:50:25 +1100 From: David Gibson To: Laurent Vivier Subject: Re: [PATCH v4] iov: Add iov_truncate() helper and use it in vu handlers Message-ID: References: <20260306115119.1589020-1-lvivier@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="JF6PZDzIJRaxH4au" Content-Disposition: inline In-Reply-To: <20260306115119.1589020-1-lvivier@redhat.com> Message-ID-Hash: 26W6R45G4LQIYELSYZFPGRPFQB2OPMBC X-Message-ID-Hash: 26W6R45G4LQIYELSYZFPGRPFQB2OPMBC 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: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --JF6PZDzIJRaxH4au Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Mar 06, 2026 at 12:51:19PM +0100, Laurent Vivier wrote: > Add a generic iov_truncate() function that truncates an IO vector to a > given number of bytes, returning the number of iov entries that contain > data after truncation. >=20 > Use it in udp_vu_sock_recv() and tcp_vu_sock_recv() to replace the > open-coded truncation logic that adjusted iov entries after recvmsg(). > Also convert the direct iov_len assignment in tcp_vu_send_flag() to use > iov_truncate() for consistency. >=20 > Add an ASSERT() in tcp_vu_data_from_sock() to quiet the Coverity error: >=20 > passt/tcp_vu.c:457:3: > 19. overflow_const: Expression "dlen + hdrlen", where "dlen" is known to > be equal to -86, and "hdrlen" is known to be equal to 86, underflo= ws > the type of "dlen + hdrlen", which is type "unsigned long". >=20 > Signed-off-by: Laurent Vivier Reviewed-by: David Gibson > --- >=20 > Notes: > v4: add ASSERT() to quiet the Coverity error > v3: use in tcp_vu_send_flag() too > v2: use iov_truncate() in udp_vu_sock_recv() too >=20 > iov.c | 22 ++++++++++++++++++++++ > iov.h | 1 + > tcp_vu.c | 20 ++++++++------------ > udp_vu.c | 12 +++--------- > 4 files changed, 34 insertions(+), 21 deletions(-) >=20 > diff --git a/iov.c b/iov.c > index ad726daa4cd8..31a3f5bc29e5 100644 > --- a/iov.c > +++ b/iov.c > @@ -147,6 +147,28 @@ size_t iov_size(const struct iovec *iov, size_t iov_= cnt) > return len; > } > =20 > +/** > + * iov_truncate() - Truncate an IO vector to a given number of bytes > + * @iov: IO vector (modified) > + * @iov_cnt: Number of entries in @iov > + * @size: Total number of bytes to keep > + * > + * Return: number of iov entries that contain data after truncation > + */ > +size_t iov_truncate(struct iovec *iov, size_t iov_cnt, size_t size) > +{ > + size_t i, offset; > + > + i =3D iov_skip_bytes(iov, iov_cnt, size, &offset); > + > + if (i < iov_cnt) { > + iov[i].iov_len =3D offset; > + i +=3D !!offset; > + } > + > + return i; > +} > + > /** > * iov_tail_prune() - Remove any unneeded buffers from an IOV tail > * @tail: IO vector tail (modified) > diff --git a/iov.h b/iov.h > index d1ab91a94e22..b4e50b0fca5a 100644 > --- a/iov.h > +++ b/iov.h > @@ -29,6 +29,7 @@ size_t iov_from_buf(const struct iovec *iov, size_t iov= _cnt, > size_t iov_to_buf(const struct iovec *iov, size_t iov_cnt, > size_t offset, void *buf, size_t bytes); > size_t iov_size(const struct iovec *iov, size_t iov_cnt); > +size_t iov_truncate(struct iovec *iov, size_t iov_cnt, size_t size); > =20 > /* > * DOC: Theory of Operation, struct iov_tail > diff --git a/tcp_vu.c b/tcp_vu.c > index 88be232dca66..fd734e857b3b 100644 > --- a/tcp_vu.c > +++ b/tcp_vu.c > @@ -131,7 +131,7 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_= tap_conn *conn, int flags) > return ret; > } > =20 > - flags_elem[0].in_sg[0].iov_len =3D hdrlen + optlen; > + iov_truncate(&flags_iov[0], 1, hdrlen + optlen); > payload =3D IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen); > =20 > if (flags & KEEPALIVE) > @@ -192,9 +192,9 @@ static ssize_t tcp_vu_sock_recv(const struct ctx *c, = struct vu_virtq *vq, > struct msghdr mh_sock =3D { 0 }; > uint16_t mss =3D MSS_GET(conn); > int s =3D conn->sock; > - ssize_t ret, len; > size_t hdrlen; > int elem_cnt; > + ssize_t ret; > int i; > =20 > *iov_cnt =3D 0; > @@ -247,15 +247,7 @@ static ssize_t tcp_vu_sock_recv(const struct ctx *c,= struct vu_virtq *vq, > ret -=3D already_sent; > =20 > /* adjust iov number and length of the last iov */ > - len =3D ret; > - for (i =3D 0; len && i < elem_cnt; i++) { > - struct iovec *iov =3D &elem[i].in_sg[0]; > - > - if (iov->iov_len > (size_t)len) > - iov->iov_len =3D len; > - > - len -=3D iov->iov_len; > - } > + i =3D iov_truncate(&iov_vu[DISCARD_IOV_NUM], elem_cnt, ret); > =20 > /* adjust head count */ > while (*head_cnt > 0 && head[*head_cnt - 1] >=3D i) > @@ -448,10 +440,14 @@ int tcp_vu_data_from_sock(const struct ctx *c, stru= ct tcp_tap_conn *conn) > for (i =3D 0, previous_dlen =3D -1, check =3D NULL; i < head_cnt; i++) { > struct iovec *iov =3D &elem[head[i]].in_sg[0]; > int buf_cnt =3D head[i + 1] - head[i]; > - ssize_t dlen =3D iov_size(iov, buf_cnt) - hdrlen; > + size_t frame_size =3D iov_size(iov, buf_cnt); > bool push =3D i =3D=3D head_cnt - 1; > + ssize_t dlen; > size_t l2len; > =20 > + ASSERT(frame_size >=3D hdrlen); > + > + dlen =3D frame_size - hdrlen; > vu_set_vnethdr(iov->iov_base, buf_cnt); > =20 > /* The IPv4 header checksum varies only with dlen */ > diff --git a/udp_vu.c b/udp_vu.c > index 3520f89e5671..5effca777e0a 100644 > --- a/udp_vu.c > +++ b/udp_vu.c > @@ -71,9 +71,9 @@ static int udp_vu_sock_recv(const struct ctx *c, struct= vu_virtq *vq, int s, > bool v6, ssize_t *dlen) > { > const struct vu_dev *vdev =3D c->vdev; > - int iov_cnt, idx, iov_used; > - size_t off, hdrlen, l2len; > struct msghdr msg =3D { 0 }; > + int iov_cnt, iov_used; > + size_t hdrlen, l2len; > =20 > ASSERT(!c->no_udp); > =20 > @@ -115,13 +115,7 @@ static int udp_vu_sock_recv(const struct ctx *c, str= uct vu_virtq *vq, int s, > iov_vu[0].iov_base =3D (char *)iov_vu[0].iov_base - hdrlen; > iov_vu[0].iov_len +=3D hdrlen; > =20 > - /* count the numbers of buffer filled by recvmsg() */ > - idx =3D iov_skip_bytes(iov_vu, iov_cnt, *dlen + hdrlen, &off); > - > - /* adjust last iov length */ > - if (idx < iov_cnt) > - iov_vu[idx].iov_len =3D off; > - iov_used =3D idx + !!off; > + iov_used =3D iov_truncate(iov_vu, iov_cnt, *dlen + hdrlen); > =20 > /* pad frame to 60 bytes: first buffer is at least ETH_ZLEN long */ > l2len =3D *dlen + hdrlen - VNET_HLEN; > --=20 > 2.53.0 >=20 --=20 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 --JF6PZDzIJRaxH4au Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmmul+AACgkQzQJF27ox 2GfXNg//Ybf14pmWwtDecIfh3nW2AZDgu0rcTs59Rz94DssOYI7m6UmuoyR5joqr l5xq810zELNKPVzppX+bkYRJeIb0nLSkzMwjJD04FABuQR+wpZ9cnt2ZwdV/IvKV wEV9vC+fLxjZg540qftJbUESHVYvIhxMun5JrceCIapvOdr6ocKHz2Aj+3685xpb TvKZCkyjee9xRMxIdxiSRfdDwrNs+nw8sbjii6itLLJ+t50QLHsCw7HRv6yFH/NA cYr3Ljh5W4UbNOMJttESO4vQrCApjQRoURfDzaUmeIuwaOuSIQa9TrHtzpLthmZ5 n7TyJrOu8gFHbvV40G0nRIlHwQdNQTIqEW4wbjTziSwqnReTPKaMFnVlTlAOAkY6 8sdyT+w/Qof3ORN9bnUk/ZXQVhqz/WoHNy8NsjUAtxnzXegULImTE5XHIs6TqQ2K 1k56hDq1yYDRQzDrwfnMPJQkN3kJHJzVcOMEJ1nO6f/kYWe+oIWf27dGHp46ozbw sp58U58YvtKUu/HlnhgXPqzldvujUZEIuwxv4uSLy9W09Ri02wFePxK2VLB9K6Z7 N1GeyqzjTuk3Hxqo+2F0CLqe5kpU7Qp/HV1ItjpRluhWPrj+JDVktu5a+LfBhsOX Tj49PXOS+FMWHf+bJ48POifW6r6svpPCV5BvLKaDIHrh+bPfAik= =OOfk -----END PGP SIGNATURE----- --JF6PZDzIJRaxH4au--