hi: Fixes: 396284f345a1 ("add app/test/test_lpm.c test lpm, add 3 new cases 1),add->lookup 2),add->delete->lookup 3),add->delete->add->lookup") [PATCH] add app/test/test_lpm.c test lpm, add 3 new cases test procedure: 1),add->lookup 2),add->delete->lookup 3),add->delete->add->lookup This is the test program to test lpm bugs. Thanks Regards yuexin --- app/test/test_lpm.c | 480 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 480 insertions(+) diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c index 8b4ded9..d2f8a52 100644 --- a/app/test/test_lpm.c +++ b/app/test/test_lpm.c @@ -35,8 +35,11 @@ #include #include #include +#include +#include #include +#include #include #include #include @@ -44,6 +47,7 @@ #include #include #include +#include #include "test.h" @@ -77,8 +81,69 @@ static int32_t test14(void); static int32_t test15(void); static int32_t test16(void); static int32_t test17(void); +static int32_t test_random(void); static int32_t perf_test(void); +#ifndef RTE_VERSION_NUM +#define RTE_VERSION_NUM(a,b,c,d) ((a) << 24 | (b) << 16 | (c) << 8 | (d)) +#endif + +#ifndef RTE_VERSION +#define RTE_VERSION RTE_VERSION_NUM( \ + RTE_VER_MAJOR, \ + RTE_VER_MINOR, \ + RTE_VER_PATCH_LEVEL,\ + 0) +#endif + + +#define LPM_ADD_ROUTE_MAX 100 +#define LPM_TEST_LOOKUP_COUNT 1 +#define ARG 32 + +#define RTE_LPM_V3_MAX_DEPTH 32 +#define RAND_SEED 1024 + + +#define PRINT_IP_FORMAT "%u.%u.%u.%u" +#define PRINT_HIP(x)\ + ((x >> 24) & 0xFF),\ + ((x >> 16) & 0xFF),\ + ((x >> 8) & 0xFF),\ + ((x >> 0) & 0xFF) + +/*route struct node define*/ +struct route_node { + uint32_t dip; + uint32_t depth; + uint16_t next_hop; + uint16_t flags; +}; + +/*global varible define*/ +struct route_node route_table_arrary[LPM_ADD_ROUTE_MAX]; + + +/*for test_random route table test functions*/ +long getCurrentTime(void); +int test_random_lpm_case_1(struct rte_lpm *lpm); +int test_random_lpm_case_2(struct rte_lpm *lpm); +int test_random_lpm_case_3(struct rte_lpm *lpm); +int lpm_random_lookup(struct rte_lpm *lpm_tree, uint32_t dip_count); +int lpm_random_add(struct rte_lpm *lpm_tree, int count); +int lpm_random_delete(struct rte_lpm *lpm_tree, uint32_t index); +int lpm_random_add_nexthop(struct rte_lpm *lpm_tree, int count, int next_hop); +void lpm_route_show(struct rte_lpm *lpm); +void lpm_route_show_v2(struct rte_lpm *lpm, uint32_t hop1, uint32_t hop2); +int route_table_arrary_create(void); +int route_table_arrary_add(uint32_t dip, uint8_t depth, uint32_t next_hop); +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) +uint32_t depth_to_mask(uint8_t depth); +int route_table_lpm_lookup(struct rte_lpm *lpm_tree, uint32_t dip, uint8_t *next_hop); +#else +int route_table_lpm_lookup(struct rte_lpm *lpm_tree, uint32_t dip, uint16_t *next_hop); +#endif + rte_lpm_test tests[] = { /* Test Cases */ test0, @@ -99,6 +164,7 @@ rte_lpm_test tests[] = { test15, test16, test17, +test_random, perf_test, }; @@ -1137,6 +1203,420 @@ test17(void) return PASS; } +long +getCurrentTime(void) +{ + struct timeval tv; + gettimeofday(&tv,NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) +/*convertt the depth to net mask*/ +uint32_t depth_to_mask(uint8_t depth) +{ + return (int)0x80000000 >> (depth - 1); +} +#endif + +/*for route test table operate*/ +int +route_table_arrary_create(void) +{ + memset(route_table_arrary, 0, sizeof(struct route_node) * LPM_ADD_ROUTE_MAX); + return 0; +} + +/*add the route to the route test table*/ +int +route_table_arrary_add(uint32_t dip, uint8_t depth, uint32_t next_hop) +{ + uint32_t i = 0; + uint32_t dip_masked = dip & depth_to_mask(depth); + + for(i = 0; i < LPM_ADD_ROUTE_MAX; i++) { + if(route_table_arrary[i].flags == 1 + && route_table_arrary[i].dip == dip + && route_table_arrary[i].depth == depth) { + + route_table_arrary[i].dip = dip_masked; + route_table_arrary[i].depth = depth; + route_table_arrary[i].next_hop = next_hop; + + return 0; //exsit, update + } + } + + for(i = 0; i < LPM_ADD_ROUTE_MAX; i++) { + if(route_table_arrary[i].flags == 0) { //add the route + route_table_arrary[i].flags = 1; + route_table_arrary[i].dip = dip_masked; + route_table_arrary[i].depth = depth; + route_table_arrary[i].next_hop = next_hop; + + return 0; //add one by one, success + } + } + + return -1; //add failed +} + +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) +int route_table_lpm_lookup(struct rte_lpm *lpm, uint32_t dip, uint8_t *next_hop) +#else +int route_table_lpm_lookup(struct rte_lpm *lpm, uint32_t dip, uint16_t *next_hop) +#endif +{ + int i, j; + int start, end; + uint32_t mask; + + for(i = RTE_LPM_V3_MAX_DEPTH - 1; i >= 0 ; i--) { +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) + start = lpm->rule_info[i].first_rule; //find from max depth rule + end = start + lpm->rule_info[i].used_rules; +#else + start = i * lpm->max_rules_per_depth; + end = start + lpm->used_rules_at_depth[i]; +#endif + for(j = start; j < end; j++) { + mask = depth_to_mask(i + 1); + + if((dip & mask) == lpm->rules_tbl[j].ip) { + *next_hop = lpm->rules_tbl[j].next_hop; + return 0; + } + } + } + + return -1; +} + +/*show lpm's route entries*/ +void lpm_route_show(struct rte_lpm *lpm) +{ + uint32_t i = 0, j = 0; + uint32_t start = 0, end = 0, count = 0; + + printf("[%s:%d]show rule in lpm tree...\n",__func__,__LINE__); + + for(i = 0; i < RTE_LPM_V3_MAX_DEPTH; i++){ +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) + start = lpm->rule_info[i].first_rule; + end = start + lpm->rule_info[i].used_rules; +#else + start = i * lpm->max_rules_per_depth; + end = start + lpm->used_rules_at_depth[i]; +#endif + for(j = start; j < end; j++) { + printf("\trule id : %u, ip : "PRINT_IP_FORMAT"/%u, next_hop : %u, \t\t lpm arrary(%u - %u - %u)\n", + ++count, PRINT_HIP(lpm->rules_tbl[j].ip), i + 1, lpm->rules_tbl[j].next_hop, i, start, end); + } + } + + return; +} + +/*show lpm's route entries on hop1 and hop2*/ +void +lpm_route_show_v2(struct rte_lpm *lpm, uint32_t hop1, uint32_t hop2) +{ + uint32_t i = 0, j = 0; + uint32_t start = 0, end = 0, count = 0; + + printf("[%s:%d]show rule in lpm tree...\n",__func__,__LINE__); + + for(i = 0; i < RTE_LPM_V3_MAX_DEPTH; i++){ +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) + start = lpm->rule_info[i].first_rule; + end = start + lpm->rule_info[i].used_rules; +#else + start = i * lpm->max_rules_per_depth; + end = start + lpm->used_rules_at_depth[i]; +#endif + for(j = start; j < end; j++) { + if(lpm->rules_tbl[j].next_hop == hop1 || lpm->rules_tbl[j].next_hop == hop2) { + printf("\trule id : %u, ip : "PRINT_IP_FORMAT"/%u, next_hop : %u, \t\t lpm arrary(%u - %u - %u)\n", + ++count, PRINT_HIP(lpm->rules_tbl[j].ip), i + 1, lpm->rules_tbl[j].next_hop, i, start, end); + } + } + } + + return; +} + +int +lpm_random_add_nexthop(struct rte_lpm *lpm_tree, int count, int next_hop) +{ + int32_t i; + int32_t status = 0; + uint32_t add_dip = 0; + uint8_t add_depth = 0; + uint8_t next_hop_add = 0; +uint32_t dip_masked = 0; + uint64_t seed = 0; + int nh = next_hop-1; + + seed = getCurrentTime(); +rte_srand(seed); + +for (i = 0; i < count; i++) { +next_hop_add = nh++; + +add_dip = 0x10200000 + (rte_rand() >> 48); + add_depth = rte_rand() % 32 + 1; +dip_masked = add_dip & depth_to_mask(add_depth); + +if(dip_masked == 0) { +i--; +continue; +} + + status = rte_lpm_add(lpm_tree, dip_masked, add_depth, next_hop_add); + if(status != 0) { + printf("lpm add routes failed, ret : %d...\n", status); + continue; +} + + route_table_arrary_add(dip_masked, add_depth, next_hop_add); + } + + return 0; +} + +/*for random route add, for route table & lpm struct*/ +int lpm_random_add(struct rte_lpm *lpm_tree, int count) +{ + int32_t i; + int32_t status = 0; + uint32_t add_dip = 0; + uint8_t add_depth = 0; + uint8_t next_hop_add = 0; +uint32_t dip_masked = 0; + uint64_t seed = 0; + + seed = getCurrentTime(); +rte_srand(seed); + printf("seed = %ld\n", seed); + +for (i = 0; i < count; i++) { +next_hop_add = i % 256; + +add_dip = 0x10200000 + (rte_rand() >> 48); + add_depth = rte_rand() % 32 + 1; +dip_masked = add_dip & depth_to_mask(add_depth); + +if(dip_masked == 0) { +i--; +continue; +} + + status = rte_lpm_add(lpm_tree, dip_masked, add_depth, next_hop_add); + if(status != 0) { + printf("lpm add routes failed, ret : %d...\n", status); + continue; +} + + route_table_arrary_add(dip_masked, add_depth, next_hop_add); + } + + return 0; +} + +/*for random lookup the route*/ +int lpm_random_lookup(struct rte_lpm *lpm_tree, uint32_t query_count) +{ + uint32_t i = 0; +#if RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0) + uint8_t lookup_next_hop_0 = 0; + uint8_t lookup_next_hop_1 = 0; +#else + uint16_t lookup_next_hop_0 = 0; + uint16_t lookup_next_hop_1 = 0; +#endif + +uint32_t dip; + int32_t status_0 = 0, status_1 = 0; + +rte_srand(getCurrentTime()); + +for (i = 0; i < query_count; i++) { +dip = 0x10200000 + (rte_rand() >> 48); + +lookup_next_hop_0 = 0xff; +lookup_next_hop_1 = 0xff; + +status_0 = route_table_lpm_lookup(lpm_tree, dip, &lookup_next_hop_0); + status_1 = rte_lpm_lookup(lpm_tree, dip, &lookup_next_hop_1); + + if(status_0 == 0 && status_1 == 0) { + if(lookup_next_hop_0 != lookup_next_hop_1) { + printf("lookup times : %u, failed, dip : "PRINT_IP_FORMAT", next_hop_0 : %u, next_hop_1 : %u\n", +i, PRINT_HIP(dip), lookup_next_hop_0, lookup_next_hop_1); + status_1 = rte_lpm_lookup(lpm_tree, dip, &lookup_next_hop_1); +printf("slit 1, for check a time, status_1 %d, next_hop : %u\n", status_1, lookup_next_hop_1); +lpm_route_show_v2(lpm_tree, lookup_next_hop_0, lookup_next_hop_1); + return -1; + } + } else if(status_0 < 0 && status_1 < 0) { + //printf("i : %u, lpm lookup don't exsit, status_0 : %d, status_1 :%d\n", i, status_0, status_1); + continue; +} else { + printf("lookup times : %u, failed, dip : "PRINT_IP_FORMAT" , status_0 : %d, status_1 :%d, next_hop_0 : %u, next_hop_1 : %u\n", +i, PRINT_HIP(dip), status_0, status_1, lookup_next_hop_0, lookup_next_hop_1); + status_1 = rte_lpm_lookup(lpm_tree, dip, &lookup_next_hop_1); +printf("slit 2, for check a time, status_1 %d, next_hop : %u\n", status_1, lookup_next_hop_1); +lpm_route_show_v2(lpm_tree, lookup_next_hop_0, lookup_next_hop_1); +return -1; + } + } + + return 0; +} + +/*for delte the route by segment, from start to end*/ +int lpm_random_delete(struct rte_lpm *lpm_tree, uint32_t index) +{ + int ret = 0; + uint32_t dip = 0; + uint8_t depth; + uint16_t next_hop; +uint32_t dip_masked; + +if(route_table_arrary[index].flags == 1) { +dip = route_table_arrary[index].dip; +depth = route_table_arrary[index].depth; +next_hop = route_table_arrary[index].next_hop; +dip_masked = dip & depth_to_mask(depth); + +route_table_arrary[index].flags = 0; +route_table_arrary[index].dip = 0; +route_table_arrary[index].depth = 0; +route_table_arrary[index].next_hop = 0; + +ret = rte_lpm_delete(lpm_tree, dip_masked, depth); +if(ret < 0) { + printf("delete, failed, index : %u, dip : "PRINT_IP_FORMAT", depth : %u\n", index, PRINT_HIP(dip), depth); + return -1; +} +} + + return 0; +} + + +/*add -> lookup*/ +int +test_random_lpm_case_1(struct rte_lpm *lpm) +{ + int ret = 0; + + ret = lpm_random_add(lpm, LPM_ADD_ROUTE_MAX); + if(ret < 0) { + return ret; + } + + ret = lpm_random_lookup(lpm, LPM_TEST_LOOKUP_COUNT); + if(ret < 0) { + return ret; + } + + return 0; +} + +/*add -> del -> lookup*/ +int +test_random_lpm_case_2(struct rte_lpm *lpm) +{ + int i = 0, ret = 0; + + for(i = 0; i < LPM_ADD_ROUTE_MAX; i++) { + lpm_random_delete(lpm, i); + + ret = lpm_random_lookup(lpm, LPM_TEST_LOOKUP_COUNT); + if(ret < 0) { + return -1; + } + } + + return 0; +} + +/*for n times: del ->add -> lookup*/ +int +test_random_lpm_case_3(struct rte_lpm *lpm) +{ + int ret = 0; + int i = 0; + int hops = 0; + int add = 1; + ret = lpm_random_add(lpm, LPM_ADD_ROUTE_MAX); + if(ret < 0) { + return ret; + } + hops = 200; + for(i = 0; i < LPM_ADD_ROUTE_MAX; i++) { + usleep(1000); + lpm_random_delete(lpm, i); + lpm_random_add_nexthop(lpm,add,hops); + hops = hops + add; + ret = lpm_random_lookup(lpm, LPM_TEST_LOOKUP_COUNT); + if(ret < 0) { + return -1; + } + } + + return 0; +} + +/* + * Test for random routing add, del and lookup + */ +int32_t +test_random(void) { + int ret = PASS; +// int case_process,i; + struct rte_lpm *lpm = NULL; + lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, LPM_ADD_ROUTE_MAX * ARG, 0); +TEST_LPM_ASSERT(lpm != NULL); + + route_table_arrary_create(); + + + ret = test_random_lpm_case_1(lpm); + if(ret != 0) { + lpm_route_show(lpm); + printf("test_random_lpm_case_1, failed...\n"); + ret = -1; + goto OUT; + } + printf("test_random_lpm_case_1, ok...\n"); + + + ret = test_random_lpm_case_2(lpm); + if(ret != 0) { + lpm_route_show(lpm); + printf("test_random_lpm_case_2, failed...\n"); + ret = -1; + goto OUT; + } + printf("test_random_lpm_case_2, ok...\n"); + + ret = test_random_lpm_case_3(lpm); + if(ret != 0) { + lpm_route_show(lpm); + printf("test_random_lpm_case_3, failed...\n"); + ret = -1; + goto OUT; + } + printf("test_random_lpm_case_3, ok...\n"); + +OUT: + rte_lpm_free(lpm) ; + return ret; +} + + /* * Lookup performance test */ -- 1.8.5.2 (Apple Git-48) &%+ N,)zW(Z9vNv^Qz۫^rM8\d^qyikMץr6{^&~5ߍwm]>-~,pDHω5.߀^]-Myӽ9_M$yǢ_ɠkM6~h\mt۝nʊXߊ{^&+a#?mrݴםӞ4ӽ4\Lm.)UȮϢ@T