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