Signed-off-by: Michal Kobylinski <michalx.kobylinski at intel.com>
Acked-by: David Hunt <david.hunt at intel.com>
---
 app/test/test_func_reentrancy.c        |   9 +-
 app/test/test_lpm.c                    | 145 +++++++++++++++++++++++++++------
 app/test/test_mp_secondary.c           |   7 +-
 app/test/test_table_combined.c         |   2 +
 app/test/test_table_tables.c           |   2 +
 doc/guides/rel_notes/release_16_04.rst |   5 ++
 lib/librte_lpm/rte_lpm.c               |  51 +++++++++---
 lib/librte_lpm/rte_lpm.h               |  23 ++++--
 lib/librte_table/rte_table_lpm.c       |  12 ++-
 lib/librte_table/rte_table_lpm.h       |   6 ++
 10 files changed, 215 insertions(+), 47 deletions(-)

diff --git a/app/test/test_func_reentrancy.c b/app/test/test_func_reentrancy.c
index dbecc52..5d09296 100644
--- a/app/test/test_func_reentrancy.c
+++ b/app/test/test_func_reentrancy.c
@@ -359,6 +359,11 @@ lpm_create_free(__attribute__((unused)) void *arg)
 {
        unsigned lcore_self = rte_lcore_id();
        struct rte_lpm *lpm;
+       struct rte_lpm_config config;
+
+       config.max_rules = 4;
+       config.number_tbl8s = 256;
+       config.flags = 0;
        char lpm_name[MAX_STRING_SIZE];
        int i;

@@ -366,7 +371,7 @@ lpm_create_free(__attribute__((unused)) void *arg)

        /* create the same lpm simultaneously on all threads */
        for (i = 0; i < MAX_ITER_TIMES; i++) {
-               lpm = rte_lpm_create("fr_test_once",  SOCKET_ID_ANY, 4, 0);
+               lpm = rte_lpm_create("fr_test_once",  SOCKET_ID_ANY, &config);
                if ((NULL == lpm) && (rte_lpm_find_existing("fr_test_once") == 
NULL))
                        return -1;
        }
@@ -374,7 +379,7 @@ lpm_create_free(__attribute__((unused)) void *arg)
        /* create mutiple fbk tables simultaneously */
        for (i = 0; i < MAX_LPM_ITER_TIMES; i++) {
                snprintf(lpm_name, sizeof(lpm_name), "fr_test_%d_%d", 
lcore_self, i);
-               lpm = rte_lpm_create(lpm_name, SOCKET_ID_ANY, 4, 0);
+               lpm = rte_lpm_create(lpm_name, SOCKET_ID_ANY, &config);
                if (NULL == lpm)
                        return -1;

diff --git a/app/test/test_lpm.c b/app/test/test_lpm.c
index f367553..aaf95ec 100644
--- a/app/test/test_lpm.c
+++ b/app/test/test_lpm.c
@@ -105,6 +105,7 @@ rte_lpm_test tests[] = {
 #define NUM_LPM_TESTS (sizeof(tests)/sizeof(tests[0]))
 #define MAX_DEPTH 32
 #define MAX_RULES 256
+#define NUMBER_TBL8S 256
 #define PASS 0

 /*
@@ -115,18 +116,25 @@ int32_t
 test0(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;

        /* rte_lpm_create: lpm name == NULL */
-       lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(NULL, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm == NULL);

        /* rte_lpm_create: max_rules = 0 */
        /* Note: __func__ inserts the function name, in this case "test0". */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 0, 0);
+       config.max_rules = 0;
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm == NULL);

        /* socket_id < -1 is invalid */
-       lpm = rte_lpm_create(__func__, -2, MAX_RULES, 0);
+       config.max_rules = MAX_RULES;
+       lpm = rte_lpm_create(__func__, -2, &config);
        TEST_LPM_ASSERT(lpm == NULL);

        return PASS;
@@ -140,11 +148,16 @@ int32_t
 test1(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        int32_t i;

        /* rte_lpm_free: Free NULL */
        for (i = 0; i < 100; i++) {
-               lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES - i, 0);
+               config.max_rules = MAX_RULES - i;
+               lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
                TEST_LPM_ASSERT(lpm != NULL);

                rte_lpm_free(lpm);
@@ -164,8 +177,13 @@ int32_t
 test2(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        rte_lpm_free(lpm);
@@ -180,6 +198,11 @@ int32_t
 test3(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip = IPv4(0, 0, 0, 0), next_hop = 100;
        uint8_t depth = 24;
        int32_t status = 0;
@@ -189,7 +212,7 @@ test3(void)
        TEST_LPM_ASSERT(status < 0);

        /*Create vaild lpm to use in rest of test. */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* rte_lpm_add: depth < 1 */
@@ -213,6 +236,11 @@ int32_t
 test4(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip = IPv4(0, 0, 0, 0);
        uint8_t depth = 24;
        int32_t status = 0;
@@ -222,7 +250,7 @@ test4(void)
        TEST_LPM_ASSERT(status < 0);

        /*Create vaild lpm to use in rest of test. */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* rte_lpm_delete: depth < 1 */
@@ -247,6 +275,11 @@ test5(void)
 {
 #if defined(RTE_LIBRTE_LPM_DEBUG)
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip = IPv4(0, 0, 0, 0), next_hop_return = 0;
        int32_t status = 0;

@@ -255,7 +288,7 @@ test5(void)
        TEST_LPM_ASSERT(status < 0);

        /*Create vaild lpm to use in rest of test. */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* rte_lpm_lookup: depth < 1 */
@@ -276,11 +309,16 @@ int32_t
 test6(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
        uint8_t depth = 24;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        status = rte_lpm_add(lpm, ip, depth, next_hop_add);
@@ -310,11 +348,16 @@ test7(void)
        __m128i ipx4;
        uint32_t hop[4];
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip = IPv4(0, 0, 0, 0), next_hop_add = 100, next_hop_return = 0;
        uint8_t depth = 32;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        status = rte_lpm_add(lpm, ip, depth, next_hop_add);
@@ -356,12 +399,17 @@ test8(void)
        __m128i ipx4;
        uint32_t hop[4];
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip1 = IPv4(127, 255, 255, 255), ip2 = IPv4(128, 0, 0, 0);
        uint32_t next_hop_add, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* Loop with rte_lpm_add. */
@@ -436,6 +484,11 @@ int32_t
 test9(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, ip_1, ip_2;
        uint8_t depth, depth_1, depth_2;
        uint32_t next_hop_add, next_hop_add_1, next_hop_add_2, next_hop_return;
@@ -446,7 +499,7 @@ test9(void)
        depth = 24;
        next_hop_add = 100;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        status = rte_lpm_add(lpm, ip, depth, next_hop_add);
@@ -600,13 +653,18 @@ test10(void)
 {

        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, next_hop_add, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

        /* Add rule that covers a TBL24 range previously invalid & lookup
         * (& delete & lookup) */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        ip = IPv4(128, 0, 0, 0);
@@ -786,11 +844,16 @@ test11(void)
 {

        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, next_hop_add, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        ip = IPv4(128, 0, 0, 0);
@@ -852,11 +915,16 @@ test12(void)
        __m128i ipx4;
        uint32_t hop[4];
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, i, next_hop_add, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        ip = IPv4(128, 0, 0, 0);
@@ -902,11 +970,16 @@ int32_t
 test13(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, i, next_hop_add_1, next_hop_add_2, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        ip = IPv4(128, 0, 0, 0);
@@ -964,12 +1037,17 @@ test14(void)
         * that we have enough storage for all rules at that depth*/

        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = 256 * 32;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint32_t ip, next_hop_add, next_hop_return;
        uint8_t depth;
        int32_t status = 0;

        /* Add enough space for 256 rules for every depth */
-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 256 * 32, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        depth = 32;
@@ -1011,9 +1089,14 @@ int32_t
 test15(void)
 {
        struct rte_lpm *lpm = NULL, *result = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = 256 * 32;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;

        /* Create lpm  */
-       lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, 256 * 32, 0);
+       lpm = rte_lpm_create("lpm_find_existing", SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* Try to find existing lpm */
@@ -1039,8 +1122,12 @@ int32_t
 test16(void)
 {
        uint32_t ip;
-       struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY,
-                       256 * 32, 0);
+       struct rte_lpm_config config;
+
+       config.max_rules = 256 * 32;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
+       struct rte_lpm *lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);

        /* ip loops through all possibilities for top 24 bits of address */
        for (ip = 0; ip < 0xFFFFFF; ip++) {
@@ -1050,10 +1137,10 @@ test16(void)
                        break;
        }

-       if (ip != RTE_LPM_TBL8_NUM_GROUPS) {
+       if (ip != NUMBER_TBL8S) {
                printf("Error, unexpected failure with filling tbl8 groups\n");
                printf("Failed after %u additions, expected after %u\n",
-                               (unsigned)ip, 
(unsigned)RTE_LPM_TBL8_NUM_GROUPS);
+                               (unsigned)ip, (unsigned)NUMBER_TBL8S);
        }

        rte_lpm_free(lpm);
@@ -1071,6 +1158,11 @@ int32_t
 test17(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = MAX_RULES;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        const uint32_t ip_10_32 = IPv4(10, 10, 10, 2);
        const uint32_t ip_10_24 = IPv4(10, 10, 10, 0);
        const uint32_t ip_20_25 = IPv4(10, 10, 20, 2);
@@ -1083,7 +1175,7 @@ test17(void)
        uint32_t next_hop_return = 0;
        int32_t status = 0;

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, MAX_RULES, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        if ((status = rte_lpm_add(lpm, ip_10_32, d_ip_10_32,
@@ -1172,6 +1264,11 @@ int32_t
 perf_test(void)
 {
        struct rte_lpm *lpm = NULL;
+       struct rte_lpm_config config;
+
+       config.max_rules = 1000000;
+       config.number_tbl8s = NUMBER_TBL8S;
+       config.flags = 0;
        uint64_t begin, total_time, lpm_used_entries = 0;
        unsigned i, j;
        uint32_t next_hop_add = 0xAA, next_hop_return = 0;
@@ -1185,7 +1282,7 @@ perf_test(void)

        print_route_distribution(large_route_table, (uint32_t) 
NUM_ROUTE_ENTRIES);

-       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, 1000000, 0);
+       lpm = rte_lpm_create(__func__, SOCKET_ID_ANY, &config);
        TEST_LPM_ASSERT(lpm != NULL);

        /* Measue add. */
diff --git a/app/test/test_mp_secondary.c b/app/test/test_mp_secondary.c
index 2f941b5..4dfe418 100644
--- a/app/test/test_mp_secondary.c
+++ b/app/test/test_mp_secondary.c
@@ -232,7 +232,12 @@ run_object_creation_tests(void)

 #ifdef RTE_LIBRTE_LPM
        rte_errno=0;
-       if ((rte_lpm_create("test_lpm", size, rte_socket_id(), 0) != NULL) &&
+       struct rte_lpm_config config;
+
+       config.max_rules = rte_socket_id();
+       config.number_tbl8s = 256;
+       config.flags = 0;
+       if ((rte_lpm_create("test_lpm", size, &config) != NULL) &&
            (rte_lpm_find_existing("test_lpm") == NULL)){
                printf("Error: unexpected return value from 
rte_lpm_create()\n");
                return -1;
diff --git a/app/test/test_table_combined.c b/app/test/test_table_combined.c
index 8bf4aeb..acb4f4d 100644
--- a/app/test/test_table_combined.c
+++ b/app/test/test_table_combined.c
@@ -295,6 +295,8 @@ test_table_lpm_combined(void)
        struct rte_table_lpm_params lpm_params = {
                .name = "LPM",
                .n_rules = 1 << 16,
+               .number_tbl8s = 1 << 8,
+               .flags = 0,
                .entry_unique_size = 8,
                .offset = APP_METADATA_OFFSET(0),
        };
diff --git a/app/test/test_table_tables.c b/app/test/test_table_tables.c
index b6364c4..cbbbfc1 100644
--- a/app/test/test_table_tables.c
+++ b/app/test/test_table_tables.c
@@ -326,6 +326,8 @@ test_table_lpm(void)
        struct rte_table_lpm_params lpm_params = {
                .name = "LPM",
                .n_rules = 1 << 24,
+               .number_tbl8s = 1 << 8,
+               .flags = 0,
                .entry_unique_size = entry_size,
                .offset = APP_METADATA_OFFSET(1)
        };
diff --git a/doc/guides/rel_notes/release_16_04.rst 
b/doc/guides/rel_notes/release_16_04.rst
index 686db70..24f4079 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -102,6 +102,11 @@ Libraries

   Extended next_hop field from 8-bits to 24-bits for IPv4.

+* **librte_lpm: Added a new rte_lpm_config structure for IPv4.**
+
+  A new rte_lpm_config structure is used so LPM library will allocate exactly
+  the amount of memory which is necessary to hold application?s rules.
+
 Examples
 ~~~~~~~~

diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index ea4d234..ccaaa2a 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -244,13 +244,13 @@ exit:
 VERSION_SYMBOL(rte_lpm_create, _v20, 2.0);

 struct rte_lpm *
-rte_lpm_create_v1604(const char *name, int socket_id, int max_rules,
-               __rte_unused int flags)
+rte_lpm_create_v1604(const char *name, int socket_id,
+               const struct rte_lpm_config *config)
 {
        char mem_name[RTE_LPM_NAMESIZE];
        struct rte_lpm *lpm = NULL;
        struct rte_tailq_entry *te;
-       uint32_t mem_size;
+       uint32_t mem_size, rules_size, tbl8s_size;
        struct rte_lpm_list *lpm_list;

        lpm_list = RTE_TAILQ_CAST(rte_lpm_tailq.head, rte_lpm_list);
@@ -258,7 +258,8 @@ rte_lpm_create_v1604(const char *name, int socket_id, int 
max_rules,
        RTE_BUILD_BUG_ON(sizeof(struct rte_lpm_tbl_entry) != 4);

        /* Check user arguments. */
-       if ((name == NULL) || (socket_id < -1) || (max_rules == 0)) {
+       if ((name == NULL) || (socket_id < -1) || (config->max_rules == 0)
+                       || config->number_tbl8s > RTE_LPM_MAX_TBL8_NUM_GROUPS) {
                rte_errno = EINVAL;
                return NULL;
        }
@@ -266,7 +267,10 @@ rte_lpm_create_v1604(const char *name, int socket_id, int 
max_rules,
        snprintf(mem_name, sizeof(mem_name), "LPM_%s", name);

        /* Determine the amount of memory to allocate. */
-       mem_size = sizeof(*lpm) + (sizeof(lpm->rules_tbl[0]) * max_rules);
+       mem_size = sizeof(*lpm);
+       rules_size = sizeof(struct rte_lpm_rule) * config->max_rules;
+       tbl8s_size = (sizeof(struct rte_lpm_tbl_entry) *
+                       RTE_LPM_TBL8_GROUP_NUM_ENTRIES * config->number_tbl8s);

        rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);

@@ -295,8 +299,29 @@ rte_lpm_create_v1604(const char *name, int socket_id, int 
max_rules,
                goto exit;
        }

+       lpm->rules_tbl = (struct rte_lpm_rule *)rte_zmalloc_socket(NULL,
+                       (size_t)rules_size, RTE_CACHE_LINE_SIZE, socket_id);
+
+       if (lpm->rules_tbl == NULL) {
+               RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+               rte_free(lpm);
+               rte_free(te);
+               goto exit;
+       }
+
+       lpm->tbl8 = (struct rte_lpm_tbl_entry *)rte_zmalloc_socket(NULL,
+                       (size_t)tbl8s_size, RTE_CACHE_LINE_SIZE, socket_id);
+
+       if (lpm->tbl8 == NULL) {
+               RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+               rte_free(lpm);
+               rte_free(te);
+               goto exit;
+       }
+
        /* Save user arguments. */
-       lpm->max_rules = max_rules;
+       lpm->max_rules = config->max_rules;
+       lpm->number_tbl8s = config->number_tbl8s;
        snprintf(lpm->name, sizeof(lpm->name), "%s", name);

        te->data = (void *) lpm;
@@ -311,7 +336,7 @@ exit:
 BIND_DEFAULT_SYMBOL(rte_lpm_create, _v1604, 16.04);
 MAP_STATIC_SYMBOL(
        struct rte_lpm *rte_lpm_create(const char *name, int socket_id,
-                       int max_rules, int flags), rte_lpm_create_v1604);
+                       const struct rte_lpm_config *config), 
rte_lpm_create_v1604);

 /*
  * Deallocates memory for given LPM table.
@@ -665,14 +690,13 @@ tbl8_alloc_v20(struct rte_lpm_tbl_entry_v20 *tbl8)
 }

 static inline int32_t
-tbl8_alloc_v1604(struct rte_lpm_tbl_entry *tbl8)
+tbl8_alloc_v1604(struct rte_lpm_tbl_entry *tbl8, uint32_t number_tbl8s)
 {
        uint32_t group_idx; /* tbl8 group index. */
        struct rte_lpm_tbl_entry *tbl8_entry;

        /* Scan through tbl8 to find a free (i.e. INVALID) tbl8 group. */
-       for (group_idx = 0; group_idx < RTE_LPM_TBL8_NUM_GROUPS;
-                       group_idx++) {
+       for (group_idx = 0; group_idx < number_tbl8s; group_idx++) {
                tbl8_entry = &tbl8[group_idx * RTE_LPM_TBL8_GROUP_NUM_ENTRIES];
                /* If a free tbl8 group is found clean it and set as VALID. */
                if (!tbl8_entry->valid_group) {
@@ -987,7 +1011,7 @@ add_depth_big_v1604(struct rte_lpm *lpm, uint32_t 
ip_masked, uint8_t depth,

        if (!lpm->tbl24[tbl24_index].valid) {
                /* Search for a free tbl8 group. */
-               tbl8_group_index = tbl8_alloc_v1604(lpm->tbl8);
+               tbl8_group_index = tbl8_alloc_v1604(lpm->tbl8, 
lpm->number_tbl8s);

                /* Check tbl8 allocation was successful. */
                if (tbl8_group_index < 0) {
@@ -1024,7 +1048,7 @@ add_depth_big_v1604(struct rte_lpm *lpm, uint32_t 
ip_masked, uint8_t depth,
        } /* If valid entry but not extended calculate the index into Table8. */
        else if (lpm->tbl24[tbl24_index].valid_group == 0) {
                /* Search for free tbl8 group. */
-               tbl8_group_index = tbl8_alloc_v1604(lpm->tbl8);
+               tbl8_group_index = tbl8_alloc_v1604(lpm->tbl8, 
lpm->number_tbl8s);

                if (tbl8_group_index < 0) {
                        return tbl8_group_index;
@@ -1882,7 +1906,8 @@ rte_lpm_delete_all_v1604(struct rte_lpm *lpm)
        memset(lpm->tbl24, 0, sizeof(lpm->tbl24));

        /* Zero tbl8. */
-       memset(lpm->tbl8, 0, sizeof(lpm->tbl8));
+       memset(lpm->tbl8, 0, sizeof(lpm->tbl8[0])
+                       * RTE_LPM_TBL8_GROUP_NUM_ENTRIES * lpm->number_tbl8s);

        /* Delete all rules form the rules table. */
        memset(lpm->rules_tbl, 0, sizeof(lpm->rules_tbl[0]) * lpm->max_rules);
diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h
index d759c8a..9aa122c 100644
--- a/lib/librte_lpm/rte_lpm.h
+++ b/lib/librte_lpm/rte_lpm.h
@@ -66,6 +66,9 @@ extern "C" {
 /** @internal Number of entries in a tbl8 group. */
 #define RTE_LPM_TBL8_GROUP_NUM_ENTRIES  256

+/** @internal Max number of tbl8 groups in the tbl8. */
+#define RTE_LPM_MAX_TBL8_NUM_GROUPS         (1 << 24)
+
 /** @internal Total number of tbl8 groups in the tbl8. */
 #define RTE_LPM_TBL8_NUM_GROUPS         256

@@ -154,6 +157,13 @@ struct rte_lpm_tbl_entry {

 #endif

+/** LPM configuration structure. */
+struct rte_lpm_config {
+       uint32_t max_rules;      /**< Max number of rules. */
+       uint32_t number_tbl8s;   /**< Number of tbl8s to allocate. */
+       int flags;               /**< This field is currently unused. */
+};
+
 /** @internal Rule structure. */
 struct rte_lpm_rule_v20 {
        uint32_t ip; /**< Rule IP address. */
@@ -191,15 +201,14 @@ struct rte_lpm {
        /* LPM metadata. */
        char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
        uint32_t max_rules; /**< Max. balanced rules per lpm. */
+       uint32_t number_tbl8s; /**< Number of tbl8s. */
        struct rte_lpm_rule_info rule_info[RTE_LPM_MAX_DEPTH]; /**< Rule info 
table. */

        /* LPM Tables. */
        struct rte_lpm_tbl_entry tbl24[RTE_LPM_TBL24_NUM_ENTRIES]
                        __rte_cache_aligned; /**< LPM tbl24 table. */
-       struct rte_lpm_tbl_entry tbl8[RTE_LPM_TBL8_NUM_ENTRIES]
-                       __rte_cache_aligned; /**< LPM tbl8 table. */
-       struct rte_lpm_rule rules_tbl[0] \
-                       __rte_cache_aligned; /**< LPM rules. */
+       struct rte_lpm_tbl_entry *tbl8; /**< LPM tbl8 table. */
+       struct rte_lpm_rule *rules_tbl; /**< LPM rules. */
 };

 /**
@@ -224,11 +233,13 @@ struct rte_lpm {
  *    - ENOMEM - no appropriate memory area found in which to create memzone
  */
 struct rte_lpm *
-rte_lpm_create(const char *name, int socket_id, int max_rules, int flags);
+rte_lpm_create(const char *name, int socket_id,
+               const struct rte_lpm_config *config);
 struct rte_lpm_v20 *
 rte_lpm_create_v20(const char *name, int socket_id, int max_rules, int flags);
 struct rte_lpm *
-rte_lpm_create_v1604(const char *name, int socket_id, int max_rules, int 
flags);
+rte_lpm_create_v1604(const char *name, int socket_id,
+               const struct rte_lpm_config *config);

 /**
  * Find an existing LPM object and return a pointer to it.
diff --git a/lib/librte_table/rte_table_lpm.c b/lib/librte_table/rte_table_lpm.c
index 7b2ecb0..cdeb0f5 100644
--- a/lib/librte_table/rte_table_lpm.c
+++ b/lib/librte_table/rte_table_lpm.c
@@ -82,6 +82,8 @@ rte_table_lpm_create(void *params, int socket_id, uint32_t 
entry_size)
 {
        struct rte_table_lpm_params *p = (struct rte_table_lpm_params *) params;
        struct rte_table_lpm *lpm;
+       struct rte_lpm_config lpm_config;
+
        uint32_t total_size, nht_size;

        /* Check input parameters */
@@ -93,6 +95,10 @@ rte_table_lpm_create(void *params, int socket_id, uint32_t 
entry_size)
                RTE_LOG(ERR, TABLE, "%s: Invalid n_rules\n", __func__);
                return NULL;
        }
+       if (p->number_tbl8s == 0) {
+               RTE_LOG(ERR, TABLE, "%s: Invalid number_tbl8s\n", __func__);
+               return NULL;
+       }
        if (p->entry_unique_size == 0) {
                RTE_LOG(ERR, TABLE, "%s: Invalid entry_unique_size\n",
                        __func__);
@@ -123,7 +129,11 @@ rte_table_lpm_create(void *params, int socket_id, uint32_t 
entry_size)
        }

        /* LPM low-level table creation */
-       lpm->lpm = rte_lpm_create(p->name, socket_id, p->n_rules, 0);
+       lpm_config.max_rules = p->n_rules;
+       lpm_config.number_tbl8s = p->number_tbl8s;
+       lpm_config.flags = p->flags;
+       lpm->lpm = rte_lpm_create(p->name, socket_id, &lpm_config);
+
        if (lpm->lpm == NULL) {
                rte_free(lpm);
                RTE_LOG(ERR, TABLE, "Unable to create low-level LPM table\n");
diff --git a/lib/librte_table/rte_table_lpm.h b/lib/librte_table/rte_table_lpm.h
index 06e8410..f303323 100644
--- a/lib/librte_table/rte_table_lpm.h
+++ b/lib/librte_table/rte_table_lpm.h
@@ -83,6 +83,12 @@ struct rte_table_lpm_params {
        /** Maximum number of LPM rules (i.e. IP routes) */
        uint32_t n_rules;

+       /**< Number of tbl8s to allocate. */
+       uint32_t number_tbl8s;
+
+       /**< This field is currently unused. */
+       int flags;
+
        /** Number of bytes at the start of the table entry that uniquely
        identify the entry. Cannot be bigger than table entry size. */
        uint32_t entry_unique_size;
-- 
1.9.1

Reply via email to