Skip to content

Commit

Permalink
vhost: support packed ring in async datapath
Browse files Browse the repository at this point in the history
For now async vhost data path only supports split ring. This patch
enables packed ring in async vhost data path to make async vhost
compatible with virtio 1.1 spec.

Signed-off-by: Cheng Jiang <cheng1.jiang@intel.com>
Reviewed-by: Jiayu Hu <jiayu.hu@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
  • Loading branch information
Cheng Jiang authored and mcoquelin committed May 4, 2021
1 parent 3d6cb86 commit 873e8da
Show file tree
Hide file tree
Showing 5 changed files with 493 additions and 48 deletions.
4 changes: 4 additions & 0 deletions doc/guides/rel_notes/release_21_05.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ New Features

* Added support for preferred busy polling.

* **Added support for vhost async packed ring data path.**

Added packed ring support for async vhost.

* **Added support of multiple data-units in cryptodev API.**

The cryptodev library has been enhanced to allow operations on multiple
Expand Down
1 change: 1 addition & 0 deletions lib/vhost/rte_vhost_async.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ struct rte_vhost_async_channel_ops {
struct async_inflight_info {
struct rte_mbuf *mbuf;
uint16_t descs; /* num of descs inflight */
uint16_t nr_buffers; /* num of buffers inflight for packed ring */
};

/**
Expand Down
79 changes: 57 additions & 22 deletions lib/vhost/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,17 +340,17 @@ cleanup_device(struct virtio_net *dev, int destroy)
static void
vhost_free_async_mem(struct vhost_virtqueue *vq)
{
if (vq->async_pkts_info)
rte_free(vq->async_pkts_info);
if (vq->async_descs_split)
rte_free(vq->async_descs_split);
if (vq->it_pool)
rte_free(vq->it_pool);
if (vq->vec_pool)
rte_free(vq->vec_pool);
rte_free(vq->async_pkts_info);

vq->async_pkts_info = NULL;
rte_free(vq->async_buffers_packed);
vq->async_buffers_packed = NULL;
rte_free(vq->async_descs_split);
vq->async_descs_split = NULL;

rte_free(vq->it_pool);
rte_free(vq->vec_pool);

vq->async_pkts_info = NULL;
vq->it_pool = NULL;
vq->vec_pool = NULL;
}
Expand All @@ -360,10 +360,10 @@ free_vq(struct virtio_net *dev, struct vhost_virtqueue *vq)
{
if (vq_is_packed(dev))
rte_free(vq->shadow_used_packed);
else {
else
rte_free(vq->shadow_used_split);
vhost_free_async_mem(vq);
}

vhost_free_async_mem(vq);
rte_free(vq->batch_copy_elems);
if (vq->iotlb_pool)
rte_mempool_free(vq->iotlb_pool);
Expand Down Expand Up @@ -1626,10 +1626,9 @@ int rte_vhost_async_channel_register(int vid, uint16_t queue_id,
if (unlikely(vq == NULL || !dev->async_copy))
return -1;

/* packed queue is not supported */
if (unlikely(vq_is_packed(dev) || !f.async_inorder)) {
if (unlikely(!f.async_inorder)) {
VHOST_LOG_CONFIG(ERR,
"async copy is not supported on packed queue or non-inorder mode "
"async copy is not supported on non-inorder mode "
"(vid %d, qid: %d)\n", vid, queue_id);
return -1;
}
Expand Down Expand Up @@ -1661,24 +1660,60 @@ int rte_vhost_async_channel_register(int vid, uint16_t queue_id,
vq->async_pkts_info = rte_malloc_socket(NULL,
vq->size * sizeof(struct async_inflight_info),
RTE_CACHE_LINE_SIZE, node);
if (!vq->async_pkts_info) {
vhost_free_async_mem(vq);
VHOST_LOG_CONFIG(ERR,
"async register failed: cannot allocate memory for async_pkts_info "
"(vid %d, qid: %d)\n", vid, queue_id);
goto reg_out;
}

vq->it_pool = rte_malloc_socket(NULL,
VHOST_MAX_ASYNC_IT * sizeof(struct rte_vhost_iov_iter),
RTE_CACHE_LINE_SIZE, node);
if (!vq->it_pool) {
vhost_free_async_mem(vq);
VHOST_LOG_CONFIG(ERR,
"async register failed: cannot allocate memory for it_pool "
"(vid %d, qid: %d)\n", vid, queue_id);
goto reg_out;
}

vq->vec_pool = rte_malloc_socket(NULL,
VHOST_MAX_ASYNC_VEC * sizeof(struct iovec),
RTE_CACHE_LINE_SIZE, node);
vq->async_descs_split = rte_malloc_socket(NULL,
vq->size * sizeof(struct vring_used_elem),
RTE_CACHE_LINE_SIZE, node);
if (!vq->async_descs_split || !vq->async_pkts_info ||
!vq->it_pool || !vq->vec_pool) {
if (!vq->vec_pool) {
vhost_free_async_mem(vq);
VHOST_LOG_CONFIG(ERR,
"async register failed: cannot allocate memory for vq data "
"(vid %d, qid: %d)\n", vid, queue_id);
"async register failed: cannot allocate memory for vec_pool "
"(vid %d, qid: %d)\n", vid, queue_id);
goto reg_out;
}

if (vq_is_packed(dev)) {
vq->async_buffers_packed = rte_malloc_socket(NULL,
vq->size * sizeof(struct vring_used_elem_packed),
RTE_CACHE_LINE_SIZE, node);
if (!vq->async_buffers_packed) {
vhost_free_async_mem(vq);
VHOST_LOG_CONFIG(ERR,
"async register failed: cannot allocate memory for async buffers "
"(vid %d, qid: %d)\n", vid, queue_id);
goto reg_out;
}
} else {
vq->async_descs_split = rte_malloc_socket(NULL,
vq->size * sizeof(struct vring_used_elem),
RTE_CACHE_LINE_SIZE, node);
if (!vq->async_descs_split) {
vhost_free_async_mem(vq);
VHOST_LOG_CONFIG(ERR,
"async register failed: cannot allocate memory for async descs "
"(vid %d, qid: %d)\n", vid, queue_id);
goto reg_out;
}
}

vq->async_ops.check_completed_copies = ops->check_completed_copies;
vq->async_ops.transfer_data = ops->transfer_data;

Expand Down
15 changes: 12 additions & 3 deletions lib/vhost/vhost.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,18 @@ struct vhost_virtqueue {
uint16_t async_pkts_idx;
uint16_t async_pkts_inflight_n;
uint16_t async_last_pkts_n;
struct vring_used_elem *async_descs_split;
uint16_t async_desc_idx;
uint16_t last_async_desc_idx;
union {
struct vring_used_elem *async_descs_split;
struct vring_used_elem_packed *async_buffers_packed;
};
union {
uint16_t async_desc_idx_split;
uint16_t async_buffer_idx_packed;
};
union {
uint16_t last_async_desc_idx_split;
uint16_t last_async_buffer_idx_packed;
};

/* vq async features */
bool async_inorder;
Expand Down
Loading

0 comments on commit 873e8da

Please sign in to comment.