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