On 11/3/25 11:16, Stefano Brivio wrote:
...instead of copying, from the input buffer, the amount of available bytes in the buffer provided via vhost-user.
The existing behaviour should be harmless due to the fact that we don't request overly large buffers from vhost-user, but it doesn't look correct to me.
I don't understand where is the problem. I think the existing behaviour is correct because the iov array is padded to size in vu_collect() by: if (iov->iov_len > size - current_size) iov->iov_len = size - current_size; total can be lesser than size but in this case we exit. So total should be equal to input size + sizeof(struct virtio_net_hdr_mrg_rxbuf). And in iov_from_buf() we copy the content of the buffer according the available room in the iovec and the size of the input buffer. Thanks, Laurent>
Signed-off-by: Stefano Brivio
--- vu_common.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/vu_common.c b/vu_common.c index b13b7c3..21cfb2a 100644 --- a/vu_common.c +++ b/vu_common.c @@ -238,7 +238,7 @@ void vu_kick_cb(struct vu_dev *vdev, union epoll_ref ref, * vu_send_single() - Send a buffer to the front-end using the RX virtqueue * @c: execution context * @buf: address of the buffer - * @size: size of the buffer + * @size: size of the input buffer * * Return: number of bytes sent, -1 if there is an error */ @@ -248,7 +248,7 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size) struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE]; struct vu_virtq_element elem[VIRTQUEUE_MAX_SIZE]; struct iovec in_sg[VIRTQUEUE_MAX_SIZE]; - size_t total; + size_t vu_buf_size; int elem_cnt; int i;
@@ -261,21 +261,20 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size)
vu_init_elem(elem, in_sg, VIRTQUEUE_MAX_SIZE);
- size += sizeof(struct virtio_net_hdr_mrg_rxbuf); - elem_cnt = vu_collect(vdev, vq, elem, VIRTQUEUE_MAX_SIZE, size, &total); - if (total < size) { + elem_cnt = vu_collect(vdev, vq, elem, VIRTQUEUE_MAX_SIZE, + size + sizeof(struct virtio_net_hdr_mrg_rxbuf), + &vu_buf_size); + if (vu_buf_size < size + sizeof(struct virtio_net_hdr_mrg_rxbuf)) { debug("vu_send_single: no space to send the data " - "elem_cnt %d size %zd", elem_cnt, total); + "elem_cnt %d size %zd", elem_cnt, size); goto err; }
vu_set_vnethdr(vdev, in_sg[0].iov_base, elem_cnt);
- total -= sizeof(struct virtio_net_hdr_mrg_rxbuf); - /* copy data from the buffer to the iovec */ iov_from_buf(in_sg, elem_cnt, sizeof(struct virtio_net_hdr_mrg_rxbuf), - buf, total); + buf, size);
if (*c->pcap) { pcap_iov(in_sg, elem_cnt, @@ -284,9 +283,10 @@ int vu_send_single(const struct ctx *c, const void *buf, size_t size)
vu_flush(vdev, vq, elem, elem_cnt);
- trace("vhost-user sent %zu", total); + trace("vhost-user sent %zu", + vu_buf_size - sizeof(struct virtio_net_hdr_mrg_rxbuf));
- return total; + return size; err: for (i = 0; i < elem_cnt; i++) vu_queue_detach_element(vq);