get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 1233,
    "url": "https://patches.dpdk.org/api/patches/1233/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1415615912-46212-1-git-send-email-jigsaw@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": "<1415615912-46212-1-git-send-email-jigsaw@gmail.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1415615912-46212-1-git-send-email-jigsaw@gmail.com",
    "date": "2014-11-10T10:38:32",
    "name": "[dpdk-dev] Add in_flight_bitmask so as to use full 32 bits of tag.",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "5e0f2d92270b8a545cbac1056a3644e9244d09ce",
    "submitter": {
        "id": 105,
        "url": "https://patches.dpdk.org/api/people/105/?format=api",
        "name": "Qinglai Xiao",
        "email": "jigsaw@gmail.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1415615912-46212-1-git-send-email-jigsaw@gmail.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/1233/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/1233/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 CBB3B7E1C;\n\tMon, 10 Nov 2014 11:29:07 +0100 (CET)",
            "from mail-lb0-f178.google.com (mail-lb0-f178.google.com\n\t[209.85.217.178]) by dpdk.org (Postfix) with ESMTP id 15F636828\n\tfor <dev@dpdk.org>; Mon, 10 Nov 2014 11:28:51 +0100 (CET)",
            "by mail-lb0-f178.google.com with SMTP id f15so6137659lbj.23\n\tfor <dev@dpdk.org>; Mon, 10 Nov 2014 02:38:35 -0800 (PST)",
            "from localhost.localdomain ([194.251.119.201])\n\tby mx.google.com with ESMTPSA id\n\tg2sm5196913lbd.35.2014.11.10.02.38.34 for <multiple recipients>\n\t(version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tMon, 10 Nov 2014 02:38:35 -0800 (PST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113;\n\th=from:to:cc:subject:date:message-id;\n\tbh=X4wqYU7rodeyMnJw1zZ7jD89ZA2af62FfZvoEPztGj8=;\n\tb=GY25sUroqNDcHmSot13NP8n8/Tsba1HFwi7emcc8IF2HeGLnondejAuwpaCN4NPfhS\n\tOgiawsgT1x/AsRUsuk/Oxv5guoI1yImR5zifocMzEDzbrB+fEvSBk2S0eiDhcrGovF1T\n\tOsZFfwTGDay4tMxK/z2NFfMWP1OxyLh7z9a9j8ZcGIJJXkveKG9s7kseFEOeNsUMvELD\n\th9o25tjkQ+1+fw8VlRzH2HlybIABZm/6m34HdOUiUWKnDtCC08kF1CZU23RMioOoPKxV\n\thHr7DHdvznrKVi71ur442V9LUWlDJdItF+9cMyOIxC/3a6oA/T1BknzWfQmSysZNU2OO\n\tcFbw==",
        "X-Received": "by 10.152.27.2 with SMTP id p2mr19216286lag.19.1415615915691;\n\tMon, 10 Nov 2014 02:38:35 -0800 (PST)",
        "From": "Qinglai Xiao <jigsaw@gmail.com>",
        "To": "dev@dpdk.org",
        "Date": "Mon, 10 Nov 2014 12:38:32 +0200",
        "Message-Id": "<1415615912-46212-1-git-send-email-jigsaw@gmail.com>",
        "X-Mailer": "git-send-email 1.7.1",
        "Cc": "Qinglai Xiao <jigsaw@gmail.com>",
        "Subject": "[dpdk-dev] [PATCH] Add in_flight_bitmask so as to use full 32 bits\n\tof tag.",
        "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": "User application is advocated to set the newly introduced union field\nmbuf->hash.usr as flow id, which is uint32_t.\nWith introduction of in_flight_bitmask, the whole 32 bits of tag can\nbe used.\n\nFurther more, this patch fixed the integer overflow when finding the\nmatched tags.\n\nNote that currently librte_distributor supports up to 64 worker\nthreads. If more workers are needed, the size of in_flight_bitmask and\nthe algorithm of finding matched tag must be revised.\n\nSigned-off-by: Qinglai Xiao <jigsaw@gmail.com>\n---\n app/test/test_distributor.c              |   18 ++++++------\n app/test/test_distributor_perf.c         |    4 +-\n lib/librte_distributor/rte_distributor.c |   45 +++++++++++++++++++++--------\n lib/librte_distributor/rte_distributor.h |    3 ++\n lib/librte_mbuf/rte_mbuf.h               |    1 +\n 5 files changed, 47 insertions(+), 24 deletions(-)",
    "diff": "diff --git a/app/test/test_distributor.c b/app/test/test_distributor.c\nindex ce06436..9e8c06d 100644\n--- a/app/test/test_distributor.c\n+++ b/app/test/test_distributor.c\n@@ -120,7 +120,7 @@ sanity_test(struct rte_distributor *d, struct rte_mempool *p)\n \t/* now set all hash values in all buffers to zero, so all pkts go to the\n \t * one worker thread */\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = 0;\n+\t\tbufs[i]->hash.usr = 0;\n \n \trte_distributor_process(d, bufs, BURST);\n \trte_distributor_flush(d);\n@@ -142,7 +142,7 @@ sanity_test(struct rte_distributor *d, struct rte_mempool *p)\n \tif (rte_lcore_count() >= 3) {\n \t\tclear_packet_count();\n \t\tfor (i = 0; i < BURST; i++)\n-\t\t\tbufs[i]->hash.rss = (i & 1) << 8;\n+\t\t\tbufs[i]->hash.usr = (i & 1) << 8;\n \n \t\trte_distributor_process(d, bufs, BURST);\n \t\trte_distributor_flush(d);\n@@ -167,7 +167,7 @@ sanity_test(struct rte_distributor *d, struct rte_mempool *p)\n \t * so load gets distributed */\n \tclear_packet_count();\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = i;\n+\t\tbufs[i]->hash.usr = i;\n \n \trte_distributor_process(d, bufs, BURST);\n \trte_distributor_flush(d);\n@@ -199,7 +199,7 @@ sanity_test(struct rte_distributor *d, struct rte_mempool *p)\n \t\treturn -1;\n \t}\n \tfor (i = 0; i < BIG_BATCH; i++)\n-\t\tmany_bufs[i]->hash.rss = i << 2;\n+\t\tmany_bufs[i]->hash.usr = i << 2;\n \n \tfor (i = 0; i < BIG_BATCH/BURST; i++) {\n \t\trte_distributor_process(d, &many_bufs[i*BURST], BURST);\n@@ -280,7 +280,7 @@ sanity_test_with_mbuf_alloc(struct rte_distributor *d, struct rte_mempool *p)\n \t\twhile (rte_mempool_get_bulk(p, (void *)bufs, BURST) < 0)\n \t\t\trte_distributor_process(d, NULL, 0);\n \t\tfor (j = 0; j < BURST; j++) {\n-\t\t\tbufs[j]->hash.rss = (i+j) << 1;\n+\t\t\tbufs[j]->hash.usr = (i+j) << 1;\n \t\t\trte_mbuf_refcnt_set(bufs[j], 1);\n \t\t}\n \n@@ -359,7 +359,7 @@ sanity_test_with_worker_shutdown(struct rte_distributor *d,\n \t/* now set all hash values in all buffers to zero, so all pkts go to the\n \t * one worker thread */\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = 0;\n+\t\tbufs[i]->hash.usr = 0;\n \n \trte_distributor_process(d, bufs, BURST);\n \t/* at this point, we will have processed some packets and have a full\n@@ -372,7 +372,7 @@ sanity_test_with_worker_shutdown(struct rte_distributor *d,\n \t\treturn -1;\n \t}\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = 0;\n+\t\tbufs[i]->hash.usr = 0;\n \n \t/* get worker zero to quit */\n \tzero_quit = 1;\n@@ -416,7 +416,7 @@ test_flush_with_worker_shutdown(struct rte_distributor *d,\n \t/* now set all hash values in all buffers to zero, so all pkts go to the\n \t * one worker thread */\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = 0;\n+\t\tbufs[i]->hash.usr = 0;\n \n \trte_distributor_process(d, bufs, BURST);\n \t/* at this point, we will have processed some packets and have a full\n@@ -488,7 +488,7 @@ quit_workers(struct rte_distributor *d, struct rte_mempool *p)\n \tzero_quit = 0;\n \tquit = 1;\n \tfor (i = 0; i < num_workers; i++)\n-\t\tbufs[i]->hash.rss = i << 1;\n+\t\tbufs[i]->hash.usr = i << 1;\n \trte_distributor_process(d, bufs, num_workers);\n \n \trte_mempool_put_bulk(p, (void *)bufs, num_workers);\ndiff --git a/app/test/test_distributor_perf.c b/app/test/test_distributor_perf.c\nindex b04864c..48ee344 100644\n--- a/app/test/test_distributor_perf.c\n+++ b/app/test/test_distributor_perf.c\n@@ -159,7 +159,7 @@ perf_test(struct rte_distributor *d, struct rte_mempool *p)\n \t}\n \t/* ensure we have different hash value for each pkt */\n \tfor (i = 0; i < BURST; i++)\n-\t\tbufs[i]->hash.rss = i;\n+\t\tbufs[i]->hash.usr = i;\n \n \tstart = rte_rdtsc();\n \tfor (i = 0; i < (1<<ITER_POWER); i++)\n@@ -198,7 +198,7 @@ quit_workers(struct rte_distributor *d, struct rte_mempool *p)\n \n \tquit = 1;\n \tfor (i = 0; i < num_workers; i++)\n-\t\tbufs[i]->hash.rss = i << 1;\n+\t\tbufs[i]->hash.usr = i << 1;\n \trte_distributor_process(d, bufs, num_workers);\n \n \trte_mempool_put_bulk(p, (void *)bufs, num_workers);\ndiff --git a/lib/librte_distributor/rte_distributor.c b/lib/librte_distributor/rte_distributor.c\nindex 656ee5c..a84ea97 100644\n--- a/lib/librte_distributor/rte_distributor.c\n+++ b/lib/librte_distributor/rte_distributor.c\n@@ -92,7 +92,13 @@ struct rte_distributor {\n \tunsigned num_workers;                 /**< Number of workers polling */\n \n \tuint32_t in_flight_tags[RTE_MAX_LCORE];\n-\t\t/**< Tracks the tag being processed per core, 0 == no pkt */\n+\t\t/**< Tracks the tag being processed per core */\n+\tuint64_t in_flight_bitmask;\n+\t\t/**< on/off bits for in-flight tags.\n+\t\t * Note that if RTE_MAX_LCORE is larger than 64 then\n+\t\t * the bitmask has to expand.\n+\t\t */\n+\n \tstruct rte_distributor_backlog backlog[RTE_MAX_LCORE];\n \n \tunion rte_distributor_buffer bufs[RTE_MAX_LCORE];\n@@ -189,6 +195,7 @@ static inline void\n handle_worker_shutdown(struct rte_distributor *d, unsigned wkr)\n {\n \td->in_flight_tags[wkr] = 0;\n+\td->in_flight_bitmask &= ~(1UL << wkr);\n \td->bufs[wkr].bufptr64 = 0;\n \tif (unlikely(d->backlog[wkr].count != 0)) {\n \t\t/* On return of a packet, we need to move the\n@@ -211,7 +218,10 @@ handle_worker_shutdown(struct rte_distributor *d, unsigned wkr)\n \t\t\tpkts[i] = (void *)((uintptr_t)(bl->pkts[idx] >>\n \t\t\t\t\tRTE_DISTRIB_FLAG_BITS));\n \t\t}\n-\t\t/* recursive call */\n+\t\t/* recursive call.\n+\t\t * Note that the tags were set before first level call\n+\t\t * to rte_distributor_process.\n+\t\t */\n \t\trte_distributor_process(d, pkts, i);\n \t\tbl->count = bl->start = 0;\n \t}\n@@ -242,6 +252,7 @@ process_returns(struct rte_distributor *d)\n \t\t\telse {\n \t\t\t\td->bufs[wkr].bufptr64 = RTE_DISTRIB_GET_BUF;\n \t\t\t\td->in_flight_tags[wkr] = 0;\n+\t\t\t\td->in_flight_bitmask &= ~(1UL << wkr);\n \t\t\t}\n \t\t\toldbuf = data >> RTE_DISTRIB_FLAG_BITS;\n \t\t} else if (data & RTE_DISTRIB_RETURN_BUF) {\n@@ -284,17 +295,21 @@ rte_distributor_process(struct rte_distributor *d,\n \t\t\tnext_value = (((int64_t)(uintptr_t)next_mb)\n \t\t\t\t\t<< RTE_DISTRIB_FLAG_BITS);\n \t\t\t/*\n-\t\t\t * Set the low bit on the tag, so we can guarantee that\n-\t\t\t * we never store a tag value of zero. That means we can\n-\t\t\t * use the zero-value to indicate that no packet is\n-\t\t\t * being processed by a worker.\n+\t\t\t * User is advocated to set tag vaue for each\n+\t\t\t * mbuf before calling rte_distributor_process.\n+\t\t\t * User defined tags are used to identify flows,\n+\t\t\t * or sessions.\n \t\t\t */\n-\t\t\tnew_tag = (next_mb->hash.rss | 1);\n+\t\t\tnew_tag = next_mb->hash.usr;\n \n-\t\t\tuint32_t match = 0;\n+\t\t\t/*\n+\t\t\t * Note that if RTE_MAX_LCORE is larger than 64 then\n+\t\t\t * the size of match has to be expanded.\n+\t\t\t */\n+\t\t\tuint64_t match = 0;\n \t\t\tunsigned i;\n \t\t\t/*\n-\t\t\t * to scan for a match use \"xor\" and \"not\" to get a 0/1\n+\t\t\t * To scan for a match use \"xor\" and \"not\" to get a 0/1\n \t\t\t * value, then use shifting to merge to single \"match\"\n \t\t\t * variable, where a one-bit indicates a match for the\n \t\t\t * worker given by the bit-position\n@@ -303,9 +318,11 @@ rte_distributor_process(struct rte_distributor *d,\n \t\t\t\tmatch |= (!(d->in_flight_tags[i] ^ new_tag)\n \t\t\t\t\t<< i);\n \n+\t\t\t/* Only turned-on bits are considered as match */\n+\t\t\tmatch &= d->in_flight_bitmask;\n \t\t\tif (match) {\n \t\t\t\tnext_mb = NULL;\n-\t\t\t\tunsigned worker = __builtin_ctz(match);\n+\t\t\t\tunsigned worker = __builtin_ctzl(match);\n \t\t\t\tif (add_to_backlog(&d->backlog[worker],\n \t\t\t\t\t\tnext_value) < 0)\n \t\t\t\t\tnext_idx--;\n@@ -322,6 +339,7 @@ rte_distributor_process(struct rte_distributor *d,\n \t\t\telse {\n \t\t\t\td->bufs[wkr].bufptr64 = next_value;\n \t\t\t\td->in_flight_tags[wkr] = new_tag;\n+\t\t\t\td->in_flight_bitmask |= (1UL << wkr);\n \t\t\t\tnext_mb = NULL;\n \t\t\t}\n \t\t\toldbuf = data >> RTE_DISTRIB_FLAG_BITS;\n@@ -379,11 +397,12 @@ rte_distributor_returned_pkts(struct rte_distributor *d,\n static inline unsigned\n total_outstanding(const struct rte_distributor *d)\n {\n-\tunsigned wkr, total_outstanding = 0;\n+\tunsigned wkr, total_outstanding;\n \n+\ttotal_outstanding = __builtin_popcountl(d->in_flight_bitmask);\n \tfor (wkr = 0; wkr < d->num_workers; wkr++)\n-\t\ttotal_outstanding += d->backlog[wkr].count +\n-\t\t\t\t!!(d->in_flight_tags[wkr]);\n+\t\ttotal_outstanding += d->backlog[wkr].count;\n+\n \treturn total_outstanding;\n }\n \ndiff --git a/lib/librte_distributor/rte_distributor.h b/lib/librte_distributor/rte_distributor.h\nindex ec0d74a..a29c506 100644\n--- a/lib/librte_distributor/rte_distributor.h\n+++ b/lib/librte_distributor/rte_distributor.h\n@@ -87,6 +87,9 @@ rte_distributor_create(const char *name, unsigned socket_id,\n  * Process a set of packets by distributing them among workers that request\n  * packets. The distributor will ensure that no two packets that have the\n  * same flow id, or tag, in the mbuf will be procesed at the same time.\n+ * The user is advocated to set tag for each mbuf. If user doesn't set the\n+ * tag, the tag value can be various values depending on driver implementation\n+ * and configuration.\n  *\n  * This is not multi-thread safe and should only be called on a single lcore.\n  *\ndiff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h\nindex e8f9bfc..f5f8658 100644\n--- a/lib/librte_mbuf/rte_mbuf.h\n+++ b/lib/librte_mbuf/rte_mbuf.h\n@@ -185,6 +185,7 @@ struct rte_mbuf {\n \t\t\tuint16_t id;\n \t\t} fdir;           /**< Filter identifier if FDIR enabled */\n \t\tuint32_t sched;   /**< Hierarchical scheduler */\n+\t\tuint32_t usr;\t  /**< User defined tags. See @rte_distributor_process */\n \t} hash;                   /**< hash information */\n \n \t/* second cache line - fields only used in slow path or on TX */\n",
    "prefixes": [
        "dpdk-dev"
    ]
}