vhost: add a flag to enable dequeue zero copy
authorYuanhan Liu <yuanhan.liu@linux.intel.com>
Sun, 9 Oct 2016 07:27:58 +0000 (15:27 +0800)
committerYuanhan Liu <yuanhan.liu@linux.intel.com>
Thu, 13 Oct 2016 08:29:20 +0000 (10:29 +0200)
Dequeue zero copy is disabled by default. Here add a new flag
``RTE_VHOST_USER_DEQUEUE_ZERO_COPY`` to explictily enable it.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Qian Xu <qian.q.xu@intel.com>
doc/guides/prog_guide/vhost_lib.rst
doc/guides/rel_notes/release_16_11.rst
lib/librte_vhost/rte_virtio_net.h
lib/librte_vhost/socket.c
lib/librte_vhost/vhost.c
lib/librte_vhost/vhost.h

index 6b0c6b2..573a318 100644 (file)
@@ -79,7 +79,7 @@ The following is an overview of the Vhost API functions:
   ``/dev/path`` character device file will be created. For vhost-user server
   mode, a Unix domain socket file ``path`` will be created.
 
   ``/dev/path`` character device file will be created. For vhost-user server
   mode, a Unix domain socket file ``path`` will be created.
 
-  Currently two flags are supported (these are valid for vhost-user only):
+  Currently supported flags are (these are valid for vhost-user only):
 
   - ``RTE_VHOST_USER_CLIENT``
 
 
   - ``RTE_VHOST_USER_CLIENT``
 
@@ -97,6 +97,38 @@ The following is an overview of the Vhost API functions:
     This reconnect option is enabled by default. However, it can be turned off
     by setting this flag.
 
     This reconnect option is enabled by default. However, it can be turned off
     by setting this flag.
 
+  - ``RTE_VHOST_USER_DEQUEUE_ZERO_COPY``
+
+    Dequeue zero copy will be enabled when this flag is set. It is disabled by
+    default.
+
+    There are some truths (including limitations) you might want to know while
+    setting this flag:
+
+    * zero copy is not good for small packets (typically for packet size below
+      512).
+
+    * zero copy is really good for VM2VM case. For iperf between two VMs, the
+      boost could be above 70% (when TSO is enableld).
+
+    * for VM2NIC case, the ``nb_tx_desc`` has to be small enough: <= 64 if virtio
+      indirect feature is not enabled and <= 128 if it is enabled.
+
+      The is because when dequeue zero copy is enabled, guest Tx used vring will
+      be updated only when corresponding mbuf is freed. Thus, the nb_tx_desc
+      has to be small enough so that the PMD driver will run out of available
+      Tx descriptors and free mbufs timely. Otherwise, guest Tx vring would be
+      starved.
+
+    * Guest memory should be backended with huge pages to achieve better
+      performance. Using 1G page size is the best.
+
+      When dequeue zero copy is enabled, the guest phys address and host phys
+      address mapping has to be established. Using non-huge pages means far
+      more page segments. To make it simple, DPDK vhost does a linear search
+      of those segments, thus the fewer the segments, the quicker we will get
+      the mapping. NOTE: we may speed it by using tree searching in future.
+
 * ``rte_vhost_driver_session_start()``
 
   This function starts the vhost session loop to handle vhost messages. It
 * ``rte_vhost_driver_session_start()``
 
   This function starts the vhost session loop to handle vhost messages. It
index 51fc707..98914e3 100644 (file)
@@ -45,6 +45,18 @@ New Features
     in an mbuf chain and retrieve its packet type by software.
   * Added new functions ``rte_get_ptype_*()`` to dump a packet type as a string.
 
     in an mbuf chain and retrieve its packet type by software.
   * Added new functions ``rte_get_ptype_*()`` to dump a packet type as a string.
 
+* **Added vhost-user dequeue zero copy support**
+
+  The copy in dequeue path is saved, which is meant to improve the performance.
+  In the VM2VM case, the boost is quite impressive. The bigger the packet size,
+  the bigger performance boost you may get. However, for VM2NIC case, there
+  are some limitations, yet the boost is not that impressive as VM2VM case.
+  It may even drop quite a bit for small packets.
+
+  For such reason, this feature is disabled by default. It can be enabled when
+  ``RTE_VHOST_USER_DEQUEUE_ZERO_COPY`` flag is given. Check the vhost section
+  at programming guide for more information.
+
 * **Added vhost-user indirect descriptors support.**
 
   If indirect descriptor feature is negotiated, each packet sent by the guest
 * **Added vhost-user indirect descriptors support.**
 
   If indirect descriptor feature is negotiated, each packet sent by the guest
index a88aecd..c53ff64 100644 (file)
@@ -53,6 +53,7 @@
 
 #define RTE_VHOST_USER_CLIENT          (1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT    (1ULL << 1)
 
 #define RTE_VHOST_USER_CLIENT          (1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT    (1ULL << 1)
+#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY       (1ULL << 2)
 
 /* Enum for virtqueue management. */
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
 /* Enum for virtqueue management. */
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
index bf03f84..967cb65 100644 (file)
@@ -62,6 +62,7 @@ struct vhost_user_socket {
        int connfd;
        bool is_server;
        bool reconnect;
        int connfd;
        bool is_server;
        bool reconnect;
+       bool dequeue_zero_copy;
 };
 
 struct vhost_user_connection {
 };
 
 struct vhost_user_connection {
@@ -203,6 +204,9 @@ vhost_user_add_connection(int fd, struct vhost_user_socket *vsocket)
        size = strnlen(vsocket->path, PATH_MAX);
        vhost_set_ifname(vid, vsocket->path, size);
 
        size = strnlen(vsocket->path, PATH_MAX);
        vhost_set_ifname(vid, vsocket->path, size);
 
+       if (vsocket->dequeue_zero_copy)
+               vhost_enable_dequeue_zero_copy(vid);
+
        RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
 
        vsocket->connfd = fd;
        RTE_LOG(INFO, VHOST_CONFIG, "new device, handle is %d\n", vid);
 
        vsocket->connfd = fd;
@@ -499,6 +503,7 @@ rte_vhost_driver_register(const char *path, uint64_t flags)
        memset(vsocket, 0, sizeof(struct vhost_user_socket));
        vsocket->path = strdup(path);
        vsocket->connfd = -1;
        memset(vsocket, 0, sizeof(struct vhost_user_socket));
        vsocket->path = strdup(path);
        vsocket->connfd = -1;
+       vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
 
        if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
                vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
 
        if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
                vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
index dbf5d1b..469117a 100644 (file)
@@ -291,6 +291,16 @@ vhost_set_ifname(int vid, const char *if_name, unsigned int if_len)
        dev->ifname[sizeof(dev->ifname) - 1] = '\0';
 }
 
        dev->ifname[sizeof(dev->ifname) - 1] = '\0';
 }
 
+void
+vhost_enable_dequeue_zero_copy(int vid)
+{
+       struct virtio_net *dev = get_device(vid);
+
+       if (dev == NULL)
+               return;
+
+       dev->dequeue_zero_copy = 1;
+}
 
 int
 rte_vhost_get_numa_node(int vid)
 
 int
 rte_vhost_get_numa_node(int vid)
index be8a398..53dbf33 100644 (file)
@@ -278,6 +278,7 @@ void vhost_destroy_device(int);
 int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
+void vhost_enable_dequeue_zero_copy(int vid);
 
 /*
  * Backend-specific cleanup. Defined by vhost-cuse and vhost-user.
 
 /*
  * Backend-specific cleanup. Defined by vhost-cuse and vhost-user.