get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 5080,
    "url": "http://patchwork.dpdk.org/api/1.0/patches/5080/?format=api",
    "project": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/1.0/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"
    },
    "msgid": "<1433235064-2773-2-git-send-email-changchun.ouyang@intel.com>",
    "date": "2015-06-02T08:51:01",
    "name": "[dpdk-dev,v4,1/4] lib_vhost: Fix enqueue/dequeue can't handle chained vring descriptors",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "be5881ca86e9363e3337017fa8d58c641453f271",
    "submitter": {
        "id": 31,
        "url": "http://patchwork.dpdk.org/api/1.0/people/31/?format=api",
        "name": "Ouyang Changchun",
        "email": "changchun.ouyang@intel.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/1433235064-2773-2-git-send-email-changchun.ouyang@intel.com/mbox/",
    "series": [],
    "check": "pending",
    "checks": "http://patchwork.dpdk.org/api/patches/5080/checks/",
    "tags": {},
    "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 22736C390;\n\tTue,  2 Jun 2015 10:51:19 +0200 (CEST)",
            "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby dpdk.org (Postfix) with ESMTP id 3B0DFC38A\n\tfor <dev@dpdk.org>; Tue,  2 Jun 2015 10:51:17 +0200 (CEST)",
            "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga103.jf.intel.com with ESMTP; 02 Jun 2015 01:51:16 -0700",
            "from shvmail01.sh.intel.com ([10.239.29.42])\n\tby orsmga003.jf.intel.com with ESMTP; 02 Jun 2015 01:51:16 -0700",
            "from shecgisg004.sh.intel.com (shecgisg004.sh.intel.com\n\t[10.239.29.89])\n\tby shvmail01.sh.intel.com with ESMTP id t528pB4I007944;\n\tTue, 2 Jun 2015 16:51:11 +0800",
            "from shecgisg004.sh.intel.com (localhost [127.0.0.1])\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/SuSE Linux 0.8) with ESMTP\n\tid t528p9g2002813; Tue, 2 Jun 2015 16:51:11 +0800",
            "(from couyang@localhost)\n\tby shecgisg004.sh.intel.com (8.13.6/8.13.6/Submit) id t528p9ki002809; \n\tTue, 2 Jun 2015 16:51:09 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.13,538,1427785200\"; d=\"scan'208\";a=\"580518722\"",
        "From": "Ouyang Changchun <changchun.ouyang@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Tue,  2 Jun 2015 16:51:01 +0800",
        "Message-Id": "<1433235064-2773-2-git-send-email-changchun.ouyang@intel.com>",
        "X-Mailer": "git-send-email 1.7.12.2",
        "In-Reply-To": "<1433235064-2773-1-git-send-email-changchun.ouyang@intel.com>",
        "References": "<1433147149-31645-1-git-send-email-changchun.ouyang@intel.com>\n\t<1433235064-2773-1-git-send-email-changchun.ouyang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v4 1/4] lib_vhost: Fix enqueue/dequeue can't\n\thandle chained vring descriptors",
        "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": "Vring enqueue need consider the 2 cases:\n 1. use separate descriptors to contain virtio header and actual data, e.g. the first descriptor\n    is for virtio header, and then followed by descriptors for actual data.\n 2. virtio header and some data are put together in one descriptor, e.g. the first descriptor contain both\n    virtio header and part of actual data, and then followed by more descriptors for rest of packet data,\n    current DPDK based virtio-net pmd implementation is this case;\n\nSo does vring dequeue, it should not assume vring descriptor is chained or not chained, it should use\ndesc->flags to check whether it is chained or not. this patch also fixes TX corrupt issue when vhost\nco-work with virtio-net driver which uses one single vring descriptor(header and data are in one descriptor)\nfor virtio tx process on default.\n\nChanges in v4\n  - remove unnecessary check for mbuf 'next' pointer\n  - refine packet copying completeness check\n\nChanges in v3\n  - support scattered mbuf, check the mbuf has 'next' pointer or not and copy all segments to vring buffer.\n\nChanges in v2\n  - drop the uncompleted packet\n  - refine code logic\n\nSigned-off-by: Changchun Ouyang <changchun.ouyang@intel.com>\n---\n lib/librte_vhost/vhost_rxtx.c | 86 ++++++++++++++++++++++++++++++++++---------\n 1 file changed, 69 insertions(+), 17 deletions(-)",
    "diff": "diff --git a/lib/librte_vhost/vhost_rxtx.c b/lib/librte_vhost/vhost_rxtx.c\nindex 4809d32..dc555a8 100644\n--- a/lib/librte_vhost/vhost_rxtx.c\n+++ b/lib/librte_vhost/vhost_rxtx.c\n@@ -46,7 +46,8 @@\n  * This function adds buffers to the virtio devices RX virtqueue. Buffers can\n  * be received from the physical port or from another virtio device. A packet\n  * count is returned to indicate the number of packets that are succesfully\n- * added to the RX queue. This function works when mergeable is disabled.\n+ * added to the RX queue. This function works when the mbuf is scattered, but\n+ * it doesn't support the mergeable feature.\n  */\n static inline uint32_t __attribute__((always_inline))\n virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,\n@@ -59,7 +60,7 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,\n \tstruct virtio_net_hdr_mrg_rxbuf virtio_hdr = {{0, 0, 0, 0, 0, 0}, 0};\n \tuint64_t buff_addr = 0;\n \tuint64_t buff_hdr_addr = 0;\n-\tuint32_t head[MAX_PKT_BURST], packet_len = 0;\n+\tuint32_t head[MAX_PKT_BURST];\n \tuint32_t head_idx, packet_success = 0;\n \tuint16_t avail_idx, res_cur_idx;\n \tuint16_t res_base_idx, res_end_idx;\n@@ -113,6 +114,10 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,\n \trte_prefetch0(&vq->desc[head[packet_success]]);\n \n \twhile (res_cur_idx != res_end_idx) {\n+\t\tuint32_t offset = 0, vb_offset = 0;\n+\t\tuint32_t pkt_len, len_to_cpy, data_len, total_copied = 0;\n+\t\tuint8_t hdr = 0, uncompleted_pkt = 0;\n+\n \t\t/* Get descriptor from available ring */\n \t\tdesc = &vq->desc[head[packet_success]];\n \n@@ -125,7 +130,6 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,\n \n \t\t/* Copy virtio_hdr to packet and increment buffer address */\n \t\tbuff_hdr_addr = buff_addr;\n-\t\tpacket_len = rte_pktmbuf_data_len(buff) + vq->vhost_hlen;\n \n \t\t/*\n \t\t * If the descriptors are chained the header and data are\n@@ -136,28 +140,71 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,\n \t\t\tdesc = &vq->desc[desc->next];\n \t\t\t/* Buffer address translation. */\n \t\t\tbuff_addr = gpa_to_vva(dev, desc->addr);\n-\t\t\tdesc->len = rte_pktmbuf_data_len(buff);\n \t\t} else {\n-\t\t\tbuff_addr += vq->vhost_hlen;\n-\t\t\tdesc->len = packet_len;\n+\t\t\tvb_offset += vq->vhost_hlen;\n+\t\t\thdr = 1;\n \t\t}\n \n+\t\tpkt_len = rte_pktmbuf_pkt_len(buff);\n+\t\tdata_len = rte_pktmbuf_data_len(buff);\n+\t\tlen_to_cpy = RTE_MIN(data_len,\n+\t\t\thdr ? desc->len - vq->vhost_hlen : desc->len);\n+\t\twhile (total_copied < pkt_len) {\n+\t\t\t/* Copy mbuf data to buffer */\n+\t\t\trte_memcpy((void *)(uintptr_t)(buff_addr + vb_offset),\n+\t\t\t\t(const void *)(rte_pktmbuf_mtod(buff, const char *) + offset),\n+\t\t\t\tlen_to_cpy);\n+\t\t\tPRINT_PACKET(dev, (uintptr_t)(buff_addr + vb_offset),\n+\t\t\t\tlen_to_cpy, 0);\n+\n+\t\t\toffset += len_to_cpy;\n+\t\t\tvb_offset += len_to_cpy;\n+\t\t\ttotal_copied += len_to_cpy;\n+\n+\t\t\t/* The whole packet completes */\n+\t\t\tif (total_copied == pkt_len)\n+\t\t\t\tbreak;\n+\n+\t\t\t/* The current segment completes */\n+\t\t\tif (offset == data_len) {\n+\t\t\t\tbuff = buff->next;\n+\t\t\t\toffset = 0;\n+\t\t\t\tdata_len = rte_pktmbuf_data_len(buff);\n+\t\t\t}\n+\n+\t\t\t/* The current vring descriptor done */\n+\t\t\tif (vb_offset == desc->len) {\n+\t\t\t\tif (desc->flags & VRING_DESC_F_NEXT) {\n+\t\t\t\t\tdesc = &vq->desc[desc->next];\n+\t\t\t\t\tbuff_addr = gpa_to_vva(dev, desc->addr);\n+\t\t\t\t\tvb_offset = 0;\n+\t\t\t\t} else {\n+\t\t\t\t\t/* Room in vring buffer is not enough */\n+\t\t\t\t\tuncompleted_pkt = 1;\n+\t\t\t\t\tbreak;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tlen_to_cpy = RTE_MIN(data_len - offset, desc->len - vb_offset);\n+\t\t};\n+\n \t\t/* Update used ring with desc information */\n \t\tvq->used->ring[res_cur_idx & (vq->size - 1)].id =\n \t\t\t\t\t\t\thead[packet_success];\n-\t\tvq->used->ring[res_cur_idx & (vq->size - 1)].len = packet_len;\n \n-\t\t/* Copy mbuf data to buffer */\n-\t\t/* FIXME for sg mbuf and the case that desc couldn't hold the mbuf data */\n-\t\trte_memcpy((void *)(uintptr_t)buff_addr,\n-\t\t\trte_pktmbuf_mtod(buff, const void *),\n-\t\t\trte_pktmbuf_data_len(buff));\n-\t\tPRINT_PACKET(dev, (uintptr_t)buff_addr,\n-\t\t\trte_pktmbuf_data_len(buff), 0);\n+\t\t/* Drop the packet if it is uncompleted */\n+\t\tif (unlikely(uncompleted_pkt == 1))\n+\t\t\tvq->used->ring[res_cur_idx & (vq->size - 1)].len =\n+\t\t\t\t\t\t\tvq->vhost_hlen;\n+\t\telse\n+\t\t\tvq->used->ring[res_cur_idx & (vq->size - 1)].len =\n+\t\t\t\t\t\t\tpkt_len + vq->vhost_hlen;\n \n \t\tres_cur_idx++;\n \t\tpacket_success++;\n \n+\t\tif (unlikely(uncompleted_pkt == 1))\n+\t\t\tcontinue;\n+\n \t\trte_memcpy((void *)(uintptr_t)buff_hdr_addr,\n \t\t\t(const void *)&virtio_hdr, vq->vhost_hlen);\n \n@@ -589,7 +636,14 @@ rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,\n \t\tdesc = &vq->desc[head[entry_success]];\n \n \t\t/* Discard first buffer as it is the virtio header */\n-\t\tdesc = &vq->desc[desc->next];\n+\t\tif (desc->flags & VRING_DESC_F_NEXT) {\n+\t\t\tdesc = &vq->desc[desc->next];\n+\t\t\tvb_offset = 0;\n+\t\t\tvb_avail = desc->len;\n+\t\t} else {\n+\t\t\tvb_offset = vq->vhost_hlen;\n+\t\t\tvb_avail = desc->len - vb_offset;\n+\t\t}\n \n \t\t/* Buffer address translation. */\n \t\tvb_addr = gpa_to_vva(dev, desc->addr);\n@@ -608,8 +662,6 @@ rte_vhost_dequeue_burst(struct virtio_net *dev, uint16_t queue_id,\n \t\tvq->used->ring[used_idx].id = head[entry_success];\n \t\tvq->used->ring[used_idx].len = 0;\n \n-\t\tvb_offset = 0;\n-\t\tvb_avail = desc->len;\n \t\t/* Allocate an mbuf and populate the structure. */\n \t\tm = rte_pktmbuf_alloc(mbuf_pool);\n \t\tif (unlikely(m == NULL)) {\n",
    "prefixes": [
        "dpdk-dev",
        "v4",
        "1/4"
    ]
}