net/ice: fix perfect match for ACL rule
[dpdk.git] / app / test / test_table_tables.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <rte_byteorder.h>
7 #include <rte_table_lpm_ipv6.h>
8 #include <rte_lru.h>
9 #include <rte_cycles.h>
10 #include "test_table_tables.h"
11 #include "test_table.h"
12
13 table_test table_tests[] = {
14         test_table_stub,
15         test_table_array,
16         test_table_lpm,
17         test_table_lpm_ipv6,
18         test_table_hash_lru,
19         test_table_hash_ext,
20         test_table_hash_cuckoo,
21 };
22
23 #define PREPARE_PACKET(mbuf, value) do {                                \
24         uint32_t *k32, *signature;                                      \
25         uint8_t *key;                                                   \
26         mbuf = rte_pktmbuf_alloc(pool);                                 \
27         signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf,                  \
28                         APP_METADATA_OFFSET(0));                        \
29         key = RTE_MBUF_METADATA_UINT8_PTR(mbuf,                 \
30                         APP_METADATA_OFFSET(32));                       \
31         memset(key, 0, 32);                                             \
32         k32 = (uint32_t *) key;                                         \
33         k32[0] = (value);                                               \
34         *signature = pipeline_test_hash(key, NULL, 0, 0);                       \
35 } while (0)
36
37 unsigned n_table_tests = RTE_DIM(table_tests);
38
39 /* Function prototypes */
40 static int
41 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size);
42 static int
43 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size);
44
45 struct rte_bucket_4_8 {
46         /* Cache line 0 */
47         uint64_t signature;
48         uint64_t lru_list;
49         struct rte_bucket_4_8 *next;
50         uint64_t next_valid;
51         uint64_t key[4];
52         /* Cache line 1 */
53         uint8_t data[0];
54 };
55
56 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
57 uint64_t shuffles = 0xfffffffdfffbfff9ULL;
58 #else
59 uint64_t shuffles = 0x0003000200010000ULL;
60 #endif
61
62 static int test_lru_update(void)
63 {
64         struct rte_bucket_4_8 b;
65         struct rte_bucket_4_8 *bucket;
66         uint32_t i;
67         uint64_t pos;
68         uint64_t iterations;
69         uint64_t j;
70         int poss;
71
72         printf("---------------------------\n");
73         printf("Testing lru_update macro...\n");
74         printf("---------------------------\n");
75         bucket = &b;
76         iterations = 10;
77 #if RTE_TABLE_HASH_LRU_STRATEGY == 3
78         bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
79 #else
80         bucket->lru_list = 0x0000000100020003ULL;
81 #endif
82         poss = 0;
83         for (j = 0; j < iterations; j++)
84                 for (i = 0; i < 9; i++) {
85                         uint32_t idx = i >> 1;
86                         lru_update(bucket, idx);
87                         pos = lru_pos(bucket);
88                         poss += pos;
89                         printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
90                                 "pos=%"PRIx64"\n",
91                                 __func__, i, bucket->lru_list, i>>1, pos);
92                 }
93
94         if (bucket->lru_list != shuffles) {
95                 printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
96                         PRIx64"\n",
97                         __func__, i, bucket->lru_list, shuffles);
98                 return -1;
99         }
100         printf("%s: output checksum of results =%d\n",
101                 __func__, poss);
102 #if 0
103         if (poss != 126) {
104                 printf("%s: ERROR output checksum of results =%d expected %d\n",
105                         __func__, poss, 126);
106                 return -1;
107         }
108 #endif
109
110         fflush(stdout);
111
112         uint64_t sc_start = rte_rdtsc();
113         iterations = 100000000;
114         poss = 0;
115         for (j = 0; j < iterations; j++) {
116                 for (i = 0; i < 4; i++) {
117                         lru_update(bucket, i);
118                         pos |= bucket->lru_list;
119                 }
120         }
121         uint64_t sc_end = rte_rdtsc();
122
123         printf("%s: output checksum of results =%llu\n",
124                 __func__, (long long unsigned int)pos);
125         printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
126                 __func__, sc_start, sc_end);
127         printf("\nlru_update: %lu cycles per loop iteration.\n\n",
128                 (long unsigned int)((sc_end-sc_start)/(iterations*4)));
129
130         return 0;
131 }
132
133 /* Table tests */
134 int
135 test_table_stub(void)
136 {
137         int i;
138         uint64_t expected_mask = 0, result_mask;
139         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
140         void *table;
141         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
142
143         /* Create */
144         table = rte_table_stub_ops.f_create(NULL, 0, 1);
145         if (table == NULL)
146                 return -1;
147
148         /* Traffic flow */
149         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
150                 if (i % 2 == 0)
151                         PREPARE_PACKET(mbufs[i], 0xadadadad);
152                 else
153                         PREPARE_PACKET(mbufs[i], 0xadadadab);
154
155         expected_mask = 0;
156         rte_table_stub_ops.f_lookup(table, mbufs, -1,
157                 &result_mask, (void **)entries);
158         if (result_mask != expected_mask)
159                 return -2;
160
161         /* Free resources */
162         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
163                 rte_pktmbuf_free(mbufs[i]);
164
165         return 0;
166 }
167
168 int
169 test_table_array(void)
170 {
171         int status, i;
172         uint64_t result_mask;
173         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
174         void *table;
175         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
176         char entry1, entry2;
177         void *entry_ptr;
178         int key_found;
179
180         /* Initialize params and create tables */
181         struct rte_table_array_params array_params = {
182                 .n_entries = 7,
183                 .offset = APP_METADATA_OFFSET(1)
184         };
185
186         table = rte_table_array_ops.f_create(NULL, 0, 1);
187         if (table != NULL)
188                 return -1;
189
190         array_params.n_entries = 0;
191
192         table = rte_table_array_ops.f_create(&array_params, 0, 1);
193         if (table != NULL)
194                 return -2;
195
196         array_params.n_entries = 7;
197
198         table = rte_table_array_ops.f_create(&array_params, 0, 1);
199         if (table != NULL)
200                 return -3;
201
202         array_params.n_entries = 1 << 24;
203         array_params.offset = APP_METADATA_OFFSET(1);
204
205         table = rte_table_array_ops.f_create(&array_params, 0, 1);
206         if (table == NULL)
207                 return -4;
208
209         array_params.offset = APP_METADATA_OFFSET(32);
210
211         table = rte_table_array_ops.f_create(&array_params, 0, 1);
212         if (table == NULL)
213                 return -5;
214
215         /* Free */
216         status = rte_table_array_ops.f_free(table);
217         if (status < 0)
218                 return -6;
219
220         status = rte_table_array_ops.f_free(NULL);
221         if (status == 0)
222                 return -7;
223
224         /* Add */
225         struct rte_table_array_key array_key_1 = {
226                 .pos = 10,
227         };
228         struct rte_table_array_key array_key_2 = {
229                 .pos = 20,
230         };
231         entry1 = 'A';
232         entry2 = 'B';
233
234         table = rte_table_array_ops.f_create(&array_params, 0, 1);
235         if (table == NULL)
236                 return -8;
237
238         status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
239                 &key_found, &entry_ptr);
240         if (status == 0)
241                 return -9;
242
243         status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
244                 &key_found, &entry_ptr);
245         if (status == 0)
246                 return -10;
247
248         status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
249                 &entry1, &key_found, &entry_ptr);
250         if (status != 0)
251                 return -11;
252
253         /* Traffic flow */
254         status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
255                 &entry2, &key_found, &entry_ptr);
256         if (status != 0)
257                 return -12;
258
259         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
260                 if (i % 2 == 0)
261                         PREPARE_PACKET(mbufs[i], 10);
262                 else
263                         PREPARE_PACKET(mbufs[i], 20);
264
265         rte_table_array_ops.f_lookup(table, mbufs, -1,
266                 &result_mask, (void **)entries);
267
268         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
269                 if (i % 2 == 0 && *entries[i] != 'A')
270                         return -13;
271                 else
272                         if (i % 2 == 1 && *entries[i] != 'B')
273                                 return -13;
274
275         /* Free resources */
276         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
277                 rte_pktmbuf_free(mbufs[i]);
278
279         status = rte_table_array_ops.f_free(table);
280
281         return 0;
282 }
283
284 int
285 test_table_lpm(void)
286 {
287         int status, i;
288         uint64_t expected_mask = 0, result_mask;
289         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
290         void *table;
291         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
292         char entry;
293         void *entry_ptr;
294         int key_found;
295         uint32_t entry_size = 1;
296
297         /* Initialize params and create tables */
298         struct rte_table_lpm_params lpm_params = {
299                 .name = "LPM",
300                 .n_rules = 1 << 24,
301                 .number_tbl8s = 1 << 8,
302                 .flags = 0,
303                 .entry_unique_size = entry_size,
304                 .offset = APP_METADATA_OFFSET(1)
305         };
306
307         table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
308         if (table != NULL)
309                 return -1;
310
311         lpm_params.name = NULL;
312
313         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
314         if (table != NULL)
315                 return -2;
316
317         lpm_params.name = "LPM";
318         lpm_params.n_rules = 0;
319
320         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
321         if (table != NULL)
322                 return -3;
323
324         lpm_params.n_rules = 1 << 24;
325         lpm_params.offset = APP_METADATA_OFFSET(32);
326         lpm_params.entry_unique_size = 0;
327
328         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
329         if (table != NULL)
330                 return -4;
331
332         lpm_params.entry_unique_size = entry_size + 1;
333
334         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
335         if (table != NULL)
336                 return -5;
337
338         lpm_params.entry_unique_size = entry_size;
339
340         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
341         if (table == NULL)
342                 return -6;
343
344         /* Free */
345         status = rte_table_lpm_ops.f_free(table);
346         if (status < 0)
347                 return -7;
348
349         status = rte_table_lpm_ops.f_free(NULL);
350         if (status == 0)
351                 return -8;
352
353         /* Add */
354         struct rte_table_lpm_key lpm_key;
355         lpm_key.ip = 0xadadadad;
356
357         table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
358         if (table == NULL)
359                 return -9;
360
361         status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
362                 &entry_ptr);
363         if (status == 0)
364                 return -10;
365
366         status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
367                 &entry_ptr);
368         if (status == 0)
369                 return -11;
370
371         status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
372                 &entry_ptr);
373         if (status == 0)
374                 return -12;
375
376         lpm_key.depth = 0;
377         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
378                 &entry_ptr);
379         if (status == 0)
380                 return -13;
381
382         lpm_key.depth = 33;
383         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
384                 &entry_ptr);
385         if (status == 0)
386                 return -14;
387
388         lpm_key.depth = 16;
389         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
390                 &entry_ptr);
391         if (status != 0)
392                 return -15;
393
394         /* Delete */
395         status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
396         if (status == 0)
397                 return -16;
398
399         status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
400         if (status == 0)
401                 return -17;
402
403         lpm_key.depth = 0;
404         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
405         if (status == 0)
406                 return -18;
407
408         lpm_key.depth = 33;
409         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
410         if (status == 0)
411                 return -19;
412
413         lpm_key.depth = 16;
414         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
415         if (status != 0)
416                 return -20;
417
418         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
419         if (status != 0)
420                 return -21;
421
422         /* Traffic flow */
423         entry = 'A';
424         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
425                 &entry_ptr);
426         if (status < 0)
427                 return -22;
428
429         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
430                 if (i % 2 == 0) {
431                         expected_mask |= (uint64_t)1 << i;
432                         PREPARE_PACKET(mbufs[i], 0xadadadad);
433                 } else
434                         PREPARE_PACKET(mbufs[i], 0xadadadab);
435
436         rte_table_lpm_ops.f_lookup(table, mbufs, -1,
437                 &result_mask, (void **)entries);
438         if (result_mask != expected_mask)
439                 return -23;
440
441         /* Free resources */
442         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
443                 rte_pktmbuf_free(mbufs[i]);
444
445         status = rte_table_lpm_ops.f_free(table);
446
447         return 0;
448 }
449
450 int
451 test_table_lpm_ipv6(void)
452 {
453         int status, i;
454         uint64_t expected_mask = 0, result_mask;
455         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
456         void *table;
457         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
458         char entry;
459         void *entry_ptr;
460         int key_found;
461         uint32_t entry_size = 1;
462
463         /* Initialize params and create tables */
464         struct rte_table_lpm_ipv6_params lpm_params = {
465                 .name = "LPM",
466                 .n_rules = 1 << 24,
467                 .number_tbl8s = 1 << 18,
468                 .entry_unique_size = entry_size,
469                 .offset = APP_METADATA_OFFSET(32)
470         };
471
472         table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
473         if (table != NULL)
474                 return -1;
475
476         lpm_params.name = NULL;
477
478         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
479         if (table != NULL)
480                 return -2;
481
482         lpm_params.name = "LPM";
483         lpm_params.n_rules = 0;
484
485         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
486         if (table != NULL)
487                 return -3;
488
489         lpm_params.n_rules = 1 << 24;
490         lpm_params.number_tbl8s = 0;
491         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
492         if (table != NULL)
493                 return -4;
494
495         lpm_params.number_tbl8s = 1 << 18;
496         lpm_params.entry_unique_size = 0;
497         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
498         if (table != NULL)
499                 return -5;
500
501         lpm_params.entry_unique_size = entry_size + 1;
502         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
503         if (table != NULL)
504                 return -6;
505
506         lpm_params.entry_unique_size = entry_size;
507         lpm_params.offset = APP_METADATA_OFFSET(32);
508
509         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
510         if (table == NULL)
511                 return -7;
512
513         /* Free */
514         status = rte_table_lpm_ipv6_ops.f_free(table);
515         if (status < 0)
516                 return -8;
517
518         status = rte_table_lpm_ipv6_ops.f_free(NULL);
519         if (status == 0)
520                 return -9;
521
522         /* Add */
523         struct rte_table_lpm_ipv6_key lpm_key;
524
525         lpm_key.ip[0] = 0xad;
526         lpm_key.ip[1] = 0xad;
527         lpm_key.ip[2] = 0xad;
528         lpm_key.ip[3] = 0xad;
529
530         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
531         if (table == NULL)
532                 return -10;
533
534         status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
535                 &key_found, &entry_ptr);
536         if (status == 0)
537                 return -11;
538
539         status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
540                 &entry_ptr);
541         if (status == 0)
542                 return -12;
543
544         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
545                 &entry_ptr);
546         if (status == 0)
547                 return -13;
548
549         lpm_key.depth = 0;
550         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
551                 &key_found, &entry_ptr);
552         if (status == 0)
553                 return -14;
554
555         lpm_key.depth = 129;
556         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
557                 &key_found, &entry_ptr);
558         if (status == 0)
559                 return -15;
560
561         lpm_key.depth = 16;
562         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
563                 &key_found, &entry_ptr);
564         if (status != 0)
565                 return -16;
566
567         /* Delete */
568         status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
569                 NULL);
570         if (status == 0)
571                 return -17;
572
573         status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
574         if (status == 0)
575                 return -18;
576
577         lpm_key.depth = 0;
578         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
579                 NULL);
580         if (status == 0)
581                 return -19;
582
583         lpm_key.depth = 129;
584         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
585                 NULL);
586         if (status == 0)
587                 return -20;
588
589         lpm_key.depth = 16;
590         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
591                 NULL);
592         if (status != 0)
593                 return -21;
594
595         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
596                 NULL);
597         if (status != 0)
598                 return -22;
599
600         /* Traffic flow */
601         entry = 'A';
602         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
603                 &key_found, &entry_ptr);
604         if (status < 0)
605                 return -23;
606
607         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
608                 if (i % 2 == 0) {
609                         expected_mask |= (uint64_t)1 << i;
610                         PREPARE_PACKET(mbufs[i], 0xadadadad);
611                 } else
612                         PREPARE_PACKET(mbufs[i], 0xadadadab);
613
614         rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
615                 &result_mask, (void **)entries);
616         if (result_mask != expected_mask)
617                 return -24;
618
619         /* Free resources */
620         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
621                 rte_pktmbuf_free(mbufs[i]);
622
623         status = rte_table_lpm_ipv6_ops.f_free(table);
624
625         return 0;
626 }
627
628 static int
629 test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
630 {
631         int status, i;
632         uint64_t expected_mask = 0, result_mask;
633         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
634         void *table;
635         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
636         char entry;
637         void *entry_ptr;
638         int key_found;
639
640         /* Initialize params and create tables */
641         struct rte_table_hash_params hash_params = {
642                 .name = "TABLE",
643                 .key_size = key_size,
644                 .key_offset = APP_METADATA_OFFSET(32),
645                 .key_mask = NULL,
646                 .n_keys = 1 << 10,
647                 .n_buckets = 1 << 10,
648                 .f_hash = pipeline_test_hash,
649                 .seed = 0,
650         };
651
652         hash_params.n_keys = 0;
653
654         table = ops->f_create(&hash_params, 0, 1);
655         if (table != NULL)
656                 return -1;
657
658         hash_params.n_keys = 1 << 10;
659         hash_params.f_hash = NULL;
660
661         table = ops->f_create(&hash_params, 0, 1);
662         if (table != NULL)
663                 return -4;
664
665         hash_params.f_hash = pipeline_test_hash;
666
667         table = ops->f_create(&hash_params, 0, 1);
668         if (table == NULL)
669                 return -5;
670
671         /* Free */
672         status = ops->f_free(table);
673         if (status < 0)
674                 return -6;
675
676         status = ops->f_free(NULL);
677         if (status == 0)
678                 return -7;
679
680         /* Add */
681         uint8_t key[32];
682         uint32_t *k32 = (uint32_t *) &key;
683
684         memset(key, 0, 32);
685         k32[0] = rte_be_to_cpu_32(0xadadadad);
686
687         table = ops->f_create(&hash_params, 0, 1);
688         if (table == NULL)
689                 return -8;
690
691         entry = 'A';
692         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
693         if (status != 0)
694                 return -9;
695
696         /* Delete */
697         status = ops->f_delete(table, &key, &key_found, NULL);
698         if (status != 0)
699                 return -10;
700
701         status = ops->f_delete(table, &key, &key_found, NULL);
702         if (status != 0)
703                 return -11;
704
705         /* Traffic flow */
706         entry = 'A';
707         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
708         if (status < 0)
709                 return -12;
710
711         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
712                 if (i % 2 == 0) {
713                         expected_mask |= (uint64_t)1 << i;
714                         PREPARE_PACKET(mbufs[i], 0xadadadad);
715                 } else
716                         PREPARE_PACKET(mbufs[i], 0xadadadab);
717
718         ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
719         if (result_mask != expected_mask)
720                 return -13;
721
722         /* Free resources */
723         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
724                 rte_pktmbuf_free(mbufs[i]);
725
726         status = ops->f_free(table);
727
728         return 0;
729 }
730
731 static int
732 test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
733 {
734         int status, i;
735         uint64_t expected_mask = 0, result_mask;
736         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
737         void *table;
738         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
739         char entry;
740         int key_found;
741         void *entry_ptr;
742
743         /* Initialize params and create tables */
744         struct rte_table_hash_params hash_params = {
745                 .name = "TABLE",
746                 .key_size = key_size,
747                 .key_offset = APP_METADATA_OFFSET(32),
748                 .key_mask = NULL,
749                 .n_keys = 1 << 10,
750                 .n_buckets = 1 << 10,
751                 .f_hash = pipeline_test_hash,
752                 .seed = 0,
753         };
754
755         hash_params.n_keys = 0;
756
757         table = ops->f_create(&hash_params, 0, 1);
758         if (table != NULL)
759                 return -1;
760
761         hash_params.n_keys = 1 << 10;
762         hash_params.key_offset = APP_METADATA_OFFSET(1);
763
764         table = ops->f_create(&hash_params, 0, 1);
765         if (table == NULL)
766                 return -3;
767
768         hash_params.key_offset = APP_METADATA_OFFSET(32);
769         hash_params.f_hash = NULL;
770
771         table = ops->f_create(&hash_params, 0, 1);
772         if (table != NULL)
773                 return -4;
774
775         hash_params.f_hash = pipeline_test_hash;
776
777         table = ops->f_create(&hash_params, 0, 1);
778         if (table == NULL)
779                 return -5;
780
781         /* Free */
782         status = ops->f_free(table);
783         if (status < 0)
784                 return -6;
785
786         status = ops->f_free(NULL);
787         if (status == 0)
788                 return -7;
789
790         /* Add */
791         uint8_t key[32];
792         uint32_t *k32 = (uint32_t *) &key;
793
794         memset(key, 0, 32);
795         k32[0] = rte_be_to_cpu_32(0xadadadad);
796
797         table = ops->f_create(&hash_params, 0, 1);
798         if (table == NULL)
799                 return -8;
800
801         entry = 'A';
802         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
803         if (status != 0)
804                 return -9;
805
806         /* Delete */
807         status = ops->f_delete(table, &key, &key_found, NULL);
808         if (status != 0)
809                 return -10;
810
811         status = ops->f_delete(table, &key, &key_found, NULL);
812         if (status != 0)
813                 return -11;
814
815         /* Traffic flow */
816         entry = 'A';
817         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
818         if (status < 0)
819                 return -12;
820
821         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
822                 if (i % 2 == 0) {
823                         expected_mask |= (uint64_t)1 << i;
824                         PREPARE_PACKET(mbufs[i], 0xadadadad);
825                 } else
826                         PREPARE_PACKET(mbufs[i], 0xadadadab);
827
828         ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
829         if (result_mask != expected_mask)
830                 return -13;
831
832         /* Free resources */
833         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
834                 rte_pktmbuf_free(mbufs[i]);
835
836         status = ops->f_free(table);
837
838         return 0;
839 }
840
841 int
842 test_table_hash_lru(void)
843 {
844         int status;
845
846         status = test_table_hash_lru_generic(
847                 &rte_table_hash_key8_lru_ops,
848                 8);
849         if (status < 0)
850                 return status;
851
852         status = test_table_hash_lru_generic(
853                 &rte_table_hash_key16_lru_ops,
854                 16);
855         if (status < 0)
856                 return status;
857
858         status = test_table_hash_lru_generic(
859                 &rte_table_hash_key32_lru_ops,
860                 32);
861         if (status < 0)
862                 return status;
863
864         status = test_lru_update();
865         if (status < 0)
866                 return status;
867
868         return 0;
869 }
870
871 int
872 test_table_hash_ext(void)
873 {
874         int status;
875
876         status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops, 8);
877         if (status < 0)
878                 return status;
879
880         status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops, 16);
881         if (status < 0)
882                 return status;
883
884         status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops, 32);
885         if (status < 0)
886                 return status;
887
888         return 0;
889 }
890
891
892 int
893 test_table_hash_cuckoo(void)
894 {
895         int status, i;
896         uint64_t expected_mask = 0, result_mask;
897         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
898         void *table;
899         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
900         char entry;
901         void *entry_ptr;
902         int key_found;
903         uint32_t entry_size = 1;
904
905         /* Initialize params and create tables */
906         struct rte_table_hash_cuckoo_params cuckoo_params = {
907                 .name = "TABLE",
908                 .key_size = 32,
909                 .key_offset = APP_METADATA_OFFSET(32),
910                 .key_mask = NULL,
911                 .n_keys = 1 << 16,
912                 .n_buckets = 1 << 16,
913                 .f_hash = pipeline_test_hash_cuckoo,
914                 .seed = 0,
915         };
916
917         table = rte_table_hash_cuckoo_ops.f_create(NULL, 0, entry_size);
918         if (table != NULL)
919                 return -1;
920
921         cuckoo_params.key_size = 0;
922
923         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
924                 0, entry_size);
925         if (table != NULL)
926                 return -2;
927
928         cuckoo_params.key_size = 32;
929         cuckoo_params.n_keys = 0;
930
931         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
932                 0, entry_size);
933         if (table != NULL)
934                 return -3;
935
936         cuckoo_params.n_keys = 1 << 24;
937         cuckoo_params.f_hash = NULL;
938
939         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
940                 0, entry_size);
941         if (table != NULL)
942                 return -4;
943
944         cuckoo_params.f_hash = pipeline_test_hash_cuckoo;
945         cuckoo_params.name = NULL;
946
947         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
948                 0, entry_size);
949         if (table != NULL)
950                 return -5;
951
952         cuckoo_params.name = "CUCKOO";
953
954         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params,
955                 0, entry_size);
956         if (table == NULL)
957                 return -6;
958
959         /* Free */
960         status = rte_table_hash_cuckoo_ops.f_free(table);
961         if (status < 0)
962                 return -7;
963
964         status = rte_table_hash_cuckoo_ops.f_free(NULL);
965         if (status == 0)
966                 return -8;
967
968         /* Add */
969         uint8_t key_cuckoo[32];
970         uint32_t *kcuckoo = (uint32_t *) &key_cuckoo;
971
972         memset(key_cuckoo, 0, 32);
973         kcuckoo[0] = rte_be_to_cpu_32(0xadadadad);
974
975         table = rte_table_hash_cuckoo_ops.f_create(&cuckoo_params, 0, 1);
976         if (table == NULL)
977                 return -9;
978
979         entry = 'A';
980         status = rte_table_hash_cuckoo_ops.f_add(NULL, &key_cuckoo,
981                 &entry, &key_found, &entry_ptr);
982         if (status == 0)
983                 return -10;
984
985         status = rte_table_hash_cuckoo_ops.f_add(table, NULL, &entry,
986                 &key_found, &entry_ptr);
987         if (status == 0)
988                 return -11;
989
990         status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
991                 NULL, &key_found, &entry_ptr);
992         if (status == 0)
993                 return -12;
994
995         status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
996                 &entry, &key_found, &entry_ptr);
997         if (status != 0)
998                 return -13;
999
1000         status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1001                 &entry, &key_found, &entry_ptr);
1002         if (status != 0)
1003                 return -14;
1004
1005         /* Delete */
1006         status = rte_table_hash_cuckoo_ops.f_delete(NULL, &key_cuckoo,
1007                 &key_found, NULL);
1008         if (status == 0)
1009                 return -15;
1010
1011         status = rte_table_hash_cuckoo_ops.f_delete(table, NULL,
1012                 &key_found, NULL);
1013         if (status == 0)
1014                 return -16;
1015
1016         status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1017                 &key_found, NULL);
1018         if (status != 0)
1019                 return -17;
1020
1021         status = rte_table_hash_cuckoo_ops.f_delete(table, &key_cuckoo,
1022                 &key_found, NULL);
1023         if (status != -ENOENT)
1024                 return -18;
1025
1026         /* Traffic flow */
1027         entry = 'A';
1028         status = rte_table_hash_cuckoo_ops.f_add(table, &key_cuckoo,
1029                 &entry, &key_found,
1030                 &entry_ptr);
1031         if (status < 0)
1032                 return -19;
1033
1034         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1035                 if (i % 2 == 0) {
1036                         expected_mask |= (uint64_t)1 << i;
1037                         PREPARE_PACKET(mbufs[i], 0xadadadad);
1038                 } else
1039                         PREPARE_PACKET(mbufs[i], 0xadadadab);
1040
1041         rte_table_hash_cuckoo_ops.f_lookup(table, mbufs, -1,
1042                 &result_mask, (void **)entries);
1043         if (result_mask != expected_mask)
1044                 return -20;
1045
1046         /* Free resources */
1047         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
1048                 rte_pktmbuf_free(mbufs[i]);
1049
1050         status = rte_table_hash_cuckoo_ops.f_free(table);
1051
1052         return 0;
1053 }