* Re: [dpdk-dev] [PATCH] fix lpm bugs
2015-10-22 2:15 ` mablexidana
@ 2015-10-23 4:40 ` mablexidana
[not found] ` <29ae0ca8.e6db.15093aafa12.Coremail.mablexidana@163.com>
1 sibling, 0 replies; 5+ messages in thread
From: mablexidana @ 2015-10-23 4:40 UTC (permalink / raw)
To: Bruce Richardson, dev
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=GBK, Size: 14941 bytes --]
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 <stdint.h>
#include <stdlib.h>
#include <errno.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/queue.h>
+#include <rte_version.h>
#include <rte_common.h>
#include <rte_cycles.h>
#include <rte_memory.h>
@@ -44,6 +47,7 @@
#include <rte_branch_prediction.h>
#include <rte_ip.h>
#include <time.h>
+#include <sys/time.h>
#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)
\x16º&Áéóê%²\x17+ ÓN,)ízW(Zâ9ËvßNôçvÓ^QzÛ«ö\a§Î^[¨È^r\b¬M8²\x18§µé\¢d^qè¯y×ë¢i kM¢×¥r¦6{^Ê&×~5ßwëm^[ÉÚ]à>-~,pØDHÄÏß5ì.ߢ·^½Ú]à\x16¸¶Üç-ÛMyÓ½9ã_´ÛM\x02\x11$ÑyÇ¢½ç_®É kM6~h§µé\¢mtÛöãnÊì\x06µÓXß{^Ê&Â+a\x11#\x13?mrݴ׶Ó4Ó½4\Lm.)×UȮϢ»@T
^ permalink raw reply [flat|nested] 5+ messages in thread