[dpdk-dev] [PATCH v3] app/test: fix a segfault when lpm_perf_autotest is run more than 1 time

2016-11-01 Thread Nikita Kozlov
num_route_entries need to be reseted.

Fixes: 17d60f5b5eea ("app/test: remove large IPv4 LPM data file")

Signed-off-by: Nikita Kozlov 
---
 app/test/test_lpm_perf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 608e17a..e7e1281 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -301,6 +301,7 @@ static void generate_large_route_rule_table(void)
uint32_t ip_class;
uint8_t  depth;

+   num_route_entries = 0;
memset(large_route_table, 0, sizeof(large_route_table));

for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
-- 
2.9.2



[dpdk-dev] [PATCH v2] app/test: fix a segfault when lpm_perf_autotest is run more than 1 time

2016-11-01 Thread Nikita Kozlov
num_route_entries need to be reseted.

V2 : resubmitting the patch with a signed-off

Signed-off-by: Nikita Kozlov 
---
 app/test/test_lpm_perf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 608e17a..e7e1281 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -301,6 +301,7 @@ static void generate_large_route_rule_table(void)
uint32_t ip_class;
uint8_t  depth;

+   num_route_entries = 0;
memset(large_route_table, 0, sizeof(large_route_table));

for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
-- 
2.9.2



[dpdk-dev] [PATCH] app/test: fix a segfault when lpm_perf_autotest is run more than 1 time

2016-11-01 Thread Nikita Kozlov
num_route_entries need to be reseted.
---
 app/test/test_lpm_perf.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 608e17a..e7e1281 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -301,6 +301,7 @@ static void generate_large_route_rule_table(void)
uint32_t ip_class;
uint8_t  depth;

+   num_route_entries = 0;
memset(large_route_table, 0, sizeof(large_route_table));

for (ip_class = IP_CLASS_A; ip_class <= IP_CLASS_C; ip_class++) {
-- 
2.9.2



[dpdk-dev] [PATCH v2 0/2] lpm6: speed improvement on delete rule

2016-09-16 Thread Nikita Kozlov
On 08/25/2016 00:59, Nikita Kozlov wrote:
> This serie of pathes focus on improving the speed of deleting rules in lpm6.
>
> It also contains some other improvement like having a dynamic number of
> rules in lpm6 and increasing the lpm6 nexthop size to 16bit for matching
> the nexthop size in lpm4.
>
> The performances improvement can be seen by running test_lpm6_perf but
> because of the limited number of rules added (1000) the improvement seen is
> just about a x10 with this test.
>
> For testing it further we have tested it with a full ipv6 bgp view which 
> represent 29296 routes in our test:
> * With the dpdk 16.04 it tooks an average of 8.46095e+09 cycles to delete a 
> rule
> (calculated with mesuring rte_rdtsc before and after the delete, the
> average is calculated by the first 10 delete, it represents several
> seconds on a E5-2650 v2)
> * With the patch it tooks 10077.1 cycles (same number of deleted rules,
> same machine, same rules inserted) for the same test.
>
> This patch was written in collaboration with Baptiste Daroussin from Gandi.
>
> Changes since V1:
> - use system bsd-tree.h
> - fix a bug when valid_group field was overwritten 
>
> Nikita Kozlov (2):
>   lpm6: speed inmprovement on delete rule
>   test_lpm6: make test_lpm6* compatible with the new rte_lpm6.c lib
>
>  app/test/test_lpm6.c  | 244 +
>  app/test/test_lpm6_perf.c |   6 +-
>  lib/librte_lpm/Makefile   |   2 +-
>  lib/librte_lpm/rte_lpm6.c | 626 
> +-
>  lib/librte_lpm/rte_lpm6.h |  50 ++-
>  lib/librte_lpm/rte_lpm_version.map|  12 +
>  lib/librte_table/rte_table_lpm_ipv6.c |   7 +-
>  7 files changed, 609 insertions(+), 338 deletions(-)
>
Hello,
If someone have some time, I feel that this patch needs some polishing
so any comments on the code are more than welcome, even if they are not
directly related to the lpm part itself.

thanks.


[dpdk-dev] [PATCH v2 2/2] test_lpm6: make test_lpm6* compatible with the new rte_lpm6.c lib

2016-08-25 Thread Nikita Kozlov
Modify of test_lpm6.c to reflect that we no longer have a maximum number
of rules.

Check in some places that we are using the same number of tbl8 as the
previous implementation after a rte_lpm6_delete.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Baptiste Daroussin 
---
 app/test/test_lpm6.c  | 244 +++---
 app/test/test_lpm6_perf.c |   6 +-
 lib/librte_table/rte_table_lpm_ipv6.c |   7 +-
 3 files changed, 84 insertions(+), 173 deletions(-)

diff --git a/app/test/test_lpm6.c b/app/test/test_lpm6.c
index 0fd0ef7..7929e44 100644
--- a/app/test/test_lpm6.c
+++ b/app/test/test_lpm6.c
@@ -77,8 +77,6 @@ static int32_t test22(void);
 static int32_t test23(void);
 static int32_t test24(void);
 static int32_t test25(void);
-static int32_t test26(void);
-static int32_t test27(void);

 rte_lpm6_test tests6[] = {
 /* Test Cases */
@@ -108,13 +106,10 @@ rte_lpm6_test tests6[] = {
test23,
test24,
test25,
-   test26,
-   test27,
 };

 #define NUM_LPM6_TESTS(sizeof(tests6)/sizeof(tests6[0]))
 #define MAX_DEPTH128
-#define MAX_RULES100
 #define NUMBER_TBL8S   (1 << 16)
 #define MAX_NUM_TBL8S  (1 << 21)
 #define PASS 0
@@ -153,7 +148,6 @@ test0(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -161,14 +155,7 @@ test0(void)
lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm == NULL);

-   /* rte_lpm6_create: max_rules = 0 */
-   /* Note: __func__ inserts the function name, in this case "test0". */
-   config.max_rules = 0;
-   lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, );
-   TEST_LPM_ASSERT(lpm == NULL);
-
/* socket_id < -1 is invalid */
-   config.max_rules = MAX_RULES;
lpm = rte_lpm6_create(__func__, -2, );
TEST_LPM_ASSERT(lpm == NULL);

@@ -195,7 +182,6 @@ test1(void)
struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -219,7 +205,6 @@ test1(void)

 /*
  * Create lpm table then delete lpm table 20 times
- * Use a slightly different rules size each time
  */
 int32_t
 test2(void)
@@ -233,7 +218,6 @@ test2(void)

/* rte_lpm6_free: Free NULL */
for (i = 0; i < 20; i++) {
-   config.max_rules = MAX_RULES - i;
lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm != NULL);

@@ -256,7 +240,6 @@ test3(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -278,10 +261,10 @@ test4(void)
struct rte_lpm6_config config;

uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t depth = 24, next_hop = 100;
+   uint8_t depth = 24;
+   uint16_t next_hop = 100;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -319,7 +302,6 @@ test5(void)
uint8_t depth = 24;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -354,10 +336,9 @@ test6(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t next_hop_return = 0;
+   uint16_t next_hop_return = 0;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -392,10 +373,9 @@ test7(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[10][16];
-   int16_t next_hop_return[10];
+   int32_t next_hop_return[10];
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -433,7 +413,6 @@ test8(void)
uint8_t depth[10];
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -469,11 +448,11 @@ test9(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0;
+   uint8_t depth = 16;
+   uint16_t next_hop_add = 100, next_hop_return = 0;
int32_t status = 0;
uint8_t i;

-   

[dpdk-dev] [PATCH v2 1/2] lpm6: speed inmprovement on delete rule

2016-08-25 Thread Nikita Kozlov
Rewrite rte_lpm6_delete* logic for deleting only the selected rule
instead of deleting all rules and re-inserting them.

the delete_step() function is called recursively and delete the rule
until the rule depth is covered. Then it calls delete_expand_step()
which will ensure to delete the expanded part of the rule if any.

The tbl8 are now allocated more dynamically through tbl8_alloc() which
will walk through all tbl8 for finding an empty one.

The rules are now stored in a RB-tree so we can have a dynamic number of
them. This part of the patch is inspired by
http://dpdk.org/dev/patchwork/patch/7981/ .

Adding of rte_lpm6_tbl8_count() and rte_lpm6_tbl8_free_count() which
permits to check that we are freeing correctly our tbl8 and permits to
check how much free tbl8 we have for adding new rules.

For consistency with lpm4, increase lpm6 nexthop size from 8bit to
16bit.

This patch was written in collaboration with Baptiste Daroussin from Gandi.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Baptiste Daroussin 
---
 lib/librte_lpm/Makefile|   2 +-
 lib/librte_lpm/rte_lpm6.c  | 626 +++--
 lib/librte_lpm/rte_lpm6.h  |  50 ++-
 lib/librte_lpm/rte_lpm_version.map |  12 +
 4 files changed, 525 insertions(+), 165 deletions(-)

diff --git a/lib/librte_lpm/Makefile b/lib/librte_lpm/Makefile
index 656ade2..cbab7da 100644
--- a/lib/librte_lpm/Makefile
+++ b/lib/librte_lpm/Makefile
@@ -39,7 +39,7 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)

 EXPORT_MAP := rte_lpm_version.map

-LIBABIVER := 2
+LIBABIVER := 3

 # all source are stored in SRCS-y
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) := rte_lpm.c rte_lpm6.c
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 32fdba0..e449152 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -52,6 +52,12 @@
 #include 
 #include 
 #include 
+#include 
+#ifdef RTE_EXEC_ENV_BSDAPP
+# include 
+#else
+# include 
+#endif

 #include "rte_lpm6.h"

@@ -97,27 +103,46 @@ struct rte_lpm6_tbl_entry {
 /** Rules tbl entry structure. */
 struct rte_lpm6_rule {
uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */
-   uint8_t next_hop; /**< Rule next hop. */
+   uint16_t next_hop; /**< Rule next hop. */
uint8_t depth; /**< Rule depth. */
+   RB_ENTRY(rte_lpm6_rule) link;
 };

 /** LPM6 structure. */
 struct rte_lpm6 {
/* LPM metadata. */
char name[RTE_LPM6_NAMESIZE];/**< Name of the lpm. */
-   uint32_t max_rules;  /**< Max number of rules. */
-   uint32_t used_rules; /**< Used rules so far. */
uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
-   uint32_t next_tbl8;  /**< Next tbl8 to be used. */
+
+   /* LPM rules. */
+   RB_HEAD(rte_lpm6_rules_tree, rte_lpm6_rule) rules[RTE_LPM6_MAX_DEPTH + 
1];

/* LPM Tables. */
-   struct rte_lpm6_rule *rules_tbl; /**< LPM rules. */
struct rte_lpm6_tbl_entry tbl24[RTE_LPM6_TBL24_NUM_ENTRIES]
__rte_cache_aligned; /**< LPM tbl24 table. */
struct rte_lpm6_tbl_entry tbl8[0]
__rte_cache_aligned; /**< LPM tbl8 table. */
 };

+/* Comparison function for red-black tree nodes.
+   "If the first argument is smaller than the second, the function
+   returns a value smaller than zero.  If they are equal, the function
+   returns zero.  Otherwise, it should return a value greater than zero."
+*/
+static inline int rules_cmp(const struct rte_lpm6_rule *r1,
+   const struct rte_lpm6_rule *r2)
+{
+   return memcmp(r1->ip, r2->ip, RTE_LPM6_IPV6_ADDR_SIZE);
+}
+
+/* Satisfy old style attribute in tree.h header */
+#ifndef __unused
+#define __unused __attribute__ ((unused))
+#endif
+
+/* Generate internal functions and make them static. */
+RB_GENERATE_STATIC(rte_lpm6_rules_tree, rte_lpm6_rule, link, rules_cmp)
+
 /*
  * Takes an array of uint8_t (IPv6 address) and masks it using the depth.
  * It leaves untouched one bit per unit in the depth variable
@@ -126,8 +151,8 @@ struct rte_lpm6 {
 static inline void
 mask_ip(uint8_t *ip, uint8_t depth)
 {
-int16_t part_depth, mask;
-int i;
+   int16_t part_depth, mask;
+   int i;

part_depth = depth;

@@ -152,7 +177,8 @@ rte_lpm6_create(const char *name, int socket_id,
char mem_name[RTE_LPM6_NAMESIZE];
struct rte_lpm6 *lpm = NULL;
struct rte_tailq_entry *te;
-   uint64_t mem_size, rules_size;
+   uint64_t mem_size;
+   unsigned int depth;
struct rte_lpm6_list *lpm_list;

lpm_list = RTE_TAILQ_CAST(rte_lpm6_tailq.head, rte_lpm6_list);
@@ -161,7 +187,6 @@ rte_lpm6_create(const char *name, int socket_id,

/* Check user arguments. */
if ((name == NULL) || (socket_id < -1) || (config == NULL) ||
-

[dpdk-dev] [PATCH v2 0/2] lpm6: speed improvement on delete rule

2016-08-25 Thread Nikita Kozlov
This serie of pathes focus on improving the speed of deleting rules in lpm6.

It also contains some other improvement like having a dynamic number of
rules in lpm6 and increasing the lpm6 nexthop size to 16bit for matching
the nexthop size in lpm4.

The performances improvement can be seen by running test_lpm6_perf but
because of the limited number of rules added (1000) the improvement seen is
just about a x10 with this test.

For testing it further we have tested it with a full ipv6 bgp view which 
represent 29296 routes in our test:
* With the dpdk 16.04 it tooks an average of 8.46095e+09 cycles to delete a rule
(calculated with mesuring rte_rdtsc before and after the delete, the
average is calculated by the first 10 delete, it represents several
seconds on a E5-2650 v2)
* With the patch it tooks 10077.1 cycles (same number of deleted rules,
same machine, same rules inserted) for the same test.

This patch was written in collaboration with Baptiste Daroussin from Gandi.

Changes since V1:
- use system bsd-tree.h
- fix a bug when valid_group field was overwritten 

Nikita Kozlov (2):
  lpm6: speed inmprovement on delete rule
  test_lpm6: make test_lpm6* compatible with the new rte_lpm6.c lib

 app/test/test_lpm6.c  | 244 +
 app/test/test_lpm6_perf.c |   6 +-
 lib/librte_lpm/Makefile   |   2 +-
 lib/librte_lpm/rte_lpm6.c | 626 +-
 lib/librte_lpm/rte_lpm6.h |  50 ++-
 lib/librte_lpm/rte_lpm_version.map|  12 +
 lib/librte_table/rte_table_lpm_ipv6.c |   7 +-
 7 files changed, 609 insertions(+), 338 deletions(-)

-- 
2.9.2


[dpdk-dev] [PATCH 4/4] test: change lpm perf test to use routes as resource

2016-06-14 Thread Nikita Kozlov
Change the lpm perf autotest to use the routes data from the resource data
stored in the binary rather than including it directly into the C file
as a C header. This speeds up compile and link time, without changing
the test results.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Bruce Richardson 
---
 app/test/test_lpm_perf.c | 83 
 1 file changed, 76 insertions(+), 7 deletions(-)

diff --git a/app/test/test_lpm_perf.c b/app/test/test_lpm_perf.c
index 41da811..f72250f 100644
--- a/app/test/test_lpm_perf.c
+++ b/app/test/test_lpm_perf.c
@@ -34,16 +34,28 @@
 #include 
 #include 
 #include 
+#include 

 #include 
 #include 
 #include 
 #include 
+#include 
+#include 

 #include "test.h"
-#include "test_lpm_routes.h"
+#include "resource.h"
 #include "test_xmmt_ops.h"

+REGISTER_LINKED_RESOURCE(test_lpm_data)
+
+struct route_rule {
+   uint32_t ip;
+   uint8_t depth;
+};
+static struct route_rule *large_route_table;
+static unsigned int num_route_entries;
+
 #define TEST_LPM_ASSERT(cond) do {\
if (!(cond)) {\
printf("Error at line %d: \n", __LINE__); \
@@ -80,6 +92,62 @@ print_route_distribution(const struct route_rule *table, 
uint32_t n)
 }

 static int
+load_large_route_table(void)
+{
+   const struct resource *r;
+   const char *lpm_data;
+
+   r = resource_find("test_lpm_data");
+   TEST_ASSERT_NOT_NULL(r, "No large lpm table data found");
+
+   /* the routing table size is going to be less than the size of the
+* resource, since text extries are more verbose. Allocate this as
+* the max size, and shrink the allocation later
+*/
+   large_route_table = rte_malloc(NULL, resource_size(r), 0);
+   if (large_route_table == NULL)
+   return -1;
+
+   /* parse the lpm table. All entries are of format:
+*  {IP-as-decimal-unsigned, depth}
+* For example:
+*  {1234567U, 24},
+* We use the "U" and "}" characters as format check characters,
+* after parsing each number.
+*/
+   for (lpm_data = r->begin; lpm_data < r->end; lpm_data++) {
+   if (*lpm_data == '{') {
+   char *endptr;
+
+   lpm_data++;
+   large_route_table[num_route_entries].ip = \
+   strtoul(lpm_data, , 0);
+   if (*endptr != 'U') {
+   if (num_route_entries > 0)
+   printf("Failed parse of %.*s\n", 12, 
lpm_data);
+   continue;
+   }
+
+   lpm_data = endptr + 2; /* skip U and , */
+   large_route_table[num_route_entries].depth = \
+   strtoul(lpm_data, , 0);
+   if (*endptr != '}') {
+   if (num_route_entries > 0)
+   printf("Failed parse of %.*s\n",5, 
lpm_data);
+   continue;
+   }
+
+   num_route_entries++;
+   }
+   }
+
+   large_route_table = rte_realloc(large_route_table,
+   sizeof(large_route_table[0]) * num_route_entries, 0);
+   printf("Read %u route entries\n", num_route_entries);
+   return 0;
+}
+
+static int
 test_lpm_perf(void)
 {
struct rte_lpm *lpm = NULL;
@@ -97,9 +165,10 @@ test_lpm_perf(void)

rte_srand(rte_rdtsc());

-   printf("No. routes = %u\n", (unsigned) NUM_ROUTE_ENTRIES);
+   TEST_ASSERT_SUCCESS(load_large_route_table(), "Error loading lpm 
table");
+   printf("No. routes = %u\n", (unsigned) num_route_entries);

-   print_route_distribution(large_route_table, (uint32_t) 
NUM_ROUTE_ENTRIES);
+   print_route_distribution(large_route_table, (uint32_t) 
num_route_entries);

lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm != NULL);
@@ -107,7 +176,7 @@ test_lpm_perf(void)
/* Measue add. */
begin = rte_rdtsc();

-   for (i = 0; i < NUM_ROUTE_ENTRIES; i++) {
+   for (i = 0; i < num_route_entries; i++) {
if (rte_lpm_add(lpm, large_route_table[i].ip,
large_route_table[i].depth, next_hop_add) == 0)
status++;
@@ -136,7 +205,7 @@ test_lpm_perf(void)
(unsigned) cache_line_counter, (unsigned) 
cache_line_counter * 64);

printf("Average LPM Add: %g cycles\n",
-   (double)total_time / NUM_ROUTE_ENTRIES);
+   (doubl

[dpdk-dev] [PATCH 3/4] test: change lpm test to use routes as resource

2016-06-14 Thread Nikita Kozlov
Change the lpm autotest to use the routes data from the resource data
stored in the binary rather than including it directly into the C file
as a C header. This speeds up compile and link time, without changing
the test results.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Bruce Richardson 
---
 app/test/test_lpm.c | 73 -
 1 file changed, 72 insertions(+), 1 deletion(-)

diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c
index f6930fb..de54720 100644
--- a/app/test/test_lpm.c
+++ b/app/test/test_lpm.c
@@ -34,13 +34,26 @@
 #include 
 #include 
 #include 
+#include 

 #include 
+#include 
+#include 

 #include "test.h"
-#include "test_lpm_routes.h"
+#include "resource.h"
+
 #include "test_xmmt_ops.h"

+REGISTER_LINKED_RESOURCE(test_lpm_data)
+
+struct route_rule {
+   uint32_t ip;
+   uint8_t depth;
+};
+static struct route_rule *large_route_table;
+static unsigned int num_route_entries;
+
 #define TEST_LPM_ASSERT(cond) do {\
if (!(cond)) {\
printf("Error at line %d: \n", __LINE__); \
@@ -1217,6 +1230,62 @@ test17(void)
return PASS;
 }

+static int
+load_large_route_table(void)
+{
+   const struct resource *r;
+   const char *lpm_data;
+
+   r = resource_find("test_lpm_data");
+   TEST_ASSERT_NOT_NULL(r, "No large lpm table data found");
+
+   /* the routing table size is going to be less than the size of the
+* resource, since text extries are more verbose. Allocate this as
+* the max size, and shrink the allocation later
+*/
+   large_route_table = rte_malloc(NULL, resource_size(r), 0);
+   if (large_route_table == NULL)
+   return -1;
+
+   /* parse the lpm table. All entries are of format:
+*  {IP-as-decimal-unsigned, depth}
+* For example:
+*  {1234567U, 24},
+* We use the "U" and "}" characters as format check characters,
+* after parsing each number.
+*/
+   for (lpm_data = r->begin; lpm_data < r->end; lpm_data++) {
+   if (*lpm_data == '{') {
+   char *endptr;
+
+   lpm_data++;
+   large_route_table[num_route_entries].ip = \
+   strtoul(lpm_data, , 0);
+   if (*endptr != 'U') {
+   if (num_route_entries > 0)
+   printf("Failed parse of %.*s\n", 12, 
lpm_data);
+   continue;
+   }
+
+   lpm_data = endptr + 2; /* skip U and , */
+   large_route_table[num_route_entries].depth = \
+   strtoul(lpm_data, , 0);
+   if (*endptr != '}') {
+   if (num_route_entries > 0)
+   printf("Failed parse of %.*s\n",5, 
lpm_data);
+   continue;
+   }
+
+   num_route_entries++;
+   }
+   }
+
+   large_route_table = rte_realloc(large_route_table,
+   sizeof(large_route_table[0]) * num_route_entries, 0);
+   printf("Read %u route entries\n", num_route_entries);
+   return 0;
+}
+
 /*
  * Do all unit tests.
  */
@@ -1227,6 +1296,8 @@ test_lpm(void)
unsigned i;
int status, global_status = 0;

+   TEST_ASSERT_SUCCESS(load_large_route_table(), "Error loading lpm 
table");
+
for (i = 0; i < NUM_LPM_TESTS; i++) {
status = tests[i]();
if (status < 0) {
-- 
2.8.1



[dpdk-dev] [PATCH 2/4] test: change lpm routes file from header to data file

2016-06-14 Thread Nikita Kozlov
Change the file extension of the test_lpm_routes file from .h to .dat.
This makes the lines-of-code counts for DPDK more realistic as they are not
affected by the huge counts from the lpm data.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Bruce Richardson 
---
 app/test/Makefile   | 1 +
 app/test/{test_lpm_routes.h => test_lpm_routes.dat} | 0
 2 files changed, 1 insertion(+)
 rename app/test/{test_lpm_routes.h => test_lpm_routes.dat} (100%)

diff --git a/app/test/Makefile b/app/test/Makefile
index 7e4d484..a3f317d 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -118,6 +118,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_functions.c
 SRCS-$(CONFIG_RTE_LIBRTE_HASH) += test_hash_scaling.c

+$(eval $(call linked_resource,test_lpm_data,test_lpm_routes.dat))
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm_perf.c
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) += test_lpm6.c
diff --git a/app/test/test_lpm_routes.h b/app/test/test_lpm_routes.dat
similarity index 100%
rename from app/test/test_lpm_routes.h
rename to app/test/test_lpm_routes.dat
-- 
2.8.1



[dpdk-dev] [PATCH 1/4] test: make all lpm routes be of unsigned type

2016-06-14 Thread Nikita Kozlov
The one route that was different to the others in the test_lpm_routes.h
file was the entry "{0, 8}" which was the only route without a "U" after
the IP part. Add in the extra "U" to that entry so that it can be used
as a check character when parsing routes manually.

Signed-off-by: Nikita Kozlov 
Signed-off-by: Bruce Richardson 
---
 app/test/test_lpm_routes.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/test/test_lpm_routes.h b/app/test/test_lpm_routes.h
index 023b0f9..1decfee 100644
--- a/app/test/test_lpm_routes.h
+++ b/app/test/test_lpm_routes.h
@@ -281825,7 +281825,7 @@ static const struct route_rule large_route_table[] =
{3536977920U, 17},
{3392992768U, 23},
{3341675008U, 23},
-   {0, 8},
+   {0U, 8},
{3326316168U, 30},
{3326316108U, 30},
{3326316060U, 30},
-- 
2.8.1



[dpdk-dev] [PATCH 0/4] Convert lpm data from header to resource

2016-06-14 Thread Nikita Kozlov
Re-submission of Bruce Richardson patch set:
http://dpdk.org/dev/patchwork/patch/12484/

This patchset is a rebase to the current head and use of 
strndupa (not posix) was replaced.

Original cover letter:

This patchset is based on the work done by Jan Viktorin to add resource
handling to the test app. [1]
It takes the existing lpm large routing table information and converts it
from a header file included at compile time to a resource linked in. This
improves things in two ways:
1. Improves DPDK build time
2. Removes approx 1 million lines of code from our LOC counts, as the header
file no longer counts as code, but more correctly as data.

Before and after approx code stats (with some additional patchsets applied).
Notice how the app folder has dropped from being the biggest component with
6x the drivers code to second place with less code than the drivers.
Future work is to repeat the same process for lpm6.

SLOCDirectory   SLOC-by-Language (Sorted)
1237464 app ansic=1236324,python=1140
192107  drivers ansic=192107
108109  lib ansic=107968,python=141
65447   examplesansic=65312,sh=135
849 tools   python=444,sh=405
799 scripts sh=799
77  doc python=75,sh=2
0   config  (none)
0   mk  (none)
0   pkg (none)
0   top_dir (none)


Totals grouped by language (dominant language first):
ansic:  1601711 (99.80%)
python:1800 (0.11%)
sh:1341 (0.08%)

---

SLOCDirectory   SLOC-by-Language (Sorted)
192107  drivers ansic=192107
160646  app ansic=159506,python=1140
108109  lib ansic=107968,python=141
65447   examplesansic=65312,sh=135
849 tools   python=444,sh=405
799 scripts sh=799
77  doc python=75,sh=2
0   config  (none)
0   mk  (none)
0   pkg (none)
0   top_dir (none)


Totals grouped by language (dominant language first):
ansic:   524893 (99.41%)
python:1800 (0.34%)
sh:1341 (0.25%)

generated using David A. Wheeler's 'SLOCCount'

[1] http://dpdk.org/ml/archives/dev/2016-April/038145.html

Nikita Kozlov (4):
  test: make all lpm routes be of unsigned type
  test: change lpm routes file from header to data file
  test: change lpm test to use routes as resource
  test: change lpm perf test to use routes as resource

 app/test/Makefile  |  1 +
 app/test/test_lpm.c| 73 ++-
 app/test/test_lpm_perf.c   | 83 --
 .../{test_lpm_routes.h => test_lpm_routes.dat} |  2 +-
 4 files changed, 150 insertions(+), 9 deletions(-)
 rename app/test/{test_lpm_routes.h => test_lpm_routes.dat} (99%)

-- 
2.8.1



[dpdk-dev] [PATCH 2/3] librte_eal: Import FreeBSD sys/tree.h into librte_eal/common

2016-06-09 Thread Nikita Kozlov
On 06/ 9/16 02:58 AM, Stephen Hemminger wrote:
> On Thu,  9 Jun 2016 02:53:53 +0200
> Nikita Kozlov  wrote:
>
>> This structure is used inside the rte_lpm6 lib for storing added rules.
>> It's imported from FreeBSD-10.3 from /usr/include/sys/tree.h, another
>> solution could have been to use on Linux the version from libbsd but it
>> would create an external dependency.
>>
>> Signed-off-by: Nikita Kozlov 
> Using Red-black tree is a good idea, and we have been doing it for a while
> both on v4 and v6.
Yes, like I said in 1/3, the idea is taken from your patch.
I have tested it and it seemed to work pretty fine, maybe we could try
to split it a little bit and try to send it again ?
It's quite difficult to tell what was wrong with it since I cannot see
any public discussion about it.
>
> But this is not the way to handle it.
> Please don't copy a header file which is available already on both BSD and 
> Linux.
>
>
I was quite hesitant on how to handle it. I had the feeling that dpdk
wanted to avoid external dependency so I copied that file. If it's not
the case I would be happy to resend the patches without that external
import.


[dpdk-dev] [PATCH 3/3] test_lpm6: make test_lpm6* compatible with the new rte_lpm6.c lib

2016-06-09 Thread Nikita Kozlov
Modify of test_lpm6.c to reflect that we no longer have a maximum number
of rules.

Check in some places that we are using the same number of tbl8 as the
previous implementation after a rte_lpm6_delete.

Signed-off-by: Nikita Kozlov 
---
 app/test/test_lpm6.c  | 131 +-
 app/test/test_lpm6_perf.c |   5 +-
 lib/librte_table/rte_table_lpm_ipv6.c |   7 +-
 3 files changed, 72 insertions(+), 71 deletions(-)

diff --git a/app/test/test_lpm6.c b/app/test/test_lpm6.c
index 458a10b..612bcef 100644
--- a/app/test/test_lpm6.c
+++ b/app/test/test_lpm6.c
@@ -114,7 +114,6 @@ rte_lpm6_test tests6[] = {

 #define NUM_LPM6_TESTS(sizeof(tests6)/sizeof(tests6[0]))
 #define MAX_DEPTH128
-#define MAX_RULES100
 #define NUMBER_TBL8S   (1 << 16)
 #define MAX_NUM_TBL8S  (1 << 21)
 #define PASS 0
@@ -153,7 +152,6 @@ test0(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -161,14 +159,7 @@ test0(void)
lpm = rte_lpm6_create(NULL, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm == NULL);

-   /* rte_lpm6_create: max_rules = 0 */
-   /* Note: __func__ inserts the function name, in this case "test0". */
-   config.max_rules = 0;
-   lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, );
-   TEST_LPM_ASSERT(lpm == NULL);
-
/* socket_id < -1 is invalid */
-   config.max_rules = MAX_RULES;
lpm = rte_lpm6_create(__func__, -2, );
TEST_LPM_ASSERT(lpm == NULL);

@@ -195,7 +186,6 @@ test1(void)
struct rte_lpm6 *lpm1 = NULL, *lpm2 = NULL, *lpm3 = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -233,7 +223,6 @@ test2(void)

/* rte_lpm6_free: Free NULL */
for (i = 0; i < 20; i++) {
-   config.max_rules = MAX_RULES - i;
lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm != NULL);

@@ -256,7 +245,6 @@ test3(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -278,10 +266,10 @@ test4(void)
struct rte_lpm6_config config;

uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t depth = 24, next_hop = 100;
+   uint8_t depth = 24;
+   uint16_t next_hop = 100;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -319,7 +307,6 @@ test5(void)
uint8_t depth = 24;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -354,10 +341,9 @@ test6(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t next_hop_return = 0;
+   uint16_t next_hop_return = 0;
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -392,10 +378,9 @@ test7(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[10][16];
-   int16_t next_hop_return[10];
+   int32_t next_hop_return[10];
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -433,7 +418,6 @@ test8(void)
uint8_t depth[10];
int32_t status = 0;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -469,11 +453,11 @@ test9(void)
struct rte_lpm6 *lpm = NULL;
struct rte_lpm6_config config;
uint8_t ip[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-   uint8_t depth = 16, next_hop_add = 100, next_hop_return = 0;
+   uint8_t depth = 16;
+   uint16_t next_hop_add = 100, next_hop_return = 0;
int32_t status = 0;
uint8_t i;

-   config.max_rules = MAX_RULES;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

@@ -517,14 +501,13 @@ test10(void)
int32_t status = 0;
int i;

-   config.max_rules = 127;
config.number_tbl8s = NUMBER_TBL8S;
config.flags = 0;

lpm = rte_lpm6_create(__func__, SOCKET_ID_ANY, );
TEST_LPM_ASSERT(lpm != NULL);

-   for (i = 1; i < 128; i++) {
+   for (i = 1; i <= 128; i++) {
depth = (uint8_t)i;
status = rte_lpm

[dpdk-dev] [PATCH 2/3] librte_eal: Import FreeBSD sys/tree.h into librte_eal/common

2016-06-09 Thread Nikita Kozlov
This structure is used inside the rte_lpm6 lib for storing added rules.
It's imported from FreeBSD-10.3 from /usr/include/sys/tree.h, another
solution could have been to use on Linux the version from libbsd but it
would create an external dependency.

Signed-off-by: Nikita Kozlov 
---
 lib/librte_eal/common/Makefile   |   2 +-
 lib/librte_eal/common/include/sys/tree.h | 801 +++
 2 files changed, 802 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_eal/common/include/sys/tree.h

diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
index f5ea0ee..57f58d6 100644
--- a/lib/librte_eal/common/Makefile
+++ b/lib/librte_eal/common/Makefile
@@ -40,7 +40,7 @@ INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
 INC += rte_hexdump.h rte_devargs.h rte_dev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
-INC += rte_malloc.h rte_keepalive.h rte_time.h
+INC += rte_malloc.h rte_keepalive.h rte_time.h sys/tree.h

 ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y)
 INC += rte_warnings.h
diff --git a/lib/librte_eal/common/include/sys/tree.h 
b/lib/librte_eal/common/include/sys/tree.h
new file mode 100644
index 000..1f5c628
--- /dev/null
+++ b/lib/librte_eal/common/include/sys/tree.h
@@ -0,0 +1,801 @@
+/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $  */
+/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $*/
+/* $FreeBSD: head/sys/sys/tree.h 277642 2015-01-24 12:43:36Z kib $ */
+
+/*-
+ * Copyright 2002 Niels Provos 
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef_SYS_TREE_H_
+#define_SYS_TREE_H_
+
+#include 
+
+/*
+ * This file defines data structures for different types of trees:
+ * splay trees and red-black trees.
+ *
+ * A splay tree is a self-organizing data structure.  Every operation
+ * on the tree causes a splay to happen.  The splay moves the requested
+ * node to the root of the tree and partly rebalances it.
+ *
+ * This has the benefit that request locality causes faster lookups as
+ * the requested nodes move to the top of the tree.  On the other hand,
+ * every lookup causes memory writes.
+ *
+ * The Balance Theorem bounds the total access time for m operations
+ * and n inserts on an initially empty tree as O((m + n)lg n).  The
+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
+ *
+ * A red-black tree is a binary search tree with the node color as an
+ * extra attribute.  It fulfills a set of conditions:
+ * - every search path from the root to a leaf consists of the
+ *   same number of black nodes,
+ * - each red node (except for the root) has a black parent,
+ * - each leaf node is black.
+ *
+ * Every operation on a red-black tree is bounded as O(lg n).
+ * The maximum height of a red-black tree is 2lg (n+1).
+ */
+
+#define SPLAY_HEAD(name, type) \
+struct name {  \
+   struct type *sph_root; /* root of the tree */   \
+}
+
+#define SPLAY_INITIALIZER(root)
\
+   { NULL }
+
+#define SPLAY_INIT(root) do {  \
+   (root)->sph_root = NULL;\
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ENTRY(type)  \
+struct {   \
+   struct type *spe_left; /* left element */   \
+   struct type *spe_right; /* right element */ \
+}
+
+#define SPLAY_LEFT(elm, field) (elm)->field.sp

[dpdk-dev] [PATCH 1/3] lpm6 speed inmprovement on delete rule

2016-06-09 Thread Nikita Kozlov
Rewrite rte_lpm6_delete* logic for deleting only the selected rule
instead of deleting all rules and re-inserting them.

the delete_step() function is called recursively and delete the rule
until the rule depth is covered. Then it calls delete_expand_step()
which will ensure to delete the expanded part of the rule if any.

The tbl8 are now allocated more dynamically through tbl8_alloc() which
will walk through all tbl8 for finding an empty one.

The rules are now stored in a RB-tree so we can have a dynamic number of
them. This part of the patch is inspired by
http://dpdk.org/dev/patchwork/patch/7981/ .

Adding of rte_lpm6_tbl8_count() and rte_lpm6_tbl8_free_count() which
permits to check that we are freeing correctly our tbl8 and permits to
check how much free tbl8 we have for adding new rules.

For consistency with lpm4, increase lpm6 nexthop size from 8bit to
16bit.

This patch was written in collaboration with Baptiste Daroussin from Gandi.

Signed-off-by: Nikita Kozlov 
---
 lib/librte_lpm/Makefile|   2 +-
 lib/librte_lpm/rte_lpm6.c  | 576 ++---
 lib/librte_lpm/rte_lpm6.h  |  49 +++-
 lib/librte_lpm/rte_lpm_version.map |  12 +
 4 files changed, 474 insertions(+), 165 deletions(-)

diff --git a/lib/librte_lpm/Makefile b/lib/librte_lpm/Makefile
index 656ade2..cbab7da 100644
--- a/lib/librte_lpm/Makefile
+++ b/lib/librte_lpm/Makefile
@@ -39,7 +39,7 @@ CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR)

 EXPORT_MAP := rte_lpm_version.map

-LIBABIVER := 2
+LIBABIVER := 3

 # all source are stored in SRCS-y
 SRCS-$(CONFIG_RTE_LIBRTE_LPM) := rte_lpm.c rte_lpm6.c
diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 32fdba0..a9de0e1 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -52,6 +52,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 

 #include "rte_lpm6.h"

@@ -97,27 +99,46 @@ struct rte_lpm6_tbl_entry {
 /** Rules tbl entry structure. */
 struct rte_lpm6_rule {
uint8_t ip[RTE_LPM6_IPV6_ADDR_SIZE]; /**< Rule IP address. */
-   uint8_t next_hop; /**< Rule next hop. */
+   uint16_t next_hop; /**< Rule next hop. */
uint8_t depth; /**< Rule depth. */
+   RB_ENTRY(rte_lpm6_rule) link;
 };

 /** LPM6 structure. */
 struct rte_lpm6 {
/* LPM metadata. */
char name[RTE_LPM6_NAMESIZE];/**< Name of the lpm. */
-   uint32_t max_rules;  /**< Max number of rules. */
-   uint32_t used_rules; /**< Used rules so far. */
uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
-   uint32_t next_tbl8;  /**< Next tbl8 to be used. */
+
+   /* LPM rules. */
+   RB_HEAD(rte_lpm6_rules_tree, rte_lpm6_rule) rules[RTE_LPM6_MAX_DEPTH + 
1];

/* LPM Tables. */
-   struct rte_lpm6_rule *rules_tbl; /**< LPM rules. */
struct rte_lpm6_tbl_entry tbl24[RTE_LPM6_TBL24_NUM_ENTRIES]
__rte_cache_aligned; /**< LPM tbl24 table. */
struct rte_lpm6_tbl_entry tbl8[0]
__rte_cache_aligned; /**< LPM tbl8 table. */
 };

+/* Comparison function for red-black tree nodes.
+   "If the first argument is smaller than the second, the function
+   returns a value smaller than zero.  If they are equal, the function
+   returns zero.  Otherwise, it should return a value greater than zero."
+*/
+static inline int rules_cmp(const struct rte_lpm6_rule *r1,
+   const struct rte_lpm6_rule *r2)
+{
+   return memcmp(r1->ip, r2->ip, RTE_LPM6_IPV6_ADDR_SIZE);
+}
+
+/* Satisfy old style attribute in tree.h header */
+#ifndef __unused
+#define __unused __attribute__ ((unused))
+#endif
+
+/* Generate internal functions and make them static. */
+RB_GENERATE_STATIC(rte_lpm6_rules_tree, rte_lpm6_rule, link, rules_cmp)
+
 /*
  * Takes an array of uint8_t (IPv6 address) and masks it using the depth.
  * It leaves untouched one bit per unit in the depth variable
@@ -126,8 +147,8 @@ struct rte_lpm6 {
 static inline void
 mask_ip(uint8_t *ip, uint8_t depth)
 {
-int16_t part_depth, mask;
-int i;
+   int16_t part_depth, mask;
+   int i;

part_depth = depth;

@@ -152,7 +173,8 @@ rte_lpm6_create(const char *name, int socket_id,
char mem_name[RTE_LPM6_NAMESIZE];
struct rte_lpm6 *lpm = NULL;
struct rte_tailq_entry *te;
-   uint64_t mem_size, rules_size;
+   uint64_t mem_size;
+   unsigned int depth;
struct rte_lpm6_list *lpm_list;

lpm_list = RTE_TAILQ_CAST(rte_lpm6_tailq.head, rte_lpm6_list);
@@ -161,7 +183,6 @@ rte_lpm6_create(const char *name, int socket_id,

/* Check user arguments. */
if ((name == NULL) || (socket_id < -1) || (config == NULL) ||
-   (config->max_rules == 0) ||
config->number_tbl

[dpdk-dev] [PATCH 0/3] lpm6: speed improvement on delete rule

2016-06-09 Thread Nikita Kozlov
This serie of pathes focus on improving the speed of deleting rules in lpm6.

It also contains some other improvement like having a dynamic number of
rules in lpm6 and increasing the lpm6 nexthop size to 16bit for matching
the nexthop size in lpm4.

The performances improvement can be seen by running test_lpm6_perf but
because of the limited number of rules added (1000) the improvement seen is
just about a x10 with this test.

For testing it further we have tested it with a full ipv6 bgp view which 
represent 29296 routes in our test:
* With the dpdk 16.04 it tooks an average of 8.46095e+09 cycles to delete a rule
(calculated with mesuring rte_rdtsc before and after the delete, the
average is calculated by the first 10 delete, it represents several
seconds on a E5-2650 v2)
* With the patch it tooks 10077.1 cycles (same number of deleted rules,
same machine, same rules inserted) for the same test.

This patch was written in collaboration with Baptiste Daroussin from Gandi.

Nikita Kozlov (3):
  lpm6 speed inmprovement on delete rule
  librte_eal: Import FreeBSD sys/tree.h into librte_eal/common
  test_lpm6: make test_lpm6* compatible with the new rte_lpm6.c lib

 app/test/test_lpm6.c | 131 ++---
 app/test/test_lpm6_perf.c|   5 +-
 lib/librte_eal/common/Makefile   |   2 +-
 lib/librte_eal/common/include/sys/tree.h | 801 +++
 lib/librte_lpm/Makefile  |   2 +-
 lib/librte_lpm/rte_lpm6.c| 576 --
 lib/librte_lpm/rte_lpm6.h|  49 +-
 lib/librte_lpm/rte_lpm_version.map   |  12 +
 lib/librte_table/rte_table_lpm_ipv6.c|   7 +-
 9 files changed, 1348 insertions(+), 237 deletions(-)
 create mode 100644 lib/librte_eal/common/include/sys/tree.h

-- 
2.8.1



[dpdk-dev] [PATCH v1] net: i40e: add VLAN tag size to RXMAX

2016-05-06 Thread Nikita Kozlov
Hello,

On 09/ 1/15 07:34 AM, Zhang, Helin wrote:
>> -Original Message-
>> From: Vlad Zolotarov [mailto:vladz at cloudius-systems.com]
>> Sent: Monday, August 31, 2015 2:42 PM
>> To: dev at dpdk.org
>> Cc: Zhang, Helin; Ananyev, Konstantin; avi at cloudius-systems.com; Vlad
>> Zolotarov
>> Subject: [dpdk-dev] [PATCH v1] net: i40e: add VLAN tag size to RXMAX
>>
>> HW requires it regardless the presence of the VLAN tag in the received frame.
>> Otherwise Rx frames are being filtered out on the MTU-4 boundary.
> Maximum packet length could have different meanings from MTU. I agree with
> you to have it be regardless of vlan tag length.
>
>> Signed-off-by: Vlad Zolotarov 
>> ---
>>  drivers/net/i40e/i40e_rxtx.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c 
>> index
>> eae4ab0..22aaeb1 100644
>> --- a/drivers/net/i40e/i40e_rxtx.c
>> +++ b/drivers/net/i40e/i40e_rxtx.c
>> @@ -3156,7 +3156,7 @@ i40e_rx_queue_init(struct i40e_rx_queue *rxq)
>>  rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_ALL;
>>  else
>>  rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
>> -rx_ctx.rxmax = rxq->max_pkt_len;
>> +rx_ctx.rxmax = rxq->max_pkt_len + I40E_VLAN_TAG_SIZE;
> It needs to take into account the double vlan case, and also VF case.
> It seems it needs more code changes. Thank you for the contribution!
I was wondering if this "bug" haven't been forgotten ? Even if it his
not patched yet maybe it is worth an entry in the documentation ?
>
> Regards,
> Helin
>
>>  rx_ctx.tphrdesc_ena = 1;
>>  rx_ctx.tphwdesc_ena = 1;
>>  rx_ctx.tphdata_ena = 1;
>> --
>> 2.1.0



[dpdk-dev] lpm patches

2016-02-01 Thread Nikita Kozlov
On 10/30/2015 11:25 PM, Matthew Hall wrote:
> On Fri, Oct 30, 2015 at 09:55:16PM +, Bruce Richardson wrote:
>> We'll see what we can do in 2.3 timeframe.
> Thanks for taking all of this up and helping us make a solid plan. I'll do my 
> best to help out from the community side. I have done some lightweight 
> functionality tests of my patched LPM to good effect.
>
> I'm working on finishing the last key feature and acquiring a Skylake system 
> in the next few weeks so I can start doing some performance testing of my 
> application with the community license of VTune, so I can make a proper 
> release of some kind.
>
> Just so I know what things I should monitor when, what is the approximate 
> schedule for 2.3? Can we host a private branch or tree somewhere to be able 
> to 
> access any progress made with the various changes and report back?
>
> Matthew.
Hello,
I wanted to know if there was something new or if I can help on this topic ?
I'm using rte_lpm in a project so I may (at least) do some tests or reviews.


[dpdk-dev] [PATCH] lib/lpm:fix two issues in the delete_depth_small()

2015-10-28 Thread Nikita Kozlov
On 10/28/2015 03:40 PM, Bruce Richardson wrote:
> On Wed, Oct 28, 2015 at 11:44:15AM +0800, Jijiang Liu wrote:
>> Fix two issues in the delete_depth_small() function.
>>  
>> 1> The control is not strict in this function.
>>  
>> In the following structure,
>> struct rte_lpm_tbl24_entry {
>> union {
>> uint8_t next_hop;
>> uint8_t tbl8_gindex;
>> };
>>  uint8_t ext_entry :1;
>> }
>>  
>> When ext_entry = 0, use next_hop.only to process rte_lpm_tbl24_entry.
>>  
>> When ext_entry = 1, use tbl8_gindex to process the rte_lpm_tbl8_entry.
>>  
>> When using LPM24 + 8 algorithm, it will use ext_entry to decide to process 
>> rte_lpm_tbl24_entry structure or rte_lpm_tbl8_entry structure. 
>> If a route is deleted, the prefix of previous route is used to override the 
>> deleted route. when (lpm->tbl24[i].ext_entry == 0 && lpm->tbl24[i].depth > 
>> depth) 
>> it should be ignored, but due to the incorrect logic, the next_hop is used 
>> as tbl8_gindex and will process the rte_lpm_tbl8_entry.
>>  
>> 2> Initialization of rte_lpm_tbl8_entry is incorrect in this function 
>>  
>> In this function, use new rte_lpm_tbl8_entry we call A to replace the old 
>> rte_lpm_tbl8_entry. But the valid_group do not set VALID, so it will be 
>> INVALID.
>> Then when adding a new route which depth is > 24,the tbl8_alloc() function 
>> will search the rte_lpm_tbl8_entrys to find INVALID valid_group, 
>> and it will return the A to the add_depth_big function, so A's data is 
>> overridden.
>>
>> Signed-off-by: NaNa 
>>
> Hi NaNa, Jijiang,
>
> since this patch contains two separate fixes, it would be better split into
> two separate patches, one for each fix. Also, please add a "Fixes" line to
> the commit log.
>
> Are there still plans for a unit test to demonstrate the bug(s) and make it 
> easy
> for us to verify the fix?
>
> Regards,
> /Bruce
Hello,

It's the same fix as the one sent here (which contained some tests,
maybe we can use them ?)
http://dpdk.org/ml/archives/dev/2015-October/025871.html .
For what is worth, we are using those fix at my company and they are
fixing the described bug.

-- 
Nikita


[dpdk-dev] libdpdk upstream changes for ecosystem best practices

2015-09-03 Thread Nikita Kozlov
On 09/02/2015 03:49 PM, Robie Basak wrote:
> Hi,
>
> We?re looking at packaging DPDK in Ubuntu. We?d like to discuss upstream
> changes to better integrate DPDK into Linux distributions.
> ...
>
> Thanks,
>
> Robie
Hello,

For your interest, we have also done some kind of packaging of dpdk for
debian : https://github.com/Gandi/dpdk-debian
It's not really clean and it triggers many lintian things, but feel free
to dig from it anything valuable.

Thanks for your packaging effort,

Nikita


[dpdk-dev] [PATCH] Add CONFIG_RTE_KNI_KMOD build option.

2015-08-03 Thread Nikita Kozlov
This option permit to build librte_kni.so without building rte_kni.ko so
you can build a sdk without building kernel drivers.

Signed-off-by: Nikita Kozlov 
---
 config/common_linuxapp   | 1 +
 lib/librte_eal/linuxapp/Makefile | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/config/common_linuxapp b/config/common_linuxapp
index bda9a63..0de43d5 100644
--- a/config/common_linuxapp
+++ b/config/common_linuxapp
@@ -425,6 +425,7 @@ CONFIG_RTE_PIPELINE_STATS_COLLECT=n
 # Compile librte_kni
 #
 CONFIG_RTE_LIBRTE_KNI=y
+CONFIG_RTE_KNI_KMOD=y
 CONFIG_RTE_KNI_PREEMPT_DEFAULT=y
 CONFIG_RTE_KNI_KO_DEBUG=n
 CONFIG_RTE_KNI_VHOST=n
diff --git a/lib/librte_eal/linuxapp/Makefile b/lib/librte_eal/linuxapp/Makefile
index 8fcfdf6..d9c5233 100644
--- a/lib/librte_eal/linuxapp/Makefile
+++ b/lib/librte_eal/linuxapp/Makefile
@@ -35,7 +35,7 @@ ifeq ($(CONFIG_RTE_EAL_IGB_UIO),y)
 DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += igb_uio
 endif
 DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += eal
-ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
+ifeq ($(CONFIG_RTE_KNI_KMOD),y)
 DIRS-$(CONFIG_RTE_LIBRTE_EAL_LINUXAPP) += kni
 endif
 ifeq ($(CONFIG_RTE_LIBRTE_XEN_DOM0),y)
-- 
2.4.6



[dpdk-dev] no packets with i40e when setting up more than 1 rx queue

2015-06-02 Thread Nikita Kozlov
Hello,

To introduce myself, I am working on a slightly enhanced version of
l3fwd which support some more features like dynamically adding new
routes in a lpm table, adding some acls, rate-limiting per dest, a
command line through unixsock etc. We hope to open source it as soon as
it is shiny enough.

Here is my problem, when I'm trying to use more than 1 rx_queue using
the i40e driver I'm not receiving any packet, the rx_status in
i40e_rx_scan_hw_ring is always 0 on all queues. Note that the code is
working with more than 1 queue with an ixgbe card.

Some details:
-We are using the same rte_eth_conf as the one in l3fwd, and we have
tested with both ETH_RSS_IP and ETH_RSS_PROTO_MASK.
-The queues setup is the same as in l3fwd.
-When I'm dumping the reta table I have my hash indexes are pointing to
queue 0 and 1.
-The rxq->queue_id in i40e_rx_scan_hw_ring (and in rte_eth_rx_burst) is
a mix of queue 0 and queue 1.
-The rss configuration taken from rte_eth_dev_rss_hash_conf_get seems ok.
-We have flashed both card to the latest  version (f4.33 a1.2 n04.42
e80001930)
-We have tested with dpdk2.0.0 and with the current HEAD.

I saw the mail "i40e and RSS woes", so I tried to set another rss_key
after the init but it doesn't help. I also tried to modify the reta
table but it doesn't help also.

I am a little bit out of new ideas to solve it, if its not to try to
downgrade the firmware version.

Anyone have a suggestion ? I will continue my dev using a ixgbe card,
but making it work with i40e too (with more than 1 rx_queue) would be
really pleasing.

-- 
Nikita