get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1353,
    "url": "https://patches.dpdk.org/api/patches/1353/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com/",
    "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": "<CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com",
    "date": "2014-11-19T20:48:33",
    "name": "[dpdk-dev] Enhance KNI DPDK-app-side to be Multi-Producer/Consumer",
    "commit_ref": null,
    "pull_url": null,
    "state": "not-applicable",
    "archived": true,
    "hash": "dcfb4f6240fc5048051b7acc671df8cf48a042c2",
    "submitter": {
        "id": 7,
        "url": "https://patches.dpdk.org/api/people/7/?format=api",
        "name": "Robert Sanford",
        "email": "rsanford2@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1353/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1353/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 5B3E57E18;\n\tWed, 19 Nov 2014 21:38:09 +0100 (CET)",
            "from mail-vc0-f173.google.com (mail-vc0-f173.google.com\n\t[209.85.220.173]) by dpdk.org (Postfix) with ESMTP id 9AA3A6A95\n\tfor <dev@dpdk.org>; Wed, 19 Nov 2014 21:38:06 +0100 (CET)",
            "by mail-vc0-f173.google.com with SMTP id id10so740891vcb.32\n\tfor <dev@dpdk.org>; Wed, 19 Nov 2014 12:48:33 -0800 (PST)",
            "by 10.31.129.205 with HTTP; Wed, 19 Nov 2014 12:48:33 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\n\th=mime-version:in-reply-to:references:date:message-id:subject:from:to\n\t:content-type; bh=0Jsj6qg+5KrPsRlL6rWSZ+qdTh9bt42vcmvjcZulXMQ=;\n\tb=p7XLXZ1oX6BUdWRIEC3AI0UtBDbhKrjhpMKnxC42UMEu3MHxfRj2UlOLP4ZI8enOce\n\t8SNg7vhiR8/umvEj3jfZ95cGIrVcwYJPqSZpvptuk6emk1+Dhd8zzVgGgloZ8l1qFrju\n\t01xUCsgyMJoqyBI3B2SVZ/gSOJ8GEQQdoKqzxSDo2nPFq91/7SwY8lKH7SrHZoa3N/ZH\n\tM+0isyljxNnYIDGhYmzec07UJRBLQXDiO7xIFrB6e47TZ+VLvwYXaYkVoJpY8h+92fW8\n\tBTyexWdrGwnkfpy3u7lIjCjjmjzUTaZ3IV33w9rjJA+AT1spedq5zQn+WtHXcogTl3vy\n\tbrbA==",
        "MIME-Version": "1.0",
        "X-Received": "by 10.52.37.43 with SMTP id v11mr32391632vdj.3.1416430113132;\n\tWed, 19 Nov 2014 12:48:33 -0800 (PST)",
        "In-Reply-To": "<DFDF335405C17848924A094BC35766CF0A9B9418@SHSMSX104.ccr.corp.intel.com>",
        "References": "<D08BA44A.4363%rsanford@akamai.com>\n\t<DFDF335405C17848924A094BC35766CF0A9B9418@SHSMSX104.ccr.corp.intel.com>",
        "Date": "Wed, 19 Nov 2014 15:48:33 -0500",
        "Message-ID": "<CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com>",
        "From": "Robert Sanford <rsanford2@gmail.com>",
        "To": "\"Zhou, Danny\" <danny.zhou@intel.com>, \"dev@dpdk.org\" <dev@dpdk.org>",
        "Content-Type": "text/plain; charset=UTF-8",
        "X-Content-Filtered-By": "Mailman/MimeDel 2.1.15",
        "Subject": "Re: [dpdk-dev] Enhance KNI DPDK-app-side to be\n\tMulti-Producer/Consumer",
        "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": "Hi Danny,\n\nOn Fri, Nov 14, 2014 at 7:04 PM, Zhou, Danny <danny.zhou@intel.com> wrote:\n\n> It will be always good if you can submit the RFC patch in terms of KNI\n> optimization.\n>\n> On the other hand, do you have any perf. data to prove that your patchset\n> could improve\n> KNI performance which is the concern that most customers care about? We\n> introduced\n> multiple-threaded KNI kernel support last year, if I remember correctly,\n> the key perform\n> bottle-neck we found is the skb alloc/free and memcpy between skb and\n> mbuf. Would be\n> very happy if your patchset can approve I am wrong.\n\n\n\nThis is not an attempt to improve raw performance. Our modest goal is to\nmake librte_kni's RX/TX burst APIs multithreaded, without changing\nrte_kni.ko. In this RFC patch, we make it possible for multiple cores to\nconcurrently invoke rte_kni_tx_burst (or rte_kni_rx_burst) for the same KNI\ndevice.\n\nAt the moment, multiple cores invoking rte_kni_tx_burst for the same device\ncannot function correctly, because the rte_kni_fifo structures (memory\nshared between app and kernel driver) are single-producer, single-consumer.\nThe following patch supplements the rte_kni_fifo structure with an\nadditional structure that is private to the application, and we borrow\nlibrte_ring's MP/MC enqueue/dequeue logic.\n\nHere is a patch for 1.8. We have only tested a 1.7.1 version. Please have a\nlook and let us know whether you think something like this would be useful.\n\n--\nThanks,\nRobert\n\n\n*Signed-off-by: Robert Sanford <rsanford@akamai.com <rsanford@akamai.com>>*\n\n---\n lib/librte_kni/rte_kni.c      |   21 +++++-\n lib/librte_kni/rte_kni_fifo.h |  131\n+++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 148 insertions(+), 4 deletions(-)\n\n+}",
    "diff": "diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c\nindex fdb7509..8009173 100644\n--- a/lib/librte_kni/rte_kni.c\n+++ b/lib/librte_kni/rte_kni.c\n@@ -76,6 +76,11 @@ struct rte_kni {\n  struct rte_kni_fifo *alloc_q;       /**< Allocated mbufs queue */\n  struct rte_kni_fifo *free_q;        /**< To be freed mbufs queue */\n\n+ struct rte_kni_fifo_multi tx_q_mc;  /**< Make tx_q multi-consumer */\n+ struct rte_kni_fifo_multi alloc_q_mp;/**< Make alloc_q multi-producer */\n+ struct rte_kni_fifo_multi rx_q_mp;  /**< Make rx_q multi-producer */\n+ struct rte_kni_fifo_multi free_q_mc;/**< Make free_q multi-consumer */\n+\n  /* For request & response */\n  struct rte_kni_fifo *req_q;         /**< Request queue */\n  struct rte_kni_fifo *resp_q;        /**< Response queue */\n@@ -414,6 +419,11 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,\n  kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);\n  dev_info.free_phys = mz->phys_addr;\n\n+ kni_fifo_multi_init(&ctx->tx_q_mc, KNI_FIFO_COUNT_MAX);\n+ kni_fifo_multi_init(&ctx->alloc_q_mp, KNI_FIFO_COUNT_MAX);\n+ kni_fifo_multi_init(&ctx->rx_q_mp, KNI_FIFO_COUNT_MAX);\n+ kni_fifo_multi_init(&ctx->free_q_mc, KNI_FIFO_COUNT_MAX);\n+\n  /* Request RING */\n  mz = slot->m_req_q;\n  ctx->req_q = mz->addr;\n@@ -557,7 +567,8 @@ rte_kni_handle_request(struct rte_kni *kni)\n unsigned\n rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned\nnum)\n {\n- unsigned ret = kni_fifo_put(kni->rx_q, (void **)mbufs, num);\n+ unsigned ret = kni_fifo_put_mp(kni->rx_q, &kni->rx_q_mp, (void **)mbufs,\n+ num);\n\n  /* Get mbufs from free_q and then free them */\n  kni_free_mbufs(kni);\n@@ -568,7 +579,8 @@ rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf\n**mbufs, unsigned num)\n unsigned\n rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned\nnum)\n {\n- unsigned ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num);\n+ unsigned ret = kni_fifo_get_mc(kni->tx_q, &kni->tx_q_mc,\n+ (void **)mbufs, num);\n\n  /* Allocate mbufs and then put them into alloc_q */\n  kni_allocate_mbufs(kni);\n@@ -582,7 +594,8 @@ kni_free_mbufs(struct rte_kni *kni)\n  int i, ret;\n  struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];\n\n- ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM);\n+ ret = kni_fifo_get_mc(kni->free_q, &kni->free_q_mc, (void **)pkts,\n+ MAX_MBUF_BURST_NUM);\n  if (likely(ret > 0)) {\n  for (i = 0; i < ret; i++)\n  rte_pktmbuf_free(pkts[i]);\n@@ -629,7 +642,7 @@ kni_allocate_mbufs(struct rte_kni *kni)\n  if (i <= 0)\n  return;\n\n- ret = kni_fifo_put(kni->alloc_q, (void **)pkts, i);\n+ ret = kni_fifo_put_mp(kni->alloc_q, &kni->alloc_q_mp, (void **)pkts, i);\n\n  /* Check if any mbufs not put into alloc_q, and then free them */\n  if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) {\ndiff --git a/lib/librte_kni/rte_kni_fifo.h b/lib/librte_kni/rte_kni_fifo.h\nindex 8cb8587..7dccba2 100644\n--- a/lib/librte_kni/rte_kni_fifo.h\n+++ b/lib/librte_kni/rte_kni_fifo.h\n@@ -91,3 +91,134 @@ kni_fifo_get(struct rte_kni_fifo *fifo, void **data,\nunsigned num)\n  fifo->read = new_read;\n  return i;\n }\n+\n+\n+/**\n+ * Suplemental members to facilitate MP/MC access to KNI FIFOs.\n+ */\n+struct rte_kni_fifo_multi {\n+ volatile uint32_t head;\n+ volatile uint32_t tail;\n+ uint32_t mask;\n+ uint32_t size;\n+};\n+\n+/**\n+ * Initialize a kni fifo MP/MC struct.\n+ */\n+static void\n+kni_fifo_multi_init(struct rte_kni_fifo_multi *multi, unsigned size)\n+{\n+ multi->head = 0;\n+ multi->tail = 0;\n+ multi->mask = (typeof(multi->mask))(size - 1);\n+ multi->size = (typeof(multi->size))size;\n+}\n+\n+/**\n+ * Adds num elements into the fifo. Return the number actually written.\n+ *\n+ * Multiple-producer version, modeled after __rte_ring_mp_do_enqueue().\n+ */\n+static inline unsigned\n+kni_fifo_put_mp(struct rte_kni_fifo *fifo, struct rte_kni_fifo_multi *prod,\n+ void **data, unsigned n)\n+{\n+ uint32_t prod_head, prod_next;\n+ uint32_t cons_tail, free_entries;\n+ const unsigned max = n;\n+ int success;\n+ unsigned i;\n+ const uint32_t mask = prod->mask;\n+\n+ /* Move prod->head atomically. */\n+ do {\n+ /* Reset n to the initial burst count. */\n+ n = max;\n+\n+ prod_head = prod->head;\n+ cons_tail = fifo->read;\n+\n+ free_entries = (mask + cons_tail - prod_head) & mask;\n+\n+ /* Check that we have enough room in ring. */\n+ if (unlikely(n > free_entries)) {\n+ if (unlikely(free_entries == 0))\n+ return 0;\n+ n = free_entries;\n+ }\n+\n+ prod_next = (prod_head + n) & mask;\n+ success = rte_atomic32_cmpset(&prod->head, prod_head, prod_next);\n+ } while (unlikely(success == 0));\n+\n+ /* Write entries in ring. */\n+ for (i = 0; i < n; i++) {\n+ fifo->buffer[(prod_head + i) & mask] = data[i];\n+ }\n+ rte_compiler_barrier();\n+\n+ /* If there are other enqueues in progress that preceded us,\n+ * we need to wait for them to complete.\n+ */\n+ while (unlikely(prod->tail != prod_head))\n+ rte_pause();\n+\n+ prod->tail = prod_next;\n+ fifo->write = prod_next;\n+ return n;\n+}\n+\n+/**\n+ * Get up to num elements from the fifo. Return the number actully read.\n+ *\n+ * Multiple-consumer version, modeled after __rte_ring_mc_do_dequeue().\n+ */\n+static inline unsigned\n+kni_fifo_get_mc(struct rte_kni_fifo *fifo, struct rte_kni_fifo_multi *cons,\n+ void **data, unsigned n)\n+{\n+ uint32_t cons_head, prod_tail;\n+ uint32_t cons_next, entries;\n+ const unsigned max = n;\n+ int success;\n+ unsigned i;\n+ const uint32_t mask = cons->mask;\n+\n+ /* Move cons->head atomically. */\n+ do {\n+ /* Restore n as it may change every loop. */\n+ n = max;\n+\n+ cons_head = cons->head;\n+ prod_tail = fifo->write;\n+\n+ entries = (prod_tail - cons_head + mask + 1) & mask;\n+\n+ /* Set the actual entries for dequeue. */\n+ if (n > entries) {\n+ if (unlikely(entries == 0))\n+ return 0;\n+ n = entries;\n+ }\n+\n+ cons_next = (cons_head + n) & mask;\n+ success = rte_atomic32_cmpset(&cons->head, cons_head, cons_next);\n+ } while (unlikely(success == 0));\n+\n+ /* Copy entries from ring. */\n+ for (i = 0; i < n; i++) {\n+ data[i] = fifo->buffer[(cons_head + i) & mask];\n+ }\n+ rte_compiler_barrier();\n+\n+ /* If there are other dequeues in progress that preceded us,\n+ * we need to wait for them to complete.\n+ */\n+ while (unlikely(cons->tail != cons_head))\n+ rte_pause();\n+\n+ cons->tail = cons_next;\n+ fifo->read = cons_next;\n+ return n;\n",
    "prefixes": [
        "dpdk-dev"
    ]
}