get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 30536,
    "url": "https://patches.dpdk.org/api/patches/30536/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1508339034-171115-10-git-send-email-cristian.dumitrescu@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": "<1508339034-171115-10-git-send-email-cristian.dumitrescu@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1508339034-171115-10-git-send-email-cristian.dumitrescu@intel.com",
    "date": "2017-10-18T15:03:26",
    "name": "[dpdk-dev,v3,09/18] librte_table: rework variable size key lru hash table",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "20873835b58dbe5b032cae85605f1c1f8c63722a",
    "submitter": {
        "id": 19,
        "url": "https://patches.dpdk.org/api/people/19/?format=api",
        "name": "Cristian Dumitrescu",
        "email": "cristian.dumitrescu@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1508339034-171115-10-git-send-email-cristian.dumitrescu@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/30536/comments/",
    "check": "warning",
    "checks": "https://patches.dpdk.org/api/patches/30536/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 0710D1B1F0;\n\tWed, 18 Oct 2017 17:04:30 +0200 (CEST)",
            "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby dpdk.org (Postfix) with ESMTP id 007791B1AB\n\tfor <dev@dpdk.org>; Wed, 18 Oct 2017 17:04:06 +0200 (CEST)",
            "from orsmga004.jf.intel.com ([10.7.209.38])\n\tby fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t18 Oct 2017 08:04:06 -0700",
            "from silpixa00382658.ir.intel.com ([10.237.223.29])\n\tby orsmga004.jf.intel.com with ESMTP; 18 Oct 2017 08:04:05 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.43,397,1503385200\"; d=\"scan'208\";a=\"139673048\"",
        "From": "Cristian Dumitrescu <cristian.dumitrescu@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "thomas@monjalon.net",
        "Date": "Wed, 18 Oct 2017 16:03:26 +0100",
        "Message-Id": "<1508339034-171115-10-git-send-email-cristian.dumitrescu@intel.com>",
        "X-Mailer": "git-send-email 2.7.4",
        "In-Reply-To": "<1508339034-171115-1-git-send-email-cristian.dumitrescu@intel.com>",
        "References": "<1507634341-72277-2-git-send-email-cristian.dumitrescu@intel.com>\n\t<1508339034-171115-1-git-send-email-cristian.dumitrescu@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v3 09/18] librte_table: rework variable size key\n\tlru hash table",
        "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": "Rework for the variable size key LRU hash table to use the\nmask-based hash function and the unified parameter structure.\n\nSigned-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>\n---\n lib/librte_table/rte_table_hash.h     |  26 ----\n lib/librte_table/rte_table_hash_lru.c | 277 +++++++++++++++++++++-------------\n test/test-pipeline/pipeline_hash.c    |   9 +-\n 3 files changed, 177 insertions(+), 135 deletions(-)",
    "diff": "diff --git a/lib/librte_table/rte_table_hash.h b/lib/librte_table/rte_table_hash.h\nindex 0024b99..fb5f4d7 100755\n--- a/lib/librte_table/rte_table_hash.h\n+++ b/lib/librte_table/rte_table_hash.h\n@@ -137,32 +137,6 @@ typedef uint64_t (*rte_table_hash_op_hash_nomask)(\n \n extern struct rte_table_ops rte_table_hash_ext_ops;\n \n-/** LRU hash table parameters */\n-struct rte_table_hash_lru_params {\n-\t/** Key size (number of bytes) */\n-\tuint32_t key_size;\n-\n-\t/** Maximum number of keys */\n-\tuint32_t n_keys;\n-\n-\t/** Number of hash table buckets. Each bucket stores up to 4 keys. */\n-\tuint32_t n_buckets;\n-\n-\t/** Hash function */\n-\trte_table_hash_op_hash_nomask f_hash;\n-\n-\t/** Seed value for the hash function */\n-\tuint64_t seed;\n-\n-\t/** Byte offset within packet meta-data where the 4-byte key signature\n-\tis located. Valid for pre-computed key signature tables, ignored for\n-\tdo-sig tables. */\n-\tuint32_t signature_offset;\n-\n-\t/** Byte offset within packet meta-data where the key is located */\n-\tuint32_t key_offset;\n-};\n-\n extern struct rte_table_ops rte_table_hash_lru_ops;\n \n /**\ndiff --git a/lib/librte_table/rte_table_hash_lru.c b/lib/librte_table/rte_table_hash_lru.c\nindex 61050f3..eebc1cd 100755\n--- a/lib/librte_table/rte_table_hash_lru.c\n+++ b/lib/librte_table/rte_table_hash_lru.c\n@@ -84,9 +84,8 @@ struct rte_table_hash {\n \tuint32_t entry_size;\n \tuint32_t n_keys;\n \tuint32_t n_buckets;\n-\trte_table_hash_op_hash_nomask f_hash;\n+\trte_table_hash_op_hash f_hash;\n \tuint64_t seed;\n-\tuint32_t signature_offset;\n \tuint32_t key_offset;\n \n \t/* Internal */\n@@ -99,6 +98,7 @@ struct rte_table_hash {\n \tstruct grinder grinders[RTE_PORT_IN_BURST_SIZE_MAX];\n \n \t/* Tables */\n+\tuint64_t *key_mask;\n \tstruct bucket *buckets;\n \tuint8_t *key_mem;\n \tuint8_t *data_mem;\n@@ -109,12 +109,39 @@ struct rte_table_hash {\n };\n \n static int\n-check_params_create(struct rte_table_hash_lru_params *params)\n+keycmp(void *a, void *b, void *b_mask, uint32_t n_bytes)\n {\n-\tuint32_t n_buckets_min;\n+\tuint64_t *a64 = a, *b64 = b, *b_mask64 = b_mask;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < n_bytes / sizeof(uint64_t); i++)\n+\t\tif (a64[i] != (b64[i] & b_mask64[i]))\n+\t\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n+static void\n+keycpy(void *dst, void *src, void *src_mask, uint32_t n_bytes)\n+{\n+\tuint64_t *dst64 = dst, *src64 = src, *src_mask64 = src_mask;\n+\tuint32_t i;\n+\n+\tfor (i = 0; i < n_bytes / sizeof(uint64_t); i++)\n+\t\tdst64[i] = src64[i] & src_mask64[i];\n+}\n+\n+static int\n+check_params_create(struct rte_table_hash_params *params)\n+{\n+\t/* name */\n+\tif (params->name == NULL) {\n+\t\tRTE_LOG(ERR, TABLE, \"%s: name invalid value\\n\", __func__);\n+\t\treturn -EINVAL;\n+\t}\n \n \t/* key_size */\n-\tif ((params->key_size == 0) ||\n+\tif ((params->key_size < sizeof(uint64_t)) ||\n \t\t(!rte_is_power_of_2(params->key_size))) {\n \t\tRTE_LOG(ERR, TABLE, \"%s: key_size invalid value\\n\", __func__);\n \t\treturn -EINVAL;\n@@ -128,10 +155,8 @@ check_params_create(struct rte_table_hash_lru_params *params)\n \t}\n \n \t/* n_buckets */\n-\tn_buckets_min = (params->n_keys + KEYS_PER_BUCKET - 1) / params->n_keys;\n \tif ((params->n_buckets == 0) ||\n-\t\t(!rte_is_power_of_2(params->n_keys)) ||\n-\t\t(params->n_buckets < n_buckets_min)) {\n+\t\t(!rte_is_power_of_2(params->n_keys))) {\n \t\tRTE_LOG(ERR, TABLE, \"%s: n_buckets invalid value\\n\", __func__);\n \t\treturn -EINVAL;\n \t}\n@@ -148,13 +173,13 @@ check_params_create(struct rte_table_hash_lru_params *params)\n static void *\n rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size)\n {\n-\tstruct rte_table_hash_lru_params *p =\n-\t\tparams;\n+\tstruct rte_table_hash_params *p = params;\n \tstruct rte_table_hash *t;\n-\tuint32_t total_size, table_meta_sz;\n-\tuint32_t bucket_sz, key_sz, key_stack_sz, data_sz;\n-\tuint32_t bucket_offset, key_offset, key_stack_offset, data_offset;\n-\tuint32_t i;\n+\tuint64_t table_meta_sz, key_mask_sz, bucket_sz, key_sz, key_stack_sz;\n+\tuint64_t data_sz, total_size;\n+\tuint64_t key_mask_offset, bucket_offset, key_offset, key_stack_offset;\n+\tuint64_t data_offset;\n+\tuint32_t n_buckets, i;\n \n \t/* Check input parameters */\n \tif ((check_params_create(p) != 0) ||\n@@ -164,33 +189,65 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size)\n \t\treturn NULL;\n \t}\n \n+\t/*\n+\t * Table dimensioning\n+\t *\n+\t * Objective: Pick the number of buckets (n_buckets) so that there a chance\n+\t * to store n_keys keys in the table.\n+\t *\n+\t * Note: Since the buckets do not get extended, it is not possible to\n+\t * guarantee that n_keys keys can be stored in the table at any time. In the\n+\t * worst case scenario when all the n_keys fall into the same bucket, only\n+\t * a maximum of KEYS_PER_BUCKET keys will be stored in the table. This case\n+\t * defeats the purpose of the hash table. It indicates unsuitable f_hash or\n+\t * n_keys to n_buckets ratio.\n+\t *\n+\t * MIN(n_buckets) = (n_keys + KEYS_PER_BUCKET - 1) / KEYS_PER_BUCKET\n+\t */\n+\tn_buckets = rte_align32pow2(\n+\t\t(p->n_keys + KEYS_PER_BUCKET - 1) / KEYS_PER_BUCKET);\n+\tn_buckets = RTE_MAX(n_buckets, p->n_buckets);\n+\n \t/* Memory allocation */\n \ttable_meta_sz = RTE_CACHE_LINE_ROUNDUP(sizeof(struct rte_table_hash));\n-\tbucket_sz = RTE_CACHE_LINE_ROUNDUP(p->n_buckets * sizeof(struct bucket));\n+\tkey_mask_sz = RTE_CACHE_LINE_ROUNDUP(p->key_size);\n+\tbucket_sz = RTE_CACHE_LINE_ROUNDUP(n_buckets * sizeof(struct bucket));\n \tkey_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * p->key_size);\n \tkey_stack_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * sizeof(uint32_t));\n \tdata_sz = RTE_CACHE_LINE_ROUNDUP(p->n_keys * entry_size);\n-\ttotal_size = table_meta_sz + bucket_sz + key_sz + key_stack_sz +\n-\t\tdata_sz;\n+\ttotal_size = table_meta_sz + key_mask_sz + bucket_sz + key_sz +\n+\t\tkey_stack_sz + data_sz;\n+\n+\tif (total_size > SIZE_MAX) {\n+\t\tRTE_LOG(ERR, TABLE,\n+\t\t\t\"%s: Cannot allocate %\" PRIu64 \" bytes for hash \"\n+\t\t\t\"table %s\\n\",\n+\t\t\t__func__, total_size, p->name);\n+\t\treturn NULL;\n+\t}\n \n-\tt = rte_zmalloc_socket(\"TABLE\", total_size, RTE_CACHE_LINE_SIZE, socket_id);\n+\tt = rte_zmalloc_socket(p->name,\n+\t\t(size_t)total_size,\n+\t\tRTE_CACHE_LINE_SIZE,\n+\t\tsocket_id);\n \tif (t == NULL) {\n \t\tRTE_LOG(ERR, TABLE,\n-\t\t\t\"%s: Cannot allocate %u bytes for hash table\\n\",\n-\t\t\t__func__, total_size);\n+\t\t\t\"%s: Cannot allocate %\" PRIu64 \" bytes for hash \"\n+\t\t\t\"table %s\\n\",\n+\t\t\t__func__, total_size, p->name);\n \t\treturn NULL;\n \t}\n-\tRTE_LOG(INFO, TABLE, \"%s (%u-byte key): Hash table memory footprint is \"\n-\t\t\"%u bytes\\n\", __func__, p->key_size, total_size);\n+\tRTE_LOG(INFO, TABLE, \"%s (%u-byte key): Hash table %s memory footprint\"\n+\t\t\" is %\" PRIu64 \" bytes\\n\",\n+\t\t__func__, p->key_size, p->name, total_size);\n \n \t/* Memory initialization */\n \tt->key_size = p->key_size;\n \tt->entry_size = entry_size;\n \tt->n_keys = p->n_keys;\n-\tt->n_buckets = p->n_buckets;\n+\tt->n_buckets = n_buckets;\n \tt->f_hash = p->f_hash;\n \tt->seed = p->seed;\n-\tt->signature_offset = p->signature_offset;\n \tt->key_offset = p->key_offset;\n \n \t/* Internal */\n@@ -199,16 +256,24 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size)\n \tt->data_size_shl = __builtin_ctzl(entry_size);\n \n \t/* Tables */\n-\tbucket_offset = 0;\n+\tkey_mask_offset = 0;\n+\tbucket_offset = key_mask_offset + key_mask_sz;\n \tkey_offset = bucket_offset + bucket_sz;\n \tkey_stack_offset = key_offset + key_sz;\n \tdata_offset = key_stack_offset + key_stack_sz;\n \n+\tt->key_mask = (uint64_t *) &t->memory[key_mask_offset];\n \tt->buckets = (struct bucket *) &t->memory[bucket_offset];\n \tt->key_mem = &t->memory[key_offset];\n \tt->key_stack = (uint32_t *) &t->memory[key_stack_offset];\n \tt->data_mem = &t->memory[data_offset];\n \n+\t/* Key mask */\n+\tif (p->key_mask == NULL)\n+\t\tmemset(t->key_mask, 0xFF, p->key_size);\n+\telse\n+\t\tmemcpy(t->key_mask, p->key_mask, p->key_size);\n+\n \t/* Key stack */\n \tfor (i = 0; i < t->n_keys; i++)\n \t\tt->key_stack[i] = t->n_keys - 1 - i;\n@@ -246,7 +311,7 @@ rte_table_hash_lru_entry_add(void *table, void *key, void *entry,\n \tuint64_t sig;\n \tuint32_t bkt_index, i;\n \n-\tsig = t->f_hash(key, t->key_size, t->seed);\n+\tsig = t->f_hash(key, t->key_mask, t->key_size, t->seed);\n \tbkt_index = sig & t->bucket_mask;\n \tbkt = &t->buckets[bkt_index];\n \tsig = (sig >> 16) | 1LLU;\n@@ -258,8 +323,8 @@ rte_table_hash_lru_entry_add(void *table, void *key, void *entry,\n \t\tuint8_t *bkt_key = &t->key_mem[bkt_key_index <<\n \t\t\tt->key_size_shl];\n \n-\t\tif ((sig == bkt_sig) && (memcmp(key, bkt_key, t->key_size)\n-\t\t\t== 0)) {\n+\t\tif ((sig == bkt_sig) && (keycmp(bkt_key, key, t->key_mask,\n+\t\t\tt->key_size) == 0)) {\n \t\t\tuint8_t *data = &t->data_mem[bkt_key_index <<\n \t\t\t\tt->data_size_shl];\n \n@@ -292,7 +357,7 @@ rte_table_hash_lru_entry_add(void *table, void *key, void *entry,\n \n \t\t\tbkt->sig[i] = (uint16_t) sig;\n \t\t\tbkt->key_pos[i] = bkt_key_index;\n-\t\t\tmemcpy(bkt_key, key, t->key_size);\n+\t\t\tkeycpy(bkt_key, key, t->key_mask, t->key_size);\n \t\t\tmemcpy(data, entry, t->entry_size);\n \t\t\tlru_update(bkt, i);\n \n@@ -311,7 +376,7 @@ rte_table_hash_lru_entry_add(void *table, void *key, void *entry,\n \t\tuint8_t *data = &t->data_mem[bkt_key_index << t->data_size_shl];\n \n \t\tbkt->sig[pos] = (uint16_t) sig;\n-\t\tmemcpy(bkt_key, key, t->key_size);\n+\t\tkeycpy(bkt_key, key, t->key_mask, t->key_size);\n \t\tmemcpy(data, entry, t->entry_size);\n \t\tlru_update(bkt, pos);\n \n@@ -330,7 +395,7 @@ rte_table_hash_lru_entry_delete(void *table, void *key, int *key_found,\n \tuint64_t sig;\n \tuint32_t bkt_index, i;\n \n-\tsig = t->f_hash(key, t->key_size, t->seed);\n+\tsig = t->f_hash(key, t->key_mask, t->key_size, t->seed);\n \tbkt_index = sig & t->bucket_mask;\n \tbkt = &t->buckets[bkt_index];\n \tsig = (sig >> 16) | 1LLU;\n@@ -343,14 +408,15 @@ rte_table_hash_lru_entry_delete(void *table, void *key, int *key_found,\n \t\t\tt->key_size_shl];\n \n \t\tif ((sig == bkt_sig) &&\n-\t\t\t(memcmp(key, bkt_key, t->key_size) == 0)) {\n+\t\t\t(keycmp(bkt_key, key, t->key_mask, t->key_size) == 0)) {\n \t\t\tuint8_t *data = &t->data_mem[bkt_key_index <<\n \t\t\t\tt->data_size_shl];\n \n \t\t\tbkt->sig[i] = 0;\n \t\t\tt->key_stack[t->key_stack_tos++] = bkt_key_index;\n \t\t\t*key_found = 1;\n-\t\t\tmemcpy(entry, data, t->entry_size);\n+\t\t\tif (entry)\n+\t\t\t\tmemcpy(entry, data, t->entry_size);\n \t\t\treturn 0;\n \t\t}\n \t}\n@@ -386,7 +452,7 @@ static int rte_table_hash_lru_lookup_unoptimized(\n \n \t\tpkt = pkts[pkt_index];\n \t\tkey = RTE_MBUF_METADATA_UINT8_PTR(pkt, t->key_offset);\n-\t\tsig = (uint64_t) t->f_hash(key, t->key_size, t->seed);\n+\t\tsig = (uint64_t) t->f_hash(key, t->key_mask, t->key_size, t->seed);\n \n \t\tbkt_index = sig & t->bucket_mask;\n \t\tbkt = &t->buckets[bkt_index];\n@@ -399,7 +465,7 @@ static int rte_table_hash_lru_lookup_unoptimized(\n \t\t\tuint8_t *bkt_key = &t->key_mem[bkt_key_index <<\n \t\t\t\tt->key_size_shl];\n \n-\t\t\tif ((sig == bkt_sig) && (memcmp(key, bkt_key,\n+\t\t\tif ((sig == bkt_sig) && (keycmp(bkt_key, key, t->key_mask,\n \t\t\t\tt->key_size) == 0)) {\n \t\t\t\tuint8_t *data = &t->data_mem[bkt_key_index <<\n \t\t\t\t\tt->data_size_shl];\n@@ -497,74 +563,75 @@ static int rte_table_hash_lru_lookup_unoptimized(\n \tmatch_pos = (LUT_MATCH_POS >> (mask_all << 1)) & 3;\t\\\n }\n \n-#define lookup_cmp_key(mbuf, key, match_key, f)\t\t\t\\\n-{\t\t\t\t\t\t\t\t\\\n+#define lookup_cmp_key(mbuf, key, match_key, f)\t\t\t\t\\\n+{\t\t\t\t\t\t\t\t\t\\\n \tuint64_t *pkt_key = RTE_MBUF_METADATA_UINT64_PTR(mbuf, f->key_offset);\\\n-\tuint64_t *bkt_key = (uint64_t *) key;\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\tswitch (f->key_size) {\t\t\t\t\t\\\n-\tcase 8:\t\t\t\t\t\t\t\\\n-\t{\t\t\t\t\t\t\t\\\n-\t\tuint64_t xor = pkt_key[0] ^ bkt_key[0];\t\t\\\n-\t\tmatch_key = 0;\t\t\t\t\t\\\n-\t\tif (xor == 0)\t\t\t\t\t\\\n-\t\t\tmatch_key = 1;\t\t\t\t\\\n-\t}\t\t\t\t\t\t\t\\\n-\tbreak;\t\t\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\tcase 16:\t\t\t\t\t\t\\\n-\t{\t\t\t\t\t\t\t\\\n-\t\tuint64_t xor[2], or;\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\t\txor[0] = pkt_key[0] ^ bkt_key[0];\t\t\\\n-\t\txor[1] = pkt_key[1] ^ bkt_key[1];\t\t\\\n-\t\tor = xor[0] | xor[1];\t\t\t\t\\\n-\t\tmatch_key = 0;\t\t\t\t\t\\\n-\t\tif (or == 0)\t\t\t\t\t\\\n-\t\t\tmatch_key = 1;\t\t\t\t\\\n-\t}\t\t\t\t\t\t\t\\\n-\tbreak;\t\t\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\tcase 32:\t\t\t\t\t\t\\\n-\t{\t\t\t\t\t\t\t\\\n-\t\tuint64_t xor[4], or;\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\t\txor[0] = pkt_key[0] ^ bkt_key[0];\t\t\\\n-\t\txor[1] = pkt_key[1] ^ bkt_key[1];\t\t\\\n-\t\txor[2] = pkt_key[2] ^ bkt_key[2];\t\t\\\n-\t\txor[3] = pkt_key[3] ^ bkt_key[3];\t\t\\\n-\t\tor = xor[0] | xor[1] | xor[2] | xor[3];\t\t\\\n-\t\tmatch_key = 0;\t\t\t\t\t\\\n-\t\tif (or == 0)\t\t\t\t\t\\\n-\t\t\tmatch_key = 1;\t\t\t\t\\\n-\t}\t\t\t\t\t\t\t\\\n-\tbreak;\t\t\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\tcase 64:\t\t\t\t\t\t\\\n-\t{\t\t\t\t\t\t\t\\\n-\t\tuint64_t xor[8], or;\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\t\txor[0] = pkt_key[0] ^ bkt_key[0];\t\t\\\n-\t\txor[1] = pkt_key[1] ^ bkt_key[1];\t\t\\\n-\t\txor[2] = pkt_key[2] ^ bkt_key[2];\t\t\\\n-\t\txor[3] = pkt_key[3] ^ bkt_key[3];\t\t\\\n-\t\txor[4] = pkt_key[4] ^ bkt_key[4];\t\t\\\n-\t\txor[5] = pkt_key[5] ^ bkt_key[5];\t\t\\\n-\t\txor[6] = pkt_key[6] ^ bkt_key[6];\t\t\\\n-\t\txor[7] = pkt_key[7] ^ bkt_key[7];\t\t\\\n-\t\tor = xor[0] | xor[1] | xor[2] | xor[3] |\t\\\n-\t\t\txor[4] | xor[5] | xor[6] | xor[7];\t\\\n-\t\tmatch_key = 0;\t\t\t\t\t\\\n-\t\tif (or == 0)\t\t\t\t\t\\\n-\t\t\tmatch_key = 1;\t\t\t\t\\\n-\t}\t\t\t\t\t\t\t\\\n-\tbreak;\t\t\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\\\n-\tdefault:\t\t\t\t\t\t\\\n-\t\tmatch_key = 0;\t\t\t\t\t\\\n-\t\tif (memcmp(pkt_key, bkt_key, f->key_size) == 0)\t\\\n-\t\t\tmatch_key = 1;\t\t\t\t\\\n-\t}\t\t\t\t\t\t\t\\\n+\tuint64_t *bkt_key = (uint64_t *) key;\t\t\t\t\\\n+\tuint64_t *key_mask = f->key_mask;\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tswitch (f->key_size) {\t\t\t\t\t\t\\\n+\tcase 8:\t\t\t\t\t\t\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tuint64_t xor = (pkt_key[0] & key_mask[0]) ^ bkt_key[0];\t\\\n+\t\tmatch_key = 0;\t\t\t\t\t\t\\\n+\t\tif (xor == 0)\t\t\t\t\t\t\\\n+\t\t\tmatch_key = 1;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+\tbreak;\t\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tcase 16:\t\t\t\t\t\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tuint64_t xor[2], or;\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\txor[0] = (pkt_key[0] & key_mask[0]) ^ bkt_key[0];\t\t\\\n+\t\txor[1] = (pkt_key[1] & key_mask[1]) ^ bkt_key[1];\t\t\\\n+\t\tor = xor[0] | xor[1];\t\t\t\t\t\\\n+\t\tmatch_key = 0;\t\t\t\t\t\t\\\n+\t\tif (or == 0)\t\t\t\t\t\t\\\n+\t\t\tmatch_key = 1;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+\tbreak;\t\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tcase 32:\t\t\t\t\t\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tuint64_t xor[4], or;\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\txor[0] = (pkt_key[0] & key_mask[0]) ^ bkt_key[0];\t\t\\\n+\t\txor[1] = (pkt_key[1] & key_mask[1]) ^ bkt_key[1];\t\t\\\n+\t\txor[2] = (pkt_key[2] & key_mask[2]) ^ bkt_key[2];\t\t\\\n+\t\txor[3] = (pkt_key[3] & key_mask[3]) ^ bkt_key[3];\t\t\\\n+\t\tor = xor[0] | xor[1] | xor[2] | xor[3];\t\t\t\\\n+\t\tmatch_key = 0;\t\t\t\t\t\t\\\n+\t\tif (or == 0)\t\t\t\t\t\t\\\n+\t\t\tmatch_key = 1;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+\tbreak;\t\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tcase 64:\t\t\t\t\t\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tuint64_t xor[8], or;\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\t\txor[0] = (pkt_key[0] & key_mask[0]) ^ bkt_key[0];\t\t\\\n+\t\txor[1] = (pkt_key[1] & key_mask[1]) ^ bkt_key[1];\t\t\\\n+\t\txor[2] = (pkt_key[2] & key_mask[2]) ^ bkt_key[2];\t\t\\\n+\t\txor[3] = (pkt_key[3] & key_mask[3]) ^ bkt_key[3];\t\t\\\n+\t\txor[4] = (pkt_key[4] & key_mask[4]) ^ bkt_key[4];\t\t\\\n+\t\txor[5] = (pkt_key[5] & key_mask[5]) ^ bkt_key[5];\t\t\\\n+\t\txor[6] = (pkt_key[6] & key_mask[6]) ^ bkt_key[6];\t\t\\\n+\t\txor[7] = (pkt_key[7] & key_mask[7]) ^ bkt_key[7];\t\t\\\n+\t\tor = xor[0] | xor[1] | xor[2] | xor[3] |\t\t\\\n+\t\t\txor[4] | xor[5] | xor[6] | xor[7];\t\t\\\n+\t\tmatch_key = 0;\t\t\t\t\t\t\\\n+\t\tif (or == 0)\t\t\t\t\t\t\\\n+\t\t\tmatch_key = 1;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n+\tbreak;\t\t\t\t\t\t\t\t\\\n+\t\t\t\t\t\t\t\t\t\\\n+\tdefault:\t\t\t\t\t\t\t\\\n+\t\tmatch_key = 0;\t\t\t\t\t\t\\\n+\t\tif (keycmp(bkt_key, pkt_key, key_mask, f->key_size) == 0)\t\\\n+\t\t\tmatch_key = 1;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\t\\\n }\n \n #define lookup2_stage0(t, g, pkts, pkts_mask, pkt00_index, pkt01_index)\\\n@@ -619,20 +686,20 @@ static int rte_table_hash_lru_lookup_unoptimized(\n \tstruct bucket *bkt10, *bkt11, *buckets = t->buckets;\t\\\n \tuint8_t *key10, *key11;\t\t\t\t\t\\\n \tuint64_t bucket_mask = t->bucket_mask;\t\t\t\\\n-\trte_table_hash_op_hash_nomask f_hash = t->f_hash;\t\t\\\n+\trte_table_hash_op_hash f_hash = t->f_hash;\t\t\\\n \tuint64_t seed = t->seed;\t\t\t\t\\\n \tuint32_t key_size = t->key_size;\t\t\t\\\n \tuint32_t key_offset = t->key_offset;\t\t\t\\\n \t\t\t\t\t\t\t\t\\\n \tmbuf10 = pkts[pkt10_index];\t\t\t\t\\\n \tkey10 = RTE_MBUF_METADATA_UINT8_PTR(mbuf10, key_offset);\\\n-\tsig10 = (uint64_t) f_hash(key10, key_size, seed);\t\\\n+\tsig10 = (uint64_t) f_hash(key10, t->key_mask, key_size, seed);\\\n \tbkt10_index = sig10 & bucket_mask;\t\t\t\\\n \tbkt10 = &buckets[bkt10_index];\t\t\t\t\\\n \t\t\t\t\t\t\t\t\\\n \tmbuf11 = pkts[pkt11_index];\t\t\t\t\\\n \tkey11 = RTE_MBUF_METADATA_UINT8_PTR(mbuf11, key_offset);\\\n-\tsig11 = (uint64_t) f_hash(key11, key_size, seed);\t\\\n+\tsig11 = (uint64_t) f_hash(key11, t->key_mask, key_size, seed);\\\n \tbkt11_index = sig11 & bucket_mask;\t\t\t\\\n \tbkt11 = &buckets[bkt11_index];\t\t\t\t\\\n \t\t\t\t\t\t\t\t\\\ndiff --git a/test/test-pipeline/pipeline_hash.c b/test/test-pipeline/pipeline_hash.c\nindex 13d309d..3c48640 100755\n--- a/test/test-pipeline/pipeline_hash.c\n+++ b/test/test-pipeline/pipeline_hash.c\n@@ -204,14 +204,15 @@ app_main_loop_worker_pipeline_hash(void) {\n \tcase e_APP_PIPELINE_HASH_KEY16_LRU:\n \tcase e_APP_PIPELINE_HASH_KEY32_LRU:\n \t{\n-\t\tstruct rte_table_hash_lru_params table_hash_params = {\n+\t\tstruct rte_table_hash_params table_hash_params = {\n+\t\t\t.name = \"TABLE\",\n \t\t\t.key_size = key_size,\n+\t\t\t.key_offset = APP_METADATA_OFFSET(32),\n+\t\t\t.key_mask = NULL,\n \t\t\t.n_keys = 1 << 24,\n \t\t\t.n_buckets = 1 << 22,\n-\t\t\t.f_hash = test_hash,\n+\t\t\t.f_hash = (rte_table_hash_op_hash)test_hash,\n \t\t\t.seed = 0,\n-\t\t\t.signature_offset = APP_METADATA_OFFSET(0),\n-\t\t\t.key_offset = APP_METADATA_OFFSET(32),\n \t\t};\n \n \t\tstruct rte_pipeline_table_params table_params = {\n",
    "prefixes": [
        "dpdk-dev",
        "v3",
        "09/18"
    ]
}