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