From f1f7261838b38f57fb1b3e62d1f97164439d017d Mon Sep 17 00:00:00 2001 From: Michal Kobylinski Date: Wed, 9 Mar 2016 17:57:16 +0100 Subject: [PATCH] lpm: add a new config structure for IPv4 MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Acked-by: David Hunt --- 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 | 4 + examples/ip_fragmentation/main.c | 7 +- examples/ip_reassembly/main.c | 7 +- examples/l3fwd-power/main.c | 10 +- examples/l3fwd-vf/main.c | 10 +- examples/l3fwd/l3fwd_lpm.c | 9 +- examples/load_balancer/init.c | 8 +- .../performance-thread/l3fwd-thread/main.c | 8 +- lib/librte_lpm/rte_lpm.c | 51 ++++-- lib/librte_lpm/rte_lpm.h | 29 ++-- lib/librte_table/rte_table_lpm.c | 12 +- lib/librte_table/rte_table_lpm.h | 6 + 17 files changed, 263 insertions(+), 63 deletions(-) diff --git a/app/test/test_func_reentrancy.c b/app/test/test_func_reentrancy.c index dbecc527e3..5d0929670a 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 f367553bd8..aaf95ec694 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 2f941b5dc6..4dfe418e72 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 8bf4aeb0c2..acb4f4decf 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 b6364c4df7..cbbbfc17b3 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 7882f54148..ab49608317 100644 --- a/doc/guides/rel_notes/release_16_04.rst +++ b/doc/guides/rel_notes/release_16_04.rst @@ -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 ----------- diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c index 0302b2c13b..8021702fc3 100644 --- a/examples/ip_fragmentation/main.c +++ b/examples/ip_fragmentation/main.c @@ -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; diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c index 6f48748c02..19ec46c16a 100644 --- a/examples/ip_reassembly/main.c +++ b/examples/ip_reassembly/main.c @@ -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; diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index a478583ec1..f8a2f1bf71 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -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); diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c index 193c3ab891..034c22a702 100644 --- a/examples/l3fwd-vf/main.c +++ b/examples/l3fwd-vf/main.c @@ -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); diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index e0ed3c44c4..a35479705d 100644 --- a/examples/l3fwd/l3fwd_lpm.c +++ b/examples/l3fwd/l3fwd_lpm.c @@ -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", diff --git a/examples/load_balancer/init.c b/examples/load_balancer/init.c index 5a560786f7..a96d778438 100644 --- a/examples/load_balancer/init.c +++ b/examples/load_balancer/init.c @@ -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); } diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c index 59b7678473..7bcca37b5e 100644 --- a/examples/performance-thread/l3fwd-thread/main.c +++ b/examples/performance-thread/l3fwd-thread/main.c @@ -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); diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c index ea4d234dee..ccaaa2af3d 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 1c00e0cb7c..c2b429f956 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. */ }; /** @@ -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. diff --git a/lib/librte_table/rte_table_lpm.c b/lib/librte_table/rte_table_lpm.c index 7b2ecb0b0b..cdeb0f5ae5 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 06e8410213..f3033234f9 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; -- 2.20.1