lpm: add a new config structure for IPv4
authorMichal Kobylinski <michalx.kobylinski@intel.com>
Wed, 9 Mar 2016 16:57:16 +0000 (17:57 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 9 Mar 2016 22:05:05 +0000 (23:05 +0100)
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.

Signed-off-by: Michal Kobylinski <michalx.kobylinski@intel.com>
Acked-by: David Hunt <david.hunt@intel.com>
17 files changed:
app/test/test_func_reentrancy.c
app/test/test_lpm.c
app/test/test_mp_secondary.c
app/test/test_table_combined.c
app/test/test_table_tables.c
doc/guides/rel_notes/release_16_04.rst
examples/ip_fragmentation/main.c
examples/ip_reassembly/main.c
examples/l3fwd-power/main.c
examples/l3fwd-vf/main.c
examples/l3fwd/l3fwd_lpm.c
examples/load_balancer/init.c
examples/performance-thread/l3fwd-thread/main.c
lib/librte_lpm/rte_lpm.c
lib/librte_lpm/rte_lpm.h
lib/librte_table/rte_table_lpm.c
lib/librte_table/rte_table_lpm.h

index dbecc52..5d09296 100644 (file)
@@ -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;
 
index f367553..aaf95ec 100644 (file)
@@ -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. */
index 2f941b5..4dfe418 100644 (file)
@@ -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;
index 8bf4aeb..acb4f4d 100644 (file)
@@ -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),
        };
index b6364c4..cbbbfc1 100644 (file)
@@ -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)
        };
index 7882f54..ab49608 100644 (file)
@@ -154,6 +154,10 @@ This section should contain API changes. Sample format:
 * The LPM ``next_hop`` field is extended from 8 bits to 24 bits for IPv4
   while keeping ABI compatibility.
 
+* 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.
+  The previous ABI is kept for compatibility.
+
 
 ABI Changes
 -----------
index 0302b2c..8021702 100644 (file)
@@ -721,6 +721,7 @@ init_mem(void)
        struct rte_mempool *mp;
        struct rte_lpm *lpm;
        struct rte_lpm6 *lpm6;
+       struct rte_lpm_config lpm_config;
        int socket;
        unsigned lcore_id;
 
@@ -768,7 +769,11 @@ init_mem(void)
                        RTE_LOG(INFO, IP_FRAG, "Creating LPM table on socket %i\n", socket);
                        snprintf(buf, sizeof(buf), "IP_FRAG_LPM_%i", socket);
 
-                       lpm = rte_lpm_create(buf, socket, LPM_MAX_RULES, 0);
+                       lpm_config.max_rules = LPM_MAX_RULES;
+                       lpm_config.number_tbl8s = 256;
+                       lpm_config.flags = 0;
+
+                       lpm = rte_lpm_create(buf, socket, &lpm_config);
                        if (lpm == NULL) {
                                RTE_LOG(ERR, IP_FRAG, "Cannot create LPM table\n");
                                return -1;
index 6f48748..19ec46c 100644 (file)
@@ -927,6 +927,7 @@ init_mem(void)
        char buf[PATH_MAX];
        struct rte_lpm *lpm;
        struct rte_lpm6 *lpm6;
+       struct rte_lpm_config lpm_config;
        int socket;
        unsigned lcore_id;
 
@@ -946,7 +947,11 @@ init_mem(void)
                        RTE_LOG(INFO, IP_RSMBL, "Creating LPM table on socket %i\n", socket);
                        snprintf(buf, sizeof(buf), "IP_RSMBL_LPM_%i", socket);
 
-                       lpm = rte_lpm_create(buf, socket, LPM_MAX_RULES, 0);
+                       lpm_config.max_rules = LPM_MAX_RULES;
+                       lpm_config.number_tbl8s = 256;
+                       lpm_config.flags = 0;
+
+                       lpm = rte_lpm_create(buf, socket, &lpm_config);
                        if (lpm == NULL) {
                                RTE_LOG(ERR, IP_RSMBL, "Cannot create LPM table\n");
                                return -1;
index a478583..f8a2f1b 100644 (file)
@@ -1430,9 +1430,15 @@ setup_lpm(int socketid)
        char s[64];
 
        /* create the LPM table */
+       struct rte_lpm_config lpm_ipv4_config;
+
+       lpm_ipv4_config.max_rules = IPV4_L3FWD_LPM_MAX_RULES;
+       lpm_ipv4_config.number_tbl8s = 256;
+       lpm_ipv4_config.flags = 0;
+
        snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid);
-       ipv4_l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-                               IPV4_L3FWD_LPM_MAX_RULES, 0);
+       ipv4_l3fwd_lookup_struct[socketid] =
+                       rte_lpm_create(s, socketid, &lpm_ipv4_config);
        if (ipv4_l3fwd_lookup_struct[socketid] == NULL)
                rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table"
                                " on socket %d\n", socketid);
index 193c3ab..034c22a 100644 (file)
@@ -869,10 +869,16 @@ setup_lpm(int socketid)
        int ret;
        char s[64];
 
+       struct rte_lpm_config lpm_ipv4_config;
+
+       lpm_ipv4_config.max_rules = L3FWD_LPM_MAX_RULES;
+       lpm_ipv4_config.number_tbl8s = 256;
+       lpm_ipv4_config.flags = 0;
+
        /* create the LPM table */
        snprintf(s, sizeof(s), "L3FWD_LPM_%d", socketid);
-       l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-                               L3FWD_LPM_MAX_RULES, 0);
+       l3fwd_lookup_struct[socketid] =
+                       rte_lpm_create(s, socketid, &lpm_ipv4_config);
        if (l3fwd_lookup_struct[socketid] == NULL)
                rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table"
                                " on socket %d\n", socketid);
index e0ed3c4..a354797 100644 (file)
@@ -98,6 +98,7 @@ static struct ipv6_l3fwd_lpm_route ipv6_l3fwd_lpm_route_array[] = {
        (sizeof(ipv6_l3fwd_lpm_route_array) / sizeof(ipv6_l3fwd_lpm_route_array[0]))
 
 #define IPV4_L3FWD_LPM_MAX_RULES         1024
+#define IPV4_L3FWD_LPM_NUMBER_TBL8S (1 << 8)
 #define IPV6_L3FWD_LPM_MAX_RULES         1024
 #define IPV6_L3FWD_LPM_NUMBER_TBL8S (1 << 16)
 
@@ -203,14 +204,18 @@ void
 setup_lpm(const int socketid)
 {
        struct rte_lpm6_config config;
+       struct rte_lpm_config config_ipv4;
        unsigned i;
        int ret;
        char s[64];
 
        /* create the LPM table */
+       config_ipv4.max_rules = IPV4_L3FWD_LPM_MAX_RULES;
+       config_ipv4.number_tbl8s = IPV4_L3FWD_LPM_NUMBER_TBL8S;
+       config_ipv4.flags = 0;
        snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid);
-       ipv4_l3fwd_lpm_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-                               IPV4_L3FWD_LPM_MAX_RULES, 0);
+       ipv4_l3fwd_lpm_lookup_struct[socketid] =
+                       rte_lpm_create(s, socketid, &config_ipv4);
        if (ipv4_l3fwd_lpm_lookup_struct[socketid] == NULL)
                rte_exit(EXIT_FAILURE,
                        "Unable to create the l3fwd LPM table on socket %d\n",
index 5a56078..a96d778 100644 (file)
@@ -160,13 +160,17 @@ app_init_lpm_tables(void)
                        continue;
                }
 
+               struct rte_lpm_config lpm_config;
+
+               lpm_config.max_rules = APP_MAX_LPM_RULES;
+               lpm_config.number_tbl8s = 256;
+               lpm_config.flags = 0;
                snprintf(name, sizeof(name), "lpm_table_%u", socket);
                printf("Creating the LPM table for socket %u ...\n", socket);
                app.lpm_tables[socket] = rte_lpm_create(
                        name,
                        socket,
-                       APP_MAX_LPM_RULES,
-                       0);
+                       &lpm_config);
                if (app.lpm_tables[socket] == NULL) {
                        rte_panic("Unable to create LPM table on socket %u\n", socket);
                }
index 59b7678..7bcca37 100644 (file)
@@ -3249,14 +3249,18 @@ static void
 setup_lpm(int socketid)
 {
        struct rte_lpm6_config config;
+       struct rte_lpm_config lpm_ipv4_config;
        unsigned i;
        int ret;
        char s[64];
 
        /* create the LPM table */
        snprintf(s, sizeof(s), "IPV4_L3FWD_LPM_%d", socketid);
-       ipv4_l3fwd_lookup_struct[socketid] = rte_lpm_create(s, socketid,
-                               IPV4_L3FWD_LPM_MAX_RULES, 0);
+       lpm_ipv4_config.max_rules = IPV4_L3FWD_LPM_MAX_RULES;
+       lpm_ipv4_config.number_tbl8s = 256;
+       lpm_ipv4_config.flags = 0;
+       ipv4_l3fwd_lookup_struct[socketid] =
+                       rte_lpm_create(s, socketid, &lpm_ipv4_config);
        if (ipv4_l3fwd_lookup_struct[socketid] == NULL)
                rte_exit(EXIT_FAILURE, "Unable to create the l3fwd LPM table"
                                " on socket %d\n", socketid);
index ea4d234..ccaaa2a 100644 (file)
@@ -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);
index 1c00e0c..c2b429f 100644 (file)
@@ -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. */
 };
 
 /**
@@ -209,10 +218,8 @@ struct rte_lpm {
  *   LPM object name
  * @param socket_id
  *   NUMA socket ID for LPM table memory allocation
- * @param max_rules
- *   Maximum number of LPM rules that can be added
- * @param flags
- *   This parameter is currently unused
+ * @param config
+ *   Structure containing the configuration
  * @return
  *   Handle to LPM object on success, NULL otherwise with rte_errno set
  *   to an appropriate values. Possible rte_errno values include:
@@ -224,11 +231,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.
index 7b2ecb0..cdeb0f5 100644 (file)
@@ -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");
index 06e8410..f303323 100644 (file)
@@ -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;