]> git.droids-corp.org - dpdk.git/commitdiff
vhost: add unsafe async API to clear packets
authorCheng Jiang <cheng1.jiang@intel.com>
Fri, 23 Jul 2021 08:09:35 +0000 (08:09 +0000)
committerChenbo Xia <chenbo.xia@intel.com>
Fri, 23 Jul 2021 08:58:53 +0000 (10:58 +0200)
Applications need to stop DMA transfers and finish all the inflight
packets when in VM memory hot-plug case and async vhost is used. This
patch is to provide an unsafe API to clear inflight packets which
are submitted to DMA engine in vhost async data path. Update the
program guide and release notes for virtqueue inflight packets clear
API in vhost lib.

Signed-off-by: Cheng Jiang <cheng1.jiang@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
doc/guides/prog_guide/vhost_lib.rst
doc/guides/rel_notes/release_21_08.rst
lib/vhost/rte_vhost_async.h
lib/vhost/version.map
lib/vhost/virtio_net.c

index 70ce4974df87e440608358a711caf7d0bccb4b29..88740331653e9d515fe5896dce3ecee28a300d9a 100644 (file)
@@ -305,6 +305,11 @@ The following is an overview of some key Vhost API functions:
   This function returns the amount of in-flight packets for the vhost
   queue using async acceleration.
 
+* ``rte_vhost_clear_queue_thread_unsafe(vid, queue_id, **pkts, count)``
+
+  Clear inflight packets which are submitted to DMA engine in vhost async data
+  path. Completed packets are returned to applications through ``pkts``.
+
 Vhost-user Implementations
 --------------------------
 
index eba3d50a6a66776f5220c406602dd21eeecd0593..9904a0e390ff58c069eacf30e6c4d4e0122ffb72 100644 (file)
@@ -116,6 +116,11 @@ New Features
 
   * Added COUNT action support for SN1000 NICs
 
+* **Added inflight packets clear API in vhost library.**
+
+  Added an API which can clear the inflight packets submitted to DMA
+  engine in vhost async data path.
+
 * **Updated Intel QuickAssist crypto PMD.**
 
   Added fourth generation of QuickAssist Technology(QAT) devices support.
index 02d012ae23d0e0347043742e313116e89fd4c421..b25ff446f7497b5f2a581b23543827e2405d52d3 100644 (file)
@@ -246,4 +246,26 @@ uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
 __rte_experimental
 int rte_vhost_async_get_inflight(int vid, uint16_t queue_id);
 
+/**
+ * This function checks async completion status and clear packets for
+ * a specific vhost device queue. Packets which are inflight will be
+ * returned in an array.
+ *
+ * @note This function does not perform any locking
+ *
+ * @param vid
+ *  ID of vhost device to clear data
+ * @param queue_id
+ *  Queue id to clear data
+ * @param pkts
+ *  Blank array to get return packet pointer
+ * @param count
+ *  Size of the packet array
+ * @return
+ *  Number of packets returned
+ */
+__rte_experimental
+uint16_t rte_vhost_clear_queue_thread_unsafe(int vid, uint16_t queue_id,
+               struct rte_mbuf **pkts, uint16_t count);
+
 #endif /* _RTE_VHOST_ASYNC_H_ */
index e0c89646e85ff7bd8ae1bdc2e0b3f0e9d79b657c..e2504ba65757920d946a33fa97af31ae5494c456 100644 (file)
@@ -84,4 +84,5 @@ EXPERIMENTAL {
        rte_vhost_async_get_inflight;
        rte_vhost_async_channel_register_thread_unsafe;
        rte_vhost_async_channel_unregister_thread_unsafe;
+       rte_vhost_clear_queue_thread_unsafe;
 };
index 3ab5229f76daf38635c34706f5ba270e8c942bb4..8549afbbe1a97d0e45dcb48f08332a3b7f2e4436 100644 (file)
@@ -2214,10 +2214,10 @@ write_back_completed_descs_packed(struct vhost_virtqueue *vq,
        } while (nr_left > 0);
 }
 
-uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
+static __rte_always_inline uint16_t
+vhost_poll_enqueue_completed(struct virtio_net *dev, uint16_t queue_id,
                struct rte_mbuf **pkts, uint16_t count)
 {
-       struct virtio_net *dev = get_device(vid);
        struct vhost_virtqueue *vq;
        uint16_t n_pkts_cpl = 0, n_pkts_put = 0, n_descs = 0, n_buffers = 0;
        uint16_t start_idx, pkts_idx, vq_size;
@@ -2225,26 +2225,8 @@ uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
        uint16_t from, i;
        int32_t n_cpl;
 
-       if (!dev)
-               return 0;
-
-       VHOST_LOG_DATA(DEBUG, "(%d) %s\n", dev->vid, __func__);
-       if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
-               VHOST_LOG_DATA(ERR, "(%d) %s: invalid virtqueue idx %d.\n",
-                       dev->vid, __func__, queue_id);
-               return 0;
-       }
-
        vq = dev->virtqueue[queue_id];
 
-       if (unlikely(!vq->async_registered)) {
-               VHOST_LOG_DATA(ERR, "(%d) %s: async not registered for queue id %d.\n",
-                       dev->vid, __func__, queue_id);
-               return 0;
-       }
-
-       rte_spinlock_lock(&vq->access_lock);
-
        pkts_idx = vq->async_pkts_idx % vq->size;
        pkts_info = vq->async_pkts_info;
        vq_size = vq->size;
@@ -2252,7 +2234,7 @@ uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
                vq_size, vq->async_pkts_inflight_n);
 
        if (count > vq->async_last_pkts_n) {
-               n_cpl = vq->async_ops.check_completed_copies(vid,
+               n_cpl = vq->async_ops.check_completed_copies(dev->vid,
                        queue_id, 0, count - vq->async_last_pkts_n);
                if (n_cpl >= 0) {
                        n_pkts_cpl = n_cpl;
@@ -2268,7 +2250,7 @@ uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
        n_pkts_put = RTE_MIN(count, n_pkts_cpl);
        if (unlikely(n_pkts_put == 0)) {
                vq->async_last_pkts_n = n_pkts_cpl;
-               goto done;
+               return 0;
        }
 
        if (vq_is_packed(dev)) {
@@ -2310,10 +2292,73 @@ uint16_t rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
                }
        }
 
-done:
+       return n_pkts_put;
+}
+
+uint16_t
+rte_vhost_poll_enqueue_completed(int vid, uint16_t queue_id,
+               struct rte_mbuf **pkts, uint16_t count)
+{
+       struct virtio_net *dev = get_device(vid);
+       struct vhost_virtqueue *vq;
+       uint16_t n_pkts_cpl = 0;
+
+       if (!dev)
+               return 0;
+
+       VHOST_LOG_DATA(DEBUG, "(%d) %s\n", dev->vid, __func__);
+       if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
+               VHOST_LOG_DATA(ERR, "(%d) %s: invalid virtqueue idx %d.\n",
+                       dev->vid, __func__, queue_id);
+               return 0;
+       }
+
+       vq = dev->virtqueue[queue_id];
+
+       if (unlikely(!vq->async_registered)) {
+               VHOST_LOG_DATA(ERR, "(%d) %s: async not registered for queue id %d.\n",
+                       dev->vid, __func__, queue_id);
+               return 0;
+       }
+
+       rte_spinlock_lock(&vq->access_lock);
+
+       n_pkts_cpl = vhost_poll_enqueue_completed(dev, queue_id, pkts, count);
+
        rte_spinlock_unlock(&vq->access_lock);
 
-       return n_pkts_put;
+       return n_pkts_cpl;
+}
+
+uint16_t
+rte_vhost_clear_queue_thread_unsafe(int vid, uint16_t queue_id,
+               struct rte_mbuf **pkts, uint16_t count)
+{
+       struct virtio_net *dev = get_device(vid);
+       struct vhost_virtqueue *vq;
+       uint16_t n_pkts_cpl = 0;
+
+       if (!dev)
+               return 0;
+
+       VHOST_LOG_DATA(DEBUG, "(%d) %s\n", dev->vid, __func__);
+       if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
+               VHOST_LOG_DATA(ERR, "(%d) %s: invalid virtqueue idx %d.\n",
+                       dev->vid, __func__, queue_id);
+               return 0;
+       }
+
+       vq = dev->virtqueue[queue_id];
+
+       if (unlikely(!vq->async_registered)) {
+               VHOST_LOG_DATA(ERR, "(%d) %s: async not registered for queue id %d.\n",
+                       dev->vid, __func__, queue_id);
+               return 0;
+       }
+
+       n_pkts_cpl = vhost_poll_enqueue_completed(dev, queue_id, pkts, count);
+
+       return n_pkts_cpl;
 }
 
 static __rte_always_inline uint32_t