get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/7895/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 7895,
    "url": "http://patches.dpdk.org/api/patches/7895/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1445517356-19780-4-git-send-email-yuanhan.liu@linux.intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1445517356-19780-4-git-send-email-yuanhan.liu@linux.intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1445517356-19780-4-git-send-email-yuanhan.liu@linux.intel.com",
    "date": "2015-10-22T12:35:51",
    "name": "[dpdk-dev,v8,3/8] vhost: vring queue setup for multiple queue support",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "73735099cb0785f0584a8e045a4d2ffd2b26449f",
    "submitter": {
        "id": 307,
        "url": "http://patches.dpdk.org/api/people/307/?format=api",
        "name": "Yuanhan Liu",
        "email": "yuanhan.liu@linux.intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1445517356-19780-4-git-send-email-yuanhan.liu@linux.intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/7895/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/7895/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id CC1DBC31E;\n\tThu, 22 Oct 2015 14:36:02 +0200 (CEST)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id 8809795BB\n\tfor <dev@dpdk.org>; Thu, 22 Oct 2015 14:35:57 +0200 (CEST)",
            "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga101.jf.intel.com with ESMTP; 22 Oct 2015 05:35:32 -0700",
            "from yliu-dev.sh.intel.com ([10.239.66.49])\n\tby orsmga002.jf.intel.com with ESMTP; 22 Oct 2015 05:35:31 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.20,182,1444719600\"; d=\"scan'208\";a=\"832542834\"",
        "From": "Yuanhan Liu <yuanhan.liu@linux.intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Thu, 22 Oct 2015 20:35:51 +0800",
        "Message-Id": "<1445517356-19780-4-git-send-email-yuanhan.liu@linux.intel.com>",
        "X-Mailer": "git-send-email 1.9.0",
        "In-Reply-To": "<1445517356-19780-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "References": "<1445399294-18826-1-git-send-email-yuanhan.liu@linux.intel.com>\n\t<1445517356-19780-1-git-send-email-yuanhan.liu@linux.intel.com>",
        "Cc": "marcel@redhat.com, \"Michael S. Tsirkin\" <mst@redhat.com>",
        "Subject": "[dpdk-dev] [PATCH v8 3/8] vhost: vring queue setup for multiple\n\tqueue support",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "All queue pairs, including the default (the first) queue pair,\nare allocated dynamically, when a vring_call message is received\nfirst time for a specific queue pair.\n\nThis is a refactor work for enabling vhost-user multiple queue;\nit should not break anything as it does no functional changes:\nwe don't support mq set, so there is only one mq at max.\n\nThis patch is based on Changchun's patch.\n\nSigned-off-by: Ouyang Changchun <changchun.ouyang@intel.com>\nSigned-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>\nAcked-by: Flavio Leitner <fbl@sysclose.org>\n\n---\n\nv8: - move virtuque field to the end of `virtio_net' struct.\n\n    - Add a FIXME at set_vring_call() for doing vring queue pair\n      allocation.\n---\n lib/librte_vhost/rte_virtio_net.h             |   3 +-\n lib/librte_vhost/vhost_user/virtio-net-user.c |  46 ++++----\n lib/librte_vhost/virtio-net.c                 | 156 ++++++++++++++++----------\n 3 files changed, 123 insertions(+), 82 deletions(-)",
    "diff": "diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h\nindex e3a21e5..9a32a95 100644\n--- a/lib/librte_vhost/rte_virtio_net.h\n+++ b/lib/librte_vhost/rte_virtio_net.h\n@@ -96,7 +96,6 @@ struct vhost_virtqueue {\n  * Device structure contains all configuration information relating to the device.\n  */\n struct virtio_net {\n-\tstruct vhost_virtqueue\t*virtqueue[VIRTIO_QNUM];\t/**< Contains all virtqueue information. */\n \tstruct virtio_memory\t*mem;\t\t/**< QEMU memory and memory region information. */\n \tuint64_t\t\tfeatures;\t/**< Negotiated feature set. */\n \tuint64_t\t\tprotocol_features;\t/**< Negotiated protocol feature set. */\n@@ -104,7 +103,9 @@ struct virtio_net {\n \tuint32_t\t\tflags;\t\t/**< Device flags. Only used to check if device is running on data core. */\n #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)\n \tchar\t\t\tifname[IF_NAME_SZ];\t/**< Name of the tap device or socket path. */\n+\tuint32_t\t\tvirt_qp_nb;\t/**< number of queue pair we have allocated */\n \tvoid\t\t\t*priv;\t\t/**< private context */\n+\tstruct vhost_virtqueue\t*virtqueue[VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX];\t/**< Contains all virtqueue information. */\n } __rte_cache_aligned;\n \n /**\ndiff --git a/lib/librte_vhost/vhost_user/virtio-net-user.c b/lib/librte_vhost/vhost_user/virtio-net-user.c\nindex 6da729d..d62f3d7 100644\n--- a/lib/librte_vhost/vhost_user/virtio-net-user.c\n+++ b/lib/librte_vhost/vhost_user/virtio-net-user.c\n@@ -206,25 +206,33 @@ err_mmap:\n }\n \n static int\n+vq_is_ready(struct vhost_virtqueue *vq)\n+{\n+\treturn vq && vq->desc   &&\n+\t       vq->kickfd != -1 &&\n+\t       vq->callfd != -1;\n+}\n+\n+static int\n virtio_is_ready(struct virtio_net *dev)\n {\n \tstruct vhost_virtqueue *rvq, *tvq;\n+\tuint32_t i;\n \n-\t/* mq support in future.*/\n-\trvq = dev->virtqueue[VIRTIO_RXQ];\n-\ttvq = dev->virtqueue[VIRTIO_TXQ];\n-\tif (rvq && tvq && rvq->desc && tvq->desc &&\n-\t\t(rvq->kickfd != -1) &&\n-\t\t(rvq->callfd != -1) &&\n-\t\t(tvq->kickfd != -1) &&\n-\t\t(tvq->callfd != -1)) {\n-\t\tRTE_LOG(INFO, VHOST_CONFIG,\n-\t\t\t\"virtio is now ready for processing.\\n\");\n-\t\treturn 1;\n+\tfor (i = 0; i < dev->virt_qp_nb; i++) {\n+\t\trvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];\n+\t\ttvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];\n+\n+\t\tif (!vq_is_ready(rvq) || !vq_is_ready(tvq)) {\n+\t\t\tRTE_LOG(INFO, VHOST_CONFIG,\n+\t\t\t\t\"virtio is not ready for processing.\\n\");\n+\t\t\treturn 0;\n+\t\t}\n \t}\n+\n \tRTE_LOG(INFO, VHOST_CONFIG,\n-\t\t\"virtio isn't ready for processing.\\n\");\n-\treturn 0;\n+\t\t\"virtio is now ready for processing.\\n\");\n+\treturn 1;\n }\n \n void\n@@ -292,13 +300,13 @@ user_get_vring_base(struct vhost_device_ctx ctx,\n \t * sent and only sent in vhost_vring_stop.\n \t * TODO: cleanup the vring, it isn't usable since here.\n \t */\n-\tif ((dev->virtqueue[VIRTIO_RXQ]->kickfd) >= 0) {\n-\t\tclose(dev->virtqueue[VIRTIO_RXQ]->kickfd);\n-\t\tdev->virtqueue[VIRTIO_RXQ]->kickfd = -1;\n+\tif ((dev->virtqueue[state->index]->kickfd + VIRTIO_RXQ) >= 0) {\n+\t\tclose(dev->virtqueue[state->index + VIRTIO_RXQ]->kickfd);\n+\t\tdev->virtqueue[state->index + VIRTIO_RXQ]->kickfd = -1;\n \t}\n-\tif ((dev->virtqueue[VIRTIO_TXQ]->kickfd) >= 0) {\n-\t\tclose(dev->virtqueue[VIRTIO_TXQ]->kickfd);\n-\t\tdev->virtqueue[VIRTIO_TXQ]->kickfd = -1;\n+\tif ((dev->virtqueue[state->index]->kickfd + VIRTIO_TXQ) >= 0) {\n+\t\tclose(dev->virtqueue[state->index + VIRTIO_TXQ]->kickfd);\n+\t\tdev->virtqueue[state->index + VIRTIO_TXQ]->kickfd = -1;\n \t}\n \n \treturn 0;\ndiff --git a/lib/librte_vhost/virtio-net.c b/lib/librte_vhost/virtio-net.c\nindex 830f22a..772f835 100644\n--- a/lib/librte_vhost/virtio-net.c\n+++ b/lib/librte_vhost/virtio-net.c\n@@ -36,6 +36,7 @@\n #include <stddef.h>\n #include <stdint.h>\n #include <stdlib.h>\n+#include <assert.h>\n #include <sys/mman.h>\n #include <unistd.h>\n #ifdef RTE_LIBRTE_VHOST_NUMA\n@@ -178,6 +179,15 @@ add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev)\n \n }\n \n+static void\n+cleanup_vq(struct vhost_virtqueue *vq)\n+{\n+\tif (vq->callfd >= 0)\n+\t\tclose(vq->callfd);\n+\tif (vq->kickfd >= 0)\n+\t\tclose(vq->kickfd);\n+}\n+\n /*\n  * Unmap any memory, close any file descriptors and\n  * free any memory owned by a device.\n@@ -185,6 +195,8 @@ add_config_ll_entry(struct virtio_net_config_ll *new_ll_dev)\n static void\n cleanup_device(struct virtio_net *dev)\n {\n+\tuint32_t i;\n+\n \t/* Unmap QEMU memory file if mapped. */\n \tif (dev->mem) {\n \t\tmunmap((void *)(uintptr_t)dev->mem->mapped_address,\n@@ -192,15 +204,10 @@ cleanup_device(struct virtio_net *dev)\n \t\tfree(dev->mem);\n \t}\n \n-\t/* Close any event notifiers opened by device. */\n-\tif (dev->virtqueue[VIRTIO_RXQ]->callfd >= 0)\n-\t\tclose(dev->virtqueue[VIRTIO_RXQ]->callfd);\n-\tif (dev->virtqueue[VIRTIO_RXQ]->kickfd >= 0)\n-\t\tclose(dev->virtqueue[VIRTIO_RXQ]->kickfd);\n-\tif (dev->virtqueue[VIRTIO_TXQ]->callfd >= 0)\n-\t\tclose(dev->virtqueue[VIRTIO_TXQ]->callfd);\n-\tif (dev->virtqueue[VIRTIO_TXQ]->kickfd >= 0)\n-\t\tclose(dev->virtqueue[VIRTIO_TXQ]->kickfd);\n+\tfor (i = 0; i < dev->virt_qp_nb; i++) {\n+\t\tcleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ]);\n+\t\tcleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ]);\n+\t}\n }\n \n /*\n@@ -209,9 +216,11 @@ cleanup_device(struct virtio_net *dev)\n static void\n free_device(struct virtio_net_config_ll *ll_dev)\n {\n-\t/* Free any malloc'd memory */\n-\trte_free(ll_dev->dev.virtqueue[VIRTIO_RXQ]);\n-\trte_free(ll_dev->dev.virtqueue[VIRTIO_TXQ]);\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < ll_dev->dev.virt_qp_nb; i++)\n+\t\trte_free(ll_dev->dev.virtqueue[i * VIRTIO_QNUM]);\n+\n \trte_free(ll_dev);\n }\n \n@@ -244,34 +253,68 @@ rm_config_ll_entry(struct virtio_net_config_ll *ll_dev,\n \t}\n }\n \n+static void\n+init_vring_queue(struct vhost_virtqueue *vq)\n+{\n+\tmemset(vq, 0, sizeof(struct vhost_virtqueue));\n+\n+\tvq->kickfd = -1;\n+\tvq->callfd = -1;\n+\n+\t/* Backends are set to -1 indicating an inactive device. */\n+\tvq->backend = -1;\n+}\n+\n+static void\n+init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)\n+{\n+\tinit_vring_queue(dev->virtqueue[qp_idx * VIRTIO_QNUM + VIRTIO_RXQ]);\n+\tinit_vring_queue(dev->virtqueue[qp_idx * VIRTIO_QNUM + VIRTIO_TXQ]);\n+}\n+\n+static int\n+alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)\n+{\n+\tstruct vhost_virtqueue *virtqueue = NULL;\n+\tuint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;\n+\tuint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;\n+\n+\tvirtqueue = rte_malloc(NULL,\n+\t\t\t       sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);\n+\tif (virtqueue == NULL) {\n+\t\tRTE_LOG(ERR, VHOST_CONFIG,\n+\t\t\t\"Failed to allocate memory for virt qp:%d.\\n\", qp_idx);\n+\t\treturn -1;\n+\t}\n+\n+\tdev->virtqueue[virt_rx_q_idx] = virtqueue;\n+\tdev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;\n+\n+\tinit_vring_queue_pair(dev, qp_idx);\n+\n+\tdev->virt_qp_nb += 1;\n+\n+\treturn 0;\n+}\n+\n /*\n  *  Initialise all variables in device structure.\n  */\n static void\n init_device(struct virtio_net *dev)\n {\n-\tuint64_t vq_offset;\n+\tint vq_offset;\n+\tuint32_t i;\n \n \t/*\n \t * Virtqueues have already been malloced so\n \t * we don't want to set them to NULL.\n \t */\n-\tvq_offset = offsetof(struct virtio_net, mem);\n-\n-\t/* Set everything to 0. */\n-\tmemset((void *)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0,\n-\t\t(sizeof(struct virtio_net) - (size_t)vq_offset));\n-\tmemset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct vhost_virtqueue));\n-\tmemset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct vhost_virtqueue));\n-\n-\tdev->virtqueue[VIRTIO_RXQ]->kickfd = -1;\n-\tdev->virtqueue[VIRTIO_RXQ]->callfd = -1;\n-\tdev->virtqueue[VIRTIO_TXQ]->kickfd = -1;\n-\tdev->virtqueue[VIRTIO_TXQ]->callfd = -1;\n+\tvq_offset = offsetof(struct virtio_net, virtqueue);\n+\tmemset(dev, 0, vq_offset);\n \n-\t/* Backends are set to -1 indicating an inactive device. */\n-\tdev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED;\n-\tdev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED;\n+\tfor (i = 0; i < dev->virt_qp_nb; i++)\n+\t\tinit_vring_queue_pair(dev, i);\n }\n \n /*\n@@ -283,7 +326,6 @@ static int\n new_device(struct vhost_device_ctx ctx)\n {\n \tstruct virtio_net_config_ll *new_ll_dev;\n-\tstruct vhost_virtqueue *virtqueue_rx, *virtqueue_tx;\n \n \t/* Setup device and virtqueues. */\n \tnew_ll_dev = rte_malloc(NULL, sizeof(struct virtio_net_config_ll), 0);\n@@ -294,28 +336,6 @@ new_device(struct vhost_device_ctx ctx)\n \t\treturn -1;\n \t}\n \n-\tvirtqueue_rx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);\n-\tif (virtqueue_rx == NULL) {\n-\t\trte_free(new_ll_dev);\n-\t\tRTE_LOG(ERR, VHOST_CONFIG,\n-\t\t\t\"(%\"PRIu64\") Failed to allocate memory for rxq.\\n\",\n-\t\t\tctx.fh);\n-\t\treturn -1;\n-\t}\n-\n-\tvirtqueue_tx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);\n-\tif (virtqueue_tx == NULL) {\n-\t\trte_free(virtqueue_rx);\n-\t\trte_free(new_ll_dev);\n-\t\tRTE_LOG(ERR, VHOST_CONFIG,\n-\t\t\t\"(%\"PRIu64\") Failed to allocate memory for txq.\\n\",\n-\t\t\tctx.fh);\n-\t\treturn -1;\n-\t}\n-\n-\tnew_ll_dev->dev.virtqueue[VIRTIO_RXQ] = virtqueue_rx;\n-\tnew_ll_dev->dev.virtqueue[VIRTIO_TXQ] = virtqueue_tx;\n-\n \t/* Initialise device and virtqueues. */\n \tinit_device(&new_ll_dev->dev);\n \n@@ -441,6 +461,8 @@ static int\n set_features(struct vhost_device_ctx ctx, uint64_t *pu)\n {\n \tstruct virtio_net *dev;\n+\tuint16_t vhost_hlen;\n+\tuint16_t i;\n \n \tdev = get_device(ctx);\n \tif (dev == NULL)\n@@ -448,27 +470,26 @@ set_features(struct vhost_device_ctx ctx, uint64_t *pu)\n \tif (*pu & ~VHOST_FEATURES)\n \t\treturn -1;\n \n-\t/* Store the negotiated feature list for the device. */\n \tdev->features = *pu;\n-\n-\t/* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF is set. */\n \tif (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {\n \t\tLOG_DEBUG(VHOST_CONFIG,\n \t\t\t\"(%\"PRIu64\") Mergeable RX buffers enabled\\n\",\n \t\t\tdev->device_fh);\n-\t\tdev->virtqueue[VIRTIO_RXQ]->vhost_hlen =\n-\t\t\tsizeof(struct virtio_net_hdr_mrg_rxbuf);\n-\t\tdev->virtqueue[VIRTIO_TXQ]->vhost_hlen =\n-\t\t\tsizeof(struct virtio_net_hdr_mrg_rxbuf);\n+\t\tvhost_hlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);\n \t} else {\n \t\tLOG_DEBUG(VHOST_CONFIG,\n \t\t\t\"(%\"PRIu64\") Mergeable RX buffers disabled\\n\",\n \t\t\tdev->device_fh);\n-\t\tdev->virtqueue[VIRTIO_RXQ]->vhost_hlen =\n-\t\t\tsizeof(struct virtio_net_hdr);\n-\t\tdev->virtqueue[VIRTIO_TXQ]->vhost_hlen =\n-\t\t\tsizeof(struct virtio_net_hdr);\n+\t\tvhost_hlen = sizeof(struct virtio_net_hdr);\n+\t}\n+\n+\tfor (i = 0; i < dev->virt_qp_nb; i++) {\n+\t\tuint16_t base_idx = i * VIRTIO_QNUM;\n+\n+\t\tdev->virtqueue[base_idx + VIRTIO_RXQ]->vhost_hlen = vhost_hlen;\n+\t\tdev->virtqueue[base_idx + VIRTIO_TXQ]->vhost_hlen = vhost_hlen;\n \t}\n+\n \treturn 0;\n }\n \n@@ -684,13 +705,24 @@ set_vring_call(struct vhost_device_ctx ctx, struct vhost_vring_file *file)\n {\n \tstruct virtio_net *dev;\n \tstruct vhost_virtqueue *vq;\n+\tuint32_t cur_qp_idx = file->index / VIRTIO_QNUM;\n \n \tdev = get_device(ctx);\n \tif (dev == NULL)\n \t\treturn -1;\n \n+\t/*\n+\t * FIXME: VHOST_SET_VRING_CALL is the first per-vring message\n+\t * we get, so we do vring queue pair allocation here.\n+\t */\n+\tif (cur_qp_idx + 1 > dev->virt_qp_nb) {\n+\t\tif (alloc_vring_queue_pair(dev, cur_qp_idx) < 0)\n+\t\t\treturn -1;\n+\t}\n+\n \t/* file->index refers to the queue index. The txq is 1, rxq is 0. */\n \tvq = dev->virtqueue[file->index];\n+\tassert(vq != NULL);\n \n \tif (vq->callfd >= 0)\n \t\tclose(vq->callfd);\n",
    "prefixes": [
        "dpdk-dev",
        "v8",
        "3/8"
    ]
}