get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 81394,
    "url": "http://patches.dpdk.org/api/patches/81394/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20201019163519.28180-4-dharmik.thakkar@arm.com/",
    "project": {
        "id": 1,
        "url": "http://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": "<20201019163519.28180-4-dharmik.thakkar@arm.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20201019163519.28180-4-dharmik.thakkar@arm.com",
    "date": "2020-10-19T16:35:19",
    "name": "[v4,3/3] test/hash: add tests for integrated RCU QSBR",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "4ad0a2201ed3abf52c25b3247b43fa73ca98a8a9",
    "submitter": {
        "id": 1108,
        "url": "http://patches.dpdk.org/api/people/1108/?format=api",
        "name": "Dharmik Thakkar",
        "email": "dharmik.thakkar@arm.com"
    },
    "delegate": {
        "id": 24651,
        "url": "http://patches.dpdk.org/api/users/24651/?format=api",
        "username": "dmarchand",
        "first_name": "David",
        "last_name": "Marchand",
        "email": "david.marchand@redhat.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20201019163519.28180-4-dharmik.thakkar@arm.com/mbox/",
    "series": [
        {
            "id": 13109,
            "url": "http://patches.dpdk.org/api/series/13109/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=13109",
            "date": "2020-10-19T16:35:17",
            "name": "hash: integrate RCU QSBR",
            "version": 4,
            "mbox": "http://patches.dpdk.org/series/13109/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/81394/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/81394/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 3FBBFA04DC;\n\tMon, 19 Oct 2020 18:36:12 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 7E14AE307;\n\tMon, 19 Oct 2020 18:35:36 +0200 (CEST)",
            "from foss.arm.com (foss.arm.com [217.140.110.172])\n by dpdk.org (Postfix) with ESMTP id 59843E27D\n for <dev@dpdk.org>; Mon, 19 Oct 2020 18:35:31 +0200 (CEST)",
            "from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14])\n by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id BA8AE1042;\n Mon, 19 Oct 2020 09:35:29 -0700 (PDT)",
            "from 2p2660v4-1.austin.arm.com (2p2660v4-1.austin.arm.com\n [10.118.12.95])\n by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id B0B0A3F66B;\n Mon, 19 Oct 2020 09:35:29 -0700 (PDT)"
        ],
        "From": "Dharmik Thakkar <dharmik.thakkar@arm.com>",
        "To": "Yipeng Wang <yipeng1.wang@intel.com>,\n Sameh Gobriel <sameh.gobriel@intel.com>,\n Bruce Richardson <bruce.richardson@intel.com>",
        "Cc": "dev@dpdk.org,\n\tnd@arm.com,\n\tDharmik Thakkar <dharmik.thakkar@arm.com>",
        "Date": "Mon, 19 Oct 2020 11:35:19 -0500",
        "Message-Id": "<20201019163519.28180-4-dharmik.thakkar@arm.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "In-Reply-To": "<20201019163519.28180-1-dharmik.thakkar@arm.com>",
        "References": "<20201016173858.1134-1-dharmik.thakkar@arm.com>\n <20201019163519.28180-1-dharmik.thakkar@arm.com>",
        "Subject": "[dpdk-dev] [PATCH v4 3/3] test/hash: add tests for integrated RCU\n\tQSBR",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Add functional and performance tests for the integrated RCU QSBR.\n\nSuggested-by: Honnappa Nagarahalli <honnappa.nagarahalli@arm.com>\nSigned-off-by: Dharmik Thakkar <dharmik.thakkar@arm.com>\nReviewed-by: Ruifeng Wang <ruifeng.wang@arm.com>\n---\n app/test/test_hash.c                   | 390 ++++++++++++++++++++++++-\n app/test/test_hash_readwrite_lf_perf.c | 171 ++++++++++-\n 2 files changed, 557 insertions(+), 4 deletions(-)",
    "diff": "diff --git a/app/test/test_hash.c b/app/test/test_hash.c\nindex 990a1815f893..22b47b3e7728 100644\n--- a/app/test/test_hash.c\n+++ b/app/test/test_hash.c\n@@ -52,7 +52,7 @@ static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21,\n \t}\t\t\t\t\t\t\t\t\\\n } while(0)\n \n-#define RETURN_IF_ERROR_FBK(cond, str, ...) do {\t\t\t\t\\\n+#define RETURN_IF_ERROR_FBK(cond, str, ...) do {\t\t\t\\\n \tif (cond) {\t\t\t\t\t\t\t\\\n \t\tprintf(\"ERROR line %d: \" str \"\\n\", __LINE__, ##__VA_ARGS__); \\\n \t\tif (handle) rte_fbk_hash_free(handle);\t\t\t\\\n@@ -60,6 +60,20 @@ static uint32_t hashtest_key_lens[] = {0, 2, 4, 5, 6, 7, 8, 10, 11, 15, 16, 21,\n \t}\t\t\t\t\t\t\t\t\\\n } while(0)\n \n+#define RETURN_IF_ERROR_RCU_QSBR(cond, str, ...) do {\t\t\t\\\n+\tif (cond) {\t\t\t\t\t\t\t\\\n+\t\tprintf(\"ERROR line %d: \" str \"\\n\", __LINE__, ##__VA_ARGS__); \\\n+\t\tif (rcu_cfg.mode == RTE_HASH_QSBR_MODE_SYNC) {\t\t\\\n+\t\t\twriter_done = 1;\t\t\t\t\\\n+\t\t\t/* Wait until reader exited. */\t\t\t\\\n+\t\t\trte_eal_mp_wait_lcore();\t\t\t\\\n+\t\t}\t\t\t\t\t\t\t\\\n+\t\tif (g_handle) rte_hash_free(g_handle);\t\t\t\\\n+\t\tif (g_qsv) rte_free(g_qsv);\t\t\t\t\\\n+\t\treturn -1;\t\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+} while(0)\n+\n /* 5-tuple key type */\n struct flow_key {\n \tuint32_t ip_src;\n@@ -1801,6 +1815,365 @@ test_hash_add_delete_jhash_3word(void)\n \treturn ret;\n }\n \n+static struct rte_hash *g_handle;\n+static struct rte_rcu_qsbr *g_qsv;\n+static volatile uint8_t writer_done;\n+struct flow_key g_rand_keys[9];\n+/*\n+ * rte_hash_rcu_qsbr_add positive and negative tests.\n+ *  - Add RCU QSBR variable to Hash\n+ *  - Add another RCU QSBR variable to Hash\n+ *  - Check returns\n+ */\n+static int\n+test_hash_rcu_qsbr_add(void)\n+{\n+\tsize_t sz;\n+\tstruct rte_rcu_qsbr *qsv2 = NULL;\n+\tint32_t status;\n+\tstruct rte_hash_rcu_config rcu_cfg = {0};\n+\n+\tstruct rte_hash_parameters params;\n+\n+\tprintf(\"\\n# Running RCU QSBR add tests\\n\");\n+\tmemcpy(&params, &ut_params, sizeof(params));\n+\tparams.name = \"test_hash_rcu_qsbr_add\";\n+\tparams.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF |\n+\t\t\t\tRTE_HASH_EXTRA_FLAGS_MULTI_WRITER_ADD;\n+\tg_handle = rte_hash_create(&params);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, \"Hash creation failed\");\n+\n+\t/* Create RCU QSBR variable */\n+\tsz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);\n+\tg_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,\n+\t\t\t\t\tRTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,\n+\t\t\t\t \"RCU QSBR variable creation failed\");\n+\n+\tstatus = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"RCU QSBR variable initialization failed\");\n+\n+\trcu_cfg.v = g_qsv;\n+\t/* Invalid QSBR mode */\n+\trcu_cfg.mode = 2;\n+\tstatus = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);\n+\tRETURN_IF_ERROR_RCU_QSBR(status == 0, \"Invalid QSBR mode test failed\");\n+\n+\trcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;\n+\t/* Attach RCU QSBR to hash table */\n+\tstatus = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"Attach RCU QSBR to hash table failed\");\n+\n+\t/* Create and attach another RCU QSBR to hash table */\n+\tqsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,\n+\t\t\t\t\tRTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);\n+\tRETURN_IF_ERROR_RCU_QSBR(qsv2 == NULL,\n+\t\t\t\t \"RCU QSBR variable creation failed\");\n+\n+\trcu_cfg.v = qsv2;\n+\trcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;\n+\tstatus = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);\n+\trte_free(qsv2);\n+\tRETURN_IF_ERROR_RCU_QSBR(status == 0,\n+\t\t\t\"Attach RCU QSBR to hash table succeeded where failure\"\n+\t\t\t\" is expected\");\n+\n+\trte_hash_free(g_handle);\n+\trte_free(g_qsv);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * rte_hash_rcu_qsbr_add DQ mode functional test.\n+ * Reader and writer are in the same thread in this test.\n+ *  - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries\n+ *  - Add RCU QSBR variable to hash\n+ *  - Add 8 hash entries and fill the bucket\n+ *  - If ext bkt is enabled, add 1 extra entry that is available in the ext bkt\n+ *  - Register a reader thread (not a real thread)\n+ *  - Reader lookup existing entry\n+ *  - Writer deletes the entry\n+ *  - Reader lookup the entry\n+ *  - Writer re-add the entry (no available free index)\n+ *  - Reader report quiescent state and unregister\n+ *  - Writer re-add the entry\n+ *  - Reader lookup the entry\n+ */\n+static int\n+test_hash_rcu_qsbr_dq_mode(uint8_t ext_bkt)\n+{\n+\tuint32_t total_entries = (ext_bkt == 0) ? 8 : 9;\n+\n+\tuint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;\n+\n+\tif (ext_bkt)\n+\t\thash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;\n+\n+\tstruct rte_hash_parameters params_pseudo_hash = {\n+\t\t.name = \"test_hash_rcu_qsbr_dq_mode\",\n+\t\t.entries = total_entries,\n+\t\t.key_len = sizeof(struct flow_key), /* 13 */\n+\t\t.hash_func = pseudo_hash,\n+\t\t.hash_func_init_val = 0,\n+\t\t.socket_id = 0,\n+\t\t.extra_flag = hash_extra_flag,\n+\t};\n+\tint pos[total_entries];\n+\tint expected_pos[total_entries];\n+\tunsigned i;\n+\tsize_t sz;\n+\tint32_t status;\n+\tstruct rte_hash_rcu_config rcu_cfg = {0};\n+\n+\tg_qsv = NULL;\n+\tg_handle = NULL;\n+\n+\tfor (i = 0; i < total_entries; i++) {\n+\t\tg_rand_keys[i].port_dst = i;\n+\t\tg_rand_keys[i].port_src = i+1;\n+\t}\n+\n+\tif (ext_bkt)\n+\t\tprintf(\"\\n# Running RCU QSBR DQ mode functional test with\"\n+\t\t       \" ext bkt\\n\");\n+\telse\n+\t\tprintf(\"\\n# Running RCU QSBR DQ mode functional test\\n\");\n+\n+\tg_handle = rte_hash_create(&params_pseudo_hash);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, \"Hash creation failed\");\n+\n+\t/* Create RCU QSBR variable */\n+\tsz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);\n+\tg_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,\n+\t\t\t\t\tRTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,\n+\t\t\t\t \"RCU QSBR variable creation failed\");\n+\n+\tstatus = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"RCU QSBR variable initialization failed\");\n+\n+\trcu_cfg.v = g_qsv;\n+\trcu_cfg.mode = RTE_HASH_QSBR_MODE_DQ;\n+\t/* Attach RCU QSBR to hash table */\n+\tstatus = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"Attach RCU QSBR to hash table failed\");\n+\n+\t/* Fill bucket */\n+\tfor (i = 0; i < total_entries; i++) {\n+\t\tpos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]);\n+\t\tprint_key_info(\"Add\", &g_rand_keys[i], pos[i]);\n+\t\tRETURN_IF_ERROR_RCU_QSBR(pos[i] < 0,\n+\t\t\t\t\t \"failed to add key (pos[%u]=%d)\", i,\n+\t\t\t\t\t pos[i]);\n+\t\texpected_pos[i] = pos[i];\n+\t}\n+\n+\t/* Register pseudo reader */\n+\tstatus = rte_rcu_qsbr_thread_register(g_qsv, 0);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"RCU QSBR thread registration failed\");\n+\trte_rcu_qsbr_thread_online(g_qsv, 0);\n+\n+\t/* Lookup */\n+\tpos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Lkp\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],\n+\t\t\t\t \"failed to find correct key (pos[%u]=%d)\", 0,\n+\t\t\t\t pos[0]);\n+\n+\t/* Writer update */\n+\tpos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Del\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],\n+\t\t\t\t \"failed to del correct key (pos[%u]=%d)\", 0,\n+\t\t\t\t pos[0]);\n+\n+\t/* Lookup */\n+\tpos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Lkp\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOENT,\n+\t\t\t\t \"found deleted key (pos[%u]=%d)\", 0, pos[0]);\n+\n+\t/* Fill bucket */\n+\tpos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Add\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != -ENOSPC,\n+\t\t\t\t \"Added key successfully (pos[%u]=%d)\", 0, pos[0]);\n+\n+\t/* Reader quiescent */\n+\trte_rcu_qsbr_quiescent(g_qsv, 0);\n+\n+\t/* Fill bucket */\n+\tpos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Add\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] < 0,\n+\t\t\t\t \"failed to add key (pos[%u]=%d)\", 0, pos[0]);\n+\texpected_pos[0] = pos[0];\n+\n+\trte_rcu_qsbr_thread_offline(g_qsv, 0);\n+\t(void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);\n+\n+\t/* Lookup */\n+\tpos[0] = rte_hash_lookup(g_handle, &g_rand_keys[0]);\n+\tprint_key_info(\"Lkp\", &g_rand_keys[0], pos[0]);\n+\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],\n+\t\t\t\t \"failed to find correct key (pos[%u]=%d)\", 0,\n+\t\t\t\t pos[0]);\n+\n+\trte_hash_free(g_handle);\n+\trte_free(g_qsv);\n+\treturn 0;\n+\n+}\n+\n+/* Report quiescent state interval every 1024 lookups. Larger critical\n+ * sections in reader will result in writer polling multiple times.\n+ */\n+#define QSBR_REPORTING_INTERVAL 1024\n+#define WRITER_ITERATIONS\t512\n+\n+/*\n+ * Reader thread using rte_hash data structure with RCU.\n+ */\n+static int\n+test_hash_rcu_qsbr_reader(void *arg)\n+{\n+\tint i;\n+\n+\tRTE_SET_USED(arg);\n+\t/* Register this thread to report quiescent state */\n+\t(void)rte_rcu_qsbr_thread_register(g_qsv, 0);\n+\trte_rcu_qsbr_thread_online(g_qsv, 0);\n+\n+\tdo {\n+\t\tfor (i = 0; i < QSBR_REPORTING_INTERVAL; i++)\n+\t\t\trte_hash_lookup(g_handle, &g_rand_keys[0]);\n+\n+\t\t/* Update quiescent state */\n+\t\trte_rcu_qsbr_quiescent(g_qsv, 0);\n+\t} while (!writer_done);\n+\n+\trte_rcu_qsbr_thread_offline(g_qsv, 0);\n+\t(void)rte_rcu_qsbr_thread_unregister(g_qsv, 0);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * rte_hash_rcu_qsbr_add sync mode functional test.\n+ * 1 Reader and 1 writer. They cannot be in the same thread in this test.\n+ *  - Create hash which supports maximum 8 (9 if ext bkt is enabled) entries\n+ *  - Add RCU QSBR variable to hash\n+ *  - Register a reader thread. Reader keeps looking up a specific key.\n+ *  - Writer keeps adding and deleting a specific key.\n+ */\n+static int\n+test_hash_rcu_qsbr_sync_mode(uint8_t ext_bkt)\n+{\n+\tuint32_t total_entries = (ext_bkt == 0) ? 8 : 9;\n+\n+\tuint8_t hash_extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF;\n+\n+\tif (ext_bkt)\n+\t\thash_extra_flag |= RTE_HASH_EXTRA_FLAGS_EXT_TABLE;\n+\n+\tstruct rte_hash_parameters params_pseudo_hash = {\n+\t\t.name = \"test_hash_rcu_qsbr_sync_mode\",\n+\t\t.entries = total_entries,\n+\t\t.key_len = sizeof(struct flow_key), /* 13 */\n+\t\t.hash_func = pseudo_hash,\n+\t\t.hash_func_init_val = 0,\n+\t\t.socket_id = 0,\n+\t\t.extra_flag = hash_extra_flag,\n+\t};\n+\tint pos[total_entries];\n+\tint expected_pos[total_entries];\n+\tunsigned i;\n+\tsize_t sz;\n+\tint32_t status;\n+\tstruct rte_hash_rcu_config rcu_cfg = {0};\n+\n+\tg_qsv = NULL;\n+\tg_handle = NULL;\n+\n+\tfor (i = 0; i < total_entries; i++) {\n+\t\tg_rand_keys[i].port_dst = i;\n+\t\tg_rand_keys[i].port_src = i+1;\n+\t}\n+\n+\tif (ext_bkt)\n+\t\tprintf(\"\\n# Running RCU QSBR sync mode functional test with\"\n+\t\t       \" ext bkt\\n\");\n+\telse\n+\t\tprintf(\"\\n# Running RCU QSBR sync mode functional test\\n\");\n+\n+\tg_handle = rte_hash_create(&params_pseudo_hash);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_handle == NULL, \"Hash creation failed\");\n+\n+\t/* Create RCU QSBR variable */\n+\tsz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);\n+\tg_qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,\n+\t\t\t\t\tRTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);\n+\tRETURN_IF_ERROR_RCU_QSBR(g_qsv == NULL,\n+\t\t\t\t \"RCU QSBR variable creation failed\");\n+\n+\tstatus = rte_rcu_qsbr_init(g_qsv, RTE_MAX_LCORE);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"RCU QSBR variable initialization failed\");\n+\n+\trcu_cfg.v = g_qsv;\n+\trcu_cfg.mode = RTE_HASH_QSBR_MODE_SYNC;\n+\t/* Attach RCU QSBR to hash table */\n+\tstatus = rte_hash_rcu_qsbr_add(g_handle, &rcu_cfg);\n+\tRETURN_IF_ERROR_RCU_QSBR(status != 0,\n+\t\t\t\t \"Attach RCU QSBR to hash table failed\");\n+\n+\t/* Launch reader thread */\n+\trte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL,\n+\t\t\t\trte_get_next_lcore(-1, 1, 0));\n+\n+\t/* Fill bucket */\n+\tfor (i = 0; i < total_entries; i++) {\n+\t\tpos[i] = rte_hash_add_key(g_handle, &g_rand_keys[i]);\n+\t\tprint_key_info(\"Add\", &g_rand_keys[i], pos[i]);\n+\t\tRETURN_IF_ERROR_RCU_QSBR(pos[i] < 0,\n+\t\t\t\t\"failed to add key (pos[%u]=%d)\", i, pos[i]);\n+\t\texpected_pos[i] = pos[i];\n+\t}\n+\twriter_done = 0;\n+\n+\t/* Writer Update */\n+\tfor (i = 0; i < WRITER_ITERATIONS; i++) {\n+\t\texpected_pos[0] = pos[0];\n+\t\tpos[0] = rte_hash_del_key(g_handle, &g_rand_keys[0]);\n+\t\tprint_key_info(\"Del\", &g_rand_keys[0], status);\n+\t\tRETURN_IF_ERROR_RCU_QSBR(pos[0] != expected_pos[0],\n+\t\t\t\t\t \"failed to del correct key (pos[%u]=%d)\"\n+\t\t\t\t\t , 0, pos[0]);\n+\n+\t\tpos[0] = rte_hash_add_key(g_handle, &g_rand_keys[0]);\n+\t\tprint_key_info(\"Add\", &g_rand_keys[0], pos[0]);\n+\t\tRETURN_IF_ERROR_RCU_QSBR(pos[0] < 0,\n+\t\t\t\t\t \"failed to add key (pos[%u]=%d)\", 0,\n+\t\t\t\t\t pos[0]);\n+\t}\n+\n+\twriter_done = 1;\n+\t/* Wait until reader exited. */\n+\trte_eal_mp_wait_lcore();\n+\n+\trte_hash_free(g_handle);\n+\trte_free(g_qsv);\n+\n+\treturn  0;\n+\n+}\n+\n /*\n  * Do all unit and performance tests.\n  */\n@@ -1862,6 +2235,21 @@ test_hash(void)\n \tif (test_crc32_hash_alg_equiv() < 0)\n \t\treturn -1;\n \n+\tif (test_hash_rcu_qsbr_add() < 0)\n+\t\treturn -1;\n+\n+\tif (test_hash_rcu_qsbr_dq_mode(0) < 0)\n+\t\treturn -1;\n+\n+\tif (test_hash_rcu_qsbr_dq_mode(1) < 0)\n+\t\treturn -1;\n+\n+\tif (test_hash_rcu_qsbr_sync_mode(0) < 0)\n+\t\treturn -1;\n+\n+\tif (test_hash_rcu_qsbr_sync_mode(1) < 0)\n+\t\treturn -1;\n+\n \treturn 0;\n }\n \ndiff --git a/app/test/test_hash_readwrite_lf_perf.c b/app/test/test_hash_readwrite_lf_perf.c\nindex 328fa5116f65..3c278ee97c23 100644\n--- a/app/test/test_hash_readwrite_lf_perf.c\n+++ b/app/test/test_hash_readwrite_lf_perf.c\n@@ -13,6 +13,7 @@\n #include <rte_malloc.h>\n #include <rte_random.h>\n #include <rte_spinlock.h>\n+#include <rte_rcu_qsbr.h>\n \n #include \"test.h\"\n \n@@ -48,6 +49,9 @@\n #define WRITE_EXT_BKT 2\n \n #define NUM_TEST 3\n+\n+#define QSBR_REPORTING_INTERVAL 1024\n+\n static unsigned int rwc_core_cnt[NUM_TEST] = {1, 2, 4};\n \n struct rwc_perf {\n@@ -58,6 +62,7 @@ struct rwc_perf {\n \tuint32_t w_ks_r_miss[2][NUM_TEST];\n \tuint32_t multi_rw[NUM_TEST - 1][2][NUM_TEST];\n \tuint32_t w_ks_r_hit_extbkt[2][NUM_TEST];\n+\tuint32_t writer_add_del[NUM_TEST];\n };\n \n static struct rwc_perf rwc_lf_results, rwc_non_lf_results;\n@@ -84,6 +89,8 @@ static struct {\n \n static uint64_t gread_cycles;\n static uint64_t greads;\n+static uint64_t gwrite_cycles;\n+static uint64_t gwrites;\n \n static volatile uint8_t writer_done;\n \n@@ -1044,7 +1051,7 @@ test_hash_add_ks_lookup_miss(struct rwc_perf *rwc_perf_results, int rwc_lf, int\n /*\n  * Test lookup perf for multi-writer:\n  * Reader(s) lookup keys present in the table and likely on the shift-path while\n- * Writers add keys causing key-shiftsi.\n+ * Writers add keys causing key-shifts.\n  * Writers are running in parallel, on different data plane cores.\n  */\n static int\n@@ -1223,6 +1230,163 @@ test_hash_add_ks_lookup_hit_extbkt(struct rwc_perf *rwc_perf_results,\n \treturn -1;\n }\n \n+static struct rte_rcu_qsbr *rv;\n+\n+/*\n+ * Reader thread using rte_hash data structure with RCU\n+ */\n+static int\n+test_hash_rcu_qsbr_reader(void *arg)\n+{\n+\tunsigned int i, j;\n+\tuint32_t num_keys = tbl_rwc_test_param.count_keys_no_ks\n+\t\t\t\t- QSBR_REPORTING_INTERVAL;\n+\tuint32_t *keys = tbl_rwc_test_param.keys_no_ks;\n+\tuint32_t lcore_id = rte_lcore_id();\n+\tRTE_SET_USED(arg);\n+\n+\t(void)rte_rcu_qsbr_thread_register(rv, lcore_id);\n+\trte_rcu_qsbr_thread_online(rv, lcore_id);\n+\tdo {\n+\t\tfor (i = 0; i < num_keys; i += j) {\n+\t\t\tfor (j = 0; j < QSBR_REPORTING_INTERVAL; j++)\n+\t\t\t\trte_hash_lookup(tbl_rwc_test_param.h,\n+\t\t\t\t\t\tkeys + i + j);\n+\t\t\t/* Update quiescent state counter */\n+\t\t\trte_rcu_qsbr_quiescent(rv, lcore_id);\n+\t\t}\n+\t} while (!writer_done);\n+\trte_rcu_qsbr_thread_offline(rv, lcore_id);\n+\t(void)rte_rcu_qsbr_thread_unregister(rv, lcore_id);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Writer thread using rte_hash data structure with RCU\n+ */\n+static int\n+test_hash_rcu_qsbr_writer(void *arg)\n+{\n+\tuint32_t i, offset;\n+\tuint64_t begin, cycles;\n+\tuint8_t pos_core = (uint32_t)((uintptr_t)arg);\n+\toffset = pos_core * tbl_rwc_test_param.single_insert;\n+\n+\tbegin = rte_rdtsc_precise();\n+\tfor (i = offset; i < offset + tbl_rwc_test_param.single_insert; i++) {\n+\t\t/* Delete element from the shared data structure */\n+\t\trte_hash_del_key(tbl_rwc_test_param.h,\n+\t\t\t\t\ttbl_rwc_test_param.keys_no_ks + i);\n+\t\trte_hash_add_key(tbl_rwc_test_param.h,\n+\t\t\t\ttbl_rwc_test_param.keys_no_ks + i);\n+\t}\n+\tcycles = rte_rdtsc_precise() - begin;\n+\t__atomic_fetch_add(&gwrite_cycles, cycles, __ATOMIC_RELAXED);\n+\t__atomic_fetch_add(&gwrites, tbl_rwc_test_param.single_insert,\n+\t\t\t   __ATOMIC_RELAXED);\n+\treturn 0;\n+}\n+\n+/*\n+ * Writer perf test with RCU QSBR in DQ mode:\n+ * Writer(s) delete and add keys in the table.\n+ * Readers lookup keys in the hash table\n+ */\n+static int\n+test_hash_rcu_qsbr_writer_perf(struct rwc_perf *rwc_perf_results, int rwc_lf,\n+\t\t\t\tint htm, int ext_bkt)\n+{\n+\tunsigned int n;\n+\tuint64_t i;\n+\tuint8_t write_type;\n+\tint use_jhash = 0;\n+\tstruct rte_hash_rcu_config rcu_config = {0};\n+\tuint32_t sz;\n+\tuint8_t pos_core;\n+\n+\tprintf(\"\\nTest: Writer perf with integrated RCU\\n\");\n+\n+\tif (init_params(rwc_lf, use_jhash, htm, ext_bkt) != 0)\n+\t\tgoto err;\n+\n+\tsz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);\n+\trv = (struct rte_rcu_qsbr *)rte_zmalloc(NULL, sz, RTE_CACHE_LINE_SIZE);\n+\trcu_config.v = rv;\n+\n+\tif (rte_hash_rcu_qsbr_add(tbl_rwc_test_param.h, &rcu_config) < 0) {\n+\t\tprintf(\"RCU init in hash failed\\n\");\n+\t\tgoto err;\n+\t}\n+\n+\tfor (n = 0; n < NUM_TEST; n++) {\n+\t\tunsigned int tot_lcore = rte_lcore_count();\n+\t\tif (tot_lcore < rwc_core_cnt[n] + 3)\n+\t\t\tgoto finish;\n+\n+\t\t/* Calculate keys added by each writer */\n+\t\ttbl_rwc_test_param.single_insert =\n+\t\t\ttbl_rwc_test_param.count_keys_no_ks /\n+\t\t\t\trwc_core_cnt[n];\n+\t\tprintf(\"\\nNumber of writers: %u\\n\", rwc_core_cnt[n]);\n+\n+\t\t__atomic_store_n(&gwrites, 0, __ATOMIC_RELAXED);\n+\t\t__atomic_store_n(&gwrite_cycles, 0, __ATOMIC_RELAXED);\n+\n+\t\trte_hash_reset(tbl_rwc_test_param.h);\n+\t\trte_rcu_qsbr_init(rv, RTE_MAX_LCORE);\n+\n+\t\twrite_type = WRITE_NO_KEY_SHIFT;\n+\t\tif (write_keys(write_type) < 0)\n+\t\t\tgoto err;\n+\t\twrite_type = WRITE_KEY_SHIFT;\n+\t\tif (write_keys(write_type) < 0)\n+\t\t\tgoto err;\n+\n+\t\t/* Launch 2 readers */\n+\t\tfor (i = 1; i <= 2; i++)\n+\t\t\trte_eal_remote_launch(test_hash_rcu_qsbr_reader, NULL,\n+\t\t\t\t\t      enabled_core_ids[i]);\n+\t\tpos_core = 0;\n+\t\t/* Launch writer(s) */\n+\t\tfor (; i <= rwc_core_cnt[n] + 2; i++) {\n+\t\t\trte_eal_remote_launch(test_hash_rcu_qsbr_writer,\n+\t\t\t\t(void *)(uintptr_t)pos_core,\n+\t\t\t\tenabled_core_ids[i]);\n+\t\t\tpos_core++;\n+\t\t}\n+\n+\t\t/* Wait for writers to complete */\n+\t\tfor (i = 3; i <= rwc_core_cnt[n] + 2; i++)\n+\t\t\trte_eal_wait_lcore(enabled_core_ids[i]);\n+\n+\t\twriter_done = 1;\n+\n+\t\t/* Wait for readers to complete */\n+\t\trte_eal_mp_wait_lcore();\n+\n+\t\tunsigned long long cycles_per_write_operation =\n+\t\t\t__atomic_load_n(&gwrite_cycles, __ATOMIC_RELAXED) /\n+\t\t\t__atomic_load_n(&gwrites, __ATOMIC_RELAXED);\n+\t\trwc_perf_results->writer_add_del[n]\n+\t\t\t\t\t= cycles_per_write_operation;\n+\t\tprintf(\"Cycles per write operation: %llu\\n\",\n+\t\t\t\tcycles_per_write_operation);\n+\t}\n+\n+finish:\n+\trte_hash_free(tbl_rwc_test_param.h);\n+\trte_free(rv);\n+\treturn 0;\n+\n+err:\n+\twriter_done = 1;\n+\trte_eal_mp_wait_lcore();\n+\trte_hash_free(tbl_rwc_test_param.h);\n+\trte_free(rv);\n+\treturn -1;\n+}\n+\n static int\n test_hash_readwrite_lf_perf_main(void)\n {\n@@ -1235,7 +1399,6 @@ test_hash_readwrite_lf_perf_main(void)\n \tint rwc_lf = 0;\n \tint htm;\n \tint ext_bkt = 0;\n-\n \tif (rte_lcore_count() < 2) {\n \t\tprintf(\"Not enough cores for hash_readwrite_lf_perf_autotest, expecting at least 2\\n\");\n \t\treturn TEST_SKIPPED;\n@@ -1255,7 +1418,6 @@ test_hash_readwrite_lf_perf_main(void)\n \t\treturn -1;\n \tif (get_enabled_cores_list() != 0)\n \t\treturn -1;\n-\n \tif (RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY_LF) {\n \t\trwc_lf = 1;\n \t\text_bkt = 1;\n@@ -1282,6 +1444,9 @@ test_hash_readwrite_lf_perf_main(void)\n \t\tif (test_hash_add_ks_lookup_hit_extbkt(&rwc_lf_results, rwc_lf,\n \t\t\t\t\t\t\thtm, ext_bkt) < 0)\n \t\t\treturn -1;\n+\t\tif (test_hash_rcu_qsbr_writer_perf(&rwc_lf_results, rwc_lf,\n+\t\t\t\t\t\t   htm, ext_bkt) < 0)\n+\t\t\treturn -1;\n \t}\n \tprintf(\"\\nTest lookup with read-write concurrency lock free support\"\n \t       \" disabled\\n\");\n",
    "prefixes": [
        "v4",
        "3/3"
    ]
}