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