From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=PzS3kRQ8; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTPS id 35AA65A026E for ; Fri, 03 Apr 2026 08:20:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1775197248; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ahnJ2yPYXWTE6SLzL6R4uO4dsUit8jBYq+Dw8rtSZR0=; b=PzS3kRQ8fpOu/TXyDWL9wrP33GZ6X8tQFpJyLfFQuIwGQUuiTn1APueTVNXfLKz54IYshw /IrOFgDv49ZBqQAmL2YBJmEfQrlDcw+zy18ro0UpemvSD6yrAd1Fa66jcPQkP8Ng5Dts9v qb2kXtHPVAGy3vpgwnFCFMNlnuA5klE= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-520-zMDmerHtObyYCALZD2r2rQ-1; Fri, 03 Apr 2026 02:20:47 -0400 X-MC-Unique: zMDmerHtObyYCALZD2r2rQ-1 X-Mimecast-MFC-AGG-ID: zMDmerHtObyYCALZD2r2rQ_1775197246 Received: by mail-wr1-f71.google.com with SMTP id ffacd0b85a97d-43ba02dc34bso1537208f8f.1 for ; Thu, 02 Apr 2026 23:20:46 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775197245; x=1775802045; h=date:content-transfer-encoding:mime-version:organization:references :in-reply-to:message-id:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ahnJ2yPYXWTE6SLzL6R4uO4dsUit8jBYq+Dw8rtSZR0=; b=PooiXND18ZkxYLcCBYhYh7Bglog6O131ckv9tW+w1G9pVbcJAFjU7Ol+X8CPClyPn3 eQ0Mh+iYnzA7WxolfvPBS/Wf0ng5mGz3Iipb9YFsBrImpXkBCJu2SdaeQI7iZdcqpg2E ywU7CFL+L2UqBfIs+Q1KaKNYKD9Zm9NPc9JgRpuYUH2YhScbihMFn7+memLWXnJ8CrRx AWo9Tm94ffQ97H6cBRgLiSIPZgw7yGrRDg3ZpxAI93CJGM97C+bkxbR34ITMZ9vcri99 4GTcMxppcavqPgfv/SpvW5/WNSpun6TBBYpQGCW2LpMKkAEHjpMAdRxMES4UtZ68oZ9b e7aw== X-Gm-Message-State: AOJu0Yxy64TEw+k/WdeXB/GZl05DNKIsfCApkJYfWgUVdSnTdUb2EYxf Jkhn6d4lqYlaPXeyoOPwx/CDExTvqmKgMm2enjz4Yav8JnaXfxT/aqyhHyie0JidickJvEkBDKb 48hf6G8uVgvLwIANaupWn2Ud8b6x9AdAvPHIlSzdeqbHbHa8orcDPVF5b7WoHXdGORf+d8CshNn YaxgRD2K7d1+4m+91TKOOhHTTL7KBXSAtv+wJG X-Gm-Gg: AeBDieuFv8s9PECIq58MXS9X4fgBh978ZerEokjcBcaG3mGgOU1B+gqdcoK+0i32Zx9 bca02qeNvgxpjGFbhZlieRaMJ5RODOkQ2gv/Gk9BsLzXLj8y6C1hNg9R3TSYKjsmU8SdRu1OvXT UdoFifB9zOmfIrB6P/K6mTwwzqpKgMbOT5tFQNB5j/89U6HhpD/lTnZUxvwks5kE24tO3rK1O65 /74eolYDW7SouuAz/to6whp1QCLjaROV5j/NrTvjBggkNA6qd6j8MU27CRrxaRrStv7S3sMfX6R XLmWV9ScnDbGaXxeKMYaGv8sySVltHhEhtijerGL/D4WcnI/ObOjb7Eh8Q7u/25dZ3ndDHad0DV QN/DIBKgWAy7tKDIf7Agyd5K9yV9W0AnC X-Received: by 2002:a5d:5f86:0:b0:43d:61d:382d with SMTP id ffacd0b85a97d-43d292a901cmr2585644f8f.22.1775197244943; Thu, 02 Apr 2026 23:20:44 -0700 (PDT) X-Received: by 2002:a5d:5f86:0:b0:43d:61d:382d with SMTP id ffacd0b85a97d-43d292a901cmr2585601f8f.22.1775197244423; Thu, 02 Apr 2026 23:20:44 -0700 (PDT) Received: from maya.myfinge.rs (ifcgrfdd.trafficplex.cloud. [2a10:fc81:a806:d6a9::1]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43d1e4d27a8sm14448475f8f.17.2026.04.02.23.20.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 02 Apr 2026 23:20:43 -0700 (PDT) From: Stefano Brivio To: Laurent Vivier Subject: Re: [PATCH 08/10] vu_common: Pass explicit frame length to vu_flush() Message-ID: <20260403082042.624f7ecb@elisabeth> In-Reply-To: <20260401191826.1782394-9-lvivier@redhat.com> References: <20260401191826.1782394-1-lvivier@redhat.com> <20260401191826.1782394-9-lvivier@redhat.com> Organization: Red Hat X-Mailer: Claws Mail 4.2.0 (GTK 3.24.49; x86_64-pc-linux-gnu) MIME-Version: 1.0 Date: Fri, 03 Apr 2026 08:20:43 +0200 (CEST) X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 7_SFBdy0ojzd_JNmEhrOv5oaF-B-nEtxQZ9aIDBEVqU_1775197246 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Message-ID-Hash: SRZ2BAMMYOBJ63TG7LIKYQ3FU5ZQ7ZOB X-Message-ID-Hash: SRZ2BAMMYOBJ63TG7LIKYQ3FU5ZQ7ZOB X-MailFrom: sbrivio@redhat.com 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: On Wed, 1 Apr 2026 21:18:24 +0200 Laurent Vivier wrote: > Currently vu_flush() derives the frame size from the iov, but in > preparation for iov arrays that may be larger than the actual frame, > pass the total length (including vnet header) explicitly so that only > the relevant portion is reported to the virtqueue. > > Ensure a minimum frame size of ETH_ZLEN + VNET_HLEN to handle short > frames. All elements are still flushed to avoid descriptor leaks, > but trailing elements beyond frame_len will report a zero length. > > Signed-off-by: Laurent Vivier > --- > tcp_vu.c | 6 +++--- > udp_vu.c | 2 +- > vu_common.c | 15 ++++++++++++--- > vu_common.h | 2 +- > 4 files changed, 17 insertions(+), 8 deletions(-) > > diff --git a/tcp_vu.c b/tcp_vu.c > index 329fa969fca1..105bca41c6de 100644 > --- a/tcp_vu.c > +++ b/tcp_vu.c > @@ -140,7 +140,7 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags) > l2len = optlen + hdrlen - VNET_HLEN; > vu_pad(&flags_elem[0].in_sg[0], l2len); > > - vu_flush(vdev, vq, flags_elem, 1); > + vu_flush(vdev, vq, flags_elem, 1, hdrlen + optlen); > > if (*c->pcap) > pcap_iov(&flags_elem[0].in_sg[0], 1, VNET_HLEN, > @@ -157,7 +157,7 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags) > flags_elem[0].in_sg[0].iov_base, > flags_elem[0].in_sg[0].iov_len); > > - vu_flush(vdev, vq, &flags_elem[1], 1); > + vu_flush(vdev, vq, &flags_elem[1], 1, hdrlen + optlen); > > if (*c->pcap) > pcap_iov(&flags_elem[1].in_sg[0], 1, VNET_HLEN, > @@ -463,7 +463,7 @@ int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) > l2len = dlen + hdrlen - VNET_HLEN; > vu_pad(iov, l2len); > > - vu_flush(vdev, vq, &elem[head[i]], buf_cnt); > + vu_flush(vdev, vq, &elem[head[i]], buf_cnt, dlen + hdrlen); > > if (*c->pcap) > pcap_iov(iov, buf_cnt, VNET_HLEN, > diff --git a/udp_vu.c b/udp_vu.c > index 81491afa7e6a..4641f42eb5c4 100644 > --- a/udp_vu.c > +++ b/udp_vu.c > @@ -234,7 +234,7 @@ void udp_vu_sock_to_tap(const struct ctx *c, int s, int n, flow_sidx_t tosidx) > pcap_iov(iov_vu, iov_cnt, VNET_HLEN, > hdrlen + dlen - VNET_HLEN); > } > - vu_flush(vdev, vq, elem, elem_used); > + vu_flush(vdev, vq, elem, elem_used, hdrlen + dlen); > vu_queue_notify(vdev, vq); > } > } > diff --git a/vu_common.c b/vu_common.c > index f254cb67ec78..d371a59a1813 100644 > --- a/vu_common.c > +++ b/vu_common.c > @@ -134,18 +134,27 @@ static void vu_set_vnethdr(struct virtio_net_hdr_mrg_rxbuf *vnethdr, > * @vq: vhost-user virtqueue > * @elem: virtqueue elements array to send back to the virtqueue > * @elem_cnt: Length of the array > + * @frame_len: Total frame length including vnet header > */ > void vu_flush(const struct vu_dev *vdev, struct vu_virtq *vq, > - struct vu_virtq_element *elem, int elem_cnt) > + struct vu_virtq_element *elem, int elem_cnt, size_t frame_len) > { > + size_t len; > int i; > > vu_set_vnethdr(elem[0].in_sg[0].iov_base, elem_cnt); > > + len = MAX(ETH_ZLEN + VNET_HLEN, frame_len); > for (i = 0; i < elem_cnt; i++) { > - size_t elem_size = iov_size(elem[i].in_sg, elem[i].in_num); > + size_t elem_size; > + > + elem_size = iov_size(elem[i].in_sg, elem[i].in_num); > + if (elem_size > len) > + elem_size = len; Convenient, but this doesn't really represent 'elem_size' anymore and it's a bit confusing because we later subtract it from 'len' (at a first glance, it looks like one might underflow it). What about: size_t elem_size, fill_size; elem_size = iov_size(elem[i].in_sg, elem[i].in_num); fill_size = MIN(len, elem_size); vu_queue_fill(vdev, vq, &elem[i], fill_size, i); len -= fill_size; ? > > vu_queue_fill(vdev, vq, &elem[i], elem_size, i); > + > + len -= elem_size; > } Should we now add a debug message or warning here if we happen to have any residual 'len'? Or it can never happen by design? I'm not quite sure. > > vu_queue_flush(vdev, vq, elem_cnt); > @@ -270,7 +279,7 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size) > if (*c->pcap) > pcap_iov(in_sg, in_total, VNET_HLEN, size); > > - vu_flush(vdev, vq, elem, elem_cnt); > + vu_flush(vdev, vq, elem, elem_cnt, VNET_HLEN + size); > vu_queue_notify(vdev, vq); > > trace("vhost-user sent %zu", total); > diff --git a/vu_common.h b/vu_common.h > index 4037ab765b7d..77d1849e6115 100644 > --- a/vu_common.h > +++ b/vu_common.h > @@ -40,7 +40,7 @@ int vu_collect(const struct vu_dev *vdev, struct vu_virtq *vq, > struct iovec *in_sg, size_t max_in_sg, size_t *in_total, > size_t size, size_t *collected); > void vu_flush(const struct vu_dev *vdev, struct vu_virtq *vq, > - struct vu_virtq_element *elem, int elem_cnt); > + struct vu_virtq_element *elem, int elem_cnt, size_t frame_len); > void vu_kick_cb(struct vu_dev *vdev, union epoll_ref ref, > const struct timespec *now); > int vu_send_single(const struct ctx *c, const void *buf, size_t size); -- Stefano