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