get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 29569,
    "url": "http://patches.dpdk.org/api/patches/29569/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1507086745-6674-7-git-send-email-yipeng1.wang@intel.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": "<1507086745-6674-7-git-send-email-yipeng1.wang@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1507086745-6674-7-git-send-email-yipeng1.wang@intel.com",
    "date": "2017-10-04T03:12:24",
    "name": "[dpdk-dev,v6,6/7] test/member: add functional and perf tests",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "0eeadfdea83bb478ff8a76d2378ffd88ac366ed4",
    "submitter": {
        "id": 754,
        "url": "http://patches.dpdk.org/api/people/754/?format=api",
        "name": "Wang, Yipeng1",
        "email": "yipeng1.wang@intel.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1507086745-6674-7-git-send-email-yipeng1.wang@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/29569/comments/",
    "check": "warning",
    "checks": "http://patches.dpdk.org/api/patches/29569/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id CF3BB1B61A;\n\tWed,  4 Oct 2017 05:16:33 +0200 (CEST)",
            "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby dpdk.org (Postfix) with ESMTP id 431D01B609\n\tfor <dev@dpdk.org>; Wed,  4 Oct 2017 05:16:31 +0200 (CEST)",
            "from fmsmga004.fm.intel.com ([10.253.24.48])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t03 Oct 2017 20:16:29 -0700",
            "from bdw-yipeng.jf.intel.com ([10.54.81.30])\n\tby fmsmga004.fm.intel.com with ESMTP; 03 Oct 2017 20:16:29 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.42,476,1500966000\"; d=\"scan'208\";a=\"319258140\"",
        "From": "Yipeng Wang <yipeng1.wang@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net, charlie.tai@intel.com, sameh.gobriel@intel.com,\n\tpablo.de.lara.guarch@intel.com, john.mcnamara@intel.com,\n\tYipeng Wang <yipeng1.wang@intel.com>",
        "Date": "Tue,  3 Oct 2017 20:12:24 -0700",
        "Message-Id": "<1507086745-6674-7-git-send-email-yipeng1.wang@intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1507086745-6674-1-git-send-email-yipeng1.wang@intel.com>",
        "References": "<1507005102-43821-1-git-send-email-yipeng1.wang@intel.com>\n\t<1507086745-6674-1-git-send-email-yipeng1.wang@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v6 6/7] test/member: add functional and perf tests",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <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": "This patch adds functional and performance tests for membership\nlibrary.\n\nSigned-off-by: Yipeng Wang <yipeng1.wang@intel.com>\nReviewed-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>\n---\n MAINTAINERS                  |   1 +\n test/test/Makefile           |   3 +\n test/test/test_member.c      | 744 +++++++++++++++++++++++++++++++++++++++++++\n test/test/test_member_perf.c | 654 +++++++++++++++++++++++++++++++++++++\n 4 files changed, 1402 insertions(+)\n create mode 100644 test/test/test_member.c\n create mode 100644 test/test/test_member_perf.c",
    "diff": "diff --git a/MAINTAINERS b/MAINTAINERS\nindex 1358e47..afd36cf 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -733,6 +733,7 @@ Membership - EXPERIMENTAL\n M: Yipeng Wang <yipeng1.wang@intel.com>\n M: Sameh Gobriel <sameh.gobriel@intel.com>\n F: lib/librte_member/\n+F: test/test/test_member*\n \n Traffic metering\n M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\ndiff --git a/test/test/Makefile b/test/test/Makefile\nindex 42d9a49..b61dde3 100644\n--- a/test/test/Makefile\n+++ b/test/test/Makefile\n@@ -123,6 +123,9 @@ SRCS-y += test_logs.c\n SRCS-y += test_memcpy.c\n SRCS-y += test_memcpy_perf.c\n \n+\n+SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member.c\n+SRCS-$(CONFIG_RTE_LIBRTE_MEMBER) += test_member_perf.c\n SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd.c\n SRCS-$(CONFIG_RTE_LIBRTE_EFD) += test_efd_perf.c\n \ndiff --git a/test/test/test_member.c b/test/test/test_member.c\nnew file mode 100644\nindex 0000000..02375fd\n--- /dev/null\n+++ b/test/test/test_member.c\n@@ -0,0 +1,744 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+/* This test is for membership library's simple feature test */\n+\n+#include <rte_memcpy.h>\n+#include <rte_malloc.h>\n+#include <rte_member.h>\n+#include <rte_byteorder.h>\n+#include <rte_random.h>\n+#include <rte_debug.h>\n+#include <rte_ip.h>\n+\n+#include \"test.h\"\n+\n+struct rte_member_setsum *setsum_ht;\n+struct rte_member_setsum *setsum_cache;\n+struct rte_member_setsum *setsum_vbf;\n+\n+/* 5-tuple key type */\n+struct flow_key {\n+\tuint32_t ip_src;\n+\tuint32_t ip_dst;\n+\tuint16_t port_src;\n+\tuint16_t port_dst;\n+\tuint8_t proto;\n+} __attribute__((packed));\n+\n+/* Set ID Macros for multimatch test usage */\n+#define M_MATCH_S 1\t/* Not start with 0 since by default 0 means no match */\n+#define M_MATCH_E 15\n+#define M_MATCH_STEP 2\n+#define M_MATCH_CNT \\\n+\t(1 + (M_MATCH_E - M_MATCH_S) / M_MATCH_STEP)\n+\n+\n+#define NUM_SAMPLES 5\n+#define MAX_MATCH 32\n+\n+/* Keys used by unit test functions */\n+static struct flow_key keys[NUM_SAMPLES] = {\n+\t{\n+\t\t.ip_src = IPv4(0x03, 0x02, 0x01, 0x00),\n+\t\t.ip_dst = IPv4(0x07, 0x06, 0x05, 0x04),\n+\t\t.port_src = 0x0908,\n+\t\t.port_dst = 0x0b0a,\n+\t\t.proto = 0x0c,\n+\t},\n+\t{\n+\t\t.ip_src = IPv4(0x13, 0x12, 0x11, 0x10),\n+\t\t.ip_dst = IPv4(0x17, 0x16, 0x15, 0x14),\n+\t\t.port_src = 0x1918,\n+\t\t.port_dst = 0x1b1a,\n+\t\t.proto = 0x1c,\n+\t},\n+\t{\n+\t\t.ip_src = IPv4(0x23, 0x22, 0x21, 0x20),\n+\t\t.ip_dst = IPv4(0x27, 0x26, 0x25, 0x24),\n+\t\t.port_src = 0x2928,\n+\t\t.port_dst = 0x2b2a,\n+\t\t.proto = 0x2c,\n+\t},\n+\t{\n+\t\t.ip_src = IPv4(0x33, 0x32, 0x31, 0x30),\n+\t\t.ip_dst = IPv4(0x37, 0x36, 0x35, 0x34),\n+\t\t.port_src = 0x3938,\n+\t\t.port_dst = 0x3b3a,\n+\t\t.proto = 0x3c,\n+\t},\n+\t{\n+\t\t.ip_src = IPv4(0x43, 0x42, 0x41, 0x40),\n+\t\t.ip_dst = IPv4(0x47, 0x46, 0x45, 0x44),\n+\t\t.port_src = 0x4948,\n+\t\t.port_dst = 0x4b4a,\n+\t\t.proto = 0x4c,\n+\t}\n+};\n+\n+uint32_t test_set[NUM_SAMPLES] = {1, 2, 3, 4, 5};\n+\n+#define ITERATIONS  3\n+#define KEY_SIZE  4\n+\n+#define MAX_ENTRIES (1 << 16)\n+uint8_t generated_keys[MAX_ENTRIES][KEY_SIZE];\n+\n+static struct rte_member_parameters params = {\n+\t\t.num_keys = MAX_ENTRIES,\t/* Total hash table entries. */\n+\t\t.key_len = KEY_SIZE,\t\t/* Length of hash key. */\n+\n+\t\t/* num_set and false_positive_rate only relevant to vBF */\n+\t\t.num_set = 16,\n+\t\t.false_positive_rate = 0.03,\n+\t\t.prim_hash_seed = 1,\n+\t\t.sec_hash_seed = 11,\n+\t\t.socket_id = 0\t\t\t/* NUMA Socket ID for memory. */\n+};\n+\n+/*\n+ * Sequence of operations for find existing setsummary\n+ *\n+ *  - create setsum\n+ *  - find existing setsum: hit\n+ *  - find non-existing setsum: miss\n+ *\n+ */\n+static int\n+test_member_find_existing(void)\n+{\n+\tstruct rte_member_setsum *tmp_setsum = NULL, *result = NULL;\n+\tstruct rte_member_parameters tmp_params = {\n+\t\t.name = \"member_find_existing\",\n+\t\t.num_keys = MAX_ENTRIES,\t/* Total hash table entries. */\n+\t\t.key_len = KEY_SIZE,\t\t/* Length of hash key. */\n+\t\t.type = RTE_MEMBER_TYPE_HT,\n+\t\t.num_set = 32,\n+\t\t.false_positive_rate = 0.03,\n+\t\t.prim_hash_seed = 1,\n+\t\t.sec_hash_seed = 11,\n+\t\t.socket_id = 0\t\t\t/* NUMA Socket ID for memory. */\n+\t};\n+\n+\t/* Create */\n+\ttmp_setsum = rte_member_create(&tmp_params);\n+\tTEST_ASSERT(tmp_setsum != NULL, \"setsum creation failed\");\n+\n+\t/* Try to find existing hash table */\n+\tresult = rte_member_find_existing(\"member_find_existing\");\n+\tTEST_ASSERT(result == tmp_setsum, \"could not find existing setsum\");\n+\n+\t/* Try to find non-existing hash table */\n+\tresult = rte_member_find_existing(\"member_find_non_existing\");\n+\tTEST_ASSERT(result == NULL, \"found setsum that shouldn't exist\");\n+\n+\t/* Cleanup. */\n+\trte_member_free(tmp_setsum);\n+\n+\treturn 0;\n+}\n+\n+/*\n+ * Test for bad creating parameters\n+ */\n+static int\n+test_member_create_bad_param(void)\n+{\n+\tstruct rte_member_setsum *bad_setsum = NULL;\n+\tstruct rte_member_parameters bad_params = {\n+\t\t.num_keys = MAX_ENTRIES,\t/* Total hash table entries. */\n+\t\t.key_len = KEY_SIZE,\t\t/* Length of hash key. */\n+\t\t.type = RTE_MEMBER_TYPE_HT,\n+\t\t.num_set = 32,\n+\t\t.false_positive_rate = 0.03,\n+\t\t.prim_hash_seed = 1,\n+\t\t.sec_hash_seed = 11,\n+\t\t.socket_id = 0\t\t\t/* NUMA Socket ID for memory. */\n+\t};\n+\n+\tprintf(\"Expected error section begin...\\n\");\n+\tbad_params.name = \"bad_param1\";\n+\tbad_params.num_set = 0;\n+\tbad_params.type = RTE_MEMBER_TYPE_VBF;\n+\t/* Test with 0 set for vBF should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with invalid \"\n+\t\t\t\"number of set for vBF\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tbad_params.name = \"bad_param2\";\n+\tbad_params.false_positive_rate = 0;\n+\tbad_params.num_set = 32;\n+\t/* Test with 0 false positive for vBF should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with invalid \"\n+\t\t\t\"false positive rate for vBF\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tbad_params.name = \"bad_param3\";\n+\tbad_params.false_positive_rate = 0.03;\n+\tbad_params.num_keys = 0;\n+\t/* Test with 0 key per BF for vBF should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with invalid \"\n+\t\t\t\"num_keys for vBF\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tbad_params.name = \"bad_param4\";\n+\tbad_params.type = RTE_MEMBER_TYPE_HT;\n+\tbad_params.num_keys = RTE_MEMBER_BUCKET_ENTRIES / 2;\n+\t/* Test with less than 1 bucket for HTSS should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with too few \"\n+\t\t\t\"number of keys(entries) for HT\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tbad_params.name = \"bad_param5\";\n+\tbad_params.num_keys = RTE_MEMBER_ENTRIES_MAX + 1;\n+\t/* Test with more than maximum entries for HTSS should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with to many \"\n+\t\t\t\"number of keys(entries) for HT\\n\");\n+\t\treturn -1;\n+\t}\n+\n+\tbad_params.name = \"bad_param5\";\n+\t/* Test with same name should fail */\n+\tbad_setsum = rte_member_create(&bad_params);\n+\tif (bad_setsum != NULL) {\n+\t\trte_member_free(bad_setsum);\n+\t\tprintf(\"Impossible creating setsum successfully with existed \"\n+\t\t\t\"name\\n\");\n+\t\treturn -1;\n+\t}\n+\tprintf(\"Expected error section end...\\n\");\n+\trte_member_free(bad_setsum);\n+\treturn 0;\n+}\n+\n+/* Create test setsummaries. */\n+static int test_member_create(void)\n+{\n+\tparams.key_len = sizeof(struct flow_key);\n+\n+\tparams.name = \"test_member_ht\";\n+\tparams.is_cache = 0;\n+\tparams.type = RTE_MEMBER_TYPE_HT;\n+\tsetsum_ht = rte_member_create(&params);\n+\n+\tparams.name = \"test_member_cache\";\n+\tparams.is_cache = 1;\n+\tsetsum_cache = rte_member_create(&params);\n+\n+\tparams.name = \"test_member_vbf\";\n+\tparams.type = RTE_MEMBER_TYPE_VBF;\n+\tsetsum_vbf = rte_member_create(&params);\n+\n+\tif (setsum_ht == NULL || setsum_cache == NULL || setsum_vbf == NULL) {\n+\t\tprintf(\"Creation of setsums fail\\n\");\n+\t\treturn -1;\n+\t}\n+\tprintf(\"Creation of setsums success\\n\");\n+\treturn 0;\n+}\n+\n+static int test_member_insert(void)\n+{\n+\tint ret_ht, ret_cache, ret_vbf, i;\n+\n+\tfor (i = 0; i < NUM_SAMPLES; i++) {\n+\t\tret_ht = rte_member_add(setsum_ht, &keys[i], test_set[i]);\n+\t\tret_cache = rte_member_add(setsum_cache, &keys[i],\n+\t\t\t\t\t\ttest_set[i]);\n+\t\tret_vbf = rte_member_add(setsum_vbf, &keys[i], test_set[i]);\n+\t\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,\n+\t\t\t\t\"insert error\");\n+\t}\n+\tprintf(\"insert key success\\n\");\n+\treturn 0;\n+}\n+\n+static int test_member_lookup(void)\n+{\n+\tint ret_ht, ret_cache, ret_vbf, i;\n+\tuint16_t set_ht, set_cache, set_vbf;\n+\tmember_set_t set_ids_ht[NUM_SAMPLES] = {0};\n+\tmember_set_t set_ids_cache[NUM_SAMPLES] = {0};\n+\tmember_set_t set_ids_vbf[NUM_SAMPLES] = {0};\n+\n+\tuint32_t num_key_ht = NUM_SAMPLES;\n+\tuint32_t num_key_cache = NUM_SAMPLES;\n+\tuint32_t num_key_vbf = NUM_SAMPLES;\n+\n+\tconst void *key_array[NUM_SAMPLES];\n+\n+\t/* Single lookup test */\n+\tfor (i = 0; i < NUM_SAMPLES; i++) {\n+\t\tret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht);\n+\t\tret_cache = rte_member_lookup(setsum_cache, &keys[i],\n+\t\t\t\t\t\t\t&set_cache);\n+\t\tret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf);\n+\t\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,\n+\t\t\t\t\"single lookup function error\");\n+\n+\t\tTEST_ASSERT(set_ht == test_set[i] &&\n+\t\t\t\tset_cache == test_set[i] &&\n+\t\t\t\tset_vbf == test_set[i],\n+\t\t\t\t\"single lookup set value error\");\n+\t}\n+\tprintf(\"lookup single key success\\n\");\n+\n+\t/* Bulk lookup test */\n+\tfor (i = 0; i < NUM_SAMPLES; i++)\n+\t\tkey_array[i] = &keys[i];\n+\n+\tret_ht = rte_member_lookup_bulk(setsum_ht, key_array,\n+\t\t\tnum_key_ht, set_ids_ht);\n+\n+\tret_cache = rte_member_lookup_bulk(setsum_cache, key_array,\n+\t\t\tnum_key_cache, set_ids_cache);\n+\n+\tret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array,\n+\t\t\tnum_key_vbf, set_ids_vbf);\n+\n+\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,\n+\t\t\t\"bulk lookup function error\");\n+\n+\tfor (i = 0; i < NUM_SAMPLES; i++) {\n+\t\tTEST_ASSERT((set_ids_ht[i] == test_set[i]) &&\n+\t\t\t\t(set_ids_cache[i] == test_set[i]) &&\n+\t\t\t\t(set_ids_vbf[i] == test_set[i]),\n+\t\t\t\t\"bulk lookup result error\");\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int test_member_delete(void)\n+{\n+\tint ret_ht, ret_cache, ret_vbf, i;\n+\tuint16_t set_ht, set_cache, set_vbf;\n+\tconst void *key_array[NUM_SAMPLES];\n+\tmember_set_t set_ids_ht[NUM_SAMPLES] = {0};\n+\tmember_set_t set_ids_cache[NUM_SAMPLES] = {0};\n+\tmember_set_t set_ids_vbf[NUM_SAMPLES] = {0};\n+\tuint32_t num_key_ht = NUM_SAMPLES;\n+\tuint32_t num_key_cache = NUM_SAMPLES;\n+\tuint32_t num_key_vbf = NUM_SAMPLES;\n+\n+\t/* Delete part of all inserted keys */\n+\tfor (i = 0; i < NUM_SAMPLES / 2; i++) {\n+\t\tret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]);\n+\t\tret_cache = rte_member_delete(setsum_cache, &keys[i],\n+\t\t\t\t\t\ttest_set[i]);\n+\t\tret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]);\n+\t\t/* VBF does not support delete yet, so return error code */\n+\t\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,\n+\t\t\t\t\"key deletion function error\");\n+\t\tTEST_ASSERT(ret_vbf < 0,\n+\t\t\t\t\"vbf does not support deletion, error\");\n+\t}\n+\n+\tfor (i = 0; i < NUM_SAMPLES; i++)\n+\t\tkey_array[i] = &keys[i];\n+\n+\tret_ht = rte_member_lookup_bulk(setsum_ht, key_array,\n+\t\t\tnum_key_ht, set_ids_ht);\n+\n+\tret_cache = rte_member_lookup_bulk(setsum_cache, key_array,\n+\t\t\tnum_key_cache, set_ids_cache);\n+\n+\tret_vbf = rte_member_lookup_bulk(setsum_vbf, key_array,\n+\t\t\tnum_key_vbf, set_ids_vbf);\n+\n+\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0 && ret_vbf >= 0,\n+\t\t\t\"bulk lookup function error\");\n+\n+\tfor (i = 0; i < NUM_SAMPLES / 2; i++) {\n+\t\tTEST_ASSERT((set_ids_ht[i] == RTE_MEMBER_NO_MATCH) &&\n+\t\t\t\t(set_ids_cache[i] == RTE_MEMBER_NO_MATCH),\n+\t\t\t\t\"bulk lookup result error\");\n+\t}\n+\n+\tfor (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) {\n+\t\tTEST_ASSERT((set_ids_ht[i] == test_set[i]) &&\n+\t\t\t\t(set_ids_cache[i] == test_set[i]) &&\n+\t\t\t\t(set_ids_vbf[i] == test_set[i]),\n+\t\t\t\t\"bulk lookup result error\");\n+\t}\n+\n+\t/* Delete the left of inserted keys */\n+\tfor (i = NUM_SAMPLES / 2; i < NUM_SAMPLES; i++) {\n+\t\tret_ht = rte_member_delete(setsum_ht, &keys[i], test_set[i]);\n+\t\tret_cache = rte_member_delete(setsum_cache, &keys[i],\n+\t\t\t\t\t\ttest_set[i]);\n+\t\tret_vbf = rte_member_delete(setsum_vbf, &keys[i], test_set[i]);\n+\t\t/* VBF does not support delete yet, so return error code */\n+\t\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,\n+\t\t\t\t\"key deletion function error\");\n+\t\tTEST_ASSERT(ret_vbf < 0,\n+\t\t\t\t\"vbf does not support deletion, error\");\n+\t}\n+\n+\tfor (i = 0; i < NUM_SAMPLES; i++) {\n+\t\tret_ht = rte_member_lookup(setsum_ht, &keys[i], &set_ht);\n+\t\tret_cache = rte_member_lookup(setsum_cache, &keys[i],\n+\t\t\t\t\t\t&set_cache);\n+\t\tret_vbf = rte_member_lookup(setsum_vbf, &keys[i], &set_vbf);\n+\t\tTEST_ASSERT(ret_ht >= 0 && ret_cache >= 0,\n+\t\t\t\t\"key lookup function error\");\n+\t\tTEST_ASSERT(set_ht == RTE_MEMBER_NO_MATCH &&\n+\t\t\t\tret_cache == RTE_MEMBER_NO_MATCH,\n+\t\t\t\t\"key deletion failed\");\n+\t}\n+\t/* Reset vbf for other following tests */\n+\trte_member_reset(setsum_vbf);\n+\n+\tprintf(\"delete success\\n\");\n+\treturn 0;\n+}\n+\n+static int test_member_multimatch(void)\n+{\n+\tint ret_ht, ret_vbf, ret_cache;\n+\tmember_set_t set_ids_ht[MAX_MATCH] = {0};\n+\tmember_set_t set_ids_vbf[MAX_MATCH] = {0};\n+\tmember_set_t set_ids_cache[MAX_MATCH] = {0};\n+\n+\tmember_set_t set_ids_ht_m[NUM_SAMPLES][MAX_MATCH] = {{0} };\n+\tmember_set_t set_ids_vbf_m[NUM_SAMPLES][MAX_MATCH] = {{0} };\n+\tmember_set_t set_ids_cache_m[NUM_SAMPLES][MAX_MATCH] = {{0} };\n+\n+\tuint32_t match_count_ht[NUM_SAMPLES];\n+\tuint32_t match_count_vbf[NUM_SAMPLES];\n+\tuint32_t match_count_cache[NUM_SAMPLES];\n+\n+\tuint32_t num_key_ht = NUM_SAMPLES;\n+\tuint32_t num_key_vbf = NUM_SAMPLES;\n+\tuint32_t num_key_cache = NUM_SAMPLES;\n+\n+\tconst void *key_array[NUM_SAMPLES];\n+\n+\tuint32_t i, j;\n+\n+\t/* Same key at most inserted 2*entry_per_bucket times for HT mode */\n+\tfor (i = M_MATCH_S; i <= M_MATCH_E; i += M_MATCH_STEP) {\n+\t\tfor (j = 0; j < NUM_SAMPLES; j++) {\n+\t\t\tret_ht = rte_member_add(setsum_ht, &keys[j], i);\n+\t\t\tret_vbf = rte_member_add(setsum_vbf, &keys[j], i);\n+\t\t\tret_cache = rte_member_add(setsum_cache, &keys[j], i);\n+\n+\t\t\tTEST_ASSERT(ret_ht >= 0 && ret_vbf >= 0 &&\n+\t\t\t\t\tret_cache >= 0,\n+\t\t\t\t\t\"insert function error\");\n+\t\t}\n+\t}\n+\n+\t/* Single multimatch test */\n+\tfor (i = 0; i < NUM_SAMPLES; i++) {\n+\t\tret_vbf = rte_member_lookup_multi(setsum_vbf, &keys[i],\n+\t\t\t\t\t\t\tMAX_MATCH, set_ids_vbf);\n+\t\tret_ht = rte_member_lookup_multi(setsum_ht, &keys[i],\n+\t\t\t\t\t\t\tMAX_MATCH, set_ids_ht);\n+\t\tret_cache = rte_member_lookup_multi(setsum_cache, &keys[i],\n+\t\t\t\t\t\tMAX_MATCH, set_ids_cache);\n+\t\t/*\n+\t\t * For cache mode, keys overwrite when signature same.\n+\t\t * the mutimatch should work like single match.\n+\t\t */\n+\t\tTEST_ASSERT(ret_ht == M_MATCH_CNT && ret_vbf == M_MATCH_CNT &&\n+\t\t\t\tret_cache == 1,\n+\t\t\t\t\"single lookup_multi error\");\n+\t\tTEST_ASSERT(set_ids_cache[0] == M_MATCH_E,\n+\t\t\t\t\"single lookup_multi cache error\");\n+\n+\t\tfor (j = 1; j <= M_MATCH_CNT; j++) {\n+\t\t\tTEST_ASSERT(set_ids_ht[j-1] == j * M_MATCH_STEP - 1 &&\n+\t\t\t\t\tset_ids_vbf[j-1] ==\n+\t\t\t\t\t\t\tj * M_MATCH_STEP - 1,\n+\t\t\t\t\t\"single multimatch lookup error\");\n+\t\t}\n+\t}\n+\tprintf(\"lookup single key for multimatch success\\n\");\n+\n+\t/* Bulk multimatch test */\n+\tfor (i = 0; i < NUM_SAMPLES; i++)\n+\t\tkey_array[i] = &keys[i];\n+\tret_vbf = rte_member_lookup_multi_bulk(setsum_vbf,\n+\t\t\t&key_array[0], num_key_ht, MAX_MATCH, match_count_vbf,\n+\t\t\t(member_set_t *)set_ids_vbf_m);\n+\n+\tret_ht = rte_member_lookup_multi_bulk(setsum_ht,\n+\t\t\t&key_array[0], num_key_vbf, MAX_MATCH, match_count_ht,\n+\t\t\t(member_set_t *)set_ids_ht_m);\n+\n+\tret_cache = rte_member_lookup_multi_bulk(setsum_cache,\n+\t\t\t&key_array[0], num_key_cache, MAX_MATCH,\n+\t\t\tmatch_count_cache, (member_set_t *)set_ids_cache_m);\n+\n+\n+\tfor (j = 0; j < NUM_SAMPLES; j++) {\n+\t\tTEST_ASSERT(match_count_ht[j] == M_MATCH_CNT,\n+\t\t\t\"bulk multimatch lookup HT match count error\");\n+\t\tTEST_ASSERT(match_count_vbf[j] == M_MATCH_CNT,\n+\t\t\t\"bulk multimatch lookup vBF match count error\");\n+\t\tTEST_ASSERT(match_count_cache[j] == 1,\n+\t\t\t\"bulk multimatch lookup CACHE match count error\");\n+\t\tTEST_ASSERT(set_ids_cache_m[j][0] == M_MATCH_E,\n+\t\t\t\"bulk multimatch lookup CACHE set value error\");\n+\n+\t\tfor (i = 1; i <= M_MATCH_CNT; i++) {\n+\t\t\tTEST_ASSERT(set_ids_ht_m[j][i-1] ==\n+\t\t\t\t\t\t\ti * M_MATCH_STEP - 1,\n+\t\t\t\t\"bulk multimatch lookup HT set value error\");\n+\t\t\tTEST_ASSERT(set_ids_vbf_m[j][i-1] ==\n+\t\t\t\t\t\t\ti * M_MATCH_STEP - 1,\n+\t\t\t\t\"bulk multimatch lookup vBF set value error\");\n+\t\t}\n+\t}\n+\n+\tprintf(\"lookup for bulk multimatch success\\n\");\n+\n+\treturn 0;\n+}\n+\n+static int key_compare(const void *key1, const void *key2)\n+{\n+\treturn memcmp(key1, key2, KEY_SIZE);\n+}\n+\n+static void\n+setup_keys_and_data(void)\n+{\n+\tunsigned int i, j;\n+\tint num_duplicates;\n+\n+\t/* Reset all arrays */\n+\tfor (i = 0; i < KEY_SIZE; i++)\n+\t\tgenerated_keys[0][i] = 0;\n+\n+\t/* Generate a list of keys, some of which may be duplicates */\n+\tfor (i = 0; i < MAX_ENTRIES; i++) {\n+\t\tfor (j = 0; j < KEY_SIZE; j++)\n+\t\t\tgenerated_keys[i][j] = rte_rand() & 0xFF;\n+\t}\n+\n+\t/* Remove duplicates from the keys array */\n+\tdo {\n+\t\tnum_duplicates = 0;\n+\t\t/* Sort the list of keys to make it easier to find duplicates */\n+\t\tqsort(generated_keys, MAX_ENTRIES, KEY_SIZE, key_compare);\n+\n+\t\t/* Sift through the list of keys and look for duplicates */\n+\t\tint num_duplicates = 0;\n+\t\tfor (i = 0; i < MAX_ENTRIES - 1; i++) {\n+\t\t\tif (memcmp(generated_keys[i], generated_keys[i + 1],\n+\t\t\t\t\tKEY_SIZE) == 0) {\n+\t\t\t\t/* This key already exists, try again */\n+\t\t\t\tnum_duplicates++;\n+\t\t\t\tfor (j = 0; j < KEY_SIZE; j++)\n+\t\t\t\t\tgenerated_keys[i][j] =\n+\t\t\t\t\t\t\trte_rand() & 0xFF;\n+\t\t\t}\n+\t\t}\n+\t} while (num_duplicates != 0);\n+}\n+\n+static inline int\n+add_generated_keys(struct rte_member_setsum *setsum, unsigned int *added_keys)\n+{\n+\tint ret = 0;\n+\n+\tfor (*added_keys = 0; ret >= 0 && *added_keys < MAX_ENTRIES;\n+\t\t\t(*added_keys)++) {\n+\t\tuint16_t set = (rte_rand() & 0xf) + 1;\n+\t\tret = rte_member_add(setsum, &generated_keys[*added_keys], set);\n+\t}\n+\treturn ret;\n+}\n+\n+static inline int\n+add_generated_keys_cache(struct rte_member_setsum *setsum,\n+\t\t\t\tunsigned int *added_keys)\n+{\n+\tint ret = 0;\n+\n+\tfor (*added_keys = 0; ret == 0 && *added_keys < MAX_ENTRIES;\n+\t\t\t(*added_keys)++) {\n+\t\tuint16_t set = (rte_rand() & 0xf) + 1;\n+\t\tret = rte_member_add(setsum, &generated_keys[*added_keys], set);\n+\t}\n+\treturn ret;\n+}\n+\n+static int\n+test_member_loadfactor(void)\n+{\n+\tunsigned  int j;\n+\tunsigned int added_keys, average_keys_added = 0;\n+\tint ret;\n+\n+\tsetup_keys_and_data();\n+\n+\trte_member_free(setsum_ht);\n+\trte_member_free(setsum_cache);\n+\trte_member_free(setsum_vbf);\n+\n+\tparams.key_len = KEY_SIZE;\n+\tparams.name = \"test_member_ht\";\n+\tparams.is_cache = 0;\n+\tparams.type = RTE_MEMBER_TYPE_HT;\n+\tsetsum_ht = rte_member_create(&params);\n+\n+\tparams.name = \"test_member_cache\";\n+\tparams.is_cache = 1;\n+\tsetsum_cache = rte_member_create(&params);\n+\n+\n+\tif (setsum_ht == NULL || setsum_cache == NULL) {\n+\t\tprintf(\"Creation of setsums fail\\n\");\n+\t\treturn -1;\n+\t}\n+\t/* Test HT non-cache mode */\n+\tfor (j = 0; j < ITERATIONS; j++) {\n+\t\t/* Add random entries until key cannot be added */\n+\t\tret = add_generated_keys(setsum_ht, &added_keys);\n+\t\tif (ret != -ENOSPC) {\n+\t\t\tprintf(\"Unexpected error when adding keys\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\taverage_keys_added += added_keys;\n+\n+\t\t/* Reset the table */\n+\t\trte_member_reset(setsum_ht);\n+\n+\t\t/* Print a dot to show progress on operations */\n+\t\tprintf(\".\");\n+\t\tfflush(stdout);\n+\t}\n+\n+\taverage_keys_added /= ITERATIONS;\n+\n+\tprintf(\"\\nKeys inserted when no space(non-cache) = %.2f%% (%u/%u)\\n\",\n+\t\t((double) average_keys_added / params.num_keys * 100),\n+\t\taverage_keys_added, params.num_keys);\n+\n+\t/* Test cache mode */\n+\tadded_keys = average_keys_added = 0;\n+\tfor (j = 0; j < ITERATIONS; j++) {\n+\t\t/* Add random entries until key cannot be added */\n+\t\tret = add_generated_keys_cache(setsum_cache, &added_keys);\n+\t\tif (ret != 1) {\n+\t\t\tprintf(\"Unexpected error when adding keys\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\taverage_keys_added += added_keys;\n+\n+\t\t/* Reset the table */\n+\t\trte_member_reset(setsum_cache);\n+\n+\t\t/* Print a dot to show progress on operations */\n+\t\tprintf(\".\");\n+\t\tfflush(stdout);\n+\t}\n+\n+\taverage_keys_added /= ITERATIONS;\n+\n+\tprintf(\"\\nKeys inserted when eviction happens(cache)= %.2f%% (%u/%u)\\n\",\n+\t\t((double) average_keys_added / params.num_keys * 100),\n+\t\taverage_keys_added, params.num_keys);\n+\treturn 0;\n+}\n+\n+static void\n+perform_free(void)\n+{\n+\trte_member_free(setsum_ht);\n+\trte_member_free(setsum_cache);\n+\trte_member_free(setsum_vbf);\n+}\n+\n+static int\n+test_member(void)\n+{\n+\tif (test_member_create_bad_param() < 0)\n+\t\treturn -1;\n+\n+\tif (test_member_find_existing() < 0)\n+\t\treturn -1;\n+\n+\tif (test_member_create() < 0) {\n+\t\tperform_free();\n+\t\treturn -1;\n+\t}\n+\tif (test_member_insert() < 0) {\n+\t\tperform_free();\n+\t\treturn -1;\n+\t}\n+\tif (test_member_lookup() < 0) {\n+\t\tperform_free();\n+\t\treturn -1;\n+\t}\n+\tif (test_member_delete() < 0) {\n+\t\tperform_free();\n+\t\treturn -1;\n+\t}\n+\tif (test_member_multimatch() < 0) {\n+\t\tperform_free();\n+\t\treturn -1;\n+\t}\n+\tif (test_member_loadfactor() < 0) {\n+\t\trte_member_free(setsum_ht);\n+\t\trte_member_free(setsum_cache);\n+\t\treturn -1;\n+\t}\n+\n+\tperform_free();\n+\treturn 0;\n+}\n+\n+REGISTER_TEST_COMMAND(member_autotest, test_member);\ndiff --git a/test/test/test_member_perf.c b/test/test/test_member_perf.c\nnew file mode 100644\nindex 0000000..e13066f\n--- /dev/null\n+++ b/test/test/test_member_perf.c\n@@ -0,0 +1,654 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2017 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <stdio.h>\n+#include <inttypes.h>\n+\n+#include <rte_lcore.h>\n+#include <rte_cycles.h>\n+#include <rte_malloc.h>\n+#include <rte_random.h>\n+#include <rte_memcpy.h>\n+#include <rte_thash.h>\n+#include <rte_member.h>\n+\n+#include \"test.h\"\n+\n+#define NUM_KEYSIZES 10\n+#define NUM_SHUFFLES 10\n+#define MAX_KEYSIZE 64\n+#define MAX_ENTRIES (1 << 19)\n+#define KEYS_TO_ADD (MAX_ENTRIES * 75 / 100) /* 75% table utilization */\n+#define NUM_LOOKUPS (KEYS_TO_ADD * 5) /* Loop among keys added, several times */\n+#define VBF_SET_CNT 16\n+#define BURST_SIZE 64\n+#define VBF_FALSE_RATE 0.03\n+\n+static unsigned int test_socket_id;\n+\n+enum sstype {\n+\tHT = 0,\n+\tCACHE,\n+\tVBF,\n+\tNUM_TYPE\n+};\n+\n+enum operations {\n+\tADD = 0,\n+\tLOOKUP,\n+\tLOOKUP_BULK,\n+\tLOOKUP_MULTI,\n+\tLOOKUP_MULTI_BULK,\n+\tDELETE,\n+\tLOOKUP_MISS,\n+\tNUM_OPERATIONS\n+};\n+\n+struct  member_perf_params {\n+\tstruct rte_member_setsum *setsum[NUM_TYPE];\n+\tuint32_t key_size;\n+\tunsigned int cycle;\n+};\n+\n+static uint32_t hashtest_key_lens[] = {\n+\t/* standard key sizes */\n+\t4, 8, 16, 32, 48, 64,\n+\t/* IPv4 SRC + DST + protocol, unpadded */\n+\t9,\n+\t/* IPv4 5-tuple, unpadded */\n+\t13,\n+\t/* IPv6 5-tuple, unpadded */\n+\t37,\n+\t/* IPv6 5-tuple, padded to 8-byte boundary */\n+\t40\n+};\n+\n+/* Array to store number of cycles per operation */\n+uint64_t cycles[NUM_TYPE][NUM_KEYSIZES][NUM_OPERATIONS];\n+uint64_t false_data[NUM_TYPE][NUM_KEYSIZES];\n+uint64_t false_data_bulk[NUM_TYPE][NUM_KEYSIZES];\n+uint64_t false_data_multi[NUM_TYPE][NUM_KEYSIZES];\n+uint64_t false_data_multi_bulk[NUM_TYPE][NUM_KEYSIZES];\n+\n+uint64_t false_hit[NUM_TYPE][NUM_KEYSIZES];\n+\n+member_set_t data[NUM_TYPE][/* Array to store the data */KEYS_TO_ADD];\n+\n+/* Array to store all input keys */\n+uint8_t keys[KEYS_TO_ADD][MAX_KEYSIZE];\n+\n+/* Shuffle the keys that have been added, so lookups will be totally random */\n+static void\n+shuffle_input_keys(struct member_perf_params *params)\n+{\n+\tmember_set_t temp_data;\n+\tunsigned int i, j;\n+\tuint32_t swap_idx;\n+\tuint8_t temp_key[MAX_KEYSIZE];\n+\n+\tfor (i = KEYS_TO_ADD - 1; i > 0; i--) {\n+\t\tswap_idx = rte_rand() % i;\n+\t\tmemcpy(temp_key, keys[i], hashtest_key_lens[params->cycle]);\n+\t\tmemcpy(keys[i], keys[swap_idx],\n+\t\t\thashtest_key_lens[params->cycle]);\n+\t\tmemcpy(keys[swap_idx], temp_key,\n+\t\t\thashtest_key_lens[params->cycle]);\n+\t\tfor (j = 0; j < NUM_TYPE; j++) {\n+\t\t\ttemp_data = data[j][i];\n+\t\t\tdata[j][i] = data[j][swap_idx];\n+\t\t\tdata[j][swap_idx] = temp_data;\n+\t\t}\n+\t}\n+}\n+\n+static int key_compare(const void *key1, const void *key2)\n+{\n+\treturn memcmp(key1, key2, MAX_KEYSIZE);\n+}\n+\n+struct rte_member_parameters member_params = {\n+\t\t.num_keys = MAX_ENTRIES,\t/* Total hash table entries. */\n+\t\t.key_len = 4,\t\t\t/* Length of hash key. */\n+\n+\t\t/* num_set and false_positive_rate only relevant to vBF */\n+\t\t.num_set = VBF_SET_CNT,\n+\t\t.false_positive_rate = 0.03,\n+\t\t.prim_hash_seed = 0,\n+\t\t.sec_hash_seed = 1,\n+\t\t.socket_id = 0,\t\t\t/* NUMA Socket ID for memory. */\n+\t};\n+\n+static int\n+setup_keys_and_data(struct member_perf_params *params, unsigned int cycle,\n+\t\tint miss)\n+{\n+\tunsigned int i, j;\n+\tint num_duplicates;\n+\n+\tparams->key_size = hashtest_key_lens[cycle];\n+\tparams->cycle = cycle;\n+\n+\t/* Reset all arrays */\n+\tfor (i = 0; i < params->key_size; i++)\n+\t\tkeys[0][i] = 0;\n+\n+\t/* Generate a list of keys, some of which may be duplicates */\n+\tfor (i = 0; i < KEYS_TO_ADD; i++) {\n+\t\tfor (j = 0; j < params->key_size; j++)\n+\t\t\tkeys[i][j] = rte_rand() & 0xFF;\n+\n+\t\tdata[HT][i] = data[CACHE][i] = (rte_rand() & 0x7FFE) + 1;\n+\t\tdata[VBF][i] = rte_rand() % VBF_SET_CNT + 1;\n+\t}\n+\n+\t/* Remove duplicates from the keys array */\n+\tdo {\n+\t\tnum_duplicates = 0;\n+\n+\t\t/* Sort the list of keys to make it easier to find duplicates */\n+\t\tqsort(keys, KEYS_TO_ADD, MAX_KEYSIZE, key_compare);\n+\n+\t\t/* Sift through the list of keys and look for duplicates */\n+\t\tint num_duplicates = 0;\n+\t\tfor (i = 0; i < KEYS_TO_ADD - 1; i++) {\n+\t\t\tif (memcmp(keys[i], keys[i + 1],\n+\t\t\t\t\tparams->key_size) == 0) {\n+\t\t\t\t/* This key already exists, try again */\n+\t\t\t\tnum_duplicates++;\n+\t\t\t\tfor (j = 0; j < params->key_size; j++)\n+\t\t\t\t\tkeys[i][j] = rte_rand() & 0xFF;\n+\t\t\t}\n+\t\t}\n+\t} while (num_duplicates != 0);\n+\n+\t/* Shuffle the random values again */\n+\tshuffle_input_keys(params);\n+\n+\t/* For testing miss lookup, we insert half and lookup the other half */\n+\tunsigned int entry_cnt, bf_key_cnt;\n+\tif (!miss) {\n+\t\tentry_cnt = MAX_ENTRIES;\n+\t\tbf_key_cnt = KEYS_TO_ADD;\n+\t} else {\n+\t\tentry_cnt = MAX_ENTRIES / 2;\n+\t\tbf_key_cnt = KEYS_TO_ADD / 2;\n+\t}\n+\tmember_params.false_positive_rate = VBF_FALSE_RATE;\n+\tmember_params.key_len = params->key_size;\n+\tmember_params.socket_id = test_socket_id;\n+\tmember_params.num_keys = entry_cnt;\n+\tmember_params.name = \"test_member_ht\";\n+\tmember_params.is_cache = 0;\n+\tmember_params.type = RTE_MEMBER_TYPE_HT;\n+\tparams->setsum[HT] = rte_member_create(&member_params);\n+\tif (params->setsum[HT] == NULL)\n+\t\tfprintf(stderr, \"ht create fail\\n\");\n+\n+\tmember_params.name = \"test_member_cache\";\n+\tmember_params.is_cache = 1;\n+\tparams->setsum[CACHE] = rte_member_create(&member_params);\n+\tif (params->setsum[CACHE] == NULL)\n+\t\tfprintf(stderr, \"CACHE create fail\\n\");\n+\n+\tmember_params.name = \"test_member_vbf\";\n+\tmember_params.type = RTE_MEMBER_TYPE_VBF;\n+\tmember_params.num_keys = bf_key_cnt;\n+\tparams->setsum[VBF] = rte_member_create(&member_params);\n+\tif (params->setsum[VBF] == NULL)\n+\t\tfprintf(stderr, \"VBF create fail\\n\");\n+\tfor (i = 0; i < NUM_TYPE; i++) {\n+\t\tif (params->setsum[i] == NULL)\n+\t\t\treturn -1;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_adds(struct member_perf_params *params, int type)\n+{\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\tunsigned int i, a;\n+\tint32_t ret;\n+\n+\tfor (i = 0; i < KEYS_TO_ADD; i++) {\n+\t\tret = rte_member_add(params->setsum[type], &keys[i],\n+\t\t\t\t\tdata[type][i]);\n+\t\tif (ret < 0) {\n+\t\t\tprintf(\"Error %d in rte_member_add - key=0x\", ret);\n+\t\t\tfor (a = 0; a < params->key_size; a++)\n+\t\t\t\tprintf(\"%02x\", keys[i][a]);\n+\t\t\tprintf(\" value=%d, type: %d\\n\", data[type][i], type);\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][ADD] = time_taken / KEYS_TO_ADD;\n+\treturn 0;\n+}\n+\n+static int\n+timed_lookups(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i, j;\n+\n+\tfalse_data[type][params->cycle] = 0;\n+\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\tmember_set_t result;\n+\tint ret;\n+\n+\tfor (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {\n+\t\tfor (j = 0; j < KEYS_TO_ADD; j++) {\n+\t\t\tret = rte_member_lookup(params->setsum[type], &keys[j],\n+\t\t\t\t\t\t&result);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tprintf(\"lookup wrong internally\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tif (type == HT && result == RTE_MEMBER_NO_MATCH) {\n+\t\t\t\tprintf(\"HT mode shouldn't have false negative\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tif (result != data[type][j])\n+\t\t\t\tfalse_data[type][params->cycle]++;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][LOOKUP] = time_taken / NUM_LOOKUPS;\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_lookups_bulk(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i, j, k;\n+\tmember_set_t result[BURST_SIZE] = {0};\n+\tconst void *keys_burst[BURST_SIZE];\n+\tint ret;\n+\n+\tfalse_data_bulk[type][params->cycle] = 0;\n+\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\n+\tfor (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {\n+\t\tfor (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {\n+\t\t\tfor (k = 0; k < BURST_SIZE; k++)\n+\t\t\t\tkeys_burst[k] = keys[j * BURST_SIZE + k];\n+\n+\t\t\tret = rte_member_lookup_bulk(params->setsum[type],\n+\t\t\t\tkeys_burst,\n+\t\t\t\tBURST_SIZE,\n+\t\t\t\tresult);\n+\t\t\tif  (ret <= 0) {\n+\t\t\t\tprintf(\"lookup bulk has wrong return value\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tfor (k = 0; k < BURST_SIZE; k++) {\n+\t\t\t\tuint32_t data_idx = j * BURST_SIZE + k;\n+\t\t\t\tif (type == HT && result[k] ==\n+\t\t\t\t\t\tRTE_MEMBER_NO_MATCH) {\n+\t\t\t\t\tprintf(\"HT mode shouldn't have \"\n+\t\t\t\t\t\t\"false negative\");\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tif (result[k] != data[type][data_idx])\n+\t\t\t\t\tfalse_data_bulk[type][params->cycle]++;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][LOOKUP_BULK] = time_taken / NUM_LOOKUPS;\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_lookups_multimatch(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i, j;\n+\tmember_set_t result[RTE_MEMBER_BUCKET_ENTRIES] = {0};\n+\tint ret;\n+\tfalse_data_multi[type][params->cycle] = 0;\n+\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\n+\tfor (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {\n+\t\tfor (j = 0; j < KEYS_TO_ADD; j++) {\n+\t\t\tret = rte_member_lookup_multi(params->setsum[type],\n+\t\t\t\t&keys[j], RTE_MEMBER_BUCKET_ENTRIES, result);\n+\t\t\tif (type != CACHE && ret <= 0) {\n+\t\t\t\tprintf(\"lookup multi has wrong return value %d,\"\n+\t\t\t\t\t\"type %d\\n\", ret, type);\n+\t\t\t}\n+\t\t\tif (type == HT && ret == 0) {\n+\t\t\t\tprintf(\"HT mode shouldn't have false negative\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\t/*\n+\t\t\t * For performance test purpose, we do not iterate all\n+\t\t\t * results here. We assume most likely each key can only\n+\t\t\t * find one match which is result[0].\n+\t\t\t */\n+\t\t\tif (result[0] != data[type][j])\n+\t\t\t\tfalse_data_multi[type][params->cycle]++;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][LOOKUP_MULTI] = time_taken / NUM_LOOKUPS;\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_lookups_multimatch_bulk(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i, j, k;\n+\tmember_set_t result[BURST_SIZE][RTE_MEMBER_BUCKET_ENTRIES] = {{0} };\n+\tconst void *keys_burst[BURST_SIZE];\n+\tuint32_t match_count[BURST_SIZE];\n+\tint ret;\n+\n+\tfalse_data_multi_bulk[type][params->cycle] = 0;\n+\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\n+\tfor (i = 0; i < NUM_LOOKUPS / KEYS_TO_ADD; i++) {\n+\t\tfor (j = 0; j < KEYS_TO_ADD / BURST_SIZE; j++) {\n+\t\t\tfor (k = 0; k < BURST_SIZE; k++)\n+\t\t\t\tkeys_burst[k] = keys[j * BURST_SIZE + k];\n+\n+\t\t\tret = rte_member_lookup_multi_bulk(\n+\t\t\t\tparams->setsum[type],\n+\t\t\t\tkeys_burst, BURST_SIZE,\n+\t\t\t\tRTE_MEMBER_BUCKET_ENTRIES, match_count,\n+\t\t\t\t(member_set_t *)result);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tprintf(\"lookup multimatch bulk has wrong return\"\n+\t\t\t\t\t\" value\\n\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tfor (k = 0; k < BURST_SIZE; k++) {\n+\t\t\t\tif (type != CACHE && match_count[k] == 0) {\n+\t\t\t\t\tprintf(\"lookup multimatch bulk get \"\n+\t\t\t\t\t\t\"wrong match count\\n\");\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tif (type == HT && match_count[k] == 0) {\n+\t\t\t\t\tprintf(\"HT mode shouldn't have \"\n+\t\t\t\t\t\t\"false negative\");\n+\t\t\t\t\treturn -1;\n+\t\t\t\t}\n+\t\t\t\tuint32_t data_idx = j * BURST_SIZE + k;\n+\t\t\t\tif (result[k][0] != data[type][data_idx])\n+\t\t\t\t\tfalse_data_multi_bulk[type][params->cycle]++;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][LOOKUP_MULTI_BULK] = time_taken /\n+\t\t\t\t\t\t\tNUM_LOOKUPS;\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_deletes(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i;\n+\tint32_t ret;\n+\n+\tif (type == VBF)\n+\t\treturn 0;\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\tfor (i = 0; i < KEYS_TO_ADD; i++) {\n+\t\tret = rte_member_delete(params->setsum[type], &keys[i],\n+\t\t\t\t\tdata[type][i]);\n+\t\tif (type != CACHE && ret < 0) {\n+\t\t\tprintf(\"delete error\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][DELETE] = time_taken / KEYS_TO_ADD;\n+\n+\treturn 0;\n+}\n+\n+static int\n+timed_miss_lookup(struct member_perf_params *params, int type)\n+{\n+\tunsigned int i, j;\n+\tint ret;\n+\n+\tfalse_hit[type][params->cycle] = 0;\n+\n+\tfor (i = 0; i < KEYS_TO_ADD / 2; i++) {\n+\t\tret = rte_member_add(params->setsum[type], &keys[i],\n+\t\t\t\t\tdata[type][i]);\n+\t\tif (ret < 0) {\n+\t\t\tunsigned int a;\n+\t\t\tprintf(\"Error %d in rte_member_add - key=0x\", ret);\n+\t\t\tfor (a = 0; a < params->key_size; a++)\n+\t\t\t\tprintf(\"%02x\", keys[i][a]);\n+\t\t\tprintf(\" value=%d, type: %d\\n\", data[type][i], type);\n+\n+\t\t\treturn -1;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t start_tsc = rte_rdtsc();\n+\tmember_set_t result;\n+\n+\tfor (i = 0; i < 2 * NUM_LOOKUPS / KEYS_TO_ADD; i++) {\n+\t\tfor (j = KEYS_TO_ADD / 2; j < KEYS_TO_ADD; j++) {\n+\t\t\tret = rte_member_lookup(params->setsum[type], &keys[j],\n+\t\t\t\t\t\t&result);\n+\t\t\tif (ret < 0) {\n+\t\t\t\tprintf(\"lookup wrong internally\");\n+\t\t\t\treturn -1;\n+\t\t\t}\n+\t\t\tif (result != RTE_MEMBER_NO_MATCH)\n+\t\t\t\tfalse_hit[type][params->cycle]++;\n+\t\t}\n+\t}\n+\n+\tconst uint64_t end_tsc = rte_rdtsc();\n+\tconst uint64_t time_taken = end_tsc - start_tsc;\n+\n+\tcycles[type][params->cycle][LOOKUP_MISS] = time_taken / NUM_LOOKUPS;\n+\n+\treturn 0;\n+}\n+\n+static void\n+perform_frees(struct member_perf_params *params)\n+{\n+\tint i;\n+\tfor (i = 0; i < NUM_TYPE; i++) {\n+\t\tif (params->setsum[i] != NULL) {\n+\t\t\trte_member_free(params->setsum[i]);\n+\t\t\tparams->setsum[i] = NULL;\n+\t\t}\n+\t}\n+}\n+\n+static int\n+exit_with_fail(const char *testname, struct member_perf_params *params,\n+\t\tunsigned int i, unsigned int j)\n+{\n+\tprintf(\"<<<<<Test %s failed at keysize %d iteration %d type %d>>>>>\\n\",\n+\t\t\ttestname, hashtest_key_lens[params->cycle], i, j);\n+\tperform_frees(params);\n+\treturn -1;\n+}\n+\n+static int\n+run_all_tbl_perf_tests(void)\n+{\n+\tunsigned int i, j, k;\n+\tstruct member_perf_params params;\n+\n+\tprintf(\"Measuring performance, please wait\\n\");\n+\tfflush(stdout);\n+\n+\ttest_socket_id = rte_socket_id();\n+\n+\tfor (i = 0; i < NUM_KEYSIZES; i++) {\n+\t\tif (setup_keys_and_data(&params, i, 0) < 0) {\n+\t\t\tprintf(\"Could not create keys/data/table\\n\");\n+\t\t\treturn -1;\n+\t\t}\n+\t\tfor (j = 0; j < NUM_TYPE; j++) {\n+\n+\t\t\tif (timed_adds(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_adds\", &params,\n+\t\t\t\t\t\t\ti, j);\n+\n+\t\t\tfor (k = 0; k < NUM_SHUFFLES; k++)\n+\t\t\t\tshuffle_input_keys(&params);\n+\n+\t\t\tif (timed_lookups(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_lookups\", &params,\n+\t\t\t\t\t\t\ti, j);\n+\n+\t\t\tif (timed_lookups_bulk(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_lookups_bulk\",\n+\t\t\t\t\t\t&params, i, j);\n+\n+\t\t\tif (timed_lookups_multimatch(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_lookups_multi\",\n+\t\t\t\t\t\t&params, i, j);\n+\n+\t\t\tif (timed_lookups_multimatch_bulk(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_lookups_multi_bulk\",\n+\t\t\t\t\t\t\t&params, i, j);\n+\n+\t\t\tif (timed_deletes(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_deletes\", &params,\n+\t\t\t\t\t\t\ti, j);\n+\n+\t\t\t/* Print a dot to show progress on operations */\n+\t\t}\n+\t\tprintf(\".\");\n+\t\tfflush(stdout);\n+\n+\t\tperform_frees(&params);\n+\t}\n+\n+\t/* Test false positive rate using un-inserted keys */\n+\tfor (i = 0; i < NUM_KEYSIZES; i++) {\n+\t\tif (setup_keys_and_data(&params, i, 1) < 0) {\n+\t\t\tprintf(\"Could not create keys/data/table\\n\");\n+\t\t\treturn -1;\n+\t\t\t}\n+\t\tfor (j = 0; j < NUM_TYPE; j++) {\n+\t\t\tif (timed_miss_lookup(&params, j) < 0)\n+\t\t\t\treturn exit_with_fail(\"timed_miss_lookup\",\n+\t\t\t\t\t\t&params, i, j);\n+\t\t}\n+\t\tperform_frees(&params);\n+\t}\n+\n+\tprintf(\"\\nResults (in CPU cycles/operation)\\n\");\n+\tprintf(\"-----------------------------------\\n\");\n+\tprintf(\"\\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s%-18s\\n\",\n+\t\t\t\"Keysize\", \"type\",  \"Add\", \"Lookup\", \"Lookup_bulk\",\n+\t\t\t\"lookup_multi\", \"lookup_multi_bulk\", \"Delete\",\n+\t\t\t\"miss_lookup\");\n+\tfor (i = 0; i < NUM_KEYSIZES; i++) {\n+\t\tfor (j = 0; j < NUM_TYPE; j++) {\n+\t\t\tprintf(\"%-18d\", hashtest_key_lens[i]);\n+\t\t\tprintf(\"%-18d\", j);\n+\t\t\tfor (k = 0; k < NUM_OPERATIONS; k++)\n+\t\t\t\tprintf(\"%-18\"PRIu64, cycles[j][i][k]);\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\t}\n+\n+\tprintf(\"\\nFalse results rate (and false positive rate)\\n\");\n+\tprintf(\"-----------------------------------\\n\");\n+\tprintf(\"\\n%-18s%-18s%-18s%-18s%-18s%-18s%-18s\\n\",\n+\t\t\t\"Keysize\", \"type\",  \"fr_single\", \"fr_bulk\", \"fr_multi\",\n+\t\t\t\"fr_multi_bulk\", \"false_positive_rate\");\n+\t/* Key size not influence False rate so just print out one key size */\n+\tfor (i = 0; i < 1; i++) {\n+\t\tfor (j = 0; j < NUM_TYPE; j++) {\n+\t\t\tprintf(\"%-18d\", hashtest_key_lens[i]);\n+\t\t\tprintf(\"%-18d\", j);\n+\t\t\tprintf(\"%-18f\", (float)false_data[j][i] / NUM_LOOKUPS);\n+\t\t\tprintf(\"%-18f\", (float)false_data_bulk[j][i] /\n+\t\t\t\t\t\tNUM_LOOKUPS);\n+\t\t\tprintf(\"%-18f\", (float)false_data_multi[j][i] /\n+\t\t\t\t\t\tNUM_LOOKUPS);\n+\t\t\tprintf(\"%-18f\", (float)false_data_multi_bulk[j][i] /\n+\t\t\t\t\t\tNUM_LOOKUPS);\n+\t\t\tprintf(\"%-18f\", (float)false_hit[j][i] /\n+\t\t\t\t\t\tNUM_LOOKUPS);\n+\t\t\tprintf(\"\\n\");\n+\t\t}\n+\t}\n+\treturn 0;\n+}\n+\n+static int\n+test_member_perf(void)\n+{\n+\n+\tif (run_all_tbl_perf_tests() < 0)\n+\t\treturn -1;\n+\n+\treturn 0;\n+}\n+\n+REGISTER_TEST_COMMAND(member_perf_autotest, test_member_perf);\n",
    "prefixes": [
        "dpdk-dev",
        "v6",
        "6/7"
    ]
}