hash: free internal ring when freeing hash
[dpdk.git] / lib / librte_hash / rte_cuckoo_hash.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <string.h>
35 #include <stdint.h>
36 #include <errno.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <sys/queue.h>
40
41 #include <rte_common.h>
42 #include <rte_memory.h>         /* for definition of RTE_CACHE_LINE_SIZE */
43 #include <rte_log.h>
44 #include <rte_memcpy.h>
45 #include <rte_prefetch.h>
46 #include <rte_branch_prediction.h>
47 #include <rte_memzone.h>
48 #include <rte_malloc.h>
49 #include <rte_eal.h>
50 #include <rte_eal_memconfig.h>
51 #include <rte_per_lcore.h>
52 #include <rte_errno.h>
53 #include <rte_string_fns.h>
54 #include <rte_cpuflags.h>
55 #include <rte_log.h>
56 #include <rte_rwlock.h>
57 #include <rte_spinlock.h>
58 #include <rte_ring.h>
59 #include <rte_compat.h>
60
61 #include "rte_hash.h"
62 #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_X32)
63 #include "rte_cmp_x86.h"
64 #endif
65
66 TAILQ_HEAD(rte_hash_list, rte_tailq_entry);
67
68 static struct rte_tailq_elem rte_hash_tailq = {
69         .name = "RTE_HASH",
70 };
71 EAL_REGISTER_TAILQ(rte_hash_tailq)
72
73 /* Macro to enable/disable run-time checking of function parameters */
74 #if defined(RTE_LIBRTE_HASH_DEBUG)
75 #define RETURN_IF_TRUE(cond, retval) do { \
76         if (cond) \
77                 return retval; \
78 } while (0)
79 #else
80 #define RETURN_IF_TRUE(cond, retval)
81 #endif
82
83 /* Hash function used if none is specified */
84 #ifdef RTE_MACHINE_CPUFLAG_SSE4_2
85 #include <rte_hash_crc.h>
86 #define DEFAULT_HASH_FUNC       rte_hash_crc
87 #else
88 #include <rte_jhash.h>
89 #define DEFAULT_HASH_FUNC       rte_jhash
90 #endif
91
92 /** Number of items per bucket. */
93 #define RTE_HASH_BUCKET_ENTRIES         4
94
95 #define NULL_SIGNATURE                  0
96
97 #define KEY_ALIGNMENT                   16
98
99 typedef int (*rte_hash_cmp_eq_t)(const void *key1, const void *key2, size_t key_len);
100
101 /** A hash table structure. */
102 struct rte_hash {
103         char name[RTE_HASH_NAMESIZE];   /**< Name of the hash. */
104         uint32_t entries;               /**< Total table entries. */
105         uint32_t num_buckets;           /**< Number of buckets in table. */
106         uint32_t key_len;               /**< Length of hash key. */
107         rte_hash_function hash_func;    /**< Function used to calculate hash. */
108         uint32_t hash_func_init_val;    /**< Init value used by hash_func. */
109         rte_hash_cmp_eq_t rte_hash_cmp_eq; /**< Function used to compare keys. */
110         uint32_t bucket_bitmask;        /**< Bitmask for getting bucket index
111                                                 from hash signature. */
112         uint32_t key_entry_size;         /**< Size of each key entry. */
113
114         struct rte_ring *free_slots;    /**< Ring that stores all indexes
115                                                 of the free slots in the key table */
116         void *key_store;                /**< Table storing all keys and data */
117         struct rte_hash_bucket *buckets;        /**< Table with buckets storing all the
118                                                         hash values and key indexes
119                                                         to the key table*/
120 } __rte_cache_aligned;
121
122 /* Structure storing both primary and secondary hashes */
123 struct rte_hash_signatures {
124         union {
125                 struct {
126                         hash_sig_t current;
127                         hash_sig_t alt;
128                 };
129                 uint64_t sig;
130         };
131 };
132
133 /* Structure that stores key-value pair */
134 struct rte_hash_key {
135         union {
136                 uintptr_t idata;
137                 void *pdata;
138         };
139         /* Variable key size */
140         char key[0];
141 } __attribute__((aligned(KEY_ALIGNMENT)));
142
143 /** Bucket structure */
144 struct rte_hash_bucket {
145         struct rte_hash_signatures signatures[RTE_HASH_BUCKET_ENTRIES];
146         /* Includes dummy key index that always contains index 0 */
147         uint32_t key_idx[RTE_HASH_BUCKET_ENTRIES + 1];
148         uint8_t flag[RTE_HASH_BUCKET_ENTRIES];
149 } __rte_cache_aligned;
150
151 struct rte_hash *
152 rte_hash_find_existing(const char *name)
153 {
154         struct rte_hash *h = NULL;
155         struct rte_tailq_entry *te;
156         struct rte_hash_list *hash_list;
157
158         hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list);
159
160         rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
161         TAILQ_FOREACH(te, hash_list, next) {
162                 h = (struct rte_hash *) te->data;
163                 if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
164                         break;
165         }
166         rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
167
168         if (te == NULL) {
169                 rte_errno = ENOENT;
170                 return NULL;
171         }
172         return h;
173 }
174
175 struct rte_hash *
176 rte_hash_create(const struct rte_hash_parameters *params)
177 {
178         struct rte_hash *h = NULL;
179         struct rte_tailq_entry *te = NULL;
180         struct rte_hash_list *hash_list;
181         struct rte_ring *r = NULL;
182         char hash_name[RTE_HASH_NAMESIZE];
183         void *k = NULL;
184         void *buckets = NULL;
185         char ring_name[RTE_RING_NAMESIZE];
186         unsigned i;
187
188         hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list);
189
190         if (params == NULL) {
191                 RTE_LOG(ERR, HASH, "rte_hash_create has no parameters\n");
192                 return NULL;
193         }
194
195         /* Check for valid parameters */
196         if ((params->entries > RTE_HASH_ENTRIES_MAX) ||
197                         (params->entries < RTE_HASH_BUCKET_ENTRIES) ||
198                         !rte_is_power_of_2(RTE_HASH_BUCKET_ENTRIES) ||
199                         (params->key_len == 0)) {
200                 rte_errno = EINVAL;
201                 RTE_LOG(ERR, HASH, "rte_hash_create has invalid parameters\n");
202                 return NULL;
203         }
204
205         snprintf(hash_name, sizeof(hash_name), "HT_%s", params->name);
206
207         /* Guarantee there's no existing */
208         h = rte_hash_find_existing(params->name);
209         if (h != NULL)
210                 return h;
211
212         te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
213         if (te == NULL) {
214                 RTE_LOG(ERR, HASH, "tailq entry allocation failed\n");
215                 goto err;
216         }
217
218         h = (struct rte_hash *)rte_zmalloc_socket(hash_name, sizeof(struct rte_hash),
219                                         RTE_CACHE_LINE_SIZE, params->socket_id);
220
221         if (h == NULL) {
222                 RTE_LOG(ERR, HASH, "memory allocation failed\n");
223                 goto err;
224         }
225
226         const uint32_t num_buckets = rte_align32pow2(params->entries)
227                                         / RTE_HASH_BUCKET_ENTRIES;
228
229         buckets = rte_zmalloc_socket(NULL,
230                                 num_buckets * sizeof(struct rte_hash_bucket),
231                                 RTE_CACHE_LINE_SIZE, params->socket_id);
232
233         if (buckets == NULL) {
234                 RTE_LOG(ERR, HASH, "memory allocation failed\n");
235                 goto err;
236         }
237
238         const uint32_t key_entry_size = sizeof(struct rte_hash_key) + params->key_len;
239
240         /* Store all keys and leave the first entry as a dummy entry for lookup_bulk */
241         const uint64_t key_tbl_size = (uint64_t) key_entry_size * (params->entries + 1);
242
243         k = rte_zmalloc_socket(NULL, key_tbl_size,
244                         RTE_CACHE_LINE_SIZE, params->socket_id);
245
246         if (k == NULL) {
247                 RTE_LOG(ERR, HASH, "memory allocation failed\n");
248                 goto err;
249         }
250
251 /*
252  * If x86 architecture is used, select appropriate compare function,
253  * which may use x86 instrinsics, otherwise use memcmp
254  */
255 #if defined(RTE_ARCH_X86_64) || defined(RTE_ARCH_I686) || defined(RTE_ARCH_X86_X32)
256         /* Select function to compare keys */
257         switch (params->key_len) {
258         case 16:
259                 h->rte_hash_cmp_eq = rte_hash_k16_cmp_eq;
260                 break;
261         case 32:
262                 h->rte_hash_cmp_eq = rte_hash_k32_cmp_eq;
263                 break;
264         case 48:
265                 h->rte_hash_cmp_eq = rte_hash_k48_cmp_eq;
266                 break;
267         case 64:
268                 h->rte_hash_cmp_eq = rte_hash_k64_cmp_eq;
269                 break;
270         case 80:
271                 h->rte_hash_cmp_eq = rte_hash_k80_cmp_eq;
272                 break;
273         case 96:
274                 h->rte_hash_cmp_eq = rte_hash_k96_cmp_eq;
275                 break;
276         case 112:
277                 h->rte_hash_cmp_eq = rte_hash_k112_cmp_eq;
278                 break;
279         case 128:
280                 h->rte_hash_cmp_eq = rte_hash_k128_cmp_eq;
281                 break;
282         default:
283                 /* If key is not multiple of 16, use generic memcmp */
284                 h->rte_hash_cmp_eq = memcmp;
285         }
286 #else
287         h->rte_hash_cmp_eq = memcmp;
288 #endif
289
290         snprintf(ring_name, sizeof(ring_name), "HT_%s", params->name);
291         r = rte_ring_create(ring_name, rte_align32pow2(params->entries + 1),
292                                 params->socket_id, 0);
293         if (r == NULL) {
294                 RTE_LOG(ERR, HASH, "memory allocation failed\n");
295                 goto err;
296         }
297
298         /* Setup hash context */
299         snprintf(h->name, sizeof(h->name), "%s", params->name);
300         h->entries = params->entries;
301         h->key_len = params->key_len;
302         h->key_entry_size = key_entry_size;
303         h->hash_func_init_val = params->hash_func_init_val;
304
305         h->num_buckets = num_buckets;
306         h->bucket_bitmask = h->num_buckets - 1;
307         h->buckets = buckets;
308         h->hash_func = (params->hash_func == NULL) ?
309                 DEFAULT_HASH_FUNC : params->hash_func;
310
311         h->key_store = k;
312         h->free_slots = r;
313
314         /* populate the free slots ring. Entry zero is reserved for key misses */
315         for (i = 1; i < params->entries + 1; i++)
316                 rte_ring_sp_enqueue(r, (void *)((uintptr_t) i));
317
318         rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
319         te->data = (void *) h;
320         TAILQ_INSERT_TAIL(hash_list, te, next);
321         rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
322
323         return h;
324 err:
325         rte_free(te);
326         rte_free(h);
327         rte_free(buckets);
328         rte_free(k);
329         return NULL;
330 }
331
332 void
333 rte_hash_free(struct rte_hash *h)
334 {
335         struct rte_tailq_entry *te;
336         struct rte_hash_list *hash_list;
337
338         if (h == NULL)
339                 return;
340
341         hash_list = RTE_TAILQ_CAST(rte_hash_tailq.head, rte_hash_list);
342
343         rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
344
345         /* find out tailq entry */
346         TAILQ_FOREACH(te, hash_list, next) {
347                 if (te->data == (void *) h)
348                         break;
349         }
350
351         if (te == NULL) {
352                 rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
353                 return;
354         }
355
356         TAILQ_REMOVE(hash_list, te, next);
357
358         rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
359
360         rte_ring_free(h->free_slots);
361         rte_free(h->key_store);
362         rte_free(h->buckets);
363         rte_free(h);
364         rte_free(te);
365 }
366
367 hash_sig_t
368 rte_hash_hash(const struct rte_hash *h, const void *key)
369 {
370         /* calc hash result by key */
371         return h->hash_func(key, h->key_len, h->hash_func_init_val);
372 }
373
374 /* Calc the secondary hash value from the primary hash value of a given key */
375 static inline hash_sig_t
376 rte_hash_secondary_hash(const hash_sig_t primary_hash)
377 {
378         static const unsigned all_bits_shift = 12;
379         static const unsigned alt_bits_xor = 0x5bd1e995;
380
381         uint32_t tag = primary_hash >> all_bits_shift;
382
383         return (primary_hash ^ ((tag + 1) * alt_bits_xor));
384 }
385
386 void
387 rte_hash_reset(struct rte_hash *h)
388 {
389         void *ptr;
390         unsigned i;
391
392         if (h == NULL)
393                 return;
394
395         memset(h->buckets, 0, h->num_buckets * sizeof(struct rte_hash_bucket));
396         memset(h->key_store, 0, h->key_entry_size * (h->entries + 1));
397
398         /* clear the free ring */
399         while (rte_ring_dequeue(h->free_slots, &ptr) == 0)
400                 rte_pause();
401
402         /* Repopulate the free slots ring. Entry zero is reserved for key misses */
403         for (i = 1; i < h->entries + 1; i++)
404                 rte_ring_sp_enqueue(h->free_slots, (void *)((uintptr_t) i));
405 }
406
407 /* Search for an entry that can be pushed to its alternative location */
408 static inline int
409 make_space_bucket(const struct rte_hash *h, struct rte_hash_bucket *bkt)
410 {
411         unsigned i, j;
412         int ret;
413         uint32_t next_bucket_idx;
414         struct rte_hash_bucket *next_bkt[RTE_HASH_BUCKET_ENTRIES];
415
416         /*
417          * Push existing item (search for bucket with space in
418          * alternative locations) to its alternative location
419          */
420         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
421                 /* Search for space in alternative locations */
422                 next_bucket_idx = bkt->signatures[i].alt & h->bucket_bitmask;
423                 next_bkt[i] = &h->buckets[next_bucket_idx];
424                 for (j = 0; j < RTE_HASH_BUCKET_ENTRIES; j++) {
425                         if (next_bkt[i]->signatures[j].sig == NULL_SIGNATURE)
426                                 break;
427                 }
428
429                 if (j != RTE_HASH_BUCKET_ENTRIES)
430                         break;
431         }
432
433         /* Alternative location has spare room (end of recursive function) */
434         if (i != RTE_HASH_BUCKET_ENTRIES) {
435                 next_bkt[i]->signatures[j].alt = bkt->signatures[i].current;
436                 next_bkt[i]->signatures[j].current = bkt->signatures[i].alt;
437                 next_bkt[i]->key_idx[j] = bkt->key_idx[i];
438                 return i;
439         }
440
441         /* Pick entry that has not been pushed yet */
442         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++)
443                 if (bkt->flag[i] == 0)
444                         break;
445
446         /* All entries have been pushed, so entry cannot be added */
447         if (i == RTE_HASH_BUCKET_ENTRIES)
448                 return -ENOSPC;
449
450         /* Set flag to indicate that this entry is going to be pushed */
451         bkt->flag[i] = 1;
452         /* Need room in alternative bucket to insert the pushed entry */
453         ret = make_space_bucket(h, next_bkt[i]);
454         /*
455          * After recursive function.
456          * Clear flags and insert the pushed entry
457          * in its alternative location if successful,
458          * or return error
459          */
460         bkt->flag[i] = 0;
461         if (ret >= 0) {
462                 next_bkt[i]->signatures[ret].alt = bkt->signatures[i].current;
463                 next_bkt[i]->signatures[ret].current = bkt->signatures[i].alt;
464                 next_bkt[i]->key_idx[ret] = bkt->key_idx[i];
465                 return i;
466         } else
467                 return ret;
468
469 }
470
471 static inline int32_t
472 __rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key,
473                                                 hash_sig_t sig, void *data)
474 {
475         hash_sig_t alt_hash;
476         uint32_t prim_bucket_idx, sec_bucket_idx;
477         unsigned i;
478         struct rte_hash_bucket *prim_bkt, *sec_bkt;
479         struct rte_hash_key *new_k, *k, *keys = h->key_store;
480         void *slot_id;
481         uint32_t new_idx;
482         int ret;
483
484         prim_bucket_idx = sig & h->bucket_bitmask;
485         prim_bkt = &h->buckets[prim_bucket_idx];
486         rte_prefetch0(prim_bkt);
487
488         alt_hash = rte_hash_secondary_hash(sig);
489         sec_bucket_idx = alt_hash & h->bucket_bitmask;
490         sec_bkt = &h->buckets[sec_bucket_idx];
491         rte_prefetch0(sec_bkt);
492
493         /* Get a new slot for storing the new key */
494         if (rte_ring_sc_dequeue(h->free_slots, &slot_id) != 0)
495                 return -ENOSPC;
496         new_k = RTE_PTR_ADD(keys, (uintptr_t)slot_id * h->key_entry_size);
497         rte_prefetch0(new_k);
498         new_idx = (uint32_t)((uintptr_t) slot_id);
499
500         /* Check if key is already inserted in primary location */
501         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
502                 if (prim_bkt->signatures[i].current == sig &&
503                                 prim_bkt->signatures[i].alt == alt_hash)  {
504                         k = (struct rte_hash_key *) ((char *)keys +
505                                         prim_bkt->key_idx[i] * h->key_entry_size);
506                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
507                                 rte_ring_sp_enqueue(h->free_slots, slot_id);
508                                 /* Update data */
509                                 k->pdata = data;
510                                 /*
511                                  * Return index where key is stored,
512                                  * substracting the first dummy index
513                                  */
514                                 return (prim_bkt->key_idx[i] - 1);
515                         }
516                 }
517         }
518
519         /* Check if key is already inserted in secondary location */
520         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
521                 if (sec_bkt->signatures[i].alt == sig &&
522                                 sec_bkt->signatures[i].current == alt_hash)  {
523                         k = (struct rte_hash_key *) ((char *)keys +
524                                         sec_bkt->key_idx[i] * h->key_entry_size);
525                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
526                                 rte_ring_sp_enqueue(h->free_slots, slot_id);
527                                 /* Update data */
528                                 k->pdata = data;
529                                 /*
530                                  * Return index where key is stored,
531                                  * substracting the first dummy index
532                                  */
533                                 return (sec_bkt->key_idx[i] - 1);
534                         }
535                 }
536         }
537
538         /* Copy key */
539         rte_memcpy(new_k->key, key, h->key_len);
540         new_k->pdata = data;
541
542         /* Insert new entry is there is room in the primary bucket */
543         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
544                 /* Check if slot is available */
545                 if (likely(prim_bkt->signatures[i].sig == NULL_SIGNATURE)) {
546                         prim_bkt->signatures[i].current = sig;
547                         prim_bkt->signatures[i].alt = alt_hash;
548                         prim_bkt->key_idx[i] = new_idx;
549                         return new_idx - 1;
550                 }
551         }
552
553         /* Primary bucket is full, so we need to make space for new entry */
554         ret = make_space_bucket(h, prim_bkt);
555         /*
556          * After recursive function.
557          * Insert the new entry in the position of the pushed entry
558          * if successful or return error and
559          * store the new slot back in the ring
560          */
561         if (ret >= 0) {
562                 prim_bkt->signatures[ret].current = sig;
563                 prim_bkt->signatures[ret].alt = alt_hash;
564                 prim_bkt->key_idx[ret] = new_idx;
565                 return (new_idx - 1);
566         }
567
568         /* Error in addition, store new slot back in the ring and return error */
569         rte_ring_sp_enqueue(h->free_slots,
570                 (void *)((uintptr_t) new_idx));
571         return ret;
572
573 }
574
575 int32_t
576 rte_hash_add_key_with_hash(const struct rte_hash *h,
577                         const void *key, hash_sig_t sig)
578 {
579         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
580         return __rte_hash_add_key_with_hash(h, key, sig, 0);
581 }
582
583 int32_t
584 rte_hash_add_key(const struct rte_hash *h, const void *key)
585 {
586         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
587         return __rte_hash_add_key_with_hash(h, key, rte_hash_hash(h, key), 0);
588 }
589
590 int
591 rte_hash_add_key_with_hash_data(const struct rte_hash *h,
592                         const void *key, hash_sig_t sig, void *data)
593 {
594         int ret;
595
596         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
597         ret = __rte_hash_add_key_with_hash(h, key, sig, data);
598         if (ret >= 0)
599                 return 0;
600         else
601                 return ret;
602 }
603
604 int
605 rte_hash_add_key_data(const struct rte_hash *h, const void *key, void *data)
606 {
607         int ret;
608
609         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
610
611         ret = __rte_hash_add_key_with_hash(h, key, rte_hash_hash(h, key), data);
612         if (ret >= 0)
613                 return 0;
614         else
615                 return ret;
616 }
617 static inline int32_t
618 __rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key,
619                                         hash_sig_t sig, void **data)
620 {
621         uint32_t bucket_idx;
622         hash_sig_t alt_hash;
623         unsigned i;
624         struct rte_hash_bucket *bkt;
625         struct rte_hash_key *k, *keys = h->key_store;
626
627         bucket_idx = sig & h->bucket_bitmask;
628         bkt = &h->buckets[bucket_idx];
629
630         /* Check if key is in primary location */
631         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
632                 if (bkt->signatures[i].current == sig &&
633                                 bkt->signatures[i].sig != NULL_SIGNATURE) {
634                         k = (struct rte_hash_key *) ((char *)keys +
635                                         bkt->key_idx[i] * h->key_entry_size);
636                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
637                                 if (data != NULL)
638                                         *data = k->pdata;
639                                 /*
640                                  * Return index where key is stored,
641                                  * substracting the first dummy index
642                                  */
643                                 return (bkt->key_idx[i] - 1);
644                         }
645                 }
646         }
647
648         /* Calculate secondary hash */
649         alt_hash = rte_hash_secondary_hash(sig);
650         bucket_idx = alt_hash & h->bucket_bitmask;
651         bkt = &h->buckets[bucket_idx];
652
653         /* Check if key is in secondary location */
654         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
655                 if (bkt->signatures[i].current == alt_hash &&
656                                 bkt->signatures[i].alt == sig) {
657                         k = (struct rte_hash_key *) ((char *)keys +
658                                         bkt->key_idx[i] * h->key_entry_size);
659                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
660                                 if (data != NULL)
661                                         *data = k->pdata;
662                                 /*
663                                  * Return index where key is stored,
664                                  * substracting the first dummy index
665                                  */
666                                 return (bkt->key_idx[i] - 1);
667                         }
668                 }
669         }
670
671         return -ENOENT;
672 }
673
674 int32_t
675 rte_hash_lookup_with_hash(const struct rte_hash *h,
676                         const void *key, hash_sig_t sig)
677 {
678         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
679         return __rte_hash_lookup_with_hash(h, key, sig, NULL);
680 }
681
682 int32_t
683 rte_hash_lookup(const struct rte_hash *h, const void *key)
684 {
685         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
686         return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key), NULL);
687 }
688
689 int
690 rte_hash_lookup_with_hash_data(const struct rte_hash *h,
691                         const void *key, hash_sig_t sig, void **data)
692 {
693         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
694         return __rte_hash_lookup_with_hash(h, key, sig, data);
695 }
696
697 int
698 rte_hash_lookup_data(const struct rte_hash *h, const void *key, void **data)
699 {
700         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
701         return __rte_hash_lookup_with_hash(h, key, rte_hash_hash(h, key), data);
702 }
703
704 static inline int32_t
705 __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key,
706                                                 hash_sig_t sig)
707 {
708         uint32_t bucket_idx;
709         hash_sig_t alt_hash;
710         unsigned i;
711         struct rte_hash_bucket *bkt;
712         struct rte_hash_key *k, *keys = h->key_store;
713
714         bucket_idx = sig & h->bucket_bitmask;
715         bkt = &h->buckets[bucket_idx];
716
717         /* Check if key is in primary location */
718         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
719                 if (bkt->signatures[i].current == sig &&
720                                 bkt->signatures[i].sig != NULL_SIGNATURE) {
721                         k = (struct rte_hash_key *) ((char *)keys +
722                                         bkt->key_idx[i] * h->key_entry_size);
723                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
724                                 bkt->signatures[i].sig = NULL_SIGNATURE;
725                                 rte_ring_sp_enqueue(h->free_slots,
726                                                 (void *)((uintptr_t)bkt->key_idx[i]));
727                                 /*
728                                  * Return index where key is stored,
729                                  * substracting the first dummy index
730                                  */
731                                 return (bkt->key_idx[i] - 1);
732                         }
733                 }
734         }
735
736         /* Calculate secondary hash */
737         alt_hash = rte_hash_secondary_hash(sig);
738         bucket_idx = alt_hash & h->bucket_bitmask;
739         bkt = &h->buckets[bucket_idx];
740
741         /* Check if key is in secondary location */
742         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
743                 if (bkt->signatures[i].current == alt_hash &&
744                                 bkt->signatures[i].sig != NULL_SIGNATURE) {
745                         k = (struct rte_hash_key *) ((char *)keys +
746                                         bkt->key_idx[i] * h->key_entry_size);
747                         if (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {
748                                 bkt->signatures[i].sig = NULL_SIGNATURE;
749                                 rte_ring_sp_enqueue(h->free_slots,
750                                                 (void *)((uintptr_t)bkt->key_idx[i]));
751                                 /*
752                                  * Return index where key is stored,
753                                  * substracting the first dummy index
754                                  */
755                                 return (bkt->key_idx[i] - 1);
756                         }
757                 }
758         }
759
760         return -ENOENT;
761 }
762
763 int32_t
764 rte_hash_del_key_with_hash(const struct rte_hash *h,
765                         const void *key, hash_sig_t sig)
766 {
767         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
768         return __rte_hash_del_key_with_hash(h, key, sig);
769 }
770
771 int32_t
772 rte_hash_del_key(const struct rte_hash *h, const void *key)
773 {
774         RETURN_IF_TRUE(((h == NULL) || (key == NULL)), -EINVAL);
775         return __rte_hash_del_key_with_hash(h, key, rte_hash_hash(h, key));
776 }
777
778 /* Lookup bulk stage 0: Prefetch input key */
779 static inline void
780 lookup_stage0(unsigned *idx, uint64_t *lookup_mask,
781                 const void * const *keys)
782 {
783         *idx = __builtin_ctzl(*lookup_mask);
784         if (*lookup_mask == 0)
785                 *idx = 0;
786
787         rte_prefetch0(keys[*idx]);
788         *lookup_mask &= ~(1llu << *idx);
789 }
790
791 /*
792  * Lookup bulk stage 1: Calculate primary/secondary hashes
793  * and prefetch primary/secondary buckets
794  */
795 static inline void
796 lookup_stage1(unsigned idx, hash_sig_t *prim_hash, hash_sig_t *sec_hash,
797                 const struct rte_hash_bucket **primary_bkt,
798                 const struct rte_hash_bucket **secondary_bkt,
799                 hash_sig_t *hash_vals, const void * const *keys,
800                 const struct rte_hash *h)
801 {
802         *prim_hash = rte_hash_hash(h, keys[idx]);
803         hash_vals[idx] = *prim_hash;
804         *sec_hash = rte_hash_secondary_hash(*prim_hash);
805
806         *primary_bkt = &h->buckets[*prim_hash & h->bucket_bitmask];
807         *secondary_bkt = &h->buckets[*sec_hash & h->bucket_bitmask];
808
809         rte_prefetch0(*primary_bkt);
810         rte_prefetch0(*secondary_bkt);
811 }
812
813 /*
814  * Lookup bulk stage 2:  Search for match hashes in primary/secondary locations
815  * and prefetch first key slot
816  */
817 static inline void
818 lookup_stage2(unsigned idx, hash_sig_t prim_hash, hash_sig_t sec_hash,
819                 const struct rte_hash_bucket *prim_bkt,
820                 const struct rte_hash_bucket *sec_bkt,
821                 const struct rte_hash_key **key_slot, int32_t *positions,
822                 uint64_t *extra_hits_mask, const void *keys,
823                 const struct rte_hash *h)
824 {
825         unsigned prim_hash_matches, sec_hash_matches, key_idx, i;
826         unsigned total_hash_matches;
827
828         prim_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES;
829         sec_hash_matches = 1 << RTE_HASH_BUCKET_ENTRIES;
830         for (i = 0; i < RTE_HASH_BUCKET_ENTRIES; i++) {
831                 prim_hash_matches |= ((prim_hash == prim_bkt->signatures[i].current) << i);
832                 sec_hash_matches |= ((sec_hash == sec_bkt->signatures[i].current) << i);
833         }
834
835         key_idx = prim_bkt->key_idx[__builtin_ctzl(prim_hash_matches)];
836         if (key_idx == 0)
837                 key_idx = sec_bkt->key_idx[__builtin_ctzl(sec_hash_matches)];
838
839         total_hash_matches = (prim_hash_matches |
840                                 (sec_hash_matches << (RTE_HASH_BUCKET_ENTRIES + 1)));
841         *key_slot = (const struct rte_hash_key *) ((const char *)keys +
842                                         key_idx * h->key_entry_size);
843
844         rte_prefetch0(*key_slot);
845         /*
846          * Return index where key is stored,
847          * substracting the first dummy index
848          */
849         positions[idx] = (key_idx - 1);
850
851         *extra_hits_mask |= (uint64_t)(__builtin_popcount(total_hash_matches) > 3) << idx;
852
853 }
854
855
856 /* Lookup bulk stage 3: Check if key matches, update hit mask and return data */
857 static inline void
858 lookup_stage3(unsigned idx, const struct rte_hash_key *key_slot, const void * const *keys,
859                 void *data[], uint64_t *hits, const struct rte_hash *h)
860 {
861         unsigned hit;
862
863         hit = !h->rte_hash_cmp_eq(key_slot->key, keys[idx], h->key_len);
864         if (data != NULL)
865                 data[idx] = key_slot->pdata;
866
867         *hits |= (uint64_t)(hit) << idx;
868 }
869
870 static inline void
871 __rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
872                         uint32_t num_keys, int32_t *positions,
873                         uint64_t *hit_mask, void *data[])
874 {
875         uint64_t hits = 0;
876         uint64_t extra_hits_mask = 0;
877         uint64_t lookup_mask, miss_mask;
878         unsigned idx;
879         const void *key_store = h->key_store;
880         int ret;
881         hash_sig_t hash_vals[RTE_HASH_LOOKUP_BULK_MAX];
882
883         unsigned idx00, idx01, idx10, idx11, idx20, idx21, idx30, idx31;
884         const struct rte_hash_bucket *primary_bkt10, *primary_bkt11;
885         const struct rte_hash_bucket *secondary_bkt10, *secondary_bkt11;
886         const struct rte_hash_bucket *primary_bkt20, *primary_bkt21;
887         const struct rte_hash_bucket *secondary_bkt20, *secondary_bkt21;
888         const struct rte_hash_key *k_slot20, *k_slot21, *k_slot30, *k_slot31;
889         hash_sig_t primary_hash10, primary_hash11;
890         hash_sig_t secondary_hash10, secondary_hash11;
891         hash_sig_t primary_hash20, primary_hash21;
892         hash_sig_t secondary_hash20, secondary_hash21;
893
894         lookup_mask = (uint64_t) -1 >> (64 - num_keys);
895         miss_mask = lookup_mask;
896
897         lookup_stage0(&idx00, &lookup_mask, keys);
898         lookup_stage0(&idx01, &lookup_mask, keys);
899
900         idx10 = idx00, idx11 = idx01;
901
902         lookup_stage0(&idx00, &lookup_mask, keys);
903         lookup_stage0(&idx01, &lookup_mask, keys);
904         lookup_stage1(idx10, &primary_hash10, &secondary_hash10,
905                         &primary_bkt10, &secondary_bkt10, hash_vals, keys, h);
906         lookup_stage1(idx11, &primary_hash11, &secondary_hash11,
907                         &primary_bkt11, &secondary_bkt11, hash_vals, keys, h);
908
909         primary_bkt20 = primary_bkt10;
910         primary_bkt21 = primary_bkt11;
911         secondary_bkt20 = secondary_bkt10;
912         secondary_bkt21 = secondary_bkt11;
913         primary_hash20 = primary_hash10;
914         primary_hash21 = primary_hash11;
915         secondary_hash20 = secondary_hash10;
916         secondary_hash21 = secondary_hash11;
917         idx20 = idx10, idx21 = idx11;
918         idx10 = idx00, idx11 = idx01;
919
920         lookup_stage0(&idx00, &lookup_mask, keys);
921         lookup_stage0(&idx01, &lookup_mask, keys);
922         lookup_stage1(idx10, &primary_hash10, &secondary_hash10,
923                         &primary_bkt10, &secondary_bkt10, hash_vals, keys, h);
924         lookup_stage1(idx11, &primary_hash11, &secondary_hash11,
925                         &primary_bkt11, &secondary_bkt11, hash_vals, keys, h);
926         lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
927                         secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
928                         key_store, h);
929         lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
930                         secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
931                         key_store, h);
932
933         while (lookup_mask) {
934                 k_slot30 = k_slot20, k_slot31 = k_slot21;
935                 idx30 = idx20, idx31 = idx21;
936                 primary_bkt20 = primary_bkt10;
937                 primary_bkt21 = primary_bkt11;
938                 secondary_bkt20 = secondary_bkt10;
939                 secondary_bkt21 = secondary_bkt11;
940                 primary_hash20 = primary_hash10;
941                 primary_hash21 = primary_hash11;
942                 secondary_hash20 = secondary_hash10;
943                 secondary_hash21 = secondary_hash11;
944                 idx20 = idx10, idx21 = idx11;
945                 idx10 = idx00, idx11 = idx01;
946
947                 lookup_stage0(&idx00, &lookup_mask, keys);
948                 lookup_stage0(&idx01, &lookup_mask, keys);
949                 lookup_stage1(idx10, &primary_hash10, &secondary_hash10,
950                         &primary_bkt10, &secondary_bkt10, hash_vals, keys, h);
951                 lookup_stage1(idx11, &primary_hash11, &secondary_hash11,
952                         &primary_bkt11, &secondary_bkt11, hash_vals, keys, h);
953                 lookup_stage2(idx20, primary_hash20, secondary_hash20,
954                         primary_bkt20, secondary_bkt20, &k_slot20, positions,
955                         &extra_hits_mask, key_store, h);
956                 lookup_stage2(idx21, primary_hash21, secondary_hash21,
957                         primary_bkt21, secondary_bkt21, &k_slot21, positions,
958                         &extra_hits_mask, key_store, h);
959                 lookup_stage3(idx30, k_slot30, keys, data, &hits, h);
960                 lookup_stage3(idx31, k_slot31, keys, data, &hits, h);
961         }
962
963         k_slot30 = k_slot20, k_slot31 = k_slot21;
964         idx30 = idx20, idx31 = idx21;
965         primary_bkt20 = primary_bkt10;
966         primary_bkt21 = primary_bkt11;
967         secondary_bkt20 = secondary_bkt10;
968         secondary_bkt21 = secondary_bkt11;
969         primary_hash20 = primary_hash10;
970         primary_hash21 = primary_hash11;
971         secondary_hash20 = secondary_hash10;
972         secondary_hash21 = secondary_hash11;
973         idx20 = idx10, idx21 = idx11;
974         idx10 = idx00, idx11 = idx01;
975
976         lookup_stage1(idx10, &primary_hash10, &secondary_hash10,
977                 &primary_bkt10, &secondary_bkt10, hash_vals, keys, h);
978         lookup_stage1(idx11, &primary_hash11, &secondary_hash11,
979                 &primary_bkt11, &secondary_bkt11, hash_vals, keys, h);
980         lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
981                 secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
982                 key_store, h);
983         lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
984                 secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
985                 key_store, h);
986         lookup_stage3(idx30, k_slot30, keys, data, &hits, h);
987         lookup_stage3(idx31, k_slot31, keys, data, &hits, h);
988
989         k_slot30 = k_slot20, k_slot31 = k_slot21;
990         idx30 = idx20, idx31 = idx21;
991         primary_bkt20 = primary_bkt10;
992         primary_bkt21 = primary_bkt11;
993         secondary_bkt20 = secondary_bkt10;
994         secondary_bkt21 = secondary_bkt11;
995         primary_hash20 = primary_hash10;
996         primary_hash21 = primary_hash11;
997         secondary_hash20 = secondary_hash10;
998         secondary_hash21 = secondary_hash11;
999         idx20 = idx10, idx21 = idx11;
1000
1001         lookup_stage2(idx20, primary_hash20, secondary_hash20, primary_bkt20,
1002                 secondary_bkt20, &k_slot20, positions, &extra_hits_mask,
1003                 key_store, h);
1004         lookup_stage2(idx21, primary_hash21, secondary_hash21, primary_bkt21,
1005                 secondary_bkt21, &k_slot21, positions, &extra_hits_mask,
1006                 key_store, h);
1007         lookup_stage3(idx30, k_slot30, keys, data, &hits, h);
1008         lookup_stage3(idx31, k_slot31, keys, data, &hits, h);
1009
1010         k_slot30 = k_slot20, k_slot31 = k_slot21;
1011         idx30 = idx20, idx31 = idx21;
1012
1013         lookup_stage3(idx30, k_slot30, keys, data, &hits, h);
1014         lookup_stage3(idx31, k_slot31, keys, data, &hits, h);
1015
1016         /* ignore any items we have already found */
1017         extra_hits_mask &= ~hits;
1018
1019         if (unlikely(extra_hits_mask)) {
1020                 /* run a single search for each remaining item */
1021                 do {
1022                         idx = __builtin_ctzl(extra_hits_mask);
1023                         if (data != NULL) {
1024                                 ret = rte_hash_lookup_with_hash_data(h,
1025                                                 keys[idx], hash_vals[idx], &data[idx]);
1026                                 if (ret >= 0)
1027                                         hits |= 1ULL << idx;
1028                         } else {
1029                                 positions[idx] = rte_hash_lookup_with_hash(h,
1030                                                         keys[idx], hash_vals[idx]);
1031                                 if (positions[idx] >= 0)
1032                                         hits |= 1llu << idx;
1033                         }
1034                         extra_hits_mask &= ~(1llu << idx);
1035                 } while (extra_hits_mask);
1036         }
1037
1038         miss_mask &= ~hits;
1039         if (unlikely(miss_mask)) {
1040                 do {
1041                         idx = __builtin_ctzl(miss_mask);
1042                         positions[idx] = -ENOENT;
1043                         miss_mask &= ~(1llu << idx);
1044                 } while (miss_mask);
1045         }
1046
1047         if (hit_mask != NULL)
1048                 *hit_mask = hits;
1049 }
1050
1051 int
1052 rte_hash_lookup_bulk(const struct rte_hash *h, const void **keys,
1053                       uint32_t num_keys, int32_t *positions)
1054 {
1055         RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) ||
1056                         (num_keys > RTE_HASH_LOOKUP_BULK_MAX) ||
1057                         (positions == NULL)), -EINVAL);
1058
1059         __rte_hash_lookup_bulk(h, keys, num_keys, positions, NULL, NULL);
1060         return 0;
1061 }
1062
1063 int
1064 rte_hash_lookup_bulk_data(const struct rte_hash *h, const void **keys,
1065                       uint32_t num_keys, uint64_t *hit_mask, void *data[])
1066 {
1067         RETURN_IF_TRUE(((h == NULL) || (keys == NULL) || (num_keys == 0) ||
1068                         (num_keys > RTE_HASH_LOOKUP_BULK_MAX) ||
1069                         (hit_mask == NULL)), -EINVAL);
1070
1071         int32_t positions[num_keys];
1072
1073         __rte_hash_lookup_bulk(h, keys, num_keys, positions, hit_mask, data);
1074
1075         /* Return number of hits */
1076         return __builtin_popcountl(*hit_mask);
1077 }
1078
1079 int32_t
1080 rte_hash_iterate(const struct rte_hash *h, const void **key, void **data, uint32_t *next)
1081 {
1082         uint32_t bucket_idx, idx, position;
1083         struct rte_hash_key *next_key;
1084
1085         RETURN_IF_TRUE(((h == NULL) || (next == NULL)), -EINVAL);
1086
1087         const uint32_t total_entries = h->num_buckets * RTE_HASH_BUCKET_ENTRIES;
1088         /* Out of bounds */
1089         if (*next >= total_entries)
1090                 return -ENOENT;
1091
1092         /* Calculate bucket and index of current iterator */
1093         bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;
1094         idx = *next % RTE_HASH_BUCKET_ENTRIES;
1095
1096         /* If current position is empty, go to the next one */
1097         while (h->buckets[bucket_idx].signatures[idx].sig == NULL_SIGNATURE) {
1098                 (*next)++;
1099                 /* End of table */
1100                 if (*next == total_entries)
1101                         return -ENOENT;
1102                 bucket_idx = *next / RTE_HASH_BUCKET_ENTRIES;
1103                 idx = *next % RTE_HASH_BUCKET_ENTRIES;
1104         }
1105
1106         /* Get position of entry in key table */
1107         position = h->buckets[bucket_idx].key_idx[idx];
1108         next_key = (struct rte_hash_key *) ((char *)h->key_store +
1109                                 position * h->key_entry_size);
1110         /* Return key and data */
1111         *key = next_key->key;
1112         *data = next_key->pdata;
1113
1114         /* Increment iterator */
1115         (*next)++;
1116
1117         return (position - 1);
1118 }