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