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