Description: lpm/lpm6: fix use after free and missing frees

In certain autotests lpm->max_rules turned out to be non initialized.
Also lpm6 autotests failed with the default alloc of 512M Memory.
While >=2500M was a workaround it became clear while debugging that it
had a leak.

That eventually led to the identification of various use after free and leaks
in the lpm/lpm6 code.

Along that is also makes the RTE_LOG messages of the failed allocation unique.

The patches are upstream accepted in 4 pieces now.
This combines them plus a minor tweak currently in review at
http://dpdk.org/dev/patchwork/patch/12025/

Forwarded: Yes - accepted 768f0e45 732a5b5c 34c4b584 d4c18f0a
Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Last-Update: 2016-04-12

Index: dpdk/lib/librte_lpm/rte_lpm.c
===================================================================
--- dpdk.orig/lib/librte_lpm/rte_lpm.c
+++ dpdk/lib/librte_lpm/rte_lpm.c
@@ -236,13 +236,10 @@ rte_lpm_free(struct rte_lpm *lpm)
 		if (te->data == (void *) lpm)
 			break;
 	}
-	if (te == NULL) {
-		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
-		return;
+	if (te != NULL) {
+		TAILQ_REMOVE(lpm_list, te, next);
 	}
 
-	TAILQ_REMOVE(lpm_list, te, next);
-
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 	rte_free(lpm);
Index: dpdk/lib/librte_lpm/rte_lpm6.c
===================================================================
--- dpdk.orig/lib/librte_lpm/rte_lpm6.c
+++ dpdk/lib/librte_lpm/rte_lpm6.c
@@ -206,8 +206,9 @@ rte_lpm6_create(const char *name, int so
 			(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_LOG(ERR, LPM, "LPM rules_tbl allocation failed\n");
 		rte_free(lpm);
+		lpm = NULL;
 		rte_free(te);
 		goto exit;
 	}
@@ -277,15 +278,14 @@ rte_lpm6_free(struct rte_lpm6 *lpm)
 		if (te->data == (void *) lpm)
 			break;
 	}
-	if (te == NULL) {
-		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
-		return;
-	}
 
-	TAILQ_REMOVE(lpm_list, te, next);
+	if (te != NULL) {
+		TAILQ_REMOVE(lpm_list, te, next);
+	}
 
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
+	rte_free(lpm->rules_tbl);
 	rte_free(lpm);
 	rte_free(te);
 }
