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 6f62dd8..79474ce 100644
--- a/doc/guides/rel_notes/release_16_04.rst
+++ b/doc/guides/rel_notes/release_16_04.rst
@@ -108,6 +108,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/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c
index 0302b2c..8021702 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 6f48748..19ec46c 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 a478583..f8a2f1b 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 193c3ab..034c22a 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 e0ed3c4..a354797 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 5a56078..a96d778 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 59b7678..7bcca37 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 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;
