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