get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1354,
    "url": "https://patches.dpdk.org/api/patches/1354/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/DFDF335405C17848924A094BC35766CF0A9C0CD9@SHSMSX104.ccr.corp.intel.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": "<DFDF335405C17848924A094BC35766CF0A9C0CD9@SHSMSX104.ccr.corp.intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/DFDF335405C17848924A094BC35766CF0A9C0CD9@SHSMSX104.ccr.corp.intel.com",
    "date": "2014-11-20T04:00:58",
    "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": "4b3dbf4e4bdbe1c4384b5d4d5e8a16047a002b3e",
    "submitter": {
        "id": 29,
        "url": "https://patches.dpdk.org/api/people/29/?format=api",
        "name": "Zhou, Danny",
        "email": "danny.zhou@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/DFDF335405C17848924A094BC35766CF0A9C0CD9@SHSMSX104.ccr.corp.intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1354/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1354/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 20B117EB3;\n\tThu, 20 Nov 2014 04:50:42 +0100 (CET)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby dpdk.org (Postfix) with ESMTP id EA4D56880\n\tfor <dev@dpdk.org>; Thu, 20 Nov 2014 04:50:36 +0100 (CET)",
            "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby fmsmga102.fm.intel.com with ESMTP; 19 Nov 2014 20:01:03 -0800",
            "from kmsmsx153.gar.corp.intel.com ([172.21.73.88])\n\tby FMSMGA003.fm.intel.com with ESMTP; 19 Nov 2014 19:51:35 -0800",
            "from shsmsx101.ccr.corp.intel.com (10.239.4.153) by\n\tKMSMSX153.gar.corp.intel.com (172.21.73.88) with Microsoft SMTP\n\tServer (TLS) id 14.3.195.1; Thu, 20 Nov 2014 12:00:59 +0800",
            "from shsmsx104.ccr.corp.intel.com ([169.254.5.182]) by\n\tSHSMSX101.ccr.corp.intel.com ([169.254.1.110]) with mapi id\n\t14.03.0195.001; Thu, 20 Nov 2014 12:00:58 +0800"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"4.97,862,1389772800\"; \n\td=\"scan'208,217\";a=\"419052586\"",
        "From": "\"Zhou, Danny\" <danny.zhou@intel.com>",
        "To": "Robert Sanford <rsanford2@gmail.com>",
        "Thread-Topic": "[dpdk-dev] Enhance KNI DPDK-app-side to be\n\tMulti-Producer/Consumer",
        "Thread-Index": "AdAATsFuOFSVQkZQSEOfgayUigXcoQAGA4TQAOQUPYAAHwr3sA==",
        "Date": "Thu, 20 Nov 2014 04:00:58 +0000",
        "Message-ID": "<DFDF335405C17848924A094BC35766CF0A9C0CD9@SHSMSX104.ccr.corp.intel.com>",
        "References": "<D08BA44A.4363%rsanford@akamai.com>\n\t<DFDF335405C17848924A094BC35766CF0A9B9418@SHSMSX104.ccr.corp.intel.com>\n\t<CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com>",
        "In-Reply-To": "<CA+cr1couxWQp+UhcKrRenuEdy34SH11Z=Lr6mrAWL_OPkC5v-A@mail.gmail.com>",
        "Accept-Language": "zh-CN, en-US",
        "Content-Language": "en-US",
        "X-MS-Has-Attach": "",
        "X-MS-TNEF-Correlator": "",
        "x-originating-ip": "[10.239.127.40]",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "X-Content-Filtered-By": "Mailman/MimeDel 2.1.15",
        "Cc": "\"dev@dpdk.org\" <dev@dpdk.org>",
        "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": "Robert, I roughly review the code below about lockless KNI fifo with MP/MC support , which looks good to me. Comparing to SP/SC implementation, I think It should introduce a little performance degradation but it will be making your multiple-threaded DPDK application easier to program.  Do you have plan to support MP/MC in kernel part of KNI as well?\r\n\r\nFrom: Robert Sanford [mailto:rsanford2@gmail.com]\r\nSent: Thursday, November 20, 2014 4:49 AM\r\nTo: Zhou, Danny; dev@dpdk.org\r\nSubject: Re: [dpdk-dev] Enhance KNI DPDK-app-side to be Multi-Producer/Consumer\r\n\r\nHi Danny,\r\n\r\nOn Fri, Nov 14, 2014 at 7:04 PM, Zhou, Danny <danny.zhou@intel.com<mailto:danny.zhou@intel.com>> wrote:\r\nIt will be always good if you can submit the RFC patch in terms of KNI optimization.\r\n\r\nOn the other hand, do you have any perf. data to prove that your patchset could improve\r\nKNI performance which is the concern that most customers care about? We introduced\r\nmultiple-threaded KNI kernel support last year, if I remember correctly, the key perform\r\nbottle-neck we found is the skb alloc/free and memcpy between skb and mbuf. Would be\r\nvery happy if your patchset can approve I am wrong.\r\n\r\n\r\nThis is not an attempt to improve raw performance. Our modest goal is to make librte_kni's RX/TX burst APIs multithreaded, without changing rte_kni.ko. In this RFC patch, we make it possible for multiple cores to concurrently invoke rte_kni_tx_burst (or rte_kni_rx_burst) for the same KNI device.\r\n\r\nAt the moment, multiple cores invoking rte_kni_tx_burst for the same device cannot function correctly, because the rte_kni_fifo structures (memory shared between app and kernel driver) are single-producer, single-consumer. The following patch supplements the rte_kni_fifo structure with an additional structure that is private to the application, and we borrow librte_ring's MP/MC enqueue/dequeue logic.\r\n\r\n\r\nHere is a patch for 1.8. We have only tested a 1.7.1 version. Please have a look and let us know whether you think something like this would be useful.\r\n\r\n--\r\nThanks,\r\nRobert\r\n\r\n\r\nSigned-off-by: Robert Sanford <rsanford@akamai.com<mailto:rsanford@akamai.com>>\r\n\r\n---\r\n lib/librte_kni/rte_kni.c      |   21 +++++-\r\n lib/librte_kni/rte_kni_fifo.h |  131 +++++++++++++++++++++++++++++++++++++++++\r\n 2 files changed, 148 insertions(+), 4 deletions(-)\r\n\r\n--\r\n1.7.1",
    "diff": "diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c\r\nindex fdb7509..8009173 100644\r\n--- a/lib/librte_kni/rte_kni.c\r\n+++ b/lib/librte_kni/rte_kni.c\r\n@@ -76,6 +76,11 @@ struct rte_kni {\r\n  struct rte_kni_fifo *alloc_q;       /**< Allocated mbufs queue */\r\n  struct rte_kni_fifo *free_q;        /**< To be freed mbufs queue */\r\n\r\n+  struct rte_kni_fifo_multi tx_q_mc;  /**< Make tx_q multi-consumer */\r\n+  struct rte_kni_fifo_multi alloc_q_mp;/**< Make alloc_q multi-producer */\r\n+  struct rte_kni_fifo_multi rx_q_mp;  /**< Make rx_q multi-producer */\r\n+  struct rte_kni_fifo_multi free_q_mc;/**< Make free_q multi-consumer */\r\n+\r\n  /* For request & response */\r\n  struct rte_kni_fifo *req_q;         /**< Request queue */\r\n  struct rte_kni_fifo *resp_q;        /**< Response queue */\r\n@@ -414,6 +419,11 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,\r\n  kni_fifo_init(ctx->free_q, KNI_FIFO_COUNT_MAX);\r\n  dev_info.free_phys = mz->phys_addr;\r\n\r\n+  kni_fifo_multi_init(&ctx->tx_q_mc, KNI_FIFO_COUNT_MAX);\r\n+  kni_fifo_multi_init(&ctx->alloc_q_mp, KNI_FIFO_COUNT_MAX);\r\n+  kni_fifo_multi_init(&ctx->rx_q_mp, KNI_FIFO_COUNT_MAX);\r\n+  kni_fifo_multi_init(&ctx->free_q_mc, KNI_FIFO_COUNT_MAX);\r\n+\r\n  /* Request RING */\r\n  mz = slot->m_req_q;\r\n  ctx->req_q = mz->addr;\r\n@@ -557,7 +567,8 @@ rte_kni_handle_request(struct rte_kni *kni)\r\n unsigned\r\n rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)\r\n {\r\n-  unsigned ret = kni_fifo_put(kni->rx_q, (void **)mbufs, num);\r\n+  unsigned ret = kni_fifo_put_mp(kni->rx_q, &kni->rx_q_mp, (void **)mbufs,\r\n+         num);\r\n\r\n  /* Get mbufs from free_q and then free them */\r\n  kni_free_mbufs(kni);\r\n@@ -568,7 +579,8 @@ rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)\r\n unsigned\r\n rte_kni_rx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned num)\r\n {\r\n-  unsigned ret = kni_fifo_get(kni->tx_q, (void **)mbufs, num);\r\n+  unsigned ret = kni_fifo_get_mc(kni->tx_q, &kni->tx_q_mc,\r\n+         (void **)mbufs, num);\r\n\r\n  /* Allocate mbufs and then put them into alloc_q */\r\n  kni_allocate_mbufs(kni);\r\n@@ -582,7 +594,8 @@ kni_free_mbufs(struct rte_kni *kni)\r\n  int i, ret;\r\n  struct rte_mbuf *pkts[MAX_MBUF_BURST_NUM];\r\n\r\n-  ret = kni_fifo_get(kni->free_q, (void **)pkts, MAX_MBUF_BURST_NUM);\r\n+  ret = kni_fifo_get_mc(kni->free_q, &kni->free_q_mc, (void **)pkts,\r\n+         MAX_MBUF_BURST_NUM);\r\n  if (likely(ret > 0)) {\r\n     for (i = 0; i < ret; i++)\r\n         rte_pktmbuf_free(pkts[i]);\r\n@@ -629,7 +642,7 @@ kni_allocate_mbufs(struct rte_kni *kni)\r\n  if (i <= 0)\r\n     return;\r\n\r\n-  ret = kni_fifo_put(kni->alloc_q, (void **)pkts, i);\r\n+  ret = kni_fifo_put_mp(kni->alloc_q, &kni->alloc_q_mp, (void **)pkts, i);\r\n\r\n  /* Check if any mbufs not put into alloc_q, and then free them */\r\n  if (ret >= 0 && ret < i && ret < MAX_MBUF_BURST_NUM) {\r\ndiff --git a/lib/librte_kni/rte_kni_fifo.h b/lib/librte_kni/rte_kni_fifo.h\r\nindex 8cb8587..7dccba2 100644\r\n--- a/lib/librte_kni/rte_kni_fifo.h\r\n+++ b/lib/librte_kni/rte_kni_fifo.h\r\n@@ -91,3 +91,134 @@ kni_fifo_get(struct rte_kni_fifo *fifo, void **data, unsigned num)\r\n  fifo->read = new_read;\r\n  return i;\r\n }\r\n+\r\n+\r\n+/**\r\n+ * Suplemental members to facilitate MP/MC access to KNI FIFOs.\r\n+ */\r\n+struct rte_kni_fifo_multi {\r\n+  volatile uint32_t head;\r\n+  volatile uint32_t tail;\r\n+  uint32_t mask;\r\n+  uint32_t size;\r\n+};\r\n+\r\n+/**\r\n+ * Initialize a kni fifo MP/MC struct.\r\n+ */\r\n+static void\r\n+kni_fifo_multi_init(struct rte_kni_fifo_multi *multi, unsigned size)\r\n+{\r\n+  multi->head = 0;\r\n+  multi->tail = 0;\r\n+  multi->mask = (typeof(multi->mask))(size - 1);\r\n+  multi->size = (typeof(multi->size))size;\r\n+}\r\n+\r\n+/**\r\n+ * Adds num elements into the fifo. Return the number actually written.\r\n+ *\r\n+ * Multiple-producer version, modeled after __rte_ring_mp_do_enqueue().\r\n+ */\r\n+static inline unsigned\r\n+kni_fifo_put_mp(struct rte_kni_fifo *fifo, struct rte_kni_fifo_multi *prod,\r\n+     void **data, unsigned n)\r\n+{\r\n+  uint32_t prod_head, prod_next;\r\n+  uint32_t cons_tail, free_entries;\r\n+  const unsigned max = n;\r\n+  int success;\r\n+  unsigned i;\r\n+  const uint32_t mask = prod->mask;\r\n+\r\n+  /* Move prod->head atomically. */\r\n+  do {\r\n+     /* Reset n to the initial burst count. */\r\n+     n = max;\r\n+\r\n+     prod_head = prod->head;\r\n+     cons_tail = fifo->read;\r\n+\r\n+     free_entries = (mask + cons_tail - prod_head) & mask;\r\n+\r\n+     /* Check that we have enough room in ring. */\r\n+     if (unlikely(n > free_entries)) {\r\n+         if (unlikely(free_entries == 0))\r\n+            return 0;\r\n+         n = free_entries;\r\n+     }\r\n+\r\n+     prod_next = (prod_head + n) & mask;\r\n+     success = rte_atomic32_cmpset(&prod->head, prod_head, prod_next);\r\n+  } while (unlikely(success == 0));\r\n+\r\n+  /* Write entries in ring. */\r\n+  for (i = 0; i < n; i++) {\r\n+     fifo->buffer[(prod_head + i) & mask] = data[i];\r\n+  }\r\n+  rte_compiler_barrier();\r\n+\r\n+  /* If there are other enqueues in progress that preceded us,\r\n+  * we need to wait for them to complete.\r\n+  */\r\n+  while (unlikely(prod->tail != prod_head))\r\n+     rte_pause();\r\n+\r\n+  prod->tail = prod_next;\r\n+  fifo->write = prod_next;\r\n+  return n;\r\n+}\r\n+\r\n+/**\r\n+ * Get up to num elements from the fifo. Return the number actully read.\r\n+ *\r\n+ * Multiple-consumer version, modeled after __rte_ring_mc_do_dequeue().\r\n+ */\r\n+static inline unsigned\r\n+kni_fifo_get_mc(struct rte_kni_fifo *fifo, struct rte_kni_fifo_multi *cons,\r\n+     void **data, unsigned n)\r\n+{\r\n+  uint32_t cons_head, prod_tail;\r\n+  uint32_t cons_next, entries;\r\n+  const unsigned max = n;\r\n+  int success;\r\n+  unsigned i;\r\n+  const uint32_t mask = cons->mask;\r\n+\r\n+  /* Move cons->head atomically. */\r\n+  do {\r\n+     /* Restore n as it may change every loop. */\r\n+     n = max;\r\n+\r\n+     cons_head = cons->head;\r\n+     prod_tail = fifo->write;\r\n+\r\n+     entries = (prod_tail - cons_head + mask + 1) & mask;\r\n+\r\n+     /* Set the actual entries for dequeue. */\r\n+     if (n > entries) {\r\n+         if (unlikely(entries == 0))\r\n+            return 0;\r\n+         n = entries;\r\n+     }\r\n+\r\n+     cons_next = (cons_head + n) & mask;\r\n+     success = rte_atomic32_cmpset(&cons->head, cons_head, cons_next);\r\n+  } while (unlikely(success == 0));\r\n+\r\n+  /* Copy entries from ring. */\r\n+  for (i = 0; i < n; i++) {\r\n+     data[i] = fifo->buffer[(cons_head + i) & mask];\r\n+  }\r\n+  rte_compiler_barrier();\r\n+\r\n+  /* If there are other dequeues in progress that preceded us,\r\n+  * we need to wait for them to complete.\r\n+  */\r\n+  while (unlikely(cons->tail != cons_head))\r\n+     rte_pause();\r\n+\r\n+  cons->tail = cons_next;\r\n+  fifo->read = cons_next;\r\n+  return n;\r\n+}\r\n",
    "prefixes": [
        "dpdk-dev"
    ]
}