The idx field of a virtqueue available ring is increased by the driver regardless of the ring size. It is for the device to mask this index modulo the ring size (2.7.6 of the virtio 1.3 specification). The same applies to the used ring.
Failing to mask triggers: - crashes when popping message received on the cvq, - system lockups (in the case of VDUSE) when the virtio-net driver waits infinitely, Fixes: 474f4d7840ad ("vhost: add control virtqueue") Cc: sta...@dpdk.org Signed-off-by: David Marchand <david.march...@redhat.com> --- lib/vhost/virtio_net_ctrl.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/lib/vhost/virtio_net_ctrl.c b/lib/vhost/virtio_net_ctrl.c index 999e84db7c..63c0a06b4f 100644 --- a/lib/vhost/virtio_net_ctrl.c +++ b/lib/vhost/virtio_net_ctrl.c @@ -40,7 +40,7 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq, return 0; } - desc_idx = cvq->avail->ring[cvq->last_avail_idx]; + desc_idx = cvq->avail->ring[cvq->last_avail_idx & (cvq->size - 1)]; if (desc_idx >= cvq->size) { VHOST_CONFIG_LOG(dev->ifname, ERR, "Out of range desc index, dropping"); goto err; @@ -167,8 +167,6 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq, } cvq->last_avail_idx++; - if (cvq->last_avail_idx >= cvq->size) - cvq->last_avail_idx -= cvq->size; vhost_virtqueue_reconnect_log_split(cvq); if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX)) @@ -180,8 +178,6 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq, free(ctrl_elem->ctrl_req); err: cvq->last_avail_idx++; - if (cvq->last_avail_idx >= cvq->size) - cvq->last_avail_idx -= cvq->size; vhost_virtqueue_reconnect_log_split(cvq); if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX)) @@ -231,13 +227,11 @@ virtio_net_ctrl_push(struct virtio_net *dev, struct virtio_net_ctrl_elem *ctrl_e struct vhost_virtqueue *cvq = dev->cvq; struct vring_used_elem *used_elem; - used_elem = &cvq->used->ring[cvq->last_used_idx]; + used_elem = &cvq->used->ring[cvq->last_used_idx & (cvq->size - 1)]; used_elem->id = ctrl_elem->head_idx; used_elem->len = ctrl_elem->n_descs; cvq->last_used_idx++; - if (cvq->last_used_idx >= cvq->size) - cvq->last_used_idx -= cvq->size; rte_atomic_store_explicit((unsigned short __rte_atomic *)&cvq->used->idx, cvq->last_used_idx, rte_memory_order_release); -- 2.48.1