Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/7731/?format=api
https://patches.dpdk.org/api/patches/7731/?format=api", "web_url": "https://patches.dpdk.org/project/dpdk/patch/1445231772-17467-4-git-send-email-stephen@networkplumber.org/", "project": { "id": 1, "url": "https://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": "<1445231772-17467-4-git-send-email-stephen@networkplumber.org>", "list_archive_url": "https://inbox.dpdk.org/dev/1445231772-17467-4-git-send-email-stephen@networkplumber.org", "date": "2015-10-19T05:16:10", "name": "[dpdk-dev,3/5] virtio: use indirect ring elements", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": true, "hash": "feff445de2fb9422cb3ccd0fded551be4491e7cd", "submitter": { "id": 27, "url": "https://patches.dpdk.org/api/people/27/?format=api", "name": "Stephen Hemminger", "email": "stephen@networkplumber.org" }, "delegate": null, "mbox": "https://patches.dpdk.org/project/dpdk/patch/1445231772-17467-4-git-send-email-stephen@networkplumber.org/mbox/", "series": [], "comments": "https://patches.dpdk.org/api/patches/7731/comments/", "check": "pending", "checks": "https://patches.dpdk.org/api/patches/7731/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 BF4548E90;\n\tMon, 19 Oct 2015 07:16:12 +0200 (CEST)", "from mail-pa0-f41.google.com (mail-pa0-f41.google.com\n\t[209.85.220.41]) by dpdk.org (Postfix) with ESMTP id 46EBC8E82\n\tfor <dev@dpdk.org>; Mon, 19 Oct 2015 07:16:08 +0200 (CEST)", "by pabrc13 with SMTP id rc13so179467675pab.0\n\tfor <dev@dpdk.org>; Sun, 18 Oct 2015 22:16:07 -0700 (PDT)", "from xeon-e3.home.lan (static-50-53-82-155.bvtn.or.frontiernet.net.\n\t[50.53.82.155]) by smtp.gmail.com with ESMTPSA id\n\tk10sm33681035pbq.78.2015.10.18.22.16.06\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128);\n\tSun, 18 Oct 2015 22:16:06 -0700 (PDT)" ], "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20130820;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=Ta9WXu3yY9jn7SX7N6isMaWxg35HDTv3xIEGd9m1ckg=;\n\tb=G1aajiLjT9oSckdpTKzAE1AV8QOXNJtryXnHuHOSM6bUOWxdaX6m1r0RLo/7fg5ovr\n\tTV6cnIZQ9On9TdkOCa7UrTDTOnwaN4S3dOSJVfk8e5mfcUeY2xBfyIA/Tci4dB6bktfD\n\tKBHJsQkbKxXben1P180imh5n1kFpveTYkjrbar8+1VOJE18vlbco8ZrzGtr33R09XuSZ\n\t3QXZMMA0SEl83o7GeNHzs34X9cPQ6RnlbgCz8QdLiLjE7tYfTyTrMI1Or5cP7ldqDklU\n\tB9uqjbhJvoAk6rW7t6AJNGiPR2lhchy+xOZHoOWGRyV+cdZU0SqZlvthiUxyO70h7kTd\n\tprLQ==", "X-Gm-Message-State": "ALoCoQkvWVIVwryrhiPVK1VcgKAaEyThHLJ5l90fQQ03DNFWMBY9OPTxU2JfIVrrQQC+uWCFxMeV", "X-Received": "by 10.67.22.34 with SMTP id hp2mr32020735pad.92.1445231767702;\n\tSun, 18 Oct 2015 22:16:07 -0700 (PDT)", "From": "Stephen Hemminger <stephen@networkplumber.org>", "To": "huawei.xie@intel.com,\n\tchangchun.ouyang@intel.com", "Date": "Sun, 18 Oct 2015 22:16:10 -0700", "Message-Id": "<1445231772-17467-4-git-send-email-stephen@networkplumber.org>", "X-Mailer": "git-send-email 2.1.4", "In-Reply-To": "<1445231772-17467-1-git-send-email-stephen@networkplumber.org>", "References": "<1445231772-17467-1-git-send-email-stephen@networkplumber.org>", "Cc": "dev@dpdk.org", "Subject": "[dpdk-dev] [PATCH 3/5] virtio: use indirect ring elements", "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": "The virtio ring in QEMU/KVM is usually limited to 256 entries\nand the normal way that virtio driver was queuing mbufs required\nnsegs + 1 ring elements. By using the indirect ring element feature\nif available, each packet will take only one ring slot even for\nmulti-segment packets.\n\nSigned-off-by: Stephen Hemminger <stephen@networkplumber.org>\n---\n drivers/net/virtio/virtio_ethdev.c | 38 +++++++++++++++++------\n drivers/net/virtio/virtio_ethdev.h | 3 +-\n drivers/net/virtio/virtio_rxtx.c | 62 +++++++++++++++++++++++++++-----------\n drivers/net/virtio/virtqueue.h | 19 ++++++++++++\n 4 files changed, 94 insertions(+), 28 deletions(-)", "diff": "diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c\nindex 465d3cd..cfce4f0 100644\n--- a/drivers/net/virtio/virtio_ethdev.c\n+++ b/drivers/net/virtio/virtio_ethdev.c\n@@ -357,27 +357,45 @@ int virtio_dev_queue_setup(struct rte_eth_dev *dev,\n \tvq->virtio_net_hdr_mem = 0;\n \n \tif (queue_type == VTNET_TQ) {\n+\t\tconst struct rte_memzone *hdr_mz;\n+\t\tstruct virtio_tx_region *txr;\n+\t\tint i;\n+\n \t\t/*\n \t\t * For each xmit packet, allocate a virtio_net_hdr\n+\t\t * and indirect ring elements\n \t\t */\n \t\tsnprintf(vq_name, sizeof(vq_name), \"port%d_tvq%d_hdrzone\",\n \t\t\tdev->data->port_id, queue_idx);\n-\t\tvq->virtio_net_hdr_mz = rte_memzone_reserve_aligned(vq_name,\n-\t\t\tvq_size * hw->vtnet_hdr_size,\n+\t\thdr_mz = rte_memzone_reserve_aligned(vq_name,\n+\t\t\tvq_size * sizeof(*txr),\n \t\t\tsocket_id, 0, RTE_CACHE_LINE_SIZE);\n-\t\tif (vq->virtio_net_hdr_mz == NULL) {\n+\t\tif (hdr_mz == NULL) {\n \t\t\tif (rte_errno == EEXIST)\n-\t\t\t\tvq->virtio_net_hdr_mz =\n-\t\t\t\t\trte_memzone_lookup(vq_name);\n-\t\t\tif (vq->virtio_net_hdr_mz == NULL) {\n+\t\t\t\thdr_mz = rte_memzone_lookup(vq_name);\n+\t\t\tif (hdr_mz == NULL) {\n \t\t\t\trte_free(vq);\n \t\t\t\treturn -ENOMEM;\n \t\t\t}\n \t\t}\n-\t\tvq->virtio_net_hdr_mem =\n-\t\t\tvq->virtio_net_hdr_mz->phys_addr;\n-\t\tmemset(vq->virtio_net_hdr_mz->addr, 0,\n-\t\t\tvq_size * hw->vtnet_hdr_size);\n+\t\tvq->virtio_net_hdr_mz = hdr_mz;\n+\t\tvq->virtio_net_hdr_mem = hdr_mz->phys_addr;\n+\n+\t\ttxr = hdr_mz->addr;\n+\t\tmemset(txr, 0, vq_size * sizeof(*txr));\n+\t\tfor (i = 0; i < vq_size; i++) {\n+\t\t\tstruct vring_desc *start_dp = txr[i].tx_indir;\n+\n+\t\t\tvring_desc_init(start_dp, VIRTIO_MAX_INDIRECT);\n+\n+\t\t\t/* first indirect descriptor is always the tx header */\n+\t\t\tstart_dp->addr = vq->virtio_net_hdr_mem\n+\t\t\t\t+ i * sizeof(*txr)\n+\t\t\t\t+ offsetof(struct virtio_tx_region, tx_hdr);\n+\n+\t\t\tstart_dp->len = vq->hw->vtnet_hdr_size;\n+\t\t\tstart_dp->flags = VRING_DESC_F_NEXT;\n+\t\t}\n \t} else if (queue_type == VTNET_CQ) {\n \t\t/* Allocate a page for control vq command, data and status */\n \t\tsnprintf(vq_name, sizeof(vq_name), \"port%d_cvq_hdrzone\",\ndiff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h\nindex 9026d42..07a9265 100644\n--- a/drivers/net/virtio/virtio_ethdev.h\n+++ b/drivers/net/virtio/virtio_ethdev.h\n@@ -64,7 +64,8 @@\n \t 1u << VIRTIO_NET_F_CTRL_VQ\t |\t\\\n \t 1u << VIRTIO_NET_F_CTRL_RX\t |\t\\\n \t 1u << VIRTIO_NET_F_CTRL_VLAN\t |\t\\\n-\t 1u << VIRTIO_NET_F_MRG_RXBUF)\n+\t 1u << VIRTIO_NET_F_MRG_RXBUF |\t\\\n+\t 1u << VIRTIO_RING_F_INDIRECT_DESC)\n \n /*\n * CQ function prototype\ndiff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c\nindex dbe6665..f68ab8f 100644\n--- a/drivers/net/virtio/virtio_rxtx.c\n+++ b/drivers/net/virtio/virtio_rxtx.c\n@@ -199,14 +199,15 @@ virtqueue_enqueue_recv_refill(struct virtqueue *vq, struct rte_mbuf *cookie)\n }\n \n static int\n-virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n+virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie,\n+\t\t int use_indirect)\n {\n \tstruct vq_desc_extra *dxp;\n \tstruct vring_desc *start_dp;\n \tuint16_t seg_num = cookie->nb_segs;\n-\tuint16_t needed = 1 + seg_num;\n+\tuint16_t needed = use_indirect ? 1 : 1 + seg_num;\n \tuint16_t head_idx, idx;\n-\tuint16_t head_size = txvq->hw->vtnet_hdr_size;\n+\tunsigned long offs;\n \n \tif (unlikely(txvq->vq_free_cnt == 0))\n \t\treturn -ENOSPC;\n@@ -220,12 +221,29 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n \tdxp = &txvq->vq_descx[idx];\n \tdxp->cookie = (void *)cookie;\n \tdxp->ndescs = needed;\n-\n \tstart_dp = txvq->vq_ring.desc;\n-\tstart_dp[idx].addr =\n-\t\ttxvq->virtio_net_hdr_mem + idx * head_size;\n-\tstart_dp[idx].len = (uint32_t)head_size;\n-\tstart_dp[idx].flags = VRING_DESC_F_NEXT;\n+\n+\tif (use_indirect) {\n+\t\tstruct virtio_tx_region *txr\n+\t\t\t= txvq->virtio_net_hdr_mz->addr;\n+\n+\t\toffs = idx * sizeof(struct virtio_tx_region)\n+\t\t\t+ offsetof(struct virtio_tx_region, tx_indir);\n+\n+\t\tstart_dp[idx].addr = txvq->virtio_net_hdr_mem + offs;\n+\t\tstart_dp[idx].len = (seg_num + 1) * sizeof(struct vring_desc);\n+\t\tstart_dp[idx].flags = VRING_DESC_F_INDIRECT;\n+\n+\t\tstart_dp = txr[idx].tx_indir;\n+\t\tidx = 0;\n+\t} else {\n+\t\toffs = idx * sizeof(struct virtio_tx_region)\n+\t\t\t+ offsetof(struct virtio_tx_region, tx_hdr);\n+\n+\t\tstart_dp[idx].addr = txvq->virtio_net_hdr_mem + offs;\n+\t\tstart_dp[idx].len = txvq->hw->vtnet_hdr_size;\n+\t\tstart_dp[idx].flags = VRING_DESC_F_NEXT;\n+\t}\n \n \tfor (; ((seg_num > 0) && (cookie != NULL)); seg_num--) {\n \t\tidx = start_dp[idx].next;\n@@ -236,7 +254,12 @@ virtqueue_enqueue_xmit(struct virtqueue *txvq, struct rte_mbuf *cookie)\n \t}\n \n \tstart_dp[idx].flags &= ~VRING_DESC_F_NEXT;\n-\tidx = start_dp[idx].next;\n+\n+\tif (use_indirect)\n+\t\tidx = txvq->vq_ring.desc[head_idx].next;\n+\telse\n+\t\tidx = start_dp[idx].next;\n+\n \ttxvq->vq_desc_head_idx = idx;\n \tif (txvq->vq_desc_head_idx == VQ_RING_DESC_CHAIN_END)\n \t\ttxvq->vq_desc_tail_idx = idx;\n@@ -261,7 +284,7 @@ static void\n virtio_dev_vring_start(struct virtqueue *vq, int queue_type)\n {\n \tstruct rte_mbuf *m;\n-\tint i, nbufs, error, size = vq->vq_nentries;\n+\tint nbufs, error, size = vq->vq_nentries;\n \tstruct vring *vr = &vq->vq_ring;\n \tuint8_t *ring_mem = vq->vq_ring_virt_mem;\n \n@@ -279,10 +302,7 @@ virtio_dev_vring_start(struct virtqueue *vq, int queue_type)\n \tvq->vq_free_cnt = vq->vq_nentries;\n \tmemset(vq->vq_descx, 0, sizeof(struct vq_desc_extra) * vq->vq_nentries);\n \n-\t/* Chain all the descriptors in the ring with an END */\n-\tfor (i = 0; i < size - 1; i++)\n-\t\tvr->desc[i].next = (uint16_t)(i + 1);\n-\tvr->desc[i].next = VQ_RING_DESC_CHAIN_END;\n+\tvring_desc_init(vr->desc, size);\n \n \t/*\n \t * Disable device(host) interrupting guest\n@@ -760,7 +780,15 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \n \tfor (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {\n \t\tstruct rte_mbuf *txm = tx_pkts[nb_tx];\n-\t\tint need = txm->nb_segs - txvq->vq_free_cnt + 1;\n+\t\tint use_indirect, slots, need;\n+\n+\t\tuse_indirect = vtpci_with_feature(txvq->hw,\n+\t\t\t\t\t\t VIRTIO_RING_F_INDIRECT_DESC)\n+\t\t\t&& (txm->nb_segs < VIRTIO_MAX_TX_INDIRECT);\n+\n+\t\t/* How many ring entries are needed to this Tx? */\n+\t\tslots = use_indirect ? 1 : 1 + txm->nb_segs;\n+\t\tneed = slots - txvq->vq_free_cnt;\n \n \t\t/* Positive value indicates it need free vring descriptors */\n \t\tif (need > 0) {\n@@ -769,7 +797,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\t\tneed = RTE_MIN(need, (int)nb_used);\n \n \t\t\tvirtio_xmit_cleanup(txvq, need);\n-\t\t\tneed = txm->nb_segs - txvq->vq_free_cnt + 1;\n+\t\t\tneed = slots - txvq->vq_free_cnt;\n \t\t\tif (unlikely(need > 0)) {\n \t\t\t\tPMD_TX_LOG(ERR,\n \t\t\t\t\t \"No free tx descriptors to transmit\");\n@@ -787,7 +815,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)\n \t\t}\n \n \t\t/* Enqueue Packet buffers */\n-\t\terror = virtqueue_enqueue_xmit(txvq, txm);\n+\t\terror = virtqueue_enqueue_xmit(txvq, txm, use_indirect);\n \t\tif (unlikely(error)) {\n \t\t\tif (error == ENOSPC)\n \t\t\t\tPMD_TX_LOG(ERR, \"virtqueue_enqueue Free count = 0\");\ndiff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h\nindex 7789411..fe3fa66 100644\n--- a/drivers/net/virtio/virtqueue.h\n+++ b/drivers/net/virtio/virtqueue.h\n@@ -237,6 +237,25 @@ struct virtio_net_hdr_mrg_rxbuf {\n \tuint16_t num_buffers; /**< Number of merged rx buffers */\n };\n \n+/* Region reserved to allow for transmit header and indirect ring */\n+#define VIRTIO_MAX_TX_INDIRECT 8\n+struct virtio_tx_region {\n+\tstruct virtio_net_hdr_mrg_rxbuf tx_hdr;\n+\tstruct vring_desc tx_indir[VIRTIO_MAX_TX_INDIRECT]\n+\t\t\t __attribute__((__aligned__(16)));\n+};\n+\n+/* Chain all the descriptors in the ring with an END */\n+static inline void\n+vring_desc_init(struct vring_desc *dp, uint16_t n)\n+{\n+\tuint16_t i;\n+\n+\tfor (i = 0; i < n - 1; i++)\n+\t\tdp[i].next = (uint16_t)(i + 1);\n+\tdp[i].next = VQ_RING_DESC_CHAIN_END;\n+}\n+\n /**\n * Tell the backend not to interrupt us.\n */\n", "prefixes": [ "dpdk-dev", "3/5" ] }{ "id": 7731, "url": "