xref: /dpdk/app/test/test_fib.c (revision 259deb73d989d91cb1ddb8c60c24de58aa09609a)
14ccd4259SVladimir Medvedkin /* SPDX-License-Identifier: BSD-3-Clause
24ccd4259SVladimir Medvedkin  * Copyright(c) 2018 Vladimir Medvedkin <medvedkinv@gmail.com>
34ccd4259SVladimir Medvedkin  * Copyright(c) 2019 Intel Corporation
44ccd4259SVladimir Medvedkin  */
54ccd4259SVladimir Medvedkin 
64ccd4259SVladimir Medvedkin #include <stdio.h>
74ccd4259SVladimir Medvedkin #include <stdint.h>
84ccd4259SVladimir Medvedkin #include <stdlib.h>
94ccd4259SVladimir Medvedkin 
104ccd4259SVladimir Medvedkin #include <rte_ip.h>
114ccd4259SVladimir Medvedkin #include <rte_log.h>
12233b41c2SStephen Hemminger #include <rte_fib.h>
1396c3d06aSVladimir Medvedkin #include <rte_malloc.h>
144ccd4259SVladimir Medvedkin 
154ccd4259SVladimir Medvedkin #include "test.h"
164ccd4259SVladimir Medvedkin 
174ccd4259SVladimir Medvedkin typedef int32_t (*rte_fib_test)(void);
184ccd4259SVladimir Medvedkin 
194ccd4259SVladimir Medvedkin static int32_t test_create_invalid(void);
204ccd4259SVladimir Medvedkin static int32_t test_multiple_create(void);
214ccd4259SVladimir Medvedkin static int32_t test_free_null(void);
224ccd4259SVladimir Medvedkin static int32_t test_add_del_invalid(void);
234ccd4259SVladimir Medvedkin static int32_t test_get_invalid(void);
244ccd4259SVladimir Medvedkin static int32_t test_lookup(void);
2596c3d06aSVladimir Medvedkin static int32_t test_invalid_rcu(void);
2696c3d06aSVladimir Medvedkin static int32_t test_fib_rcu_sync_rw(void);
274ccd4259SVladimir Medvedkin 
284ccd4259SVladimir Medvedkin #define MAX_ROUTES	(1 << 16)
294ccd4259SVladimir Medvedkin #define MAX_TBL8	(1 << 15)
304ccd4259SVladimir Medvedkin 
314ccd4259SVladimir Medvedkin /*
324ccd4259SVladimir Medvedkin  * Check that rte_fib_create fails gracefully for incorrect user input
334ccd4259SVladimir Medvedkin  * arguments
344ccd4259SVladimir Medvedkin  */
354ccd4259SVladimir Medvedkin int32_t
364ccd4259SVladimir Medvedkin test_create_invalid(void)
374ccd4259SVladimir Medvedkin {
384ccd4259SVladimir Medvedkin 	struct rte_fib *fib = NULL;
39e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config = { 0 };
404ccd4259SVladimir Medvedkin 
414ccd4259SVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
4211c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
434ccd4259SVladimir Medvedkin 	config.default_nh = 0;
444ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
454ccd4259SVladimir Medvedkin 
464ccd4259SVladimir Medvedkin 	/* rte_fib_create: fib name == NULL */
474ccd4259SVladimir Medvedkin 	fib = rte_fib_create(NULL, SOCKET_ID_ANY, &config);
484ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
494ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
504ccd4259SVladimir Medvedkin 
514ccd4259SVladimir Medvedkin 	/* rte_fib_create: config == NULL */
524ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, NULL);
534ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
544ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
554ccd4259SVladimir Medvedkin 
564ccd4259SVladimir Medvedkin 	/* socket_id < -1 is invalid */
574ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, -2, &config);
584ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
594ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
604ccd4259SVladimir Medvedkin 
614ccd4259SVladimir Medvedkin 	/* rte_fib_create: max_routes = 0 */
624ccd4259SVladimir Medvedkin 	config.max_routes = 0;
634ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
644ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
654ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
664ccd4259SVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
674ccd4259SVladimir Medvedkin 
684f66d3beSVladimir Medvedkin 	config.type = RTE_FIB_DIR24_8 + 1;
694ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
704ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
714ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
724ccd4259SVladimir Medvedkin 
734ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DIR24_8;
744ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = MAX_TBL8;
754ccd4259SVladimir Medvedkin 
764ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B + 1;
774ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
784ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
794ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
804ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
814ccd4259SVladimir Medvedkin 
824ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = 0;
834ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
844ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib == NULL,
854ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
864ccd4259SVladimir Medvedkin 
874ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
884ccd4259SVladimir Medvedkin }
894ccd4259SVladimir Medvedkin 
904ccd4259SVladimir Medvedkin /*
914ccd4259SVladimir Medvedkin  * Create fib table then delete fib table 10 times
924ccd4259SVladimir Medvedkin  * Use a slightly different rules size each time
934ccd4259SVladimir Medvedkin  */
944ccd4259SVladimir Medvedkin int32_t
954ccd4259SVladimir Medvedkin test_multiple_create(void)
964ccd4259SVladimir Medvedkin {
974ccd4259SVladimir Medvedkin 	struct rte_fib *fib = NULL;
98e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config = { 0 };
994ccd4259SVladimir Medvedkin 	int32_t i;
1004ccd4259SVladimir Medvedkin 
10111c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
1024ccd4259SVladimir Medvedkin 	config.default_nh = 0;
1034ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
1044ccd4259SVladimir Medvedkin 
1054ccd4259SVladimir Medvedkin 	for (i = 0; i < 100; i++) {
1064ccd4259SVladimir Medvedkin 		config.max_routes = MAX_ROUTES - i;
1074ccd4259SVladimir Medvedkin 		fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
1084ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
1094ccd4259SVladimir Medvedkin 		rte_fib_free(fib);
1104ccd4259SVladimir Medvedkin 	}
1114ccd4259SVladimir Medvedkin 	/* Can not test free so return success */
1124ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
1134ccd4259SVladimir Medvedkin }
1144ccd4259SVladimir Medvedkin 
1154ccd4259SVladimir Medvedkin /*
1164ccd4259SVladimir Medvedkin  * Call rte_fib_free for NULL pointer user input. Note: free has no return and
1174ccd4259SVladimir Medvedkin  * therefore it is impossible to check for failure but this test is added to
1184ccd4259SVladimir Medvedkin  * increase function coverage metrics and to validate that freeing null does
1194ccd4259SVladimir Medvedkin  * not crash.
1204ccd4259SVladimir Medvedkin  */
1214ccd4259SVladimir Medvedkin int32_t
1224ccd4259SVladimir Medvedkin test_free_null(void)
1234ccd4259SVladimir Medvedkin {
1244ccd4259SVladimir Medvedkin 	struct rte_fib *fib = NULL;
125e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config = { 0 };
1264ccd4259SVladimir Medvedkin 
1274ccd4259SVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
12811c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
1294ccd4259SVladimir Medvedkin 	config.default_nh = 0;
1304ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
1314ccd4259SVladimir Medvedkin 
1324ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
1334ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
1344ccd4259SVladimir Medvedkin 
1354ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
1364ccd4259SVladimir Medvedkin 	rte_fib_free(NULL);
1374ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
1384ccd4259SVladimir Medvedkin }
1394ccd4259SVladimir Medvedkin 
1404ccd4259SVladimir Medvedkin /*
1414ccd4259SVladimir Medvedkin  * Check that rte_fib_add and rte_fib_delete fails gracefully
1424ccd4259SVladimir Medvedkin  * for incorrect user input arguments
1434ccd4259SVladimir Medvedkin  */
1444ccd4259SVladimir Medvedkin int32_t
1454ccd4259SVladimir Medvedkin test_add_del_invalid(void)
1464ccd4259SVladimir Medvedkin {
1474ccd4259SVladimir Medvedkin 	struct rte_fib *fib = NULL;
148e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config = { 0 };
1494ccd4259SVladimir Medvedkin 	uint64_t nh = 100;
1504ccd4259SVladimir Medvedkin 	uint32_t ip = RTE_IPV4(0, 0, 0, 0);
1514ccd4259SVladimir Medvedkin 	int ret;
1524ccd4259SVladimir Medvedkin 	uint8_t depth = 24;
1534ccd4259SVladimir Medvedkin 
1544ccd4259SVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
15511c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
1564ccd4259SVladimir Medvedkin 	config.default_nh = 0;
1574ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
1584ccd4259SVladimir Medvedkin 
1594ccd4259SVladimir Medvedkin 	/* rte_fib_add: fib == NULL */
1604ccd4259SVladimir Medvedkin 	ret = rte_fib_add(NULL, ip, depth, nh);
1614ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret < 0,
1624ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
1634ccd4259SVladimir Medvedkin 
1644ccd4259SVladimir Medvedkin 	/* rte_fib_delete: fib == NULL */
1654ccd4259SVladimir Medvedkin 	ret = rte_fib_delete(NULL, ip, depth);
1664ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret < 0,
1674ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
1684ccd4259SVladimir Medvedkin 
1694ccd4259SVladimir Medvedkin 	/*Create valid fib to use in rest of test. */
1704ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
1714ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
1724ccd4259SVladimir Medvedkin 
1734ccd4259SVladimir Medvedkin 	/* rte_fib_add: depth > RTE_FIB_MAXDEPTH */
1744ccd4259SVladimir Medvedkin 	ret = rte_fib_add(fib, ip, RTE_FIB_MAXDEPTH + 1, nh);
1754ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret < 0,
1764ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
1774ccd4259SVladimir Medvedkin 
1784ccd4259SVladimir Medvedkin 	/* rte_fib_delete: depth > RTE_FIB_MAXDEPTH */
1794ccd4259SVladimir Medvedkin 	ret = rte_fib_delete(fib, ip, RTE_FIB_MAXDEPTH + 1);
1804ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret < 0,
1814ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
1824ccd4259SVladimir Medvedkin 
1834ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
1844ccd4259SVladimir Medvedkin 
1854ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
1864ccd4259SVladimir Medvedkin }
1874ccd4259SVladimir Medvedkin 
1884ccd4259SVladimir Medvedkin /*
1894ccd4259SVladimir Medvedkin  * Check that rte_fib_get_dp and rte_fib_get_rib fails gracefully
1904ccd4259SVladimir Medvedkin  * for incorrect user input arguments
1914ccd4259SVladimir Medvedkin  */
1924ccd4259SVladimir Medvedkin int32_t
1934ccd4259SVladimir Medvedkin test_get_invalid(void)
1944ccd4259SVladimir Medvedkin {
1954ccd4259SVladimir Medvedkin 	void *p;
1964ccd4259SVladimir Medvedkin 
1974ccd4259SVladimir Medvedkin 	p = rte_fib_get_dp(NULL);
1984ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(p == NULL,
1994ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
2004ccd4259SVladimir Medvedkin 
2014ccd4259SVladimir Medvedkin 	p = rte_fib_get_rib(NULL);
2024ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(p == NULL,
2034ccd4259SVladimir Medvedkin 		"Call succeeded with invalid parameters\n");
2044ccd4259SVladimir Medvedkin 
2054ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
2064ccd4259SVladimir Medvedkin }
2074ccd4259SVladimir Medvedkin 
2084ccd4259SVladimir Medvedkin /*
2094ccd4259SVladimir Medvedkin  * Add routes for one supernet with all possible depths and do lookup
2104ccd4259SVladimir Medvedkin  * on each step
2114ccd4259SVladimir Medvedkin  * After delete routes with doing lookup on each step
2124ccd4259SVladimir Medvedkin  */
2134ccd4259SVladimir Medvedkin static int
2144ccd4259SVladimir Medvedkin lookup_and_check_asc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
2154ccd4259SVladimir Medvedkin 	uint32_t ip_missing, uint64_t def_nh, uint32_t n)
2164ccd4259SVladimir Medvedkin {
2174ccd4259SVladimir Medvedkin 	uint64_t nh_arr[RTE_FIB_MAXDEPTH];
2184ccd4259SVladimir Medvedkin 	int ret;
2194ccd4259SVladimir Medvedkin 	uint32_t i = 0;
2204ccd4259SVladimir Medvedkin 
2214ccd4259SVladimir Medvedkin 	ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
2224ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
2234ccd4259SVladimir Medvedkin 
2244ccd4259SVladimir Medvedkin 	for (; i <= RTE_FIB_MAXDEPTH - n; i++)
2254ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(nh_arr[i] == n,
2264ccd4259SVladimir Medvedkin 			"Failed to get proper nexthop\n");
2274ccd4259SVladimir Medvedkin 
2284ccd4259SVladimir Medvedkin 	for (; i < RTE_FIB_MAXDEPTH; i++)
2294ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(nh_arr[i] == --n,
2304ccd4259SVladimir Medvedkin 			"Failed to get proper nexthop\n");
2314ccd4259SVladimir Medvedkin 
2324ccd4259SVladimir Medvedkin 	ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
2334ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
2344ccd4259SVladimir Medvedkin 		"Failed to get proper nexthop\n");
2354ccd4259SVladimir Medvedkin 
2364ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
2374ccd4259SVladimir Medvedkin }
2384ccd4259SVladimir Medvedkin 
2394ccd4259SVladimir Medvedkin static int
2404ccd4259SVladimir Medvedkin lookup_and_check_desc(struct rte_fib *fib, uint32_t ip_arr[RTE_FIB_MAXDEPTH],
2414ccd4259SVladimir Medvedkin 	uint32_t ip_missing, uint64_t def_nh, uint32_t n)
2424ccd4259SVladimir Medvedkin {
2434ccd4259SVladimir Medvedkin 	uint64_t nh_arr[RTE_FIB_MAXDEPTH];
2444ccd4259SVladimir Medvedkin 	int ret;
2454ccd4259SVladimir Medvedkin 	uint32_t i = 0;
2464ccd4259SVladimir Medvedkin 
2474ccd4259SVladimir Medvedkin 	ret = rte_fib_lookup_bulk(fib, ip_arr, nh_arr, RTE_FIB_MAXDEPTH);
2484ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Failed to lookup\n");
2494ccd4259SVladimir Medvedkin 
2504ccd4259SVladimir Medvedkin 	for (; i < n; i++)
2514ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(nh_arr[i] == RTE_FIB_MAXDEPTH - i,
2524ccd4259SVladimir Medvedkin 			"Failed to get proper nexthop\n");
2534ccd4259SVladimir Medvedkin 
2544ccd4259SVladimir Medvedkin 	for (; i < RTE_FIB_MAXDEPTH; i++)
2554ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(nh_arr[i] == def_nh,
2564ccd4259SVladimir Medvedkin 			"Failed to get proper nexthop\n");
2574ccd4259SVladimir Medvedkin 
2584ccd4259SVladimir Medvedkin 	ret = rte_fib_lookup_bulk(fib, &ip_missing, nh_arr, 1);
2594ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT((ret == 0) && (nh_arr[0] == def_nh),
2604ccd4259SVladimir Medvedkin 		"Failed to get proper nexthop\n");
2614ccd4259SVladimir Medvedkin 
2624ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
2634ccd4259SVladimir Medvedkin }
2644ccd4259SVladimir Medvedkin 
2654ccd4259SVladimir Medvedkin static int
2664ccd4259SVladimir Medvedkin check_fib(struct rte_fib *fib)
2674ccd4259SVladimir Medvedkin {
2684ccd4259SVladimir Medvedkin 	uint64_t def_nh = 100;
2694ccd4259SVladimir Medvedkin 	uint32_t ip_arr[RTE_FIB_MAXDEPTH];
2704ccd4259SVladimir Medvedkin 	uint32_t ip_add = RTE_IPV4(128, 0, 0, 0);
2714ccd4259SVladimir Medvedkin 	uint32_t i, ip_missing = RTE_IPV4(127, 255, 255, 255);
2724ccd4259SVladimir Medvedkin 	int ret;
2734ccd4259SVladimir Medvedkin 
2744ccd4259SVladimir Medvedkin 	for (i = 0; i < RTE_FIB_MAXDEPTH; i++)
2754ccd4259SVladimir Medvedkin 		ip_arr[i] = ip_add + (1ULL << i) - 1;
2764ccd4259SVladimir Medvedkin 
2774ccd4259SVladimir Medvedkin 	ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
2784ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
2794ccd4259SVladimir Medvedkin 
2804ccd4259SVladimir Medvedkin 	for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
2814ccd4259SVladimir Medvedkin 		ret = rte_fib_add(fib, ip_add, i, i);
2824ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
2834ccd4259SVladimir Medvedkin 		ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
2844ccd4259SVladimir Medvedkin 				def_nh, i);
2854ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
2864ccd4259SVladimir Medvedkin 	}
2874ccd4259SVladimir Medvedkin 
2884ccd4259SVladimir Medvedkin 	for (i = RTE_FIB_MAXDEPTH; i > 1; i--) {
2894ccd4259SVladimir Medvedkin 		ret = rte_fib_delete(fib, ip_add, i);
2904ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
2914ccd4259SVladimir Medvedkin 		ret = lookup_and_check_asc(fib, ip_arr, ip_missing,
2924ccd4259SVladimir Medvedkin 			def_nh, i - 1);
2934ccd4259SVladimir Medvedkin 
2944ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
2954ccd4259SVladimir Medvedkin 	}
2964ccd4259SVladimir Medvedkin 	ret = rte_fib_delete(fib, ip_add, i);
2974ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
2984ccd4259SVladimir Medvedkin 	ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh, 0);
2994ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
3004ccd4259SVladimir Medvedkin 
3014ccd4259SVladimir Medvedkin 	for (i = 0; i < RTE_FIB_MAXDEPTH; i++) {
3024ccd4259SVladimir Medvedkin 		ret = rte_fib_add(fib, ip_add, RTE_FIB_MAXDEPTH - i,
3034ccd4259SVladimir Medvedkin 			RTE_FIB_MAXDEPTH - i);
3044ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == 0, "Failed to add a route\n");
3054ccd4259SVladimir Medvedkin 		ret = lookup_and_check_desc(fib, ip_arr, ip_missing,
3064ccd4259SVladimir Medvedkin 			def_nh, i + 1);
3074ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
3084ccd4259SVladimir Medvedkin 	}
3094ccd4259SVladimir Medvedkin 
3104ccd4259SVladimir Medvedkin 	for (i = 1; i <= RTE_FIB_MAXDEPTH; i++) {
3114ccd4259SVladimir Medvedkin 		ret = rte_fib_delete(fib, ip_add, i);
3124ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == 0, "Failed to delete a route\n");
3134ccd4259SVladimir Medvedkin 		ret = lookup_and_check_desc(fib, ip_arr, ip_missing, def_nh,
3144ccd4259SVladimir Medvedkin 			RTE_FIB_MAXDEPTH - i);
3154ccd4259SVladimir Medvedkin 		RTE_TEST_ASSERT(ret == TEST_SUCCESS, "Lookup and check fails\n");
3164ccd4259SVladimir Medvedkin 	}
3174ccd4259SVladimir Medvedkin 
3184ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
3194ccd4259SVladimir Medvedkin }
3204ccd4259SVladimir Medvedkin 
3214ccd4259SVladimir Medvedkin int32_t
3224ccd4259SVladimir Medvedkin test_lookup(void)
3234ccd4259SVladimir Medvedkin {
3244ccd4259SVladimir Medvedkin 	struct rte_fib *fib = NULL;
325e194f3cdSVladimir Medvedkin 	struct rte_fib_conf config = { 0 };
3264ccd4259SVladimir Medvedkin 	uint64_t def_nh = 100;
3274ccd4259SVladimir Medvedkin 	int ret;
3284ccd4259SVladimir Medvedkin 
3294ccd4259SVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
33011c5b9b5SVladimir Medvedkin 	config.rib_ext_sz = 0;
3314ccd4259SVladimir Medvedkin 	config.default_nh = def_nh;
3324ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
3334ccd4259SVladimir Medvedkin 
3344ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
3354ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
3364ccd4259SVladimir Medvedkin 	ret = check_fib(fib);
3374ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
3384ccd4259SVladimir Medvedkin 		"Check_fib fails for DUMMY type\n");
3394ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
3404ccd4259SVladimir Medvedkin 
3414ccd4259SVladimir Medvedkin 	config.type = RTE_FIB_DIR24_8;
3424ccd4259SVladimir Medvedkin 
3434ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_1B;
3444ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = 127;
3454ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
3464ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
3474ccd4259SVladimir Medvedkin 	ret = check_fib(fib);
3484ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
3494ccd4259SVladimir Medvedkin 		"Check_fib fails for DIR24_8_1B type\n");
3504ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
3514ccd4259SVladimir Medvedkin 
3524ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_2B;
3534ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = MAX_TBL8 - 1;
3544ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
3554ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
3564ccd4259SVladimir Medvedkin 	ret = check_fib(fib);
3574ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
3584ccd4259SVladimir Medvedkin 		"Check_fib fails for DIR24_8_2B type\n");
3594ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
3604ccd4259SVladimir Medvedkin 
3614ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
3624ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = MAX_TBL8;
3634ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
3644ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
3654ccd4259SVladimir Medvedkin 	ret = check_fib(fib);
3664ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
3674ccd4259SVladimir Medvedkin 		"Check_fib fails for DIR24_8_4B type\n");
3684ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
3694ccd4259SVladimir Medvedkin 
3704ccd4259SVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_8B;
3714ccd4259SVladimir Medvedkin 	config.dir24_8.num_tbl8 = MAX_TBL8;
3724ccd4259SVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
3734ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
3744ccd4259SVladimir Medvedkin 	ret = check_fib(fib);
3754ccd4259SVladimir Medvedkin 	RTE_TEST_ASSERT(ret == TEST_SUCCESS,
3764ccd4259SVladimir Medvedkin 		"Check_fib fails for DIR24_8_8B type\n");
3774ccd4259SVladimir Medvedkin 	rte_fib_free(fib);
3784ccd4259SVladimir Medvedkin 
3794ccd4259SVladimir Medvedkin 	return TEST_SUCCESS;
3804ccd4259SVladimir Medvedkin }
3814ccd4259SVladimir Medvedkin 
38296c3d06aSVladimir Medvedkin /*
38396c3d06aSVladimir Medvedkin  * rte_fib_rcu_qsbr_add positive and negative tests.
38496c3d06aSVladimir Medvedkin  *  - Add RCU QSBR variable to FIB
38596c3d06aSVladimir Medvedkin  *  - Add another RCU QSBR variable to FIB
38696c3d06aSVladimir Medvedkin  *  - Check returns
38796c3d06aSVladimir Medvedkin  */
38896c3d06aSVladimir Medvedkin int32_t
38996c3d06aSVladimir Medvedkin test_invalid_rcu(void)
39096c3d06aSVladimir Medvedkin {
39196c3d06aSVladimir Medvedkin 	struct rte_fib *fib = NULL;
39219d463aaSDavid Marchand 	struct rte_fib_conf config = { 0 };
39396c3d06aSVladimir Medvedkin 	size_t sz;
39496c3d06aSVladimir Medvedkin 	struct rte_rcu_qsbr *qsv;
39596c3d06aSVladimir Medvedkin 	struct rte_rcu_qsbr *qsv2;
39696c3d06aSVladimir Medvedkin 	int32_t status;
39796c3d06aSVladimir Medvedkin 	struct rte_fib_rcu_config rcu_cfg = {0};
39896c3d06aSVladimir Medvedkin 	uint64_t def_nh = 100;
39996c3d06aSVladimir Medvedkin 
40096c3d06aSVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
40196c3d06aSVladimir Medvedkin 	config.rib_ext_sz = 0;
40296c3d06aSVladimir Medvedkin 	config.default_nh = def_nh;
40396c3d06aSVladimir Medvedkin 
40496c3d06aSVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
40596c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
40696c3d06aSVladimir Medvedkin 
40796c3d06aSVladimir Medvedkin 	/* Create RCU QSBR variable */
40896c3d06aSVladimir Medvedkin 	sz = rte_rcu_qsbr_get_memsize(RTE_MAX_LCORE);
40996c3d06aSVladimir Medvedkin 	qsv = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
41096c3d06aSVladimir Medvedkin 		SOCKET_ID_ANY);
41196c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(qsv != NULL, "Can not allocate memory for RCU\n");
41296c3d06aSVladimir Medvedkin 
41396c3d06aSVladimir Medvedkin 	status = rte_rcu_qsbr_init(qsv, RTE_MAX_LCORE);
41496c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(status == 0, "Can not initialize RCU\n");
41596c3d06aSVladimir Medvedkin 
41696c3d06aSVladimir Medvedkin 	rcu_cfg.v = qsv;
41796c3d06aSVladimir Medvedkin 
41896c3d06aSVladimir Medvedkin 	/* adding rcu to RTE_FIB_DUMMY FIB type */
419*259deb73SVladimir Medvedkin 	config.type = RTE_FIB_DUMMY;
42096c3d06aSVladimir Medvedkin 	rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
42196c3d06aSVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
422*259deb73SVladimir Medvedkin 	RTE_TEST_ASSERT(status == -ENOTSUP,
423*259deb73SVladimir Medvedkin 		"rte_fib_rcu_qsbr_add returned wrong error status when called with DUMMY type FIB\n");
42496c3d06aSVladimir Medvedkin 	rte_fib_free(fib);
42596c3d06aSVladimir Medvedkin 
42696c3d06aSVladimir Medvedkin 	config.type = RTE_FIB_DIR24_8;
42796c3d06aSVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
42896c3d06aSVladimir Medvedkin 	config.dir24_8.num_tbl8 = MAX_TBL8;
42996c3d06aSVladimir Medvedkin 	fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
43096c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(fib != NULL, "Failed to create FIB\n");
431*259deb73SVladimir Medvedkin 
432*259deb73SVladimir Medvedkin 	/* Call rte_fib_rcu_qsbr_add without fib or config */
433*259deb73SVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(NULL, &rcu_cfg);
434*259deb73SVladimir Medvedkin 	RTE_TEST_ASSERT(status == -EINVAL, "RCU added without fib\n");
435*259deb73SVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(fib, NULL);
436*259deb73SVladimir Medvedkin 	RTE_TEST_ASSERT(status == -EINVAL, "RCU added without config\n");
437*259deb73SVladimir Medvedkin 
438*259deb73SVladimir Medvedkin 	/* Invalid QSBR mode */
43996c3d06aSVladimir Medvedkin 	rcu_cfg.mode = 2;
44096c3d06aSVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
441*259deb73SVladimir Medvedkin 	RTE_TEST_ASSERT(status == -EINVAL, "RCU added with incorrect mode\n");
44296c3d06aSVladimir Medvedkin 
44396c3d06aSVladimir Medvedkin 	rcu_cfg.mode = RTE_FIB_QSBR_MODE_DQ;
444*259deb73SVladimir Medvedkin 
445*259deb73SVladimir Medvedkin 	/* Attach RCU QSBR to FIB to check for double attach */
44696c3d06aSVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
44796c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(status == 0, "Can not attach RCU to FIB\n");
44896c3d06aSVladimir Medvedkin 
44996c3d06aSVladimir Medvedkin 	/* Create and attach another RCU QSBR to FIB table */
45096c3d06aSVladimir Medvedkin 	qsv2 = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
45196c3d06aSVladimir Medvedkin 		SOCKET_ID_ANY);
45296c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(qsv2 != NULL, "Can not allocate memory for RCU\n");
45396c3d06aSVladimir Medvedkin 
45496c3d06aSVladimir Medvedkin 	rcu_cfg.v = qsv2;
45596c3d06aSVladimir Medvedkin 	rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
45696c3d06aSVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(fib, &rcu_cfg);
457*259deb73SVladimir Medvedkin 	RTE_TEST_ASSERT(status == -EEXIST, "Secondary RCU was mistakenly attached\n");
45896c3d06aSVladimir Medvedkin 
45996c3d06aSVladimir Medvedkin 	rte_fib_free(fib);
46096c3d06aSVladimir Medvedkin 	rte_free(qsv);
46196c3d06aSVladimir Medvedkin 	rte_free(qsv2);
46296c3d06aSVladimir Medvedkin 
46396c3d06aSVladimir Medvedkin 	return TEST_SUCCESS;
46496c3d06aSVladimir Medvedkin }
46596c3d06aSVladimir Medvedkin 
46696c3d06aSVladimir Medvedkin static struct rte_fib *g_fib;
46796c3d06aSVladimir Medvedkin static struct rte_rcu_qsbr *g_v;
46896c3d06aSVladimir Medvedkin static uint32_t g_ip = RTE_IPV4(192, 0, 2, 100);
46996c3d06aSVladimir Medvedkin static volatile uint8_t writer_done;
47096c3d06aSVladimir Medvedkin /* Report quiescent state interval every 1024 lookups. Larger critical
47196c3d06aSVladimir Medvedkin  * sections in reader will result in writer polling multiple times.
47296c3d06aSVladimir Medvedkin  */
47396c3d06aSVladimir Medvedkin #define QSBR_REPORTING_INTERVAL 1024
47496c3d06aSVladimir Medvedkin #define WRITER_ITERATIONS	512
47596c3d06aSVladimir Medvedkin 
47696c3d06aSVladimir Medvedkin /*
47796c3d06aSVladimir Medvedkin  * Reader thread using rte_fib data structure with RCU.
47896c3d06aSVladimir Medvedkin  */
47996c3d06aSVladimir Medvedkin static int
48096c3d06aSVladimir Medvedkin test_fib_rcu_qsbr_reader(void *arg)
48196c3d06aSVladimir Medvedkin {
48296c3d06aSVladimir Medvedkin 	int i;
48396c3d06aSVladimir Medvedkin 	uint64_t next_hop_return = 0;
48496c3d06aSVladimir Medvedkin 
48596c3d06aSVladimir Medvedkin 	RTE_SET_USED(arg);
48696c3d06aSVladimir Medvedkin 	/* Register this thread to report quiescent state */
48796c3d06aSVladimir Medvedkin 	rte_rcu_qsbr_thread_register(g_v, 0);
48896c3d06aSVladimir Medvedkin 	rte_rcu_qsbr_thread_online(g_v, 0);
48996c3d06aSVladimir Medvedkin 
49096c3d06aSVladimir Medvedkin 	do {
49196c3d06aSVladimir Medvedkin 		for (i = 0; i < QSBR_REPORTING_INTERVAL; i++)
49296c3d06aSVladimir Medvedkin 			rte_fib_lookup_bulk(g_fib, &g_ip, &next_hop_return, 1);
49396c3d06aSVladimir Medvedkin 
49496c3d06aSVladimir Medvedkin 		/* Update quiescent state */
49596c3d06aSVladimir Medvedkin 		rte_rcu_qsbr_quiescent(g_v, 0);
49696c3d06aSVladimir Medvedkin 	} while (!writer_done);
49796c3d06aSVladimir Medvedkin 
49896c3d06aSVladimir Medvedkin 	rte_rcu_qsbr_thread_offline(g_v, 0);
49996c3d06aSVladimir Medvedkin 	rte_rcu_qsbr_thread_unregister(g_v, 0);
50096c3d06aSVladimir Medvedkin 
50196c3d06aSVladimir Medvedkin 	return 0;
50296c3d06aSVladimir Medvedkin }
50396c3d06aSVladimir Medvedkin 
50496c3d06aSVladimir Medvedkin /*
50596c3d06aSVladimir Medvedkin  * rte_fib_rcu_qsbr_add sync mode functional test.
50696c3d06aSVladimir Medvedkin  * 1 Reader and 1 writer. They cannot be in the same thread in this test.
50796c3d06aSVladimir Medvedkin  *  - Create FIB which supports 1 tbl8 group at max
50896c3d06aSVladimir Medvedkin  *  - Add RCU QSBR variable with sync mode to FIB
50996c3d06aSVladimir Medvedkin  *  - Register a reader thread. Reader keeps looking up a specific rule.
51096c3d06aSVladimir Medvedkin  *  - Writer keeps adding and deleting a specific rule with depth=28 (> 24)
51196c3d06aSVladimir Medvedkin  */
51296c3d06aSVladimir Medvedkin int32_t
51396c3d06aSVladimir Medvedkin test_fib_rcu_sync_rw(void)
51496c3d06aSVladimir Medvedkin {
51519d463aaSDavid Marchand 	struct rte_fib_conf config = { 0 };
51696c3d06aSVladimir Medvedkin 	size_t sz;
51796c3d06aSVladimir Medvedkin 	int32_t status;
51896c3d06aSVladimir Medvedkin 	uint32_t i, next_hop;
51996c3d06aSVladimir Medvedkin 	uint8_t depth;
52096c3d06aSVladimir Medvedkin 	struct rte_fib_rcu_config rcu_cfg = {0};
52196c3d06aSVladimir Medvedkin 	uint64_t def_nh = 100;
52296c3d06aSVladimir Medvedkin 
52396c3d06aSVladimir Medvedkin 	if (rte_lcore_count() < 2) {
52496c3d06aSVladimir Medvedkin 		printf("Not enough cores for %s, expecting at least 2\n", __func__);
52596c3d06aSVladimir Medvedkin 		return TEST_SKIPPED;
52696c3d06aSVladimir Medvedkin 	}
52796c3d06aSVladimir Medvedkin 
52896c3d06aSVladimir Medvedkin 	config.max_routes = MAX_ROUTES;
52996c3d06aSVladimir Medvedkin 	config.rib_ext_sz = 0;
53096c3d06aSVladimir Medvedkin 	config.default_nh = def_nh;
53196c3d06aSVladimir Medvedkin 	config.type = RTE_FIB_DIR24_8;
53296c3d06aSVladimir Medvedkin 	config.dir24_8.nh_sz = RTE_FIB_DIR24_8_4B;
53396c3d06aSVladimir Medvedkin 	config.dir24_8.num_tbl8 = 1;
53496c3d06aSVladimir Medvedkin 
53596c3d06aSVladimir Medvedkin 	g_fib = rte_fib_create(__func__, SOCKET_ID_ANY, &config);
53696c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(g_fib != NULL, "Failed to create FIB\n");
53796c3d06aSVladimir Medvedkin 
53896c3d06aSVladimir Medvedkin 	/* Create RCU QSBR variable */
53996c3d06aSVladimir Medvedkin 	sz = rte_rcu_qsbr_get_memsize(1);
54096c3d06aSVladimir Medvedkin 	g_v = (struct rte_rcu_qsbr *)rte_zmalloc_socket(NULL, sz, RTE_CACHE_LINE_SIZE,
54196c3d06aSVladimir Medvedkin 		SOCKET_ID_ANY);
54296c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(g_v != NULL, "Can not allocate memory for RCU\n");
54396c3d06aSVladimir Medvedkin 
54496c3d06aSVladimir Medvedkin 	status = rte_rcu_qsbr_init(g_v, 1);
54596c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(status == 0, "Can not initialize RCU\n");
54696c3d06aSVladimir Medvedkin 
54796c3d06aSVladimir Medvedkin 	rcu_cfg.v = g_v;
54896c3d06aSVladimir Medvedkin 	rcu_cfg.mode = RTE_FIB_QSBR_MODE_SYNC;
54996c3d06aSVladimir Medvedkin 	/* Attach RCU QSBR to FIB table */
55096c3d06aSVladimir Medvedkin 	status = rte_fib_rcu_qsbr_add(g_fib, &rcu_cfg);
55196c3d06aSVladimir Medvedkin 	RTE_TEST_ASSERT(status == 0, "Can not attach RCU to FIB\n");
55296c3d06aSVladimir Medvedkin 
55396c3d06aSVladimir Medvedkin 	writer_done = 0;
55496c3d06aSVladimir Medvedkin 	/* Launch reader thread */
55596c3d06aSVladimir Medvedkin 	rte_eal_remote_launch(test_fib_rcu_qsbr_reader, NULL, rte_get_next_lcore(-1, 1, 0));
55696c3d06aSVladimir Medvedkin 
55796c3d06aSVladimir Medvedkin 	depth = 28;
55896c3d06aSVladimir Medvedkin 	next_hop = 1;
55996c3d06aSVladimir Medvedkin 	status = rte_fib_add(g_fib, g_ip, depth, next_hop);
56096c3d06aSVladimir Medvedkin 	if (status != 0) {
56196c3d06aSVladimir Medvedkin 		printf("%s: Failed to add rule\n", __func__);
56296c3d06aSVladimir Medvedkin 		goto error;
56396c3d06aSVladimir Medvedkin 	}
56496c3d06aSVladimir Medvedkin 
56596c3d06aSVladimir Medvedkin 	/* Writer update */
56696c3d06aSVladimir Medvedkin 	for (i = 0; i < WRITER_ITERATIONS; i++) {
56796c3d06aSVladimir Medvedkin 		status = rte_fib_delete(g_fib, g_ip, depth);
56896c3d06aSVladimir Medvedkin 		if (status != 0) {
56996c3d06aSVladimir Medvedkin 			printf("%s: Failed to delete rule at iteration %d\n", __func__, i);
57096c3d06aSVladimir Medvedkin 			goto error;
57196c3d06aSVladimir Medvedkin 		}
57296c3d06aSVladimir Medvedkin 
57396c3d06aSVladimir Medvedkin 		status = rte_fib_add(g_fib, g_ip, depth, next_hop);
57496c3d06aSVladimir Medvedkin 		if (status != 0) {
57596c3d06aSVladimir Medvedkin 			printf("%s: Failed to add rule at iteration %d\n", __func__, i);
57696c3d06aSVladimir Medvedkin 			goto error;
57796c3d06aSVladimir Medvedkin 		}
57896c3d06aSVladimir Medvedkin 	}
57996c3d06aSVladimir Medvedkin 
58096c3d06aSVladimir Medvedkin error:
58196c3d06aSVladimir Medvedkin 	writer_done = 1;
58296c3d06aSVladimir Medvedkin 	/* Wait until reader exited. */
58396c3d06aSVladimir Medvedkin 	rte_eal_mp_wait_lcore();
58496c3d06aSVladimir Medvedkin 
58596c3d06aSVladimir Medvedkin 	rte_fib_free(g_fib);
58696c3d06aSVladimir Medvedkin 	rte_free(g_v);
58796c3d06aSVladimir Medvedkin 
58896c3d06aSVladimir Medvedkin 	return status == 0 ? TEST_SUCCESS : TEST_FAILED;
58996c3d06aSVladimir Medvedkin }
59096c3d06aSVladimir Medvedkin 
5914ccd4259SVladimir Medvedkin static struct unit_test_suite fib_fast_tests = {
5924ccd4259SVladimir Medvedkin 	.suite_name = "fib autotest",
5934ccd4259SVladimir Medvedkin 	.setup = NULL,
5944ccd4259SVladimir Medvedkin 	.teardown = NULL,
5954ccd4259SVladimir Medvedkin 	.unit_test_cases = {
5964ccd4259SVladimir Medvedkin 	TEST_CASE(test_create_invalid),
5974ccd4259SVladimir Medvedkin 	TEST_CASE(test_free_null),
5984ccd4259SVladimir Medvedkin 	TEST_CASE(test_add_del_invalid),
5994ccd4259SVladimir Medvedkin 	TEST_CASE(test_get_invalid),
6004ccd4259SVladimir Medvedkin 	TEST_CASE(test_lookup),
60196c3d06aSVladimir Medvedkin 	TEST_CASE(test_invalid_rcu),
60296c3d06aSVladimir Medvedkin 	TEST_CASE(test_fib_rcu_sync_rw),
6034ccd4259SVladimir Medvedkin 	TEST_CASES_END()
6044ccd4259SVladimir Medvedkin 	}
6054ccd4259SVladimir Medvedkin };
6064ccd4259SVladimir Medvedkin 
6074ccd4259SVladimir Medvedkin static struct unit_test_suite fib_slow_tests = {
6084ccd4259SVladimir Medvedkin 	.suite_name = "fib slow autotest",
6094ccd4259SVladimir Medvedkin 	.setup = NULL,
6104ccd4259SVladimir Medvedkin 	.teardown = NULL,
6114ccd4259SVladimir Medvedkin 	.unit_test_cases = {
6124ccd4259SVladimir Medvedkin 	TEST_CASE(test_multiple_create),
6134ccd4259SVladimir Medvedkin 	TEST_CASES_END()
6144ccd4259SVladimir Medvedkin 	}
6154ccd4259SVladimir Medvedkin };
6164ccd4259SVladimir Medvedkin 
6174ccd4259SVladimir Medvedkin /*
6184ccd4259SVladimir Medvedkin  * Do all unit tests.
6194ccd4259SVladimir Medvedkin  */
6204ccd4259SVladimir Medvedkin static int
6214ccd4259SVladimir Medvedkin test_fib(void)
6224ccd4259SVladimir Medvedkin {
6234ccd4259SVladimir Medvedkin 	return unit_test_suite_runner(&fib_fast_tests);
6244ccd4259SVladimir Medvedkin }
6254ccd4259SVladimir Medvedkin 
6264ccd4259SVladimir Medvedkin static int
6274ccd4259SVladimir Medvedkin test_slow_fib(void)
6284ccd4259SVladimir Medvedkin {
6294ccd4259SVladimir Medvedkin 	return unit_test_suite_runner(&fib_slow_tests);
6304ccd4259SVladimir Medvedkin }
6314ccd4259SVladimir Medvedkin 
632e0a8442cSBruce Richardson REGISTER_FAST_TEST(fib_autotest, true, true, test_fib);
633e0a8442cSBruce Richardson REGISTER_PERF_TEST(fib_slow_autotest, test_slow_fib);
634