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