table: fix crash during key overload
[dpdk.git] / lib / librte_table / rte_table_hash_key8.c
1 /*-
2  *       BSD LICENSE
3  *
4  *       Copyright(c) 2010-2014 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 #include <string.h>
34 #include <stdio.h>
35
36 #include <rte_common.h>
37 #include <rte_mbuf.h>
38 #include <rte_memory.h>
39 #include <rte_malloc.h>
40 #include <rte_log.h>
41
42 #include "rte_table_hash.h"
43 #include "rte_lru.h"
44
45 #define RTE_TABLE_HASH_KEY_SIZE                                         8
46
47 struct rte_bucket_4_8 {
48         /* Cache line 0 */
49         uint64_t signature;
50         uint64_t lru_list;
51         struct rte_bucket_4_8 *next;
52         uint64_t next_valid;
53
54         uint64_t key[4];
55
56         /* Cache line 1 */
57         uint8_t data[0];
58 };
59
60 struct rte_table_hash {
61         /* Input parameters */
62         uint32_t n_buckets;
63         uint32_t n_entries_per_bucket;
64         uint32_t key_size;
65         uint32_t entry_size;
66         uint32_t bucket_size;
67         uint32_t signature_offset;
68         uint32_t key_offset;
69         rte_table_hash_op_hash f_hash;
70         uint64_t seed;
71
72         /* Extendible buckets */
73         uint32_t n_buckets_ext;
74         uint32_t stack_pos;
75         uint32_t *stack;
76
77         /* Lookup table */
78         uint8_t memory[0] __rte_cache_aligned;
79 };
80
81 static int
82 check_params_create_lru(struct rte_table_hash_key8_lru_params *params) {
83         /* n_entries */
84         if (params->n_entries == 0) {
85                 RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__);
86                 return -EINVAL;
87         }
88
89         /* signature offset */
90         if ((params->signature_offset & 0x3) != 0) {
91                 RTE_LOG(ERR, TABLE, "%s: invalid signature_offset\n", __func__);
92                 return -EINVAL;
93         }
94
95         /* key offset */
96         if ((params->key_offset & 0x7) != 0) {
97                 RTE_LOG(ERR, TABLE, "%s: invalid key_offset\n", __func__);
98                 return -EINVAL;
99         }
100
101         /* f_hash */
102         if (params->f_hash == NULL) {
103                 RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n",
104                         __func__);
105                 return -EINVAL;
106         }
107
108         return 0;
109 }
110
111 static void *
112 rte_table_hash_create_key8_lru(void *params, int socket_id, uint32_t entry_size)
113 {
114         struct rte_table_hash_key8_lru_params *p =
115                 (struct rte_table_hash_key8_lru_params *) params;
116         struct rte_table_hash *f;
117         uint32_t n_buckets, n_entries_per_bucket, key_size, bucket_size_cl;
118         uint32_t total_size, i;
119
120         /* Check input parameters */
121         if ((check_params_create_lru(p) != 0) ||
122                 ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) ||
123                 ((sizeof(struct rte_bucket_4_8) % RTE_CACHE_LINE_SIZE) != 0)) {
124                 return NULL;
125         }
126         n_entries_per_bucket = 4;
127         key_size = 8;
128
129         /* Memory allocation */
130         n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) /
131                 n_entries_per_bucket);
132         bucket_size_cl = (sizeof(struct rte_bucket_4_8) + n_entries_per_bucket *
133                 entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE;
134         total_size = sizeof(struct rte_table_hash) + n_buckets *
135                 bucket_size_cl * RTE_CACHE_LINE_SIZE;
136
137         f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id);
138         if (f == NULL) {
139                 RTE_LOG(ERR, TABLE,
140                         "%s: Cannot allocate %u bytes for hash table\n",
141                         __func__, total_size);
142                 return NULL;
143         }
144         RTE_LOG(INFO, TABLE,
145                 "%s: Hash table memory footprint is %u bytes\n",
146                 __func__, total_size);
147
148         /* Memory initialization */
149         f->n_buckets = n_buckets;
150         f->n_entries_per_bucket = n_entries_per_bucket;
151         f->key_size = key_size;
152         f->entry_size = entry_size;
153         f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE;
154         f->signature_offset = p->signature_offset;
155         f->key_offset = p->key_offset;
156         f->f_hash = p->f_hash;
157         f->seed = p->seed;
158
159         for (i = 0; i < n_buckets; i++) {
160                 struct rte_bucket_4_8 *bucket;
161
162                 bucket = (struct rte_bucket_4_8 *) &f->memory[i *
163                         f->bucket_size];
164                 bucket->lru_list = 0x0000000100020003LLU;
165         }
166
167         return f;
168 }
169
170 static int
171 rte_table_hash_free_key8_lru(void *table)
172 {
173         struct rte_table_hash *f = (struct rte_table_hash *) table;
174
175         /* Check input parameters */
176         if (f == NULL) {
177                 RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__);
178                 return -EINVAL;
179         }
180
181         rte_free(f);
182         return 0;
183 }
184
185 static int
186 rte_table_hash_entry_add_key8_lru(
187         void *table,
188         void *key,
189         void *entry,
190         int *key_found,
191         void **entry_ptr)
192 {
193         struct rte_table_hash *f = (struct rte_table_hash *) table;
194         struct rte_bucket_4_8 *bucket;
195         uint64_t signature, mask, pos;
196         uint32_t bucket_index, i;
197
198         signature = f->f_hash(key, f->key_size, f->seed);
199         bucket_index = signature & (f->n_buckets - 1);
200         bucket = (struct rte_bucket_4_8 *)
201                 &f->memory[bucket_index * f->bucket_size];
202
203         /* Key is present in the bucket */
204         for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
205                 uint64_t bucket_signature = bucket->signature;
206                 uint64_t bucket_key = bucket->key[i];
207
208                 if ((bucket_signature & mask) &&
209                     (*((uint64_t *) key) == bucket_key)) {
210                         uint8_t *bucket_data = &bucket->data[i * f->entry_size];
211
212                         memcpy(bucket_data, entry, f->entry_size);
213                         lru_update(bucket, i);
214                         *key_found = 1;
215                         *entry_ptr = (void *) bucket_data;
216                         return 0;
217                 }
218         }
219
220         /* Key is not present in the bucket */
221         for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
222                 uint64_t bucket_signature = bucket->signature;
223
224                 if ((bucket_signature & mask) == 0) {
225                         uint8_t *bucket_data = &bucket->data[i * f->entry_size];
226
227                         bucket->signature |= mask;
228                         bucket->key[i] = *((uint64_t *) key);
229                         memcpy(bucket_data, entry, f->entry_size);
230                         lru_update(bucket, i);
231                         *key_found = 0;
232                         *entry_ptr = (void *) bucket_data;
233
234                         return 0;
235                 }
236         }
237
238         /* Bucket full: replace LRU entry */
239         pos = lru_pos(bucket);
240         bucket->key[pos] = *((uint64_t *) key);
241         memcpy(&bucket->data[pos * f->entry_size], entry, f->entry_size);
242         lru_update(bucket, pos);
243         *key_found      = 0;
244         *entry_ptr = (void *) &bucket->data[pos * f->entry_size];
245
246         return 0;
247 }
248
249 static int
250 rte_table_hash_entry_delete_key8_lru(
251         void *table,
252         void *key,
253         int *key_found,
254         void *entry)
255 {
256         struct rte_table_hash *f = (struct rte_table_hash *) table;
257         struct rte_bucket_4_8 *bucket;
258         uint64_t signature, mask;
259         uint32_t bucket_index, i;
260
261         signature = f->f_hash(key, f->key_size, f->seed);
262         bucket_index = signature & (f->n_buckets - 1);
263         bucket = (struct rte_bucket_4_8 *)
264                 &f->memory[bucket_index * f->bucket_size];
265
266         /* Key is present in the bucket */
267         for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
268                 uint64_t bucket_signature = bucket->signature;
269                 uint64_t bucket_key = bucket->key[i];
270
271                 if ((bucket_signature & mask) &&
272                     (*((uint64_t *) key) == bucket_key)) {
273                         uint8_t *bucket_data = &bucket->data[i * f->entry_size];
274
275                         bucket->signature &= ~mask;
276                         *key_found = 1;
277                         if (entry)
278                                 memcpy(entry, bucket_data, f->entry_size);
279
280                         return 0;
281                 }
282         }
283
284         /* Key is not present in the bucket */
285         *key_found = 0;
286         return 0;
287 }
288
289 static int
290 check_params_create_ext(struct rte_table_hash_key8_ext_params *params) {
291         /* n_entries */
292         if (params->n_entries == 0) {
293                 RTE_LOG(ERR, TABLE, "%s: n_entries is zero\n", __func__);
294                 return -EINVAL;
295         }
296
297         /* n_entries_ext */
298         if (params->n_entries_ext == 0) {
299                 RTE_LOG(ERR, TABLE, "%s: n_entries_ext is zero\n", __func__);
300                 return -EINVAL;
301         }
302
303         /* signature offset */
304         if ((params->signature_offset & 0x3) != 0) {
305                 RTE_LOG(ERR, TABLE, "%s: invalid signature_offset\n", __func__);
306                 return -EINVAL;
307         }
308
309         /* key offset */
310         if ((params->key_offset & 0x7) != 0) {
311                 RTE_LOG(ERR, TABLE, "%s: invalid key_offset\n", __func__);
312                 return -EINVAL;
313         }
314
315         /* f_hash */
316         if (params->f_hash == NULL) {
317                 RTE_LOG(ERR, TABLE, "%s: f_hash function pointer is NULL\n",
318                         __func__);
319                 return -EINVAL;
320         }
321
322         return 0;
323 }
324
325 static void *
326 rte_table_hash_create_key8_ext(void *params, int socket_id, uint32_t entry_size)
327 {
328         struct rte_table_hash_key8_ext_params *p =
329                 (struct rte_table_hash_key8_ext_params *) params;
330         struct rte_table_hash *f;
331         uint32_t n_buckets, n_buckets_ext, n_entries_per_bucket, key_size;
332         uint32_t bucket_size_cl, stack_size_cl, total_size, i;
333
334         /* Check input parameters */
335         if ((check_params_create_ext(p) != 0) ||
336                 ((sizeof(struct rte_table_hash) % RTE_CACHE_LINE_SIZE) != 0) ||
337                 ((sizeof(struct rte_bucket_4_8) % RTE_CACHE_LINE_SIZE) != 0))
338                 return NULL;
339
340         n_entries_per_bucket = 4;
341         key_size = 8;
342
343         /* Memory allocation */
344         n_buckets = rte_align32pow2((p->n_entries + n_entries_per_bucket - 1) /
345                 n_entries_per_bucket);
346         n_buckets_ext = (p->n_entries_ext + n_entries_per_bucket - 1) /
347                 n_entries_per_bucket;
348         bucket_size_cl = (sizeof(struct rte_bucket_4_8) + n_entries_per_bucket *
349                 entry_size + RTE_CACHE_LINE_SIZE - 1) / RTE_CACHE_LINE_SIZE;
350         stack_size_cl = (n_buckets_ext * sizeof(uint32_t) + RTE_CACHE_LINE_SIZE - 1)
351                 / RTE_CACHE_LINE_SIZE;
352         total_size = sizeof(struct rte_table_hash) + ((n_buckets +
353                 n_buckets_ext) * bucket_size_cl + stack_size_cl) *
354                 RTE_CACHE_LINE_SIZE;
355
356         f = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id);
357         if (f == NULL) {
358                 RTE_LOG(ERR, TABLE,
359                         "%s: Cannot allocate %u bytes for hash table\n",
360                         __func__, total_size);
361                 return NULL;
362         }
363         RTE_LOG(INFO, TABLE,
364                 "%s: Hash table memory footprint is %u bytes\n",
365                 __func__, total_size);
366
367         /* Memory initialization */
368         f->n_buckets = n_buckets;
369         f->n_entries_per_bucket = n_entries_per_bucket;
370         f->key_size = key_size;
371         f->entry_size = entry_size;
372         f->bucket_size = bucket_size_cl * RTE_CACHE_LINE_SIZE;
373         f->signature_offset = p->signature_offset;
374         f->key_offset = p->key_offset;
375         f->f_hash = p->f_hash;
376         f->seed = p->seed;
377
378         f->n_buckets_ext = n_buckets_ext;
379         f->stack_pos = n_buckets_ext;
380         f->stack = (uint32_t *)
381                 &f->memory[(n_buckets + n_buckets_ext) * f->bucket_size];
382
383         for (i = 0; i < n_buckets_ext; i++)
384                 f->stack[i] = i;
385
386         return f;
387 }
388
389 static int
390 rte_table_hash_free_key8_ext(void *table)
391 {
392         struct rte_table_hash *f = (struct rte_table_hash *) table;
393
394         /* Check input parameters */
395         if (f == NULL) {
396                 RTE_LOG(ERR, TABLE, "%s: table parameter is NULL\n", __func__);
397                 return -EINVAL;
398         }
399
400         rte_free(f);
401         return 0;
402 }
403
404 static int
405 rte_table_hash_entry_add_key8_ext(
406         void *table,
407         void *key,
408         void *entry,
409         int *key_found,
410         void **entry_ptr)
411 {
412         struct rte_table_hash *f = (struct rte_table_hash *) table;
413         struct rte_bucket_4_8 *bucket0, *bucket, *bucket_prev;
414         uint64_t signature;
415         uint32_t bucket_index, i;
416
417         signature = f->f_hash(key, f->key_size, f->seed);
418         bucket_index = signature & (f->n_buckets - 1);
419         bucket0 = (struct rte_bucket_4_8 *)
420                 &f->memory[bucket_index * f->bucket_size];
421
422         /* Key is present in the bucket */
423         for (bucket = bucket0; bucket != NULL; bucket = bucket->next) {
424                 uint64_t mask;
425
426                 for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
427                         uint64_t bucket_signature = bucket->signature;
428                         uint64_t bucket_key = bucket->key[i];
429
430                         if ((bucket_signature & mask) &&
431                                         (*((uint64_t *) key) == bucket_key)) {
432                                 uint8_t *bucket_data = &bucket->data[i *
433                                         f->entry_size];
434
435                                 memcpy(bucket_data, entry, f->entry_size);
436                                 *key_found = 1;
437                                 *entry_ptr = (void *) bucket_data;
438                                 return 0;
439                         }
440                 }
441         }
442
443         /* Key is not present in the bucket */
444         for (bucket_prev = NULL, bucket = bucket0;
445                 bucket != NULL; bucket_prev = bucket, bucket = bucket->next) {
446                 uint64_t mask;
447
448                 for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
449                         uint64_t bucket_signature = bucket->signature;
450
451                         if ((bucket_signature & mask) == 0) {
452                                 uint8_t *bucket_data = &bucket->data[i *
453                                         f->entry_size];
454
455                                 bucket->signature |= mask;
456                                 bucket->key[i] = *((uint64_t *) key);
457                                 memcpy(bucket_data, entry, f->entry_size);
458                                 *key_found = 0;
459                                 *entry_ptr = (void *) bucket_data;
460
461                                 return 0;
462                         }
463                 }
464         }
465
466         /* Bucket full: extend bucket */
467         if (f->stack_pos > 0) {
468                 bucket_index = f->stack[--f->stack_pos];
469
470                 bucket = (struct rte_bucket_4_8 *) &f->memory[(f->n_buckets +
471                         bucket_index) * f->bucket_size];
472                 bucket_prev->next = bucket;
473                 bucket_prev->next_valid = 1;
474
475                 bucket->signature = 1;
476                 bucket->key[0] = *((uint64_t *) key);
477                 memcpy(&bucket->data[0], entry, f->entry_size);
478                 *key_found = 0;
479                 *entry_ptr = (void *) &bucket->data[0];
480                 return 0;
481         }
482
483         return -ENOSPC;
484 }
485
486 static int
487 rte_table_hash_entry_delete_key8_ext(
488         void *table,
489         void *key,
490         int *key_found,
491         void *entry)
492 {
493         struct rte_table_hash *f = (struct rte_table_hash *) table;
494         struct rte_bucket_4_8 *bucket0, *bucket, *bucket_prev;
495         uint64_t signature;
496         uint32_t bucket_index, i;
497
498         signature = f->f_hash(key, f->key_size, f->seed);
499         bucket_index = signature & (f->n_buckets - 1);
500         bucket0 = (struct rte_bucket_4_8 *)
501                 &f->memory[bucket_index * f->bucket_size];
502
503         /* Key is present in the bucket */
504         for (bucket_prev = NULL, bucket = bucket0; bucket != NULL;
505                 bucket_prev = bucket, bucket = bucket->next) {
506                 uint64_t mask;
507
508                 for (i = 0, mask = 1LLU; i < 4; i++, mask <<= 1) {
509                         uint64_t bucket_signature = bucket->signature;
510                         uint64_t bucket_key = bucket->key[i];
511
512                         if ((bucket_signature & mask) &&
513                                 (*((uint64_t *) key) == bucket_key)) {
514                                 uint8_t *bucket_data = &bucket->data[i *
515                                         f->entry_size];
516
517                                 bucket->signature &= ~mask;
518                                 *key_found = 1;
519                                 if (entry)
520                                         memcpy(entry, bucket_data,
521                                                 f->entry_size);
522
523                                 if ((bucket->signature == 0) &&
524                                     (bucket_prev != NULL)) {
525                                         bucket_prev->next = bucket->next;
526                                         bucket_prev->next_valid =
527                                                 bucket->next_valid;
528
529                                         memset(bucket, 0,
530                                                 sizeof(struct rte_bucket_4_8));
531                                         bucket_index = (((uint8_t *)bucket -
532                                                 (uint8_t *)f->memory)/f->bucket_size) - f->n_buckets;
533                                         f->stack[f->stack_pos++] = bucket_index;
534                                 }
535
536                                 return 0;
537                         }
538                 }
539         }
540
541         /* Key is not present in the bucket */
542         *key_found = 0;
543         return 0;
544 }
545
546 #define lookup_key8_cmp(key_in, bucket, pos)                    \
547 {                                                               \
548         uint64_t xor[4], signature;                             \
549                                                                 \
550         signature = ~bucket->signature;                         \
551                                                                 \
552         xor[0] = (key_in[0] ^    bucket->key[0]) | (signature & 1);\
553         xor[1] = (key_in[0] ^    bucket->key[1]) | (signature & 2);\
554         xor[2] = (key_in[0] ^    bucket->key[2]) | (signature & 4);\
555         xor[3] = (key_in[0] ^    bucket->key[3]) | (signature & 8);\
556                                                                 \
557         pos = 4;                                                \
558         if (xor[0] == 0)                                        \
559                 pos = 0;                                        \
560         if (xor[1] == 0)                                        \
561                 pos = 1;                                        \
562         if (xor[2] == 0)                                        \
563                 pos = 2;                                        \
564         if (xor[3] == 0)                                        \
565                 pos = 3;                                        \
566 }
567
568 #define lookup1_stage0(pkt0_index, mbuf0, pkts, pkts_mask)      \
569 {                                                               \
570         uint64_t pkt_mask;                                      \
571                                                                 \
572         pkt0_index = __builtin_ctzll(pkts_mask);                \
573         pkt_mask = 1LLU << pkt0_index;                          \
574         pkts_mask &= ~pkt_mask;                                 \
575                                                                 \
576         mbuf0 = pkts[pkt0_index];                               \
577         rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf0, 0));   \
578 }
579
580 #define lookup1_stage1(mbuf1, bucket1, f)                       \
581 {                                                               \
582         uint64_t signature;                                     \
583         uint32_t bucket_index;                                  \
584                                                                 \
585         signature = RTE_MBUF_METADATA_UINT32(mbuf1, f->signature_offset);\
586         bucket_index = signature & (f->n_buckets - 1);          \
587         bucket1 = (struct rte_bucket_4_8 *)                     \
588                 &f->memory[bucket_index * f->bucket_size];      \
589         rte_prefetch0(bucket1);                                 \
590 }
591
592 #define lookup1_stage1_dosig(mbuf1, bucket1, f)                 \
593 {                                                               \
594         uint64_t *key;                                          \
595         uint64_t signature;                                     \
596         uint32_t bucket_index;                                  \
597                                                                 \
598         key = RTE_MBUF_METADATA_UINT64_PTR(mbuf1, f->key_offset);\
599         signature = f->f_hash(key, RTE_TABLE_HASH_KEY_SIZE, f->seed);\
600         bucket_index = signature & (f->n_buckets - 1);          \
601         bucket1 = (struct rte_bucket_4_8 *)                     \
602                 &f->memory[bucket_index * f->bucket_size];      \
603         rte_prefetch0(bucket1);                                 \
604 }
605
606 #define lookup1_stage2_lru(pkt2_index, mbuf2, bucket2,          \
607         pkts_mask_out, entries, f)                              \
608 {                                                               \
609         void *a;                                                \
610         uint64_t pkt_mask;                                      \
611         uint64_t *key;                                          \
612         uint32_t pos;                                           \
613                                                                 \
614         key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\
615                                                                 \
616         lookup_key8_cmp(key, bucket2, pos);                     \
617                                                                 \
618         pkt_mask = ((bucket2->signature >> pos) & 1LLU) << pkt2_index;\
619         pkts_mask_out |= pkt_mask;                              \
620                                                                 \
621         a = (void *) &bucket2->data[pos * f->entry_size];       \
622         rte_prefetch0(a);                                       \
623         entries[pkt2_index] = a;                                \
624         lru_update(bucket2, pos);                               \
625 }
626
627 #define lookup1_stage2_ext(pkt2_index, mbuf2, bucket2, pkts_mask_out,\
628         entries, buckets_mask, buckets, keys, f)                \
629 {                                                               \
630         struct rte_bucket_4_8 *bucket_next;                     \
631         void *a;                                                \
632         uint64_t pkt_mask, bucket_mask;                         \
633         uint64_t *key;                                          \
634         uint32_t pos;                                           \
635                                                                 \
636         key = RTE_MBUF_METADATA_UINT64_PTR(mbuf2, f->key_offset);\
637                                                                 \
638         lookup_key8_cmp(key, bucket2, pos);                     \
639                                                                 \
640         pkt_mask = ((bucket2->signature >> pos) & 1LLU) << pkt2_index;\
641         pkts_mask_out |= pkt_mask;                              \
642                                                                 \
643         a = (void *) &bucket2->data[pos * f->entry_size];       \
644         rte_prefetch0(a);                                       \
645         entries[pkt2_index] = a;                                \
646                                                                 \
647         bucket_mask = (~pkt_mask) & (bucket2->next_valid << pkt2_index);\
648         buckets_mask |= bucket_mask;                            \
649         bucket_next = bucket2->next;                            \
650         buckets[pkt2_index] = bucket_next;                      \
651         keys[pkt2_index] = key;                                 \
652 }
653
654 #define lookup_grinder(pkt_index, buckets, keys, pkts_mask_out, entries,\
655         buckets_mask, f)                                        \
656 {                                                               \
657         struct rte_bucket_4_8 *bucket, *bucket_next;            \
658         void *a;                                                \
659         uint64_t pkt_mask, bucket_mask;                         \
660         uint64_t *key;                                          \
661         uint32_t pos;                                           \
662                                                                 \
663         bucket = buckets[pkt_index];                            \
664         key = keys[pkt_index];                                  \
665                                                                 \
666         lookup_key8_cmp(key, bucket, pos);                      \
667                                                                 \
668         pkt_mask = ((bucket->signature >> pos) & 1LLU) << pkt_index;\
669         pkts_mask_out |= pkt_mask;                              \
670                                                                 \
671         a = (void *) &bucket->data[pos * f->entry_size];        \
672         rte_prefetch0(a);                                       \
673         entries[pkt_index] = a;                                 \
674                                                                 \
675         bucket_mask = (~pkt_mask) & (bucket->next_valid << pkt_index);\
676         buckets_mask |= bucket_mask;                            \
677         bucket_next = bucket->next;                             \
678         rte_prefetch0(bucket_next);                             \
679         buckets[pkt_index] = bucket_next;                       \
680         keys[pkt_index] = key;                                  \
681 }
682
683 #define lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01,\
684         pkts, pkts_mask)                                        \
685 {                                                               \
686         uint64_t pkt00_mask, pkt01_mask;                        \
687                                                                 \
688         pkt00_index = __builtin_ctzll(pkts_mask);               \
689         pkt00_mask = 1LLU << pkt00_index;                       \
690         pkts_mask &= ~pkt00_mask;                               \
691                                                                 \
692         mbuf00 = pkts[pkt00_index];                             \
693         rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0));  \
694                                                                 \
695         pkt01_index = __builtin_ctzll(pkts_mask);               \
696         pkt01_mask = 1LLU << pkt01_index;                       \
697         pkts_mask &= ~pkt01_mask;                               \
698                                                                 \
699         mbuf01 = pkts[pkt01_index];                             \
700         rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0));  \
701 }
702
703 #define lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,\
704         mbuf00, mbuf01, pkts, pkts_mask)                        \
705 {                                                               \
706         uint64_t pkt00_mask, pkt01_mask;                        \
707                                                                 \
708         pkt00_index = __builtin_ctzll(pkts_mask);               \
709         pkt00_mask = 1LLU << pkt00_index;                       \
710         pkts_mask &= ~pkt00_mask;                               \
711                                                                 \
712         mbuf00 = pkts[pkt00_index];                             \
713         rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf00, 0));  \
714                                                                 \
715         pkt01_index = __builtin_ctzll(pkts_mask);               \
716         if (pkts_mask == 0)                                     \
717                 pkt01_index = pkt00_index;                      \
718                                                                 \
719         pkt01_mask = 1LLU << pkt01_index;                       \
720         pkts_mask &= ~pkt01_mask;                               \
721                                                                 \
722         mbuf01 = pkts[pkt01_index];                             \
723         rte_prefetch0(RTE_MBUF_METADATA_UINT8_PTR(mbuf01, 0));  \
724 }
725
726 #define lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f)   \
727 {                                                               \
728         uint64_t signature10, signature11;                      \
729         uint32_t bucket10_index, bucket11_index;                \
730                                                                 \
731         signature10 = RTE_MBUF_METADATA_UINT32(mbuf10, f->signature_offset);\
732         bucket10_index = signature10 & (f->n_buckets - 1);      \
733         bucket10 = (struct rte_bucket_4_8 *)                    \
734                 &f->memory[bucket10_index * f->bucket_size];    \
735         rte_prefetch0(bucket10);                                \
736                                                                 \
737         signature11 = RTE_MBUF_METADATA_UINT32(mbuf11, f->signature_offset);\
738         bucket11_index = signature11 & (f->n_buckets - 1);      \
739         bucket11 = (struct rte_bucket_4_8 *)                    \
740                 &f->memory[bucket11_index * f->bucket_size];    \
741         rte_prefetch0(bucket11);                                \
742 }
743
744 #define lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f)\
745 {                                                               \
746         uint64_t *key10, *key11;                                \
747         uint64_t signature10, signature11;                      \
748         uint32_t bucket10_index, bucket11_index;                \
749         rte_table_hash_op_hash f_hash = f->f_hash;              \
750         uint64_t seed = f->seed;                                \
751         uint32_t key_offset = f->key_offset;                    \
752                                                                 \
753         key10 = RTE_MBUF_METADATA_UINT64_PTR(mbuf10, key_offset);\
754         key11 = RTE_MBUF_METADATA_UINT64_PTR(mbuf11, key_offset);\
755                                                                 \
756         signature10 = f_hash(key10, RTE_TABLE_HASH_KEY_SIZE, seed);\
757         bucket10_index = signature10 & (f->n_buckets - 1);      \
758         bucket10 = (struct rte_bucket_4_8 *)                    \
759                 &f->memory[bucket10_index * f->bucket_size];    \
760         rte_prefetch0(bucket10);                                \
761                                                                 \
762         signature11 = f_hash(key11, RTE_TABLE_HASH_KEY_SIZE, seed);\
763         bucket11_index = signature11 & (f->n_buckets - 1);      \
764         bucket11 = (struct rte_bucket_4_8 *)                    \
765                 &f->memory[bucket11_index * f->bucket_size];    \
766         rte_prefetch0(bucket11);                                \
767 }
768
769 #define lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,\
770         bucket20, bucket21, pkts_mask_out, entries, f)          \
771 {                                                               \
772         void *a20, *a21;                                        \
773         uint64_t pkt20_mask, pkt21_mask;                        \
774         uint64_t *key20, *key21;                                \
775         uint32_t pos20, pos21;                                  \
776                                                                 \
777         key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\
778         key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\
779                                                                 \
780         lookup_key8_cmp(key20, bucket20, pos20);                \
781         lookup_key8_cmp(key21, bucket21, pos21);                \
782                                                                 \
783         pkt20_mask = ((bucket20->signature >> pos20) & 1LLU) << pkt20_index;\
784         pkt21_mask = ((bucket21->signature >> pos21) & 1LLU) << pkt21_index;\
785         pkts_mask_out |= pkt20_mask | pkt21_mask;               \
786                                                                 \
787         a20 = (void *) &bucket20->data[pos20 * f->entry_size];  \
788         a21 = (void *) &bucket21->data[pos21 * f->entry_size];  \
789         rte_prefetch0(a20);                                     \
790         rte_prefetch0(a21);                                     \
791         entries[pkt20_index] = a20;                             \
792         entries[pkt21_index] = a21;                             \
793         lru_update(bucket20, pos20);                            \
794         lru_update(bucket21, pos21);                            \
795 }
796
797 #define lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21, bucket20, \
798         bucket21, pkts_mask_out, entries, buckets_mask, buckets, keys, f)\
799 {                                                               \
800         struct rte_bucket_4_8 *bucket20_next, *bucket21_next;   \
801         void *a20, *a21;                                        \
802         uint64_t pkt20_mask, pkt21_mask, bucket20_mask, bucket21_mask;\
803         uint64_t *key20, *key21;                                \
804         uint32_t pos20, pos21;                                  \
805                                                                 \
806         key20 = RTE_MBUF_METADATA_UINT64_PTR(mbuf20, f->key_offset);\
807         key21 = RTE_MBUF_METADATA_UINT64_PTR(mbuf21, f->key_offset);\
808                                                                 \
809         lookup_key8_cmp(key20, bucket20, pos20);                \
810         lookup_key8_cmp(key21, bucket21, pos21);                \
811                                                                 \
812         pkt20_mask = ((bucket20->signature >> pos20) & 1LLU) << pkt20_index;\
813         pkt21_mask = ((bucket21->signature >> pos21) & 1LLU) << pkt21_index;\
814         pkts_mask_out |= pkt20_mask | pkt21_mask;               \
815                                                                 \
816         a20 = (void *) &bucket20->data[pos20 * f->entry_size];  \
817         a21 = (void *) &bucket21->data[pos21 * f->entry_size];  \
818         rte_prefetch0(a20);                                     \
819         rte_prefetch0(a21);                                     \
820         entries[pkt20_index] = a20;                             \
821         entries[pkt21_index] = a21;                             \
822                                                                 \
823         bucket20_mask = (~pkt20_mask) & (bucket20->next_valid << pkt20_index);\
824         bucket21_mask = (~pkt21_mask) & (bucket21->next_valid << pkt21_index);\
825         buckets_mask |= bucket20_mask | bucket21_mask;          \
826         bucket20_next = bucket20->next;                         \
827         bucket21_next = bucket21->next;                         \
828         buckets[pkt20_index] = bucket20_next;                   \
829         buckets[pkt21_index] = bucket21_next;                   \
830         keys[pkt20_index] = key20;                              \
831         keys[pkt21_index] = key21;                              \
832 }
833
834 static int
835 rte_table_hash_lookup_key8_lru(
836         void *table,
837         struct rte_mbuf **pkts,
838         uint64_t pkts_mask,
839         uint64_t *lookup_hit_mask,
840         void **entries)
841 {
842         struct rte_table_hash *f = (struct rte_table_hash *) table;
843         struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21;
844         struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21;
845         uint32_t pkt00_index, pkt01_index, pkt10_index,
846                         pkt11_index, pkt20_index, pkt21_index;
847         uint64_t pkts_mask_out = 0;
848
849         /* Cannot run the pipeline with less than 5 packets */
850         if (__builtin_popcountll(pkts_mask) < 5) {
851                 for ( ; pkts_mask; ) {
852                         struct rte_bucket_4_8 *bucket;
853                         struct rte_mbuf *mbuf;
854                         uint32_t pkt_index;
855
856                         lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask);
857                         lookup1_stage1(mbuf, bucket, f);
858                         lookup1_stage2_lru(pkt_index, mbuf, bucket,
859                                         pkts_mask_out, entries, f);
860                 }
861
862                 *lookup_hit_mask = pkts_mask_out;
863                 return 0;
864         }
865
866         /*
867          * Pipeline fill
868          *
869          */
870         /* Pipeline stage 0 */
871         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
872                 pkts_mask);
873
874         /* Pipeline feed */
875         mbuf10 = mbuf00;
876         mbuf11 = mbuf01;
877         pkt10_index = pkt00_index;
878         pkt11_index = pkt01_index;
879
880         /* Pipeline stage 0 */
881         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
882                 pkts_mask);
883
884         /* Pipeline stage 1 */
885         lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
886
887         /*
888          * Pipeline run
889          *
890          */
891         for ( ; pkts_mask; ) {
892                 /* Pipeline feed */
893                 bucket20 = bucket10;
894                 bucket21 = bucket11;
895                 mbuf20 = mbuf10;
896                 mbuf21 = mbuf11;
897                 mbuf10 = mbuf00;
898                 mbuf11 = mbuf01;
899                 pkt20_index = pkt10_index;
900                 pkt21_index = pkt11_index;
901                 pkt10_index = pkt00_index;
902                 pkt11_index = pkt01_index;
903
904                 /* Pipeline stage 0 */
905                 lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,
906                         mbuf00, mbuf01, pkts, pkts_mask);
907
908                 /* Pipeline stage 1 */
909                 lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
910
911                 /* Pipeline stage 2 */
912                 lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
913                         bucket20, bucket21, pkts_mask_out, entries, f);
914         }
915
916         /*
917          * Pipeline flush
918          *
919          */
920         /* Pipeline feed */
921         bucket20 = bucket10;
922         bucket21 = bucket11;
923         mbuf20 = mbuf10;
924         mbuf21 = mbuf11;
925         mbuf10 = mbuf00;
926         mbuf11 = mbuf01;
927         pkt20_index = pkt10_index;
928         pkt21_index = pkt11_index;
929         pkt10_index = pkt00_index;
930         pkt11_index = pkt01_index;
931
932         /* Pipeline stage 1 */
933         lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
934
935         /* Pipeline stage 2 */
936         lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
937                 bucket20, bucket21, pkts_mask_out, entries, f);
938
939         /* Pipeline feed */
940         bucket20 = bucket10;
941         bucket21 = bucket11;
942         mbuf20 = mbuf10;
943         mbuf21 = mbuf11;
944         pkt20_index = pkt10_index;
945         pkt21_index = pkt11_index;
946
947         /* Pipeline stage 2 */
948         lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
949                 bucket20, bucket21, pkts_mask_out, entries, f);
950
951         *lookup_hit_mask = pkts_mask_out;
952         return 0;
953 } /* rte_table_hash_lookup_key8_lru() */
954
955 static int
956 rte_table_hash_lookup_key8_lru_dosig(
957         void *table,
958         struct rte_mbuf **pkts,
959         uint64_t pkts_mask,
960         uint64_t *lookup_hit_mask,
961         void **entries)
962 {
963         struct rte_table_hash *f = (struct rte_table_hash *) table;
964         struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21;
965         struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21;
966         uint32_t pkt00_index, pkt01_index, pkt10_index;
967         uint32_t pkt11_index, pkt20_index, pkt21_index;
968         uint64_t pkts_mask_out = 0;
969
970         /* Cannot run the pipeline with less than 5 packets */
971         if (__builtin_popcountll(pkts_mask) < 5) {
972                 for ( ; pkts_mask; ) {
973                         struct rte_bucket_4_8 *bucket;
974                         struct rte_mbuf *mbuf;
975                         uint32_t pkt_index;
976
977                         lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask);
978                         lookup1_stage1_dosig(mbuf, bucket, f);
979                         lookup1_stage2_lru(pkt_index, mbuf, bucket,
980                                 pkts_mask_out, entries, f);
981                 }
982
983                 *lookup_hit_mask = pkts_mask_out;
984                 return 0;
985         }
986
987         /*
988          * Pipeline fill
989          *
990          */
991         /* Pipeline stage 0 */
992         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
993                 pkts_mask);
994
995         /* Pipeline feed */
996         mbuf10 = mbuf00;
997         mbuf11 = mbuf01;
998         pkt10_index = pkt00_index;
999         pkt11_index = pkt01_index;
1000
1001         /* Pipeline stage 0 */
1002         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
1003                 pkts_mask);
1004
1005         /* Pipeline stage 1 */
1006         lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1007
1008         /*
1009          * Pipeline run
1010          *
1011          */
1012         for ( ; pkts_mask; ) {
1013                 /* Pipeline feed */
1014                 bucket20 = bucket10;
1015                 bucket21 = bucket11;
1016                 mbuf20 = mbuf10;
1017                 mbuf21 = mbuf11;
1018                 mbuf10 = mbuf00;
1019                 mbuf11 = mbuf01;
1020                 pkt20_index = pkt10_index;
1021                 pkt21_index = pkt11_index;
1022                 pkt10_index = pkt00_index;
1023                 pkt11_index = pkt01_index;
1024
1025                 /* Pipeline stage 0 */
1026                 lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,
1027                         mbuf00, mbuf01, pkts, pkts_mask);
1028
1029                 /* Pipeline stage 1 */
1030                 lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1031
1032                 /* Pipeline stage 2 */
1033                 lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
1034                         bucket20, bucket21, pkts_mask_out, entries, f);
1035         }
1036
1037         /*
1038          * Pipeline flush
1039          *
1040          */
1041         /* Pipeline feed */
1042         bucket20 = bucket10;
1043         bucket21 = bucket11;
1044         mbuf20 = mbuf10;
1045         mbuf21 = mbuf11;
1046         mbuf10 = mbuf00;
1047         mbuf11 = mbuf01;
1048         pkt20_index = pkt10_index;
1049         pkt21_index = pkt11_index;
1050         pkt10_index = pkt00_index;
1051         pkt11_index = pkt01_index;
1052
1053         /* Pipeline stage 1 */
1054         lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1055
1056         /* Pipeline stage 2 */
1057         lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
1058                 bucket20, bucket21, pkts_mask_out, entries, f);
1059
1060         /* Pipeline feed */
1061         bucket20 = bucket10;
1062         bucket21 = bucket11;
1063         mbuf20 = mbuf10;
1064         mbuf21 = mbuf11;
1065         pkt20_index = pkt10_index;
1066         pkt21_index = pkt11_index;
1067
1068         /* Pipeline stage 2 */
1069         lookup2_stage2_lru(pkt20_index, pkt21_index, mbuf20, mbuf21,
1070                 bucket20, bucket21, pkts_mask_out, entries, f);
1071
1072         *lookup_hit_mask = pkts_mask_out;
1073         return 0;
1074 } /* rte_table_hash_lookup_key8_lru_dosig() */
1075
1076 static int
1077 rte_table_hash_lookup_key8_ext(
1078         void *table,
1079         struct rte_mbuf **pkts,
1080         uint64_t pkts_mask,
1081         uint64_t *lookup_hit_mask,
1082         void **entries)
1083 {
1084         struct rte_table_hash *f = (struct rte_table_hash *) table;
1085         struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21;
1086         struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21;
1087         uint32_t pkt00_index, pkt01_index, pkt10_index;
1088         uint32_t pkt11_index, pkt20_index, pkt21_index;
1089         uint64_t pkts_mask_out = 0, buckets_mask = 0;
1090         struct rte_bucket_4_8 *buckets[RTE_PORT_IN_BURST_SIZE_MAX];
1091         uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX];
1092
1093         /* Cannot run the pipeline with less than 5 packets */
1094         if (__builtin_popcountll(pkts_mask) < 5) {
1095                 for ( ; pkts_mask; ) {
1096                         struct rte_bucket_4_8 *bucket;
1097                         struct rte_mbuf *mbuf;
1098                         uint32_t pkt_index;
1099
1100                         lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask);
1101                         lookup1_stage1(mbuf, bucket, f);
1102                         lookup1_stage2_ext(pkt_index, mbuf, bucket,
1103                                 pkts_mask_out, entries, buckets_mask, buckets,
1104                                 keys, f);
1105                 }
1106
1107                 goto grind_next_buckets;
1108         }
1109
1110         /*
1111          * Pipeline fill
1112          *
1113          */
1114         /* Pipeline stage 0 */
1115         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
1116                 pkts_mask);
1117
1118         /* Pipeline feed */
1119         mbuf10 = mbuf00;
1120         mbuf11 = mbuf01;
1121         pkt10_index = pkt00_index;
1122         pkt11_index = pkt01_index;
1123
1124         /* Pipeline stage 0 */
1125         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
1126                 pkts_mask);
1127
1128         /* Pipeline stage 1 */
1129         lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
1130
1131         /*
1132          * Pipeline run
1133          *
1134          */
1135         for ( ; pkts_mask; ) {
1136                 /* Pipeline feed */
1137                 bucket20 = bucket10;
1138                 bucket21 = bucket11;
1139                 mbuf20 = mbuf10;
1140                 mbuf21 = mbuf11;
1141                 mbuf10 = mbuf00;
1142                 mbuf11 = mbuf01;
1143                 pkt20_index = pkt10_index;
1144                 pkt21_index = pkt11_index;
1145                 pkt10_index = pkt00_index;
1146                 pkt11_index = pkt01_index;
1147
1148                 /* Pipeline stage 0 */
1149                 lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,
1150                         mbuf00, mbuf01, pkts, pkts_mask);
1151
1152                 /* Pipeline stage 1 */
1153                 lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
1154
1155                 /* Pipeline stage 2 */
1156                 lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1157                         bucket20, bucket21, pkts_mask_out, entries,
1158                         buckets_mask, buckets, keys, f);
1159         }
1160
1161         /*
1162          * Pipeline flush
1163          *
1164          */
1165         /* Pipeline feed */
1166         bucket20 = bucket10;
1167         bucket21 = bucket11;
1168         mbuf20 = mbuf10;
1169         mbuf21 = mbuf11;
1170         mbuf10 = mbuf00;
1171         mbuf11 = mbuf01;
1172         pkt20_index = pkt10_index;
1173         pkt21_index = pkt11_index;
1174         pkt10_index = pkt00_index;
1175         pkt11_index = pkt01_index;
1176
1177         /* Pipeline stage 1 */
1178         lookup2_stage1(mbuf10, mbuf11, bucket10, bucket11, f);
1179
1180         /* Pipeline stage 2 */
1181         lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1182                 bucket20, bucket21, pkts_mask_out, entries,
1183                 buckets_mask, buckets, keys, f);
1184
1185         /* Pipeline feed */
1186         bucket20 = bucket10;
1187         bucket21 = bucket11;
1188         mbuf20 = mbuf10;
1189         mbuf21 = mbuf11;
1190         pkt20_index = pkt10_index;
1191         pkt21_index = pkt11_index;
1192
1193         /* Pipeline stage 2 */
1194         lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1195                 bucket20, bucket21, pkts_mask_out, entries,
1196                 buckets_mask, buckets, keys, f);
1197
1198 grind_next_buckets:
1199         /* Grind next buckets */
1200         for ( ; buckets_mask; ) {
1201                 uint64_t buckets_mask_next = 0;
1202
1203                 for ( ; buckets_mask; ) {
1204                         uint64_t pkt_mask;
1205                         uint32_t pkt_index;
1206
1207                         pkt_index = __builtin_ctzll(buckets_mask);
1208                         pkt_mask = 1LLU << pkt_index;
1209                         buckets_mask &= ~pkt_mask;
1210
1211                         lookup_grinder(pkt_index, buckets, keys, pkts_mask_out,
1212                                 entries, buckets_mask_next, f);
1213                 }
1214
1215                 buckets_mask = buckets_mask_next;
1216         }
1217
1218         *lookup_hit_mask = pkts_mask_out;
1219         return 0;
1220 } /* rte_table_hash_lookup_key8_ext() */
1221
1222 static int
1223 rte_table_hash_lookup_key8_ext_dosig(
1224         void *table,
1225         struct rte_mbuf **pkts,
1226         uint64_t pkts_mask,
1227         uint64_t *lookup_hit_mask,
1228         void **entries)
1229 {
1230         struct rte_table_hash *f = (struct rte_table_hash *) table;
1231         struct rte_bucket_4_8 *bucket10, *bucket11, *bucket20, *bucket21;
1232         struct rte_mbuf *mbuf00, *mbuf01, *mbuf10, *mbuf11, *mbuf20, *mbuf21;
1233         uint32_t pkt00_index, pkt01_index, pkt10_index;
1234         uint32_t pkt11_index, pkt20_index, pkt21_index;
1235         uint64_t pkts_mask_out = 0, buckets_mask = 0;
1236         struct rte_bucket_4_8 *buckets[RTE_PORT_IN_BURST_SIZE_MAX];
1237         uint64_t *keys[RTE_PORT_IN_BURST_SIZE_MAX];
1238
1239         /* Cannot run the pipeline with less than 5 packets */
1240         if (__builtin_popcountll(pkts_mask) < 5) {
1241                 for ( ; pkts_mask; ) {
1242                         struct rte_bucket_4_8 *bucket;
1243                         struct rte_mbuf *mbuf;
1244                         uint32_t pkt_index;
1245
1246                         lookup1_stage0(pkt_index, mbuf, pkts, pkts_mask);
1247                         lookup1_stage1_dosig(mbuf, bucket, f);
1248                         lookup1_stage2_ext(pkt_index, mbuf, bucket,
1249                                 pkts_mask_out, entries, buckets_mask,
1250                                 buckets, keys, f);
1251                 }
1252
1253                 goto grind_next_buckets;
1254         }
1255
1256         /*
1257          * Pipeline fill
1258          *
1259          */
1260         /* Pipeline stage 0 */
1261         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
1262                 pkts_mask);
1263
1264         /* Pipeline feed */
1265         mbuf10 = mbuf00;
1266         mbuf11 = mbuf01;
1267         pkt10_index = pkt00_index;
1268         pkt11_index = pkt01_index;
1269
1270         /* Pipeline stage 0 */
1271         lookup2_stage0(pkt00_index, pkt01_index, mbuf00, mbuf01, pkts,
1272                 pkts_mask);
1273
1274         /* Pipeline stage 1 */
1275         lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1276
1277         /*
1278          * Pipeline run
1279          *
1280          */
1281         for ( ; pkts_mask; ) {
1282                 /* Pipeline feed */
1283                 bucket20 = bucket10;
1284                 bucket21 = bucket11;
1285                 mbuf20 = mbuf10;
1286                 mbuf21 = mbuf11;
1287                 mbuf10 = mbuf00;
1288                 mbuf11 = mbuf01;
1289                 pkt20_index = pkt10_index;
1290                 pkt21_index = pkt11_index;
1291                 pkt10_index = pkt00_index;
1292                 pkt11_index = pkt01_index;
1293
1294                 /* Pipeline stage 0 */
1295                 lookup2_stage0_with_odd_support(pkt00_index, pkt01_index,
1296                         mbuf00, mbuf01, pkts, pkts_mask);
1297
1298                 /* Pipeline stage 1 */
1299                 lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1300
1301                 /* Pipeline stage 2 */
1302                 lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1303                         bucket20, bucket21, pkts_mask_out, entries,
1304                         buckets_mask, buckets, keys, f);
1305         }
1306
1307         /*
1308          * Pipeline flush
1309          *
1310          */
1311         /* Pipeline feed */
1312         bucket20 = bucket10;
1313         bucket21 = bucket11;
1314         mbuf20 = mbuf10;
1315         mbuf21 = mbuf11;
1316         mbuf10 = mbuf00;
1317         mbuf11 = mbuf01;
1318         pkt20_index = pkt10_index;
1319         pkt21_index = pkt11_index;
1320         pkt10_index = pkt00_index;
1321         pkt11_index = pkt01_index;
1322
1323         /* Pipeline stage 1 */
1324         lookup2_stage1_dosig(mbuf10, mbuf11, bucket10, bucket11, f);
1325
1326         /* Pipeline stage 2 */
1327         lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1328                 bucket20, bucket21, pkts_mask_out, entries,
1329                 buckets_mask, buckets, keys, f);
1330
1331         /* Pipeline feed */
1332         bucket20 = bucket10;
1333         bucket21 = bucket11;
1334         mbuf20 = mbuf10;
1335         mbuf21 = mbuf11;
1336         pkt20_index = pkt10_index;
1337         pkt21_index = pkt11_index;
1338
1339         /* Pipeline stage 2 */
1340         lookup2_stage2_ext(pkt20_index, pkt21_index, mbuf20, mbuf21,
1341                 bucket20, bucket21, pkts_mask_out, entries,
1342                 buckets_mask, buckets, keys, f);
1343
1344 grind_next_buckets:
1345         /* Grind next buckets */
1346         for ( ; buckets_mask; ) {
1347                 uint64_t buckets_mask_next = 0;
1348
1349                 for ( ; buckets_mask; ) {
1350                         uint64_t pkt_mask;
1351                         uint32_t pkt_index;
1352
1353                         pkt_index = __builtin_ctzll(buckets_mask);
1354                         pkt_mask = 1LLU << pkt_index;
1355                         buckets_mask &= ~pkt_mask;
1356
1357                         lookup_grinder(pkt_index, buckets, keys, pkts_mask_out,
1358                                 entries, buckets_mask_next, f);
1359                 }
1360
1361                 buckets_mask = buckets_mask_next;
1362         }
1363
1364         *lookup_hit_mask = pkts_mask_out;
1365         return 0;
1366 } /* rte_table_hash_lookup_key8_dosig_ext() */
1367
1368 struct rte_table_ops rte_table_hash_key8_lru_ops = {
1369         .f_create = rte_table_hash_create_key8_lru,
1370         .f_free = rte_table_hash_free_key8_lru,
1371         .f_add = rte_table_hash_entry_add_key8_lru,
1372         .f_delete = rte_table_hash_entry_delete_key8_lru,
1373         .f_lookup = rte_table_hash_lookup_key8_lru,
1374 };
1375
1376 struct rte_table_ops rte_table_hash_key8_lru_dosig_ops = {
1377         .f_create = rte_table_hash_create_key8_lru,
1378         .f_free = rte_table_hash_free_key8_lru,
1379         .f_add = rte_table_hash_entry_add_key8_lru,
1380         .f_delete = rte_table_hash_entry_delete_key8_lru,
1381         .f_lookup = rte_table_hash_lookup_key8_lru_dosig,
1382 };
1383
1384 struct rte_table_ops rte_table_hash_key8_ext_ops = {
1385         .f_create = rte_table_hash_create_key8_ext,
1386         .f_free = rte_table_hash_free_key8_ext,
1387         .f_add = rte_table_hash_entry_add_key8_ext,
1388         .f_delete = rte_table_hash_entry_delete_key8_ext,
1389         .f_lookup = rte_table_hash_lookup_key8_ext,
1390 };
1391
1392 struct rte_table_ops rte_table_hash_key8_ext_dosig_ops = {
1393         .f_create = rte_table_hash_create_key8_ext,
1394         .f_free = rte_table_hash_free_key8_ext,
1395         .f_add = rte_table_hash_entry_add_key8_ext,
1396         .f_delete = rte_table_hash_entry_delete_key8_ext,
1397         .f_lookup = rte_table_hash_lookup_key8_ext_dosig,
1398 };