xref: /dpdk/app/test/test_table_tables.c (revision cf435a07)
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 
1110