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