app/test: packet framework unit tests
[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 #ifdef RTE_LIBRTE_TABLE
35
36 #include <string.h>
37 #include <rte_byteorder.h>
38 #include <rte_table_lpm_ipv6.h>
39 #include <rte_lru.h>
40 #include <rte_cycles.h>
41 #include "test_table_tables.h"
42 #include "test_table.h"
43
44 table_test table_tests[] = {
45         test_table_stub,
46         test_table_array,
47         test_table_lpm,
48         test_table_lpm_ipv6,
49         test_table_hash_lru,
50         test_table_hash_ext,
51 };
52
53 #define PREPARE_PACKET(mbuf, value) do {                                \
54         uint32_t *k32, *signature;                                      \
55         uint8_t *key;                                                   \
56         mbuf = rte_pktmbuf_alloc(pool);                                 \
57         signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, 0);              \
58         key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, 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         /* Create */
209         struct rte_table_array_params array_params;
210
211         table = rte_table_array_ops.f_create(NULL, 0, 1);
212         if (table != NULL)
213                 return -1;
214
215         array_params.n_entries = 0;
216
217         table = rte_table_array_ops.f_create(&array_params, 0, 1);
218         if (table != NULL)
219                 return -2;
220
221         array_params.n_entries = 7;
222
223         table = rte_table_array_ops.f_create(&array_params, 0, 1);
224         if (table != NULL)
225                 return -3;
226
227         array_params.n_entries = 1 << 24;
228         array_params.offset = 1;
229
230         table = rte_table_array_ops.f_create(&array_params, 0, 1);
231         if (table != NULL)
232                 return -4;
233
234         array_params.offset = 32;
235
236         table = rte_table_array_ops.f_create(&array_params, 0, 1);
237         if (table == NULL)
238                 return -5;
239
240         /* Free */
241         status = rte_table_array_ops.f_free(table);
242         if (status < 0)
243                 return -6;
244
245         status = rte_table_array_ops.f_free(NULL);
246         if (status == 0)
247                 return -7;
248
249         /* Add */
250         struct rte_table_array_key array_key_1 = {
251                 .pos = 10,
252         };
253         struct rte_table_array_key array_key_2 = {
254                 .pos = 20,
255         };
256         entry1 = 'A';
257         entry2 = 'B';
258
259         table = rte_table_array_ops.f_create(&array_params, 0, 1);
260         if (table == NULL)
261                 return -8;
262
263         status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
264                 &key_found, &entry_ptr);
265         if (status == 0)
266                 return -9;
267
268         status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
269                 &key_found, &entry_ptr);
270         if (status == 0)
271                 return -10;
272
273         status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
274                 &entry1, &key_found, &entry_ptr);
275         if (status != 0)
276                 return -11;
277
278         /* Traffic flow */
279         status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
280                 &entry2, &key_found, &entry_ptr);
281         if (status != 0)
282                 return -12;
283
284         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
285                 if (i % 2 == 0)
286                         PREPARE_PACKET(mbufs[i], 10);
287                 else
288                         PREPARE_PACKET(mbufs[i], 20);
289
290         rte_table_array_ops.f_lookup(table, mbufs, -1,
291                 &result_mask, (void **)entries);
292
293         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
294                 if (i % 2 == 0 && *entries[i] != 'A')
295                         return -13;
296                 else
297                         if (i % 2 == 1 && *entries[i] != 'B')
298                                 return -13;
299
300         /* Free resources */
301         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
302                 rte_pktmbuf_free(mbufs[i]);
303
304         status = rte_table_array_ops.f_free(table);
305
306         return 0;
307 }
308
309 int
310 test_table_lpm(void)
311 {
312         int status, i;
313         uint64_t expected_mask = 0, result_mask;
314         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
315         void *table;
316         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
317         char entry;
318         void *entry_ptr;
319         int key_found;
320         uint32_t entry_size = 1;
321
322         /* Create */
323         struct rte_table_lpm_params lpm_params;
324
325         table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
326         if (table != NULL)
327                 return -1;
328
329         lpm_params.n_rules = 0;
330
331         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
332         if (table != NULL)
333                 return -2;
334
335         lpm_params.n_rules = 1 << 24;
336         lpm_params.offset = 1;
337
338         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
339         if (table != NULL)
340                 return -3;
341
342         lpm_params.offset = 32;
343         lpm_params.entry_unique_size = 0;
344
345         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
346         if (table != NULL)
347                 return -4;
348
349         lpm_params.entry_unique_size = entry_size + 1;
350
351         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
352         if (table != NULL)
353                 return -5;
354
355         lpm_params.entry_unique_size = entry_size;
356
357         table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
358         if (table == NULL)
359                 return -6;
360
361         /* Free */
362         status = rte_table_lpm_ops.f_free(table);
363         if (status < 0)
364                 return -7;
365
366         status = rte_table_lpm_ops.f_free(NULL);
367         if (status == 0)
368                 return -8;
369
370         /* Add */
371         struct rte_table_lpm_key lpm_key;
372         lpm_key.ip = 0xadadadad;
373
374         table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
375         if (table == NULL)
376                 return -9;
377
378         status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
379                 &entry_ptr);
380         if (status == 0)
381                 return -10;
382
383         status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
384                 &entry_ptr);
385         if (status == 0)
386                 return -11;
387
388         status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
389                 &entry_ptr);
390         if (status == 0)
391                 return -12;
392
393         lpm_key.depth = 0;
394         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
395                 &entry_ptr);
396         if (status == 0)
397                 return -13;
398
399         lpm_key.depth = 33;
400         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
401                 &entry_ptr);
402         if (status == 0)
403                 return -14;
404
405         lpm_key.depth = 16;
406         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
407                 &entry_ptr);
408         if (status != 0)
409                 return -15;
410
411         /* Delete */
412         status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
413         if (status == 0)
414                 return -16;
415
416         status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
417         if (status == 0)
418                 return -17;
419
420         lpm_key.depth = 0;
421         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
422         if (status == 0)
423                 return -18;
424
425         lpm_key.depth = 33;
426         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
427         if (status == 0)
428                 return -19;
429
430         lpm_key.depth = 16;
431         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
432         if (status != 0)
433                 return -20;
434
435         status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
436         if (status != 0)
437                 return -21;
438
439         /* Traffic flow */
440         entry = 'A';
441         status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
442                 &entry_ptr);
443         if (status < 0)
444                 return -22;
445
446         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
447                 if (i % 2 == 0) {
448                         expected_mask |= (uint64_t)1 << i;
449                         PREPARE_PACKET(mbufs[i], 0xadadadad);
450                 } else
451                         PREPARE_PACKET(mbufs[i], 0xadadadab);
452
453         rte_table_lpm_ops.f_lookup(table, mbufs, -1,
454                 &result_mask, (void **)entries);
455         if (result_mask != expected_mask)
456                 return -21;
457
458         /* Free resources */
459         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
460                 rte_pktmbuf_free(mbufs[i]);
461
462         status = rte_table_lpm_ops.f_free(table);
463
464         return 0;
465 }
466
467 int
468 test_table_lpm_ipv6(void)
469 {
470         int status, i;
471         uint64_t expected_mask = 0, result_mask;
472         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
473         void *table;
474         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
475         char entry;
476         void *entry_ptr;
477         int key_found;
478         uint32_t entry_size = 1;
479
480         /* Create */
481         struct rte_table_lpm_ipv6_params lpm_params;
482
483         table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
484         if (table != NULL)
485                 return -1;
486
487         lpm_params.n_rules = 0;
488
489         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
490         if (table != NULL)
491                 return -2;
492
493         lpm_params.n_rules = 1 << 24;
494         lpm_params.number_tbl8s = 0;
495         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
496         if (table != NULL)
497                 return -2;
498
499         lpm_params.number_tbl8s = 1 << 21;
500         lpm_params.entry_unique_size = 0;
501         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
502         if (table != NULL)
503                 return -2;
504
505         lpm_params.entry_unique_size = entry_size + 1;
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.entry_unique_size = entry_size;
511         lpm_params.offset = 32;
512
513         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
514         if (table == NULL)
515                 return -3;
516
517         /* Free */
518         status = rte_table_lpm_ipv6_ops.f_free(table);
519         if (status < 0)
520                 return -4;
521
522         status = rte_table_lpm_ipv6_ops.f_free(NULL);
523         if (status == 0)
524                 return -5;
525
526         /* Add */
527         struct rte_table_lpm_ipv6_key lpm_key;
528
529         lpm_key.ip[0] = 0xad;
530         lpm_key.ip[1] = 0xad;
531         lpm_key.ip[2] = 0xad;
532         lpm_key.ip[3] = 0xad;
533
534         table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
535         if (table == NULL)
536                 return -6;
537
538         status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
539                 &key_found, &entry_ptr);
540         if (status == 0)
541                 return -7;
542
543         status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
544                 &entry_ptr);
545         if (status == 0)
546                 return -8;
547
548         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
549                 &entry_ptr);
550         if (status == 0)
551                 return -9;
552
553         lpm_key.depth = 0;
554         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
555                 &key_found, &entry_ptr);
556         if (status == 0)
557                 return -10;
558
559         lpm_key.depth = 129;
560         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
561                 &key_found, &entry_ptr);
562         if (status == 0)
563                 return -11;
564
565         lpm_key.depth = 16;
566         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
567                 &key_found, &entry_ptr);
568         if (status != 0)
569                 return -12;
570
571         /* Delete */
572         status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
573                 NULL);
574         if (status == 0)
575                 return -13;
576
577         status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
578         if (status == 0)
579                 return -14;
580
581         lpm_key.depth = 0;
582         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
583                 NULL);
584         if (status == 0)
585                 return -15;
586
587         lpm_key.depth = 129;
588         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
589                 NULL);
590         if (status == 0)
591                 return -16;
592
593         lpm_key.depth = 16;
594         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
595                 NULL);
596         if (status != 0)
597                 return -17;
598
599         status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
600                 NULL);
601         if (status != 0)
602                 return -18;
603
604         /* Traffic flow */
605         entry = 'A';
606         status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
607                 &key_found, &entry_ptr);
608         if (status < 0)
609                 return -19;
610
611         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
612                 if (i % 2 == 0) {
613                         expected_mask |= (uint64_t)1 << i;
614                         PREPARE_PACKET(mbufs[i], 0xadadadad);
615                 } else
616                         PREPARE_PACKET(mbufs[i], 0xadadadab);
617
618         rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
619                 &result_mask, (void **)entries);
620         if (result_mask != expected_mask)
621                 return -20;
622
623         /* Free resources */
624         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
625                 rte_pktmbuf_free(mbufs[i]);
626
627         status = rte_table_lpm_ipv6_ops.f_free(table);
628
629         return 0;
630 }
631
632 static int
633 test_table_hash_lru_generic(struct rte_table_ops *ops)
634 {
635         int status, i;
636         uint64_t expected_mask = 0, result_mask;
637         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
638         void *table;
639         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
640         char entry;
641         void *entry_ptr;
642         int key_found;
643
644         /* Create */
645         struct rte_table_hash_key8_lru_params hash_params;
646
647         hash_params.n_entries = 0;
648
649         table = ops->f_create(&hash_params, 0, 1);
650         if (table != NULL)
651                 return -1;
652
653         hash_params.n_entries = 1 << 10;
654         hash_params.signature_offset = 1;
655
656         table = ops->f_create(&hash_params, 0, 1);
657         if (table != NULL)
658                 return -2;
659
660         hash_params.signature_offset = 0;
661         hash_params.key_offset = 1;
662
663         table = ops->f_create(&hash_params, 0, 1);
664         if (table != NULL)
665                 return -3;
666
667         hash_params.key_offset = 32;
668         hash_params.f_hash = NULL;
669
670         table = ops->f_create(&hash_params, 0, 1);
671         if (table != NULL)
672                 return -4;
673
674         hash_params.f_hash = pipeline_test_hash;
675
676         table = ops->f_create(&hash_params, 0, 1);
677         if (table == NULL)
678                 return -5;
679
680         /* Free */
681         status = ops->f_free(table);
682         if (status < 0)
683                 return -6;
684
685         status = ops->f_free(NULL);
686         if (status == 0)
687                 return -7;
688
689         /* Add */
690         uint8_t key[32];
691         uint32_t *k32 = (uint32_t *) &key;
692
693         memset(key, 0, 32);
694         k32[0] = rte_be_to_cpu_32(0xadadadad);
695
696         table = ops->f_create(&hash_params, 0, 1);
697         if (table == NULL)
698                 return -8;
699
700         entry = 'A';
701         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
702         if (status != 0)
703                 return -9;
704
705         /* Delete */
706         status = ops->f_delete(table, &key, &key_found, NULL);
707         if (status != 0)
708                 return -10;
709
710         status = ops->f_delete(table, &key, &key_found, NULL);
711         if (status != 0)
712                 return -11;
713
714         /* Traffic flow */
715         entry = 'A';
716         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
717         if (status < 0)
718                 return -12;
719
720         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
721                 if (i % 2 == 0) {
722                         expected_mask |= (uint64_t)1 << i;
723                         PREPARE_PACKET(mbufs[i], 0xadadadad);
724                 } else
725                         PREPARE_PACKET(mbufs[i], 0xadadadab);
726
727         ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
728         if (result_mask != expected_mask)
729                 return -13;
730
731         /* Free resources */
732         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
733                 rte_pktmbuf_free(mbufs[i]);
734
735         status = ops->f_free(table);
736
737         return 0;
738 }
739
740 static int
741 test_table_hash_ext_generic(struct rte_table_ops *ops)
742 {
743         int status, i;
744         uint64_t expected_mask = 0, result_mask;
745         struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
746         void *table;
747         char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
748         char entry;
749         int key_found;
750         void *entry_ptr;
751
752         /* Create */
753         struct rte_table_hash_key8_ext_params hash_params;
754
755         hash_params.n_entries = 0;
756
757         table = ops->f_create(&hash_params, 0, 1);
758         if (table != NULL)
759                 return -1;
760
761         hash_params.n_entries = 1 << 10;
762         hash_params.n_entries_ext = 0;
763         table = ops->f_create(&hash_params, 0, 1);
764         if (table != NULL)
765                 return -2;
766
767         hash_params.n_entries_ext = 1 << 4;
768         hash_params.signature_offset = 1;
769         table = ops->f_create(&hash_params, 0, 1);
770         if (table != NULL)
771                 return -2;
772
773         hash_params.signature_offset = 0;
774         hash_params.key_offset = 1;
775
776         table = ops->f_create(&hash_params, 0, 1);
777         if (table != NULL)
778                 return -3;
779
780         hash_params.key_offset = 32;
781         hash_params.f_hash = NULL;
782
783         table = ops->f_create(&hash_params, 0, 1);
784         if (table != NULL)
785                 return -4;
786
787         hash_params.f_hash = pipeline_test_hash;
788
789         table = ops->f_create(&hash_params, 0, 1);
790         if (table == NULL)
791                 return -5;
792
793         /* Free */
794         status = ops->f_free(table);
795         if (status < 0)
796                 return -6;
797
798         status = ops->f_free(NULL);
799         if (status == 0)
800                 return -7;
801
802         /* Add */
803         uint8_t key[32];
804         uint32_t *k32 = (uint32_t *) &key;
805
806         memset(key, 0, 32);
807         k32[0] = rte_be_to_cpu_32(0xadadadad);
808
809         table = ops->f_create(&hash_params, 0, 1);
810         if (table == NULL)
811                 return -8;
812
813         entry = 'A';
814         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
815         if (status != 0)
816                 return -9;
817
818         /* Delete */
819         status = ops->f_delete(table, &key, &key_found, NULL);
820         if (status != 0)
821                 return -10;
822
823         status = ops->f_delete(table, &key, &key_found, NULL);
824         if (status != 0)
825                 return -11;
826
827         /* Traffic flow */
828         entry = 'A';
829         status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
830         if (status < 0)
831                 return -12;
832
833         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
834                 if (i % 2 == 0) {
835                         expected_mask |= (uint64_t)1 << i;
836                         PREPARE_PACKET(mbufs[i], 0xadadadad);
837                 } else
838                         PREPARE_PACKET(mbufs[i], 0xadadadab);
839
840         ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
841         if (result_mask != expected_mask)
842                 return -13;
843
844         /* Free resources */
845         for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
846                 rte_pktmbuf_free(mbufs[i]);
847
848         status = ops->f_free(table);
849
850         return 0;
851 }
852
853 int
854 test_table_hash_lru(void)
855 {
856         int status;
857
858         status = test_table_hash_lru_generic(&rte_table_hash_key8_lru_ops);
859         if (status < 0)
860                 return status;
861
862         status = test_table_hash_lru_generic(
863                 &rte_table_hash_key8_lru_dosig_ops);
864         if (status < 0)
865                 return status;
866
867         status = test_table_hash_lru_generic(&rte_table_hash_key16_lru_ops);
868         if (status < 0)
869                 return status;
870
871         status = test_table_hash_lru_generic(&rte_table_hash_key32_lru_ops);
872         if (status < 0)
873                 return status;
874
875         status = test_lru_update();
876         if (status < 0)
877                 return status;
878
879         return 0;
880 }
881
882 int
883 test_table_hash_ext(void)
884 {
885         int status;
886
887         status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops);
888         if (status < 0)
889                 return status;
890
891         status = test_table_hash_ext_generic(
892                 &rte_table_hash_key8_ext_dosig_ops);
893         if (status < 0)
894                 return status;
895
896         status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops);
897         if (status < 0)
898                 return status;
899
900         status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops);
901         if (status < 0)
902                 return status;
903
904         return 0;
905 }
906
907 #endif