xref: /f-stack/dpdk/app/test/test_lpm.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2014 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <stdio.h>
64418919fSjohnjiang #include <stdint.h>
74418919fSjohnjiang #include <stdlib.h>
84418919fSjohnjiang 
94418919fSjohnjiang #include <rte_ip.h>
104418919fSjohnjiang #include <rte_lpm.h>
11*2d9fd380Sjfb8856606 #include <rte_malloc.h>
124418919fSjohnjiang 
134418919fSjohnjiang #include "test.h"
144418919fSjohnjiang #include "test_xmmt_ops.h"
154418919fSjohnjiang 
164418919fSjohnjiang #define TEST_LPM_ASSERT(cond) do {                                            \
174418919fSjohnjiang 	if (!(cond)) {                                                        \
184418919fSjohnjiang 		printf("Error at line %d: \n", __LINE__);                     \
194418919fSjohnjiang 		return -1;                                                    \
204418919fSjohnjiang 	}                                                                     \
214418919fSjohnjiang } while(0)
224418919fSjohnjiang 
234418919fSjohnjiang typedef int32_t (*rte_lpm_test)(void);
244418919fSjohnjiang 
254418919fSjohnjiang static int32_t test0(void);
264418919fSjohnjiang static int32_t test1(void);
274418919fSjohnjiang static int32_t test2(void);
284418919fSjohnjiang static int32_t test3(void);
294418919fSjohnjiang static int32_t test4(void);
304418919fSjohnjiang static int32_t test5(void);
314418919fSjohnjiang static int32_t test6(void);
324418919fSjohnjiang static int32_t test7(void);
334418919fSjohnjiang static int32_t test8(void);
344418919fSjohnjiang static int32_t test9(void);
354418919fSjohnjiang static int32_t test10(void);
364418919fSjohnjiang static int32_t test11(void);
374418919fSjohnjiang static int32_t test12(void);
384418919fSjohnjiang static int32_t test13(void);
394418919fSjohnjiang static int32_t test14(void);
404418919fSjohnjiang static int32_t test15(void);
414418919fSjohnjiang static int32_t test16(void);
424418919fSjohnjiang static int32_t test17(void);
434418919fSjohnjiang static int32_t test18(void);
44*2d9fd380Sjfb8856606 static int32_t test19(void);
45*2d9fd380Sjfb8856606 static int32_t test20(void);
46*2d9fd380Sjfb8856606 static int32_t test21(void);
474418919fSjohnjiang 
484418919fSjohnjiang rte_lpm_test tests[] = {
494418919fSjohnjiang /* Test Cases */
504418919fSjohnjiang 	test0,
514418919fSjohnjiang 	test1,
524418919fSjohnjiang 	test2,
534418919fSjohnjiang 	test3,
544418919fSjohnjiang 	test4,
554418919fSjohnjiang 	test5,
564418919fSjohnjiang 	test6,
574418919fSjohnjiang 	test7,
584418919fSjohnjiang 	test8,
594418919fSjohnjiang 	test9,
604418919fSjohnjiang 	test10,
614418919fSjohnjiang 	test11,
624418919fSjohnjiang 	test12,
634418919fSjohnjiang 	test13,
644418919fSjohnjiang 	test14,
654418919fSjohnjiang 	test15,
664418919fSjohnjiang 	test16,
674418919fSjohnjiang 	test17,
68*2d9fd380Sjfb8856606 	test18,
69*2d9fd380Sjfb8856606 	test19,
70*2d9fd380Sjfb8856606 	test20,
71*2d9fd380Sjfb8856606 	test21
724418919fSjohnjiang };
734418919fSjohnjiang 
744418919fSjohnjiang #define MAX_DEPTH 32
754418919fSjohnjiang #define MAX_RULES 256
764418919fSjohnjiang #define NUMBER_TBL8S 256
774418919fSjohnjiang #define PASS 0
784418919fSjohnjiang 
794418919fSjohnjiang /*
804418919fSjohnjiang  * Check that rte_lpm_create fails gracefully for incorrect user input
814418919fSjohnjiang  * arguments
824418919fSjohnjiang  */
834418919fSjohnjiang int32_t
test0(void)844418919fSjohnjiang test0(void)
854418919fSjohnjiang {
864418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
874418919fSjohnjiang 	struct rte_lpm_config config;
884418919fSjohnjiang 
894418919fSjohnjiang 	config.max_rules = MAX_RULES;
904418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
914418919fSjohnjiang 	config.flags = 0;
924418919fSjohnjiang 
934418919fSjohnjiang 	/* rte_lpm_create: lpm name == NULL */
944418919fSjohnjiang 	lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
954418919fSjohnjiang 	TEST_LPM_ASSERT(lpm == NULL);
964418919fSjohnjiang 
974418919fSjohnjiang 	/* rte_lpm_create: max_rules = 0 */
984418919fSjohnjiang 	/* Note: __func__ inserts the function name, in this case "test0". */
994418919fSjohnjiang 	config.max_rules = 0;
1004418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1014418919fSjohnjiang 	TEST_LPM_ASSERT(lpm == NULL);
1024418919fSjohnjiang 
1034418919fSjohnjiang 	/* socket_id < -1 is invalid */
1044418919fSjohnjiang 	config.max_rules = MAX_RULES;
1054418919fSjohnjiang 	lpm = rte_lpm_create(__func__, -2, &config);
1064418919fSjohnjiang 	TEST_LPM_ASSERT(lpm == NULL);
1074418919fSjohnjiang 
1084418919fSjohnjiang 	return PASS;
1094418919fSjohnjiang }
1104418919fSjohnjiang 
1114418919fSjohnjiang /*
1124418919fSjohnjiang  * Create lpm table then delete lpm table 100 times
1134418919fSjohnjiang  * Use a slightly different rules size each time
1144418919fSjohnjiang  * */
1154418919fSjohnjiang int32_t
test1(void)1164418919fSjohnjiang test1(void)
1174418919fSjohnjiang {
1184418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
1194418919fSjohnjiang 	struct rte_lpm_config config;
1204418919fSjohnjiang 
1214418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
1224418919fSjohnjiang 	config.flags = 0;
1234418919fSjohnjiang 	int32_t i;
1244418919fSjohnjiang 
1254418919fSjohnjiang 	/* rte_lpm_free: Free NULL */
1264418919fSjohnjiang 	for (i = 0; i < 100; i++) {
1274418919fSjohnjiang 		config.max_rules = MAX_RULES - i;
1284418919fSjohnjiang 		lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1294418919fSjohnjiang 		TEST_LPM_ASSERT(lpm != NULL);
1304418919fSjohnjiang 
1314418919fSjohnjiang 		rte_lpm_free(lpm);
1324418919fSjohnjiang 	}
1334418919fSjohnjiang 
1344418919fSjohnjiang 	/* Can not test free so return success */
1354418919fSjohnjiang 	return PASS;
1364418919fSjohnjiang }
1374418919fSjohnjiang 
1384418919fSjohnjiang /*
1394418919fSjohnjiang  * Call rte_lpm_free for NULL pointer user input. Note: free has no return and
1404418919fSjohnjiang  * therefore it is impossible to check for failure but this test is added to
1414418919fSjohnjiang  * increase function coverage metrics and to validate that freeing null does
1424418919fSjohnjiang  * not crash.
1434418919fSjohnjiang  */
1444418919fSjohnjiang int32_t
test2(void)1454418919fSjohnjiang test2(void)
1464418919fSjohnjiang {
1474418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
1484418919fSjohnjiang 	struct rte_lpm_config config;
1494418919fSjohnjiang 
1504418919fSjohnjiang 	config.max_rules = MAX_RULES;
1514418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
1524418919fSjohnjiang 	config.flags = 0;
1534418919fSjohnjiang 
1544418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1554418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
1564418919fSjohnjiang 
1574418919fSjohnjiang 	rte_lpm_free(lpm);
1584418919fSjohnjiang 	rte_lpm_free(NULL);
1594418919fSjohnjiang 	return PASS;
1604418919fSjohnjiang }
1614418919fSjohnjiang 
1624418919fSjohnjiang /*
1634418919fSjohnjiang  * Check that rte_lpm_add fails gracefully for incorrect user input arguments
1644418919fSjohnjiang  */
1654418919fSjohnjiang int32_t
test3(void)1664418919fSjohnjiang test3(void)
1674418919fSjohnjiang {
1684418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
1694418919fSjohnjiang 	struct rte_lpm_config config;
1704418919fSjohnjiang 
1714418919fSjohnjiang 	config.max_rules = MAX_RULES;
1724418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
1734418919fSjohnjiang 	config.flags = 0;
1744418919fSjohnjiang 	uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop = 100;
1754418919fSjohnjiang 	uint8_t depth = 24;
1764418919fSjohnjiang 	int32_t status = 0;
1774418919fSjohnjiang 
1784418919fSjohnjiang 	/* rte_lpm_add: lpm == NULL */
1794418919fSjohnjiang 	status = rte_lpm_add(NULL, ip, depth, next_hop);
1804418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
1814418919fSjohnjiang 
1824418919fSjohnjiang 	/*Create vaild lpm to use in rest of test. */
1834418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1844418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
1854418919fSjohnjiang 
1864418919fSjohnjiang 	/* rte_lpm_add: depth < 1 */
1874418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, 0, next_hop);
1884418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
1894418919fSjohnjiang 
1904418919fSjohnjiang 	/* rte_lpm_add: depth > MAX_DEPTH */
1914418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, (MAX_DEPTH + 1), next_hop);
1924418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
1934418919fSjohnjiang 
1944418919fSjohnjiang 	rte_lpm_free(lpm);
1954418919fSjohnjiang 
1964418919fSjohnjiang 	return PASS;
1974418919fSjohnjiang }
1984418919fSjohnjiang 
1994418919fSjohnjiang /*
2004418919fSjohnjiang  * Check that rte_lpm_delete fails gracefully for incorrect user input
2014418919fSjohnjiang  * arguments
2024418919fSjohnjiang  */
2034418919fSjohnjiang int32_t
test4(void)2044418919fSjohnjiang test4(void)
2054418919fSjohnjiang {
2064418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
2074418919fSjohnjiang 	struct rte_lpm_config config;
2084418919fSjohnjiang 
2094418919fSjohnjiang 	config.max_rules = MAX_RULES;
2104418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
2114418919fSjohnjiang 	config.flags = 0;
2124418919fSjohnjiang 	uint32_t ip = RTE_IPV4(0, 0, 0, 0);
2134418919fSjohnjiang 	uint8_t depth = 24;
2144418919fSjohnjiang 	int32_t status = 0;
2154418919fSjohnjiang 
2164418919fSjohnjiang 	/* rte_lpm_delete: lpm == NULL */
2174418919fSjohnjiang 	status = rte_lpm_delete(NULL, ip, depth);
2184418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
2194418919fSjohnjiang 
2204418919fSjohnjiang 	/*Create vaild lpm to use in rest of test. */
2214418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
2224418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
2234418919fSjohnjiang 
2244418919fSjohnjiang 	/* rte_lpm_delete: depth < 1 */
2254418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, 0);
2264418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
2274418919fSjohnjiang 
2284418919fSjohnjiang 	/* rte_lpm_delete: depth > MAX_DEPTH */
2294418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, (MAX_DEPTH + 1));
2304418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
2314418919fSjohnjiang 
2324418919fSjohnjiang 	rte_lpm_free(lpm);
2334418919fSjohnjiang 
2344418919fSjohnjiang 	return PASS;
2354418919fSjohnjiang }
2364418919fSjohnjiang 
2374418919fSjohnjiang /*
2384418919fSjohnjiang  * Check that rte_lpm_lookup fails gracefully for incorrect user input
2394418919fSjohnjiang  * arguments
2404418919fSjohnjiang  */
2414418919fSjohnjiang int32_t
test5(void)2424418919fSjohnjiang test5(void)
2434418919fSjohnjiang {
2444418919fSjohnjiang #if defined(RTE_LIBRTE_LPM_DEBUG)
2454418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
2464418919fSjohnjiang 	struct rte_lpm_config config;
2474418919fSjohnjiang 
2484418919fSjohnjiang 	config.max_rules = MAX_RULES;
2494418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
2504418919fSjohnjiang 	config.flags = 0;
2514418919fSjohnjiang 	uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_return = 0;
2524418919fSjohnjiang 	int32_t status = 0;
2534418919fSjohnjiang 
2544418919fSjohnjiang 	/* rte_lpm_lookup: lpm == NULL */
2554418919fSjohnjiang 	status = rte_lpm_lookup(NULL, ip, &next_hop_return);
2564418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
2574418919fSjohnjiang 
2584418919fSjohnjiang 	/*Create vaild lpm to use in rest of test. */
2594418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
2604418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
2614418919fSjohnjiang 
2624418919fSjohnjiang 	/* rte_lpm_lookup: depth < 1 */
2634418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, NULL);
2644418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
2654418919fSjohnjiang 
2664418919fSjohnjiang 	rte_lpm_free(lpm);
2674418919fSjohnjiang #endif
2684418919fSjohnjiang 	return PASS;
2694418919fSjohnjiang }
2704418919fSjohnjiang 
2714418919fSjohnjiang 
2724418919fSjohnjiang 
2734418919fSjohnjiang /*
2744418919fSjohnjiang  * Call add, lookup and delete for a single rule with depth <= 24
2754418919fSjohnjiang  */
2764418919fSjohnjiang int32_t
test6(void)2774418919fSjohnjiang test6(void)
2784418919fSjohnjiang {
2794418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
2804418919fSjohnjiang 	struct rte_lpm_config config;
2814418919fSjohnjiang 
2824418919fSjohnjiang 	config.max_rules = MAX_RULES;
2834418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
2844418919fSjohnjiang 	config.flags = 0;
2854418919fSjohnjiang 	uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
2864418919fSjohnjiang 	uint8_t depth = 24;
2874418919fSjohnjiang 	int32_t status = 0;
2884418919fSjohnjiang 
2894418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
2904418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
2914418919fSjohnjiang 
2924418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
2934418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
2944418919fSjohnjiang 
2954418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
2964418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
2974418919fSjohnjiang 
2984418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
2994418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
3004418919fSjohnjiang 
3014418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
3024418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
3034418919fSjohnjiang 
3044418919fSjohnjiang 	rte_lpm_free(lpm);
3054418919fSjohnjiang 
3064418919fSjohnjiang 	return PASS;
3074418919fSjohnjiang }
3084418919fSjohnjiang 
3094418919fSjohnjiang /*
3104418919fSjohnjiang  * Call add, lookup and delete for a single rule with depth > 24
3114418919fSjohnjiang  */
3124418919fSjohnjiang 
3134418919fSjohnjiang int32_t
test7(void)3144418919fSjohnjiang test7(void)
3154418919fSjohnjiang {
3164418919fSjohnjiang 	xmm_t ipx4;
3174418919fSjohnjiang 	uint32_t hop[4];
3184418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
3194418919fSjohnjiang 	struct rte_lpm_config config;
3204418919fSjohnjiang 
3214418919fSjohnjiang 	config.max_rules = MAX_RULES;
3224418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
3234418919fSjohnjiang 	config.flags = 0;
3244418919fSjohnjiang 	uint32_t ip = RTE_IPV4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
3254418919fSjohnjiang 	uint8_t depth = 32;
3264418919fSjohnjiang 	int32_t status = 0;
3274418919fSjohnjiang 
3284418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
3294418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
3304418919fSjohnjiang 
3314418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
3324418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
3334418919fSjohnjiang 
3344418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
3354418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
3364418919fSjohnjiang 
3374418919fSjohnjiang 	ipx4 = vect_set_epi32(ip, ip + 0x100, ip - 0x100, ip);
3384418919fSjohnjiang 	rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
3394418919fSjohnjiang 	TEST_LPM_ASSERT(hop[0] == next_hop_add);
3404418919fSjohnjiang 	TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
3414418919fSjohnjiang 	TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
3424418919fSjohnjiang 	TEST_LPM_ASSERT(hop[3] == next_hop_add);
3434418919fSjohnjiang 
3444418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
3454418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
3464418919fSjohnjiang 
3474418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
3484418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
3494418919fSjohnjiang 
3504418919fSjohnjiang 	rte_lpm_free(lpm);
3514418919fSjohnjiang 
3524418919fSjohnjiang 	return PASS;
3534418919fSjohnjiang }
3544418919fSjohnjiang 
3554418919fSjohnjiang /*
3564418919fSjohnjiang  * Use rte_lpm_add to add rules which effect only the second half of the lpm
3574418919fSjohnjiang  * table. Use all possible depths ranging from 1..32. Set the next hop = to the
3584418919fSjohnjiang  * depth. Check lookup hit for on every add and check for lookup miss on the
3594418919fSjohnjiang  * first half of the lpm table after each add. Finally delete all rules going
3604418919fSjohnjiang  * backwards (i.e. from depth = 32 ..1) and carry out a lookup after each
3614418919fSjohnjiang  * delete. The lookup should return the next_hop_add value related to the
3624418919fSjohnjiang  * previous depth value (i.e. depth -1).
3634418919fSjohnjiang  */
3644418919fSjohnjiang int32_t
test8(void)3654418919fSjohnjiang test8(void)
3664418919fSjohnjiang {
3674418919fSjohnjiang 	xmm_t ipx4;
3684418919fSjohnjiang 	uint32_t hop[4];
3694418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
3704418919fSjohnjiang 	struct rte_lpm_config config;
3714418919fSjohnjiang 
3724418919fSjohnjiang 	config.max_rules = MAX_RULES;
3734418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
3744418919fSjohnjiang 	config.flags = 0;
3754418919fSjohnjiang 	uint32_t ip1 = RTE_IPV4(127, 255, 255, 255), ip2 = RTE_IPV4(128, 0, 0, 0);
3764418919fSjohnjiang 	uint32_t next_hop_add, next_hop_return;
3774418919fSjohnjiang 	uint8_t depth;
3784418919fSjohnjiang 	int32_t status = 0;
3794418919fSjohnjiang 
3804418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
3814418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
3824418919fSjohnjiang 
3834418919fSjohnjiang 	/* Loop with rte_lpm_add. */
3844418919fSjohnjiang 	for (depth = 1; depth <= 32; depth++) {
3854418919fSjohnjiang 		/* Let the next_hop_add value = depth. Just for change. */
3864418919fSjohnjiang 		next_hop_add = depth;
3874418919fSjohnjiang 
3884418919fSjohnjiang 		status = rte_lpm_add(lpm, ip2, depth, next_hop_add);
3894418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
3904418919fSjohnjiang 
3914418919fSjohnjiang 		/* Check IP in first half of tbl24 which should be empty. */
3924418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
3934418919fSjohnjiang 		TEST_LPM_ASSERT(status == -ENOENT);
3944418919fSjohnjiang 
3954418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
3964418919fSjohnjiang 		TEST_LPM_ASSERT((status == 0) &&
3974418919fSjohnjiang 			(next_hop_return == next_hop_add));
3984418919fSjohnjiang 
3994418919fSjohnjiang 		ipx4 = vect_set_epi32(ip2, ip1, ip2, ip1);
4004418919fSjohnjiang 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
4014418919fSjohnjiang 		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
4024418919fSjohnjiang 		TEST_LPM_ASSERT(hop[1] == next_hop_add);
4034418919fSjohnjiang 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
4044418919fSjohnjiang 		TEST_LPM_ASSERT(hop[3] == next_hop_add);
4054418919fSjohnjiang 	}
4064418919fSjohnjiang 
4074418919fSjohnjiang 	/* Loop with rte_lpm_delete. */
4084418919fSjohnjiang 	for (depth = 32; depth >= 1; depth--) {
4094418919fSjohnjiang 		next_hop_add = (uint8_t) (depth - 1);
4104418919fSjohnjiang 
4114418919fSjohnjiang 		status = rte_lpm_delete(lpm, ip2, depth);
4124418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
4134418919fSjohnjiang 
4144418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip2, &next_hop_return);
4154418919fSjohnjiang 
4164418919fSjohnjiang 		if (depth != 1) {
4174418919fSjohnjiang 			TEST_LPM_ASSERT((status == 0) &&
4184418919fSjohnjiang 				(next_hop_return == next_hop_add));
4194418919fSjohnjiang 		} else {
4204418919fSjohnjiang 			TEST_LPM_ASSERT(status == -ENOENT);
4214418919fSjohnjiang 		}
4224418919fSjohnjiang 
4234418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip1, &next_hop_return);
4244418919fSjohnjiang 		TEST_LPM_ASSERT(status == -ENOENT);
4254418919fSjohnjiang 
4264418919fSjohnjiang 		ipx4 = vect_set_epi32(ip1, ip1, ip2, ip2);
4274418919fSjohnjiang 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
4284418919fSjohnjiang 		if (depth != 1) {
4294418919fSjohnjiang 			TEST_LPM_ASSERT(hop[0] == next_hop_add);
4304418919fSjohnjiang 			TEST_LPM_ASSERT(hop[1] == next_hop_add);
4314418919fSjohnjiang 		} else {
4324418919fSjohnjiang 			TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
4334418919fSjohnjiang 			TEST_LPM_ASSERT(hop[1] == UINT32_MAX);
4344418919fSjohnjiang 		}
4354418919fSjohnjiang 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
4364418919fSjohnjiang 		TEST_LPM_ASSERT(hop[3] == UINT32_MAX);
4374418919fSjohnjiang 	}
4384418919fSjohnjiang 
4394418919fSjohnjiang 	rte_lpm_free(lpm);
4404418919fSjohnjiang 
4414418919fSjohnjiang 	return PASS;
4424418919fSjohnjiang }
4434418919fSjohnjiang 
4444418919fSjohnjiang /*
4454418919fSjohnjiang  * - Add & lookup to hit invalid TBL24 entry
4464418919fSjohnjiang  * - Add & lookup to hit valid TBL24 entry not extended
4474418919fSjohnjiang  * - Add & lookup to hit valid extended TBL24 entry with invalid TBL8 entry
4484418919fSjohnjiang  * - Add & lookup to hit valid extended TBL24 entry with valid TBL8 entry
4494418919fSjohnjiang  *
4504418919fSjohnjiang  */
4514418919fSjohnjiang int32_t
test9(void)4524418919fSjohnjiang test9(void)
4534418919fSjohnjiang {
4544418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
4554418919fSjohnjiang 	struct rte_lpm_config config;
4564418919fSjohnjiang 
4574418919fSjohnjiang 	config.max_rules = MAX_RULES;
4584418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
4594418919fSjohnjiang 	config.flags = 0;
4604418919fSjohnjiang 	uint32_t ip, ip_1, ip_2;
4614418919fSjohnjiang 	uint8_t depth, depth_1, depth_2;
4624418919fSjohnjiang 	uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
4634418919fSjohnjiang 	int32_t status = 0;
4644418919fSjohnjiang 
4654418919fSjohnjiang 	/* Add & lookup to hit invalid TBL24 entry */
4664418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
4674418919fSjohnjiang 	depth = 24;
4684418919fSjohnjiang 	next_hop_add = 100;
4694418919fSjohnjiang 
4704418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
4714418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
4724418919fSjohnjiang 
4734418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
4744418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
4754418919fSjohnjiang 
4764418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
4774418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
4784418919fSjohnjiang 
4794418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
4804418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
4814418919fSjohnjiang 
4824418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
4834418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
4844418919fSjohnjiang 
4854418919fSjohnjiang 	rte_lpm_delete_all(lpm);
4864418919fSjohnjiang 
4874418919fSjohnjiang 	/* Add & lookup to hit valid TBL24 entry not extended */
4884418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
4894418919fSjohnjiang 	depth = 23;
4904418919fSjohnjiang 	next_hop_add = 100;
4914418919fSjohnjiang 
4924418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
4934418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
4944418919fSjohnjiang 
4954418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
4964418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
4974418919fSjohnjiang 
4984418919fSjohnjiang 	depth = 24;
4994418919fSjohnjiang 	next_hop_add = 101;
5004418919fSjohnjiang 
5014418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
5024418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5034418919fSjohnjiang 
5044418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5054418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
5064418919fSjohnjiang 
5074418919fSjohnjiang 	depth = 24;
5084418919fSjohnjiang 
5094418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
5104418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5114418919fSjohnjiang 
5124418919fSjohnjiang 	depth = 23;
5134418919fSjohnjiang 
5144418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
5154418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5164418919fSjohnjiang 
5174418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5184418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
5194418919fSjohnjiang 
5204418919fSjohnjiang 	rte_lpm_delete_all(lpm);
5214418919fSjohnjiang 
5224418919fSjohnjiang 	/* Add & lookup to hit valid extended TBL24 entry with invalid TBL8
5234418919fSjohnjiang 	 * entry */
5244418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
5254418919fSjohnjiang 	depth = 32;
5264418919fSjohnjiang 	next_hop_add = 100;
5274418919fSjohnjiang 
5284418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
5294418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5304418919fSjohnjiang 
5314418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5324418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
5334418919fSjohnjiang 
5344418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 5);
5354418919fSjohnjiang 	depth = 32;
5364418919fSjohnjiang 	next_hop_add = 101;
5374418919fSjohnjiang 
5384418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
5394418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5404418919fSjohnjiang 
5414418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5424418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
5434418919fSjohnjiang 
5444418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
5454418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5464418919fSjohnjiang 
5474418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5484418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
5494418919fSjohnjiang 
5504418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
5514418919fSjohnjiang 	depth = 32;
5524418919fSjohnjiang 	next_hop_add = 100;
5534418919fSjohnjiang 
5544418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5554418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
5564418919fSjohnjiang 
5574418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
5584418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5594418919fSjohnjiang 
5604418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
5614418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
5624418919fSjohnjiang 
5634418919fSjohnjiang 	rte_lpm_delete_all(lpm);
5644418919fSjohnjiang 
5654418919fSjohnjiang 	/* Add & lookup to hit valid extended TBL24 entry with valid TBL8
5664418919fSjohnjiang 	 * entry */
5674418919fSjohnjiang 	ip_1 = RTE_IPV4(128, 0, 0, 0);
5684418919fSjohnjiang 	depth_1 = 25;
5694418919fSjohnjiang 	next_hop_add_1 = 101;
5704418919fSjohnjiang 
5714418919fSjohnjiang 	ip_2 = RTE_IPV4(128, 0, 0, 5);
5724418919fSjohnjiang 	depth_2 = 32;
5734418919fSjohnjiang 	next_hop_add_2 = 102;
5744418919fSjohnjiang 
5754418919fSjohnjiang 	next_hop_return = 0;
5764418919fSjohnjiang 
5774418919fSjohnjiang 	status = rte_lpm_add(lpm, ip_1, depth_1, next_hop_add_1);
5784418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5794418919fSjohnjiang 
5804418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
5814418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
5824418919fSjohnjiang 
5834418919fSjohnjiang 	status = rte_lpm_add(lpm, ip_2, depth_2, next_hop_add_2);
5844418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5854418919fSjohnjiang 
5864418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
5874418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_2));
5884418919fSjohnjiang 
5894418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip_2, depth_2);
5904418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5914418919fSjohnjiang 
5924418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_2, &next_hop_return);
5934418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
5944418919fSjohnjiang 
5954418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip_1, depth_1);
5964418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
5974418919fSjohnjiang 
5984418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_1, &next_hop_return);
5994418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
6004418919fSjohnjiang 
6014418919fSjohnjiang 	rte_lpm_free(lpm);
6024418919fSjohnjiang 
6034418919fSjohnjiang 	return PASS;
6044418919fSjohnjiang }
6054418919fSjohnjiang 
6064418919fSjohnjiang 
6074418919fSjohnjiang /*
6084418919fSjohnjiang  * - Add rule that covers a TBL24 range previously invalid & lookup (& delete &
6094418919fSjohnjiang  *   lookup)
6104418919fSjohnjiang  * - Add rule that extends a TBL24 invalid entry & lookup (& delete & lookup)
6114418919fSjohnjiang  * - Add rule that extends a TBL24 valid entry & lookup for both rules (&
6124418919fSjohnjiang  *   delete & lookup)
6134418919fSjohnjiang  * - Add rule that updates the next hop in TBL24 & lookup (& delete & lookup)
6144418919fSjohnjiang  * - Add rule that updates the next hop in TBL8 & lookup (& delete & lookup)
6154418919fSjohnjiang  * - Delete a rule that is not present in the TBL24 & lookup
6164418919fSjohnjiang  * - Delete a rule that is not present in the TBL8 & lookup
6174418919fSjohnjiang  *
6184418919fSjohnjiang  */
6194418919fSjohnjiang int32_t
test10(void)6204418919fSjohnjiang test10(void)
6214418919fSjohnjiang {
6224418919fSjohnjiang 
6234418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
6244418919fSjohnjiang 	struct rte_lpm_config config;
6254418919fSjohnjiang 
6264418919fSjohnjiang 	config.max_rules = MAX_RULES;
6274418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
6284418919fSjohnjiang 	config.flags = 0;
6294418919fSjohnjiang 	uint32_t ip, next_hop_add, next_hop_return;
6304418919fSjohnjiang 	uint8_t depth;
6314418919fSjohnjiang 	int32_t status = 0;
6324418919fSjohnjiang 
6334418919fSjohnjiang 	/* Add rule that covers a TBL24 range previously invalid & lookup
6344418919fSjohnjiang 	 * (& delete & lookup) */
6354418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
6364418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
6374418919fSjohnjiang 
6384418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
6394418919fSjohnjiang 	depth = 16;
6404418919fSjohnjiang 	next_hop_add = 100;
6414418919fSjohnjiang 
6424418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
6434418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6444418919fSjohnjiang 
6454418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
6464418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
6474418919fSjohnjiang 
6484418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
6494418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6504418919fSjohnjiang 
6514418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
6524418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
6534418919fSjohnjiang 
6544418919fSjohnjiang 	rte_lpm_delete_all(lpm);
6554418919fSjohnjiang 
6564418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
6574418919fSjohnjiang 	depth = 25;
6584418919fSjohnjiang 	next_hop_add = 100;
6594418919fSjohnjiang 
6604418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
6614418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6624418919fSjohnjiang 
6634418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
6644418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
6654418919fSjohnjiang 
6664418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
6674418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6684418919fSjohnjiang 
6694418919fSjohnjiang 	rte_lpm_delete_all(lpm);
6704418919fSjohnjiang 
6714418919fSjohnjiang 	/* Add rule that extends a TBL24 valid entry & lookup for both rules
6724418919fSjohnjiang 	 * (& delete & lookup) */
6734418919fSjohnjiang 
6744418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
6754418919fSjohnjiang 	depth = 24;
6764418919fSjohnjiang 	next_hop_add = 100;
6774418919fSjohnjiang 
6784418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
6794418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6804418919fSjohnjiang 
6814418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 10);
6824418919fSjohnjiang 	depth = 32;
6834418919fSjohnjiang 	next_hop_add = 101;
6844418919fSjohnjiang 
6854418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
6864418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
6874418919fSjohnjiang 
6884418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
6894418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
6904418919fSjohnjiang 
6914418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
6924418919fSjohnjiang 	next_hop_add = 100;
6934418919fSjohnjiang 
6944418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
6954418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
6964418919fSjohnjiang 
6974418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
6984418919fSjohnjiang 	depth = 24;
6994418919fSjohnjiang 
7004418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7014418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7024418919fSjohnjiang 
7034418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7044418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7054418919fSjohnjiang 
7064418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 10);
7074418919fSjohnjiang 	depth = 32;
7084418919fSjohnjiang 
7094418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7104418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7114418919fSjohnjiang 
7124418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7134418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7144418919fSjohnjiang 
7154418919fSjohnjiang 	rte_lpm_delete_all(lpm);
7164418919fSjohnjiang 
7174418919fSjohnjiang 	/* Add rule that updates the next hop in TBL24 & lookup
7184418919fSjohnjiang 	 * (& delete & lookup) */
7194418919fSjohnjiang 
7204418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
7214418919fSjohnjiang 	depth = 24;
7224418919fSjohnjiang 	next_hop_add = 100;
7234418919fSjohnjiang 
7244418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
7254418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7264418919fSjohnjiang 
7274418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7284418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
7294418919fSjohnjiang 
7304418919fSjohnjiang 	next_hop_add = 101;
7314418919fSjohnjiang 
7324418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
7334418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7344418919fSjohnjiang 
7354418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7364418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
7374418919fSjohnjiang 
7384418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7394418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7404418919fSjohnjiang 
7414418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7424418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7434418919fSjohnjiang 
7444418919fSjohnjiang 	rte_lpm_delete_all(lpm);
7454418919fSjohnjiang 
7464418919fSjohnjiang 	/* Add rule that updates the next hop in TBL8 & lookup
7474418919fSjohnjiang 	 * (& delete & lookup) */
7484418919fSjohnjiang 
7494418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
7504418919fSjohnjiang 	depth = 32;
7514418919fSjohnjiang 	next_hop_add = 100;
7524418919fSjohnjiang 
7534418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
7544418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7554418919fSjohnjiang 
7564418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7574418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
7584418919fSjohnjiang 
7594418919fSjohnjiang 	next_hop_add = 101;
7604418919fSjohnjiang 
7614418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
7624418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7634418919fSjohnjiang 
7644418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7654418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
7664418919fSjohnjiang 
7674418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7684418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
7694418919fSjohnjiang 
7704418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7714418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7724418919fSjohnjiang 
7734418919fSjohnjiang 	rte_lpm_delete_all(lpm);
7744418919fSjohnjiang 
7754418919fSjohnjiang 	/* Delete a rule that is not present in the TBL24 & lookup */
7764418919fSjohnjiang 
7774418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
7784418919fSjohnjiang 	depth = 24;
7794418919fSjohnjiang 
7804418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7814418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
7824418919fSjohnjiang 
7834418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7844418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7854418919fSjohnjiang 
7864418919fSjohnjiang 	rte_lpm_delete_all(lpm);
7874418919fSjohnjiang 
7884418919fSjohnjiang 	/* Delete a rule that is not present in the TBL8 & lookup */
7894418919fSjohnjiang 
7904418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
7914418919fSjohnjiang 	depth = 32;
7924418919fSjohnjiang 
7934418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
7944418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
7954418919fSjohnjiang 
7964418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
7974418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
7984418919fSjohnjiang 
7994418919fSjohnjiang 	rte_lpm_free(lpm);
8004418919fSjohnjiang 
8014418919fSjohnjiang 	return PASS;
8024418919fSjohnjiang }
8034418919fSjohnjiang 
8044418919fSjohnjiang /*
8054418919fSjohnjiang  * Add two rules, lookup to hit the more specific one, lookup to hit the less
8064418919fSjohnjiang  * specific one delete the less specific rule and lookup previous values again;
8074418919fSjohnjiang  * add a more specific rule than the existing rule, lookup again
8084418919fSjohnjiang  *
8094418919fSjohnjiang  * */
8104418919fSjohnjiang int32_t
test11(void)8114418919fSjohnjiang test11(void)
8124418919fSjohnjiang {
8134418919fSjohnjiang 
8144418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
8154418919fSjohnjiang 	struct rte_lpm_config config;
8164418919fSjohnjiang 
8174418919fSjohnjiang 	config.max_rules = MAX_RULES;
8184418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
8194418919fSjohnjiang 	config.flags = 0;
8204418919fSjohnjiang 	uint32_t ip, next_hop_add, next_hop_return;
8214418919fSjohnjiang 	uint8_t depth;
8224418919fSjohnjiang 	int32_t status = 0;
8234418919fSjohnjiang 
8244418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
8254418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
8264418919fSjohnjiang 
8274418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
8284418919fSjohnjiang 	depth = 24;
8294418919fSjohnjiang 	next_hop_add = 100;
8304418919fSjohnjiang 
8314418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
8324418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
8334418919fSjohnjiang 
8344418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 10);
8354418919fSjohnjiang 	depth = 32;
8364418919fSjohnjiang 	next_hop_add = 101;
8374418919fSjohnjiang 
8384418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
8394418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
8404418919fSjohnjiang 
8414418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
8424418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
8434418919fSjohnjiang 
8444418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
8454418919fSjohnjiang 	next_hop_add = 100;
8464418919fSjohnjiang 
8474418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
8484418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add));
8494418919fSjohnjiang 
8504418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
8514418919fSjohnjiang 	depth = 24;
8524418919fSjohnjiang 
8534418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
8544418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
8554418919fSjohnjiang 
8564418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
8574418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
8584418919fSjohnjiang 
8594418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 10);
8604418919fSjohnjiang 	depth = 32;
8614418919fSjohnjiang 
8624418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
8634418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
8644418919fSjohnjiang 
8654418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
8664418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
8674418919fSjohnjiang 
8684418919fSjohnjiang 	rte_lpm_free(lpm);
8694418919fSjohnjiang 
8704418919fSjohnjiang 	return PASS;
8714418919fSjohnjiang }
8724418919fSjohnjiang 
8734418919fSjohnjiang /*
8744418919fSjohnjiang  * Add an extended rule (i.e. depth greater than 24, lookup (hit), delete,
8754418919fSjohnjiang  * lookup (miss) in a for loop of 1000 times. This will check tbl8 extension
8764418919fSjohnjiang  * and contraction.
8774418919fSjohnjiang  *
8784418919fSjohnjiang  * */
8794418919fSjohnjiang 
8804418919fSjohnjiang int32_t
test12(void)8814418919fSjohnjiang test12(void)
8824418919fSjohnjiang {
8834418919fSjohnjiang 	xmm_t ipx4;
8844418919fSjohnjiang 	uint32_t hop[4];
8854418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
8864418919fSjohnjiang 	struct rte_lpm_config config;
8874418919fSjohnjiang 
8884418919fSjohnjiang 	config.max_rules = MAX_RULES;
8894418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
8904418919fSjohnjiang 	config.flags = 0;
8914418919fSjohnjiang 	uint32_t ip, i, next_hop_add, next_hop_return;
8924418919fSjohnjiang 	uint8_t depth;
8934418919fSjohnjiang 	int32_t status = 0;
8944418919fSjohnjiang 
8954418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
8964418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
8974418919fSjohnjiang 
8984418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
8994418919fSjohnjiang 	depth = 32;
9004418919fSjohnjiang 	next_hop_add = 100;
9014418919fSjohnjiang 
9024418919fSjohnjiang 	for (i = 0; i < 1000; i++) {
9034418919fSjohnjiang 		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
9044418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
9054418919fSjohnjiang 
9064418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9074418919fSjohnjiang 		TEST_LPM_ASSERT((status == 0) &&
9084418919fSjohnjiang 				(next_hop_return == next_hop_add));
9094418919fSjohnjiang 
9104418919fSjohnjiang 		ipx4 = vect_set_epi32(ip, ip + 1, ip, ip - 1);
9114418919fSjohnjiang 		rte_lpm_lookupx4(lpm, ipx4, hop, UINT32_MAX);
9124418919fSjohnjiang 		TEST_LPM_ASSERT(hop[0] == UINT32_MAX);
9134418919fSjohnjiang 		TEST_LPM_ASSERT(hop[1] == next_hop_add);
9144418919fSjohnjiang 		TEST_LPM_ASSERT(hop[2] == UINT32_MAX);
9154418919fSjohnjiang 		TEST_LPM_ASSERT(hop[3] == next_hop_add);
9164418919fSjohnjiang 
9174418919fSjohnjiang 		status = rte_lpm_delete(lpm, ip, depth);
9184418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
9194418919fSjohnjiang 
9204418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9214418919fSjohnjiang 		TEST_LPM_ASSERT(status == -ENOENT);
9224418919fSjohnjiang 	}
9234418919fSjohnjiang 
9244418919fSjohnjiang 	rte_lpm_free(lpm);
9254418919fSjohnjiang 
9264418919fSjohnjiang 	return PASS;
9274418919fSjohnjiang }
9284418919fSjohnjiang 
9294418919fSjohnjiang /*
9304418919fSjohnjiang  * Add a rule to tbl24, lookup (hit), then add a rule that will extend this
9314418919fSjohnjiang  * tbl24 entry, lookup (hit). delete the rule that caused the tbl24 extension,
9324418919fSjohnjiang  * lookup (miss) and repeat for loop of 1000 times. This will check tbl8
9334418919fSjohnjiang  * extension and contraction.
9344418919fSjohnjiang  *
9354418919fSjohnjiang  * */
9364418919fSjohnjiang 
9374418919fSjohnjiang int32_t
test13(void)9384418919fSjohnjiang test13(void)
9394418919fSjohnjiang {
9404418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
9414418919fSjohnjiang 	struct rte_lpm_config config;
9424418919fSjohnjiang 
9434418919fSjohnjiang 	config.max_rules = MAX_RULES;
9444418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
9454418919fSjohnjiang 	config.flags = 0;
9464418919fSjohnjiang 	uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
9474418919fSjohnjiang 	uint8_t depth;
9484418919fSjohnjiang 	int32_t status = 0;
9494418919fSjohnjiang 
9504418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
9514418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
9524418919fSjohnjiang 
9534418919fSjohnjiang 	ip = RTE_IPV4(128, 0, 0, 0);
9544418919fSjohnjiang 	depth = 24;
9554418919fSjohnjiang 	next_hop_add_1 = 100;
9564418919fSjohnjiang 
9574418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add_1);
9584418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
9594418919fSjohnjiang 
9604418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9614418919fSjohnjiang 	TEST_LPM_ASSERT((status == 0) && (next_hop_return == next_hop_add_1));
9624418919fSjohnjiang 
9634418919fSjohnjiang 	depth = 32;
9644418919fSjohnjiang 	next_hop_add_2 = 101;
9654418919fSjohnjiang 
9664418919fSjohnjiang 	for (i = 0; i < 1000; i++) {
9674418919fSjohnjiang 		status = rte_lpm_add(lpm, ip, depth, next_hop_add_2);
9684418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
9694418919fSjohnjiang 
9704418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9714418919fSjohnjiang 		TEST_LPM_ASSERT((status == 0) &&
9724418919fSjohnjiang 				(next_hop_return == next_hop_add_2));
9734418919fSjohnjiang 
9744418919fSjohnjiang 		status = rte_lpm_delete(lpm, ip, depth);
9754418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
9764418919fSjohnjiang 
9774418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9784418919fSjohnjiang 		TEST_LPM_ASSERT((status == 0) &&
9794418919fSjohnjiang 				(next_hop_return == next_hop_add_1));
9804418919fSjohnjiang 	}
9814418919fSjohnjiang 
9824418919fSjohnjiang 	depth = 24;
9834418919fSjohnjiang 
9844418919fSjohnjiang 	status = rte_lpm_delete(lpm, ip, depth);
9854418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
9864418919fSjohnjiang 
9874418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
9884418919fSjohnjiang 	TEST_LPM_ASSERT(status == -ENOENT);
9894418919fSjohnjiang 
9904418919fSjohnjiang 	rte_lpm_free(lpm);
9914418919fSjohnjiang 
9924418919fSjohnjiang 	return PASS;
9934418919fSjohnjiang }
9944418919fSjohnjiang 
9954418919fSjohnjiang /*
9964418919fSjohnjiang  * Fore TBL8 extension exhaustion. Add 256 rules that require a tbl8 extension.
9974418919fSjohnjiang  * No more tbl8 extensions will be allowed. Now add one more rule that required
9984418919fSjohnjiang  * a tbl8 extension and get fail.
9994418919fSjohnjiang  * */
10004418919fSjohnjiang int32_t
test14(void)10014418919fSjohnjiang test14(void)
10024418919fSjohnjiang {
10034418919fSjohnjiang 
10044418919fSjohnjiang 	/* We only use depth = 32 in the loop below so we must make sure
10054418919fSjohnjiang 	 * that we have enough storage for all rules at that depth*/
10064418919fSjohnjiang 
10074418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
10084418919fSjohnjiang 	struct rte_lpm_config config;
10094418919fSjohnjiang 
10104418919fSjohnjiang 	config.max_rules = 256 * 32;
10114418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
10124418919fSjohnjiang 	config.flags = 0;
10134418919fSjohnjiang 	uint32_t ip, next_hop_add, next_hop_return;
10144418919fSjohnjiang 	uint8_t depth;
10154418919fSjohnjiang 	int32_t status = 0;
10164418919fSjohnjiang 
10174418919fSjohnjiang 	/* Add enough space for 256 rules for every depth */
10184418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
10194418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
10204418919fSjohnjiang 
10214418919fSjohnjiang 	depth = 32;
10224418919fSjohnjiang 	next_hop_add = 100;
10234418919fSjohnjiang 	ip = RTE_IPV4(0, 0, 0, 0);
10244418919fSjohnjiang 
10254418919fSjohnjiang 	/* Add 256 rules that require a tbl8 extension */
10264418919fSjohnjiang 	for (; ip <= RTE_IPV4(0, 0, 255, 0); ip += 256) {
10274418919fSjohnjiang 		status = rte_lpm_add(lpm, ip, depth, next_hop_add);
10284418919fSjohnjiang 		TEST_LPM_ASSERT(status == 0);
10294418919fSjohnjiang 
10304418919fSjohnjiang 		status = rte_lpm_lookup(lpm, ip, &next_hop_return);
10314418919fSjohnjiang 		TEST_LPM_ASSERT((status == 0) &&
10324418919fSjohnjiang 				(next_hop_return == next_hop_add));
10334418919fSjohnjiang 	}
10344418919fSjohnjiang 
10354418919fSjohnjiang 	/* All tbl8 extensions have been used above. Try to add one more and
10364418919fSjohnjiang 	 * we get a fail */
10374418919fSjohnjiang 	ip = RTE_IPV4(1, 0, 0, 0);
10384418919fSjohnjiang 	depth = 32;
10394418919fSjohnjiang 
10404418919fSjohnjiang 	status = rte_lpm_add(lpm, ip, depth, next_hop_add);
10414418919fSjohnjiang 	TEST_LPM_ASSERT(status < 0);
10424418919fSjohnjiang 
10434418919fSjohnjiang 	rte_lpm_free(lpm);
10444418919fSjohnjiang 
10454418919fSjohnjiang 	return PASS;
10464418919fSjohnjiang }
10474418919fSjohnjiang 
10484418919fSjohnjiang /*
10494418919fSjohnjiang  * Sequence of operations for find existing lpm table
10504418919fSjohnjiang  *
10514418919fSjohnjiang  *  - create table
10524418919fSjohnjiang  *  - find existing table: hit
10534418919fSjohnjiang  *  - find non-existing table: miss
10544418919fSjohnjiang  *
10554418919fSjohnjiang  */
10564418919fSjohnjiang int32_t
test15(void)10574418919fSjohnjiang test15(void)
10584418919fSjohnjiang {
10594418919fSjohnjiang 	struct rte_lpm *lpm = NULL, *result = NULL;
10604418919fSjohnjiang 	struct rte_lpm_config config;
10614418919fSjohnjiang 
10624418919fSjohnjiang 	config.max_rules = 256 * 32;
10634418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
10644418919fSjohnjiang 	config.flags = 0;
10654418919fSjohnjiang 
10664418919fSjohnjiang 	/* Create lpm  */
10674418919fSjohnjiang 	lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
10684418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
10694418919fSjohnjiang 
10704418919fSjohnjiang 	/* Try to find existing lpm */
10714418919fSjohnjiang 	result = rte_lpm_find_existing("lpm_find_existing");
10724418919fSjohnjiang 	TEST_LPM_ASSERT(result == lpm);
10734418919fSjohnjiang 
10744418919fSjohnjiang 	/* Try to find non-existing lpm */
10754418919fSjohnjiang 	result = rte_lpm_find_existing("lpm_find_non_existing");
10764418919fSjohnjiang 	TEST_LPM_ASSERT(result == NULL);
10774418919fSjohnjiang 
10784418919fSjohnjiang 	/* Cleanup. */
10794418919fSjohnjiang 	rte_lpm_delete_all(lpm);
10804418919fSjohnjiang 	rte_lpm_free(lpm);
10814418919fSjohnjiang 
10824418919fSjohnjiang 	return PASS;
10834418919fSjohnjiang }
10844418919fSjohnjiang 
10854418919fSjohnjiang /*
10864418919fSjohnjiang  * test failure condition of overloading the tbl8 so no more will fit
10874418919fSjohnjiang  * Check we get an error return value in that case
10884418919fSjohnjiang  */
10894418919fSjohnjiang int32_t
test16(void)10904418919fSjohnjiang test16(void)
10914418919fSjohnjiang {
10924418919fSjohnjiang 	uint32_t ip;
10934418919fSjohnjiang 	struct rte_lpm_config config;
10944418919fSjohnjiang 
10954418919fSjohnjiang 	config.max_rules = 256 * 32;
10964418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
10974418919fSjohnjiang 	config.flags = 0;
10984418919fSjohnjiang 	struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
10994418919fSjohnjiang 
11004418919fSjohnjiang 	/* ip loops through all possibilities for top 24 bits of address */
11014418919fSjohnjiang 	for (ip = 0; ip < 0xFFFFFF; ip++) {
11024418919fSjohnjiang 		/* add an entry within a different tbl8 each time, since
11034418919fSjohnjiang 		 * depth >24 and the top 24 bits are different */
11044418919fSjohnjiang 		if (rte_lpm_add(lpm, (ip << 8) + 0xF0, 30, 0) < 0)
11054418919fSjohnjiang 			break;
11064418919fSjohnjiang 	}
11074418919fSjohnjiang 
11084418919fSjohnjiang 	if (ip != NUMBER_TBL8S) {
11094418919fSjohnjiang 		printf("Error, unexpected failure with filling tbl8 groups\n");
11104418919fSjohnjiang 		printf("Failed after %u additions, expected after %u\n",
11114418919fSjohnjiang 				(unsigned)ip, (unsigned)NUMBER_TBL8S);
11124418919fSjohnjiang 	}
11134418919fSjohnjiang 
11144418919fSjohnjiang 	rte_lpm_free(lpm);
11154418919fSjohnjiang 	return 0;
11164418919fSjohnjiang }
11174418919fSjohnjiang 
11184418919fSjohnjiang /*
11194418919fSjohnjiang  * Test for overwriting of tbl8:
11204418919fSjohnjiang  *  - add rule /32 and lookup
11214418919fSjohnjiang  *  - add new rule /24 and lookup
11224418919fSjohnjiang  *	- add third rule /25 and lookup
11234418919fSjohnjiang  *	- lookup /32 and /24 rule to ensure the table has not been overwritten.
11244418919fSjohnjiang  */
11254418919fSjohnjiang int32_t
test17(void)11264418919fSjohnjiang test17(void)
11274418919fSjohnjiang {
11284418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
11294418919fSjohnjiang 	struct rte_lpm_config config;
11304418919fSjohnjiang 
11314418919fSjohnjiang 	config.max_rules = MAX_RULES;
11324418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
11334418919fSjohnjiang 	config.flags = 0;
11344418919fSjohnjiang 	const uint32_t ip_10_32 = RTE_IPV4(10, 10, 10, 2);
11354418919fSjohnjiang 	const uint32_t ip_10_24 = RTE_IPV4(10, 10, 10, 0);
11364418919fSjohnjiang 	const uint32_t ip_20_25 = RTE_IPV4(10, 10, 20, 2);
11374418919fSjohnjiang 	const uint8_t d_ip_10_32 = 32,
11384418919fSjohnjiang 			d_ip_10_24 = 24,
11394418919fSjohnjiang 			d_ip_20_25 = 25;
11404418919fSjohnjiang 	const uint32_t next_hop_ip_10_32 = 100,
11414418919fSjohnjiang 			next_hop_ip_10_24 = 105,
11424418919fSjohnjiang 			next_hop_ip_20_25 = 111;
11434418919fSjohnjiang 	uint32_t next_hop_return = 0;
11444418919fSjohnjiang 	int32_t status = 0;
11454418919fSjohnjiang 
11464418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
11474418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
11484418919fSjohnjiang 
11494418919fSjohnjiang 	if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
11504418919fSjohnjiang 			next_hop_ip_10_32)) < 0)
11514418919fSjohnjiang 		return -1;
11524418919fSjohnjiang 
11534418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
11544418919fSjohnjiang 	uint32_t test_hop_10_32 = next_hop_return;
11554418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
11564418919fSjohnjiang 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
11574418919fSjohnjiang 
11584418919fSjohnjiang 	if ((status = rte_lpm_add(lpm, ip_10_24, d_ip_10_24,
11594418919fSjohnjiang 			next_hop_ip_10_24)) < 0)
11604418919fSjohnjiang 			return -1;
11614418919fSjohnjiang 
11624418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
11634418919fSjohnjiang 	uint32_t test_hop_10_24 = next_hop_return;
11644418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
11654418919fSjohnjiang 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
11664418919fSjohnjiang 
11674418919fSjohnjiang 	if ((status = rte_lpm_add(lpm, ip_20_25, d_ip_20_25,
11684418919fSjohnjiang 			next_hop_ip_20_25)) < 0)
11694418919fSjohnjiang 		return -1;
11704418919fSjohnjiang 
11714418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_20_25, &next_hop_return);
11724418919fSjohnjiang 	uint32_t test_hop_20_25 = next_hop_return;
11734418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
11744418919fSjohnjiang 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_20_25);
11754418919fSjohnjiang 
11764418919fSjohnjiang 	if (test_hop_10_32 == test_hop_10_24) {
11774418919fSjohnjiang 		printf("Next hop return equal\n");
11784418919fSjohnjiang 		return -1;
11794418919fSjohnjiang 	}
11804418919fSjohnjiang 
11814418919fSjohnjiang 	if (test_hop_10_24 == test_hop_20_25) {
11824418919fSjohnjiang 		printf("Next hop return equal\n");
11834418919fSjohnjiang 		return -1;
11844418919fSjohnjiang 	}
11854418919fSjohnjiang 
11864418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_10_32, &next_hop_return);
11874418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
11884418919fSjohnjiang 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_32);
11894418919fSjohnjiang 
11904418919fSjohnjiang 	status = rte_lpm_lookup(lpm, ip_10_24, &next_hop_return);
11914418919fSjohnjiang 	TEST_LPM_ASSERT(status == 0);
11924418919fSjohnjiang 	TEST_LPM_ASSERT(next_hop_return == next_hop_ip_10_24);
11934418919fSjohnjiang 
11944418919fSjohnjiang 	rte_lpm_free(lpm);
11954418919fSjohnjiang 
11964418919fSjohnjiang 	return PASS;
11974418919fSjohnjiang }
11984418919fSjohnjiang 
11994418919fSjohnjiang /*
12004418919fSjohnjiang  * Test for recycle of tbl8
12014418919fSjohnjiang  *  - step 1: add a rule with depth=28 (> 24)
12024418919fSjohnjiang  *  - step 2: add a rule with same 24-bit prefix and depth=23 (< 24)
12034418919fSjohnjiang  *  - step 3: delete the first rule
12044418919fSjohnjiang  *  - step 4: check tbl8 is freed
12054418919fSjohnjiang  *  - step 5: add a rule same as the first one (depth=28)
12064418919fSjohnjiang  *  - step 6: check same tbl8 is allocated
12074418919fSjohnjiang  *  - step 7: add a rule with same 24-bit prefix and depth=24
12084418919fSjohnjiang  *  - step 8: delete the rule (depth=28) added in step 5
12094418919fSjohnjiang  *  - step 9: check tbl8 is freed
12104418919fSjohnjiang  *  - step 10: add a rule with same 24-bit prefix and depth = 28
12114418919fSjohnjiang  *  - setp 11: check same tbl8 is allocated again
12124418919fSjohnjiang  */
12134418919fSjohnjiang int32_t
test18(void)12144418919fSjohnjiang test18(void)
12154418919fSjohnjiang {
12164418919fSjohnjiang #define group_idx next_hop
12174418919fSjohnjiang 	struct rte_lpm *lpm = NULL;
12184418919fSjohnjiang 	struct rte_lpm_config config;
12194418919fSjohnjiang 	uint32_t ip, next_hop;
12204418919fSjohnjiang 	uint8_t depth;
12214418919fSjohnjiang 	uint32_t tbl8_group_index;
12224418919fSjohnjiang 
12234418919fSjohnjiang 	config.max_rules = MAX_RULES;
12244418919fSjohnjiang 	config.number_tbl8s = NUMBER_TBL8S;
12254418919fSjohnjiang 	config.flags = 0;
12264418919fSjohnjiang 
12274418919fSjohnjiang 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
12284418919fSjohnjiang 	TEST_LPM_ASSERT(lpm != NULL);
12294418919fSjohnjiang 
12304418919fSjohnjiang 	ip = RTE_IPV4(192, 168, 100, 100);
12314418919fSjohnjiang 	depth = 28;
12324418919fSjohnjiang 	next_hop = 1;
12334418919fSjohnjiang 	rte_lpm_add(lpm, ip, depth, next_hop);
12344418919fSjohnjiang 
12354418919fSjohnjiang 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
12364418919fSjohnjiang 	tbl8_group_index = lpm->tbl24[ip>>8].group_idx;
12374418919fSjohnjiang 
12384418919fSjohnjiang 	depth = 23;
12394418919fSjohnjiang 	next_hop = 2;
12404418919fSjohnjiang 	rte_lpm_add(lpm, ip, depth, next_hop);
12414418919fSjohnjiang 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
12424418919fSjohnjiang 
12434418919fSjohnjiang 	depth = 28;
12444418919fSjohnjiang 	rte_lpm_delete(lpm, ip, depth);
12454418919fSjohnjiang 
12464418919fSjohnjiang 	TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
12474418919fSjohnjiang 
12484418919fSjohnjiang 	next_hop = 3;
12494418919fSjohnjiang 	rte_lpm_add(lpm, ip, depth, next_hop);
12504418919fSjohnjiang 
12514418919fSjohnjiang 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
12524418919fSjohnjiang 	TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
12534418919fSjohnjiang 
12544418919fSjohnjiang 	depth = 24;
12554418919fSjohnjiang 	next_hop = 4;
12564418919fSjohnjiang 	rte_lpm_add(lpm, ip, depth, next_hop);
12574418919fSjohnjiang 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
12584418919fSjohnjiang 
12594418919fSjohnjiang 	depth = 28;
12604418919fSjohnjiang 	rte_lpm_delete(lpm, ip, depth);
12614418919fSjohnjiang 
12624418919fSjohnjiang 	TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid_group);
12634418919fSjohnjiang 
12644418919fSjohnjiang 	next_hop = 5;
12654418919fSjohnjiang 	rte_lpm_add(lpm, ip, depth, next_hop);
12664418919fSjohnjiang 
12674418919fSjohnjiang 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
12684418919fSjohnjiang 	TEST_LPM_ASSERT(tbl8_group_index == lpm->tbl24[ip>>8].group_idx);
12694418919fSjohnjiang 
12704418919fSjohnjiang 	rte_lpm_free(lpm);
12714418919fSjohnjiang #undef group_idx
12724418919fSjohnjiang 	return PASS;
12734418919fSjohnjiang }
12744418919fSjohnjiang 
12754418919fSjohnjiang /*
1276*2d9fd380Sjfb8856606  * rte_lpm_rcu_qsbr_add positive and negative tests.
1277*2d9fd380Sjfb8856606  *  - Add RCU QSBR variable to LPM
1278*2d9fd380Sjfb8856606  *  - Add another RCU QSBR variable to LPM
1279*2d9fd380Sjfb8856606  *  - Check returns
1280*2d9fd380Sjfb8856606  */
1281*2d9fd380Sjfb8856606 int32_t
test19(void)1282*2d9fd380Sjfb8856606 test19(void)
1283*2d9fd380Sjfb8856606 {
1284*2d9fd380Sjfb8856606 	struct rte_lpm *lpm = NULL;
1285*2d9fd380Sjfb8856606 	struct rte_lpm_config config;
1286*2d9fd380Sjfb8856606 	size_t sz;
1287*2d9fd380Sjfb8856606 	struct rte_rcu_qsbr *qsv;
1288*2d9fd380Sjfb8856606 	struct rte_rcu_qsbr *qsv2;
1289*2d9fd380Sjfb8856606 	int32_t status;
1290*2d9fd380Sjfb8856606 	struct rte_lpm_rcu_config rcu_cfg = {0};
1291*2d9fd380Sjfb8856606 
1292*2d9fd380Sjfb8856606 	config.max_rules = MAX_RULES;
1293*2d9fd380Sjfb8856606 	config.number_tbl8s = NUMBER_TBL8S;
1294*2d9fd380Sjfb8856606 	config.flags = 0;
1295*2d9fd380Sjfb8856606 
1296*2d9fd380Sjfb8856606 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1297*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(lpm != NULL);
1298*2d9fd380Sjfb8856606 
1299*2d9fd380Sjfb8856606 	/* Create RCU QSBR variable */
1300*2d9fd380Sjfb8856606 	sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
1301*2d9fd380Sjfb8856606 	qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1302*2d9fd380Sjfb8856606 					RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1303*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(qsv != NULL);
1304*2d9fd380Sjfb8856606 
1305*2d9fd380Sjfb8856606 	status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
1306*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1307*2d9fd380Sjfb8856606 
1308*2d9fd380Sjfb8856606 	rcu_cfg.v = qsv;
1309*2d9fd380Sjfb8856606 	/* Invalid QSBR mode */
1310*2d9fd380Sjfb8856606 	rcu_cfg.mode = 2;
1311*2d9fd380Sjfb8856606 	status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1312*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status != 0);
1313*2d9fd380Sjfb8856606 
1314*2d9fd380Sjfb8856606 	rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
1315*2d9fd380Sjfb8856606 	/* Attach RCU QSBR to LPM table */
1316*2d9fd380Sjfb8856606 	status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1317*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1318*2d9fd380Sjfb8856606 
1319*2d9fd380Sjfb8856606 	/* Create and attach another RCU QSBR to LPM table */
1320*2d9fd380Sjfb8856606 	qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1321*2d9fd380Sjfb8856606 					RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1322*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(qsv2 != NULL);
1323*2d9fd380Sjfb8856606 
1324*2d9fd380Sjfb8856606 	rcu_cfg.v = qsv2;
1325*2d9fd380Sjfb8856606 	rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
1326*2d9fd380Sjfb8856606 	status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1327*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status != 0);
1328*2d9fd380Sjfb8856606 
1329*2d9fd380Sjfb8856606 	rte_lpm_free(lpm);
1330*2d9fd380Sjfb8856606 	rte_free(qsv);
1331*2d9fd380Sjfb8856606 	rte_free(qsv2);
1332*2d9fd380Sjfb8856606 
1333*2d9fd380Sjfb8856606 	return PASS;
1334*2d9fd380Sjfb8856606 }
1335*2d9fd380Sjfb8856606 
1336*2d9fd380Sjfb8856606 /*
1337*2d9fd380Sjfb8856606  * rte_lpm_rcu_qsbr_add DQ mode functional test.
1338*2d9fd380Sjfb8856606  * Reader and writer are in the same thread in this test.
1339*2d9fd380Sjfb8856606  *  - Create LPM which supports 1 tbl8 group at max
1340*2d9fd380Sjfb8856606  *  - Add RCU QSBR variable to LPM
1341*2d9fd380Sjfb8856606  *  - Add a rule with depth=28 (> 24)
1342*2d9fd380Sjfb8856606  *  - Register a reader thread (not a real thread)
1343*2d9fd380Sjfb8856606  *  - Reader lookup existing rule
1344*2d9fd380Sjfb8856606  *  - Writer delete the rule
1345*2d9fd380Sjfb8856606  *  - Reader lookup the rule
1346*2d9fd380Sjfb8856606  *  - Writer re-add the rule (no available tbl8 group)
1347*2d9fd380Sjfb8856606  *  - Reader report quiescent state and unregister
1348*2d9fd380Sjfb8856606  *  - Writer re-add the rule
1349*2d9fd380Sjfb8856606  *  - Reader lookup the rule
1350*2d9fd380Sjfb8856606  */
1351*2d9fd380Sjfb8856606 int32_t
test20(void)1352*2d9fd380Sjfb8856606 test20(void)
1353*2d9fd380Sjfb8856606 {
1354*2d9fd380Sjfb8856606 	struct rte_lpm *lpm = NULL;
1355*2d9fd380Sjfb8856606 	struct rte_lpm_config config;
1356*2d9fd380Sjfb8856606 	size_t sz;
1357*2d9fd380Sjfb8856606 	struct rte_rcu_qsbr *qsv;
1358*2d9fd380Sjfb8856606 	int32_t status;
1359*2d9fd380Sjfb8856606 	uint32_t ip, next_hop, next_hop_return;
1360*2d9fd380Sjfb8856606 	uint8_t depth;
1361*2d9fd380Sjfb8856606 	struct rte_lpm_rcu_config rcu_cfg = {0};
1362*2d9fd380Sjfb8856606 
1363*2d9fd380Sjfb8856606 	config.max_rules = MAX_RULES;
1364*2d9fd380Sjfb8856606 	config.number_tbl8s = 1;
1365*2d9fd380Sjfb8856606 	config.flags = 0;
1366*2d9fd380Sjfb8856606 
1367*2d9fd380Sjfb8856606 	lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1368*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(lpm != NULL);
1369*2d9fd380Sjfb8856606 
1370*2d9fd380Sjfb8856606 	/* Create RCU QSBR variable */
1371*2d9fd380Sjfb8856606 	sz = rte_rcu_qsbr_get_memsize(1);
1372*2d9fd380Sjfb8856606 	qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1373*2d9fd380Sjfb8856606 				RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1374*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(qsv != NULL);
1375*2d9fd380Sjfb8856606 
1376*2d9fd380Sjfb8856606 	status = rte_rcu_qsbr_init(qsv, 1);
1377*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1378*2d9fd380Sjfb8856606 
1379*2d9fd380Sjfb8856606 	rcu_cfg.v = qsv;
1380*2d9fd380Sjfb8856606 	rcu_cfg.mode = RTE_LPM_QSBR_MODE_DQ;
1381*2d9fd380Sjfb8856606 	/* Attach RCU QSBR to LPM table */
1382*2d9fd380Sjfb8856606 	status = rte_lpm_rcu_qsbr_add(lpm, &rcu_cfg);
1383*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1384*2d9fd380Sjfb8856606 
1385*2d9fd380Sjfb8856606 	ip = RTE_IPV4(192, 0, 2, 100);
1386*2d9fd380Sjfb8856606 	depth = 28;
1387*2d9fd380Sjfb8856606 	next_hop = 1;
1388*2d9fd380Sjfb8856606 	status = rte_lpm_add(lpm, ip, depth, next_hop);
1389*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1390*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(lpm->tbl24[ip>>8].valid_group);
1391*2d9fd380Sjfb8856606 
1392*2d9fd380Sjfb8856606 	/* Register pseudo reader */
1393*2d9fd380Sjfb8856606 	status = rte_rcu_qsbr_thread_register(qsv, 0);
1394*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1395*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_online(qsv, 0);
1396*2d9fd380Sjfb8856606 
1397*2d9fd380Sjfb8856606 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1398*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1399*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(next_hop_return == next_hop);
1400*2d9fd380Sjfb8856606 
1401*2d9fd380Sjfb8856606 	/* Writer update */
1402*2d9fd380Sjfb8856606 	status = rte_lpm_delete(lpm, ip, depth);
1403*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1404*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(!lpm->tbl24[ip>>8].valid);
1405*2d9fd380Sjfb8856606 
1406*2d9fd380Sjfb8856606 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1407*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status != 0);
1408*2d9fd380Sjfb8856606 
1409*2d9fd380Sjfb8856606 	status = rte_lpm_add(lpm, ip, depth, next_hop);
1410*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status != 0);
1411*2d9fd380Sjfb8856606 
1412*2d9fd380Sjfb8856606 	/* Reader quiescent */
1413*2d9fd380Sjfb8856606 	rte_rcu_qsbr_quiescent(qsv, 0);
1414*2d9fd380Sjfb8856606 
1415*2d9fd380Sjfb8856606 	status = rte_lpm_add(lpm, ip, depth, next_hop);
1416*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1417*2d9fd380Sjfb8856606 
1418*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_offline(qsv, 0);
1419*2d9fd380Sjfb8856606 	status = rte_rcu_qsbr_thread_unregister(qsv, 0);
1420*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1421*2d9fd380Sjfb8856606 
1422*2d9fd380Sjfb8856606 	status = rte_lpm_lookup(lpm, ip, &next_hop_return);
1423*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1424*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(next_hop_return == next_hop);
1425*2d9fd380Sjfb8856606 
1426*2d9fd380Sjfb8856606 	rte_lpm_free(lpm);
1427*2d9fd380Sjfb8856606 	rte_free(qsv);
1428*2d9fd380Sjfb8856606 
1429*2d9fd380Sjfb8856606 	return PASS;
1430*2d9fd380Sjfb8856606 }
1431*2d9fd380Sjfb8856606 
1432*2d9fd380Sjfb8856606 static struct rte_lpm *g_lpm;
1433*2d9fd380Sjfb8856606 static struct rte_rcu_qsbr *g_v;
1434*2d9fd380Sjfb8856606 static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
1435*2d9fd380Sjfb8856606 static volatile uint8_t writer_done;
1436*2d9fd380Sjfb8856606 /* Report quiescent state interval every 1024 lookups. Larger critical
1437*2d9fd380Sjfb8856606  * sections in reader will result in writer polling multiple times.
1438*2d9fd380Sjfb8856606  */
1439*2d9fd380Sjfb8856606 #define QSBR_REPORTING_INTERVAL 1024
1440*2d9fd380Sjfb8856606 #define WRITER_ITERATIONS	512
1441*2d9fd380Sjfb8856606 
1442*2d9fd380Sjfb8856606 /*
1443*2d9fd380Sjfb8856606  * Reader thread using rte_lpm data structure with RCU.
1444*2d9fd380Sjfb8856606  */
1445*2d9fd380Sjfb8856606 static int
test_lpm_rcu_qsbr_reader(void * arg)1446*2d9fd380Sjfb8856606 test_lpm_rcu_qsbr_reader(void *arg)
1447*2d9fd380Sjfb8856606 {
1448*2d9fd380Sjfb8856606 	int i;
1449*2d9fd380Sjfb8856606 	uint32_t next_hop_return = 0;
1450*2d9fd380Sjfb8856606 
1451*2d9fd380Sjfb8856606 	RTE_SET_USED(arg);
1452*2d9fd380Sjfb8856606 	/* Register this thread to report quiescent state */
1453*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_register(g_v, 0);
1454*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_online(g_v, 0);
1455*2d9fd380Sjfb8856606 
1456*2d9fd380Sjfb8856606 	do {
1457*2d9fd380Sjfb8856606 		for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
1458*2d9fd380Sjfb8856606 			rte_lpm_lookup(g_lpm, g_ip, &next_hop_return);
1459*2d9fd380Sjfb8856606 
1460*2d9fd380Sjfb8856606 		/* Update quiescent state */
1461*2d9fd380Sjfb8856606 		rte_rcu_qsbr_quiescent(g_v, 0);
1462*2d9fd380Sjfb8856606 	} while (!writer_done);
1463*2d9fd380Sjfb8856606 
1464*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_offline(g_v, 0);
1465*2d9fd380Sjfb8856606 	rte_rcu_qsbr_thread_unregister(g_v, 0);
1466*2d9fd380Sjfb8856606 
1467*2d9fd380Sjfb8856606 	return 0;
1468*2d9fd380Sjfb8856606 }
1469*2d9fd380Sjfb8856606 
1470*2d9fd380Sjfb8856606 /*
1471*2d9fd380Sjfb8856606  * rte_lpm_rcu_qsbr_add sync mode functional test.
1472*2d9fd380Sjfb8856606  * 1 Reader and 1 writer. They cannot be in the same thread in this test.
1473*2d9fd380Sjfb8856606  *  - Create LPM which supports 1 tbl8 group at max
1474*2d9fd380Sjfb8856606  *  - Add RCU QSBR variable with sync mode to LPM
1475*2d9fd380Sjfb8856606  *  - Register a reader thread. Reader keeps looking up a specific rule.
1476*2d9fd380Sjfb8856606  *  - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
1477*2d9fd380Sjfb8856606  */
1478*2d9fd380Sjfb8856606 int32_t
test21(void)1479*2d9fd380Sjfb8856606 test21(void)
1480*2d9fd380Sjfb8856606 {
1481*2d9fd380Sjfb8856606 	struct rte_lpm_config config;
1482*2d9fd380Sjfb8856606 	size_t sz;
1483*2d9fd380Sjfb8856606 	int32_t status;
1484*2d9fd380Sjfb8856606 	uint32_t i, next_hop;
1485*2d9fd380Sjfb8856606 	uint8_t depth;
1486*2d9fd380Sjfb8856606 	struct rte_lpm_rcu_config rcu_cfg = {0};
1487*2d9fd380Sjfb8856606 
1488*2d9fd380Sjfb8856606 	if (rte_lcore_count() < 2) {
1489*2d9fd380Sjfb8856606 		printf("Not enough cores for %s, expecting at least 2\n",
1490*2d9fd380Sjfb8856606 			__func__);
1491*2d9fd380Sjfb8856606 		return TEST_SKIPPED;
1492*2d9fd380Sjfb8856606 	}
1493*2d9fd380Sjfb8856606 
1494*2d9fd380Sjfb8856606 	config.max_rules = MAX_RULES;
1495*2d9fd380Sjfb8856606 	config.number_tbl8s = 1;
1496*2d9fd380Sjfb8856606 	config.flags = 0;
1497*2d9fd380Sjfb8856606 
1498*2d9fd380Sjfb8856606 	g_lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
1499*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(g_lpm != NULL);
1500*2d9fd380Sjfb8856606 
1501*2d9fd380Sjfb8856606 	/* Create RCU QSBR variable */
1502*2d9fd380Sjfb8856606 	sz = rte_rcu_qsbr_get_memsize(1);
1503*2d9fd380Sjfb8856606 	g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz,
1504*2d9fd380Sjfb8856606 				RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
1505*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(g_v != NULL);
1506*2d9fd380Sjfb8856606 
1507*2d9fd380Sjfb8856606 	status = rte_rcu_qsbr_init(g_v, 1);
1508*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1509*2d9fd380Sjfb8856606 
1510*2d9fd380Sjfb8856606 	rcu_cfg.v = g_v;
1511*2d9fd380Sjfb8856606 	rcu_cfg.mode = RTE_LPM_QSBR_MODE_SYNC;
1512*2d9fd380Sjfb8856606 	/* Attach RCU QSBR to LPM table */
1513*2d9fd380Sjfb8856606 	status = rte_lpm_rcu_qsbr_add(g_lpm, &rcu_cfg);
1514*2d9fd380Sjfb8856606 	TEST_LPM_ASSERT(status == 0);
1515*2d9fd380Sjfb8856606 
1516*2d9fd380Sjfb8856606 	writer_done = 0;
1517*2d9fd380Sjfb8856606 	/* Launch reader thread */
1518*2d9fd380Sjfb8856606 	rte_eal_remote_launch(test_lpm_rcu_qsbr_reader, NULL,
1519*2d9fd380Sjfb8856606 				rte_get_next_lcore(-1, 1, 0));
1520*2d9fd380Sjfb8856606 
1521*2d9fd380Sjfb8856606 	depth = 28;
1522*2d9fd380Sjfb8856606 	next_hop = 1;
1523*2d9fd380Sjfb8856606 	status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
1524*2d9fd380Sjfb8856606 	if (status != 0) {
1525*2d9fd380Sjfb8856606 		printf("%s: Failed to add rule\n", __func__);
1526*2d9fd380Sjfb8856606 		goto error;
1527*2d9fd380Sjfb8856606 	}
1528*2d9fd380Sjfb8856606 
1529*2d9fd380Sjfb8856606 	/* Writer update */
1530*2d9fd380Sjfb8856606 	for (i = 0; i < WRITER_ITERATIONS; i++) {
1531*2d9fd380Sjfb8856606 		status = rte_lpm_delete(g_lpm, g_ip, depth);
1532*2d9fd380Sjfb8856606 		if (status != 0) {
1533*2d9fd380Sjfb8856606 			printf("%s: Failed to delete rule at iteration %d\n",
1534*2d9fd380Sjfb8856606 				__func__, i);
1535*2d9fd380Sjfb8856606 			goto error;
1536*2d9fd380Sjfb8856606 		}
1537*2d9fd380Sjfb8856606 
1538*2d9fd380Sjfb8856606 		status = rte_lpm_add(g_lpm, g_ip, depth, next_hop);
1539*2d9fd380Sjfb8856606 		if (status != 0) {
1540*2d9fd380Sjfb8856606 			printf("%s: Failed to add rule at iteration %d\n",
1541*2d9fd380Sjfb8856606 				__func__, i);
1542*2d9fd380Sjfb8856606 			goto error;
1543*2d9fd380Sjfb8856606 		}
1544*2d9fd380Sjfb8856606 	}
1545*2d9fd380Sjfb8856606 
1546*2d9fd380Sjfb8856606 error:
1547*2d9fd380Sjfb8856606 	writer_done = 1;
1548*2d9fd380Sjfb8856606 	/* Wait until reader exited. */
1549*2d9fd380Sjfb8856606 	rte_eal_mp_wait_lcore();
1550*2d9fd380Sjfb8856606 
1551*2d9fd380Sjfb8856606 	rte_lpm_free(g_lpm);
1552*2d9fd380Sjfb8856606 	rte_free(g_v);
1553*2d9fd380Sjfb8856606 
1554*2d9fd380Sjfb8856606 	return (status == 0) ? PASS : -1;
1555*2d9fd380Sjfb8856606 }
1556*2d9fd380Sjfb8856606 
1557*2d9fd380Sjfb8856606 /*
15584418919fSjohnjiang  * Do all unit tests.
15594418919fSjohnjiang  */
15604418919fSjohnjiang 
15614418919fSjohnjiang static int
test_lpm(void)15624418919fSjohnjiang test_lpm(void)
15634418919fSjohnjiang {
15644418919fSjohnjiang 	unsigned i;
15654418919fSjohnjiang 	int status, global_status = 0;
15664418919fSjohnjiang 
1567*2d9fd380Sjfb8856606 	for (i = 0; i < RTE_DIM(tests); i++) {
15684418919fSjohnjiang 		status = tests[i]();
15694418919fSjohnjiang 		if (status < 0) {
15704418919fSjohnjiang 			printf("ERROR: LPM Test %u: FAIL\n", i);
15714418919fSjohnjiang 			global_status = status;
15724418919fSjohnjiang 		}
15734418919fSjohnjiang 	}
15744418919fSjohnjiang 
15754418919fSjohnjiang 	return global_status;
15764418919fSjohnjiang }
15774418919fSjohnjiang 
15784418919fSjohnjiang REGISTER_TEST_COMMAND(lpm_autotest, test_lpm);
1579