DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local
@ 2014-06-13 15:29 Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 1/7] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
                   ` (8 more replies)
  0 siblings, 9 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

This issue was reported by OVS-DPDK project, and the fix should go to
upstream DPDK. This is not memnic-related - this is to do with
DPDK's rte_ivshmem library.

Every DPDK data structure has a corresponding TAILQ reserved for it in
the runtime config file. Those TAILQs are fully local to the process,
however most data structures contain pointers to next entry in the
TAILQ.

Since the data structures such as rings are shared in their entirety,
those TAILQ pointers are shared as well. Meaning that, after a
successful rte_ring creation, the tailq_next pointer of the last
ring in the TAILQ will be updated with a pointer to a ring which may
not be present in the address space of another process (i.e. a ring
that may be host-local or guest-local, and not shared over IVSHMEM).
Any successive ring create/lookup on the other side of IVSHMEM will
result in trying to dereference an invalid pointer.

This patchset fixes this problem by creating a default tailq entry
that may be used by any data structure that chooses to use TAILQs.
This default TAILQ entry will consist of a tailq_next/tailq_prev
pointers, and an opaque pointer to arbitrary data. All TAILQ
pointers from data structures themselves will be removed and
replaced by those generic TAILQ entries, thus fixing the problem
of potentially exposing local address space to shared structures.

Technically, only rte_ring structure require modification, because
IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
but for consistency's sake other TAILQ-based data structures were
adapted as well.

Anatoly Burakov (7):
  rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  rte_ring: make ring tailq completely local
  rte_hash: make rte_hash tailq fully local
  rte_fbk_hash: make rte_fbk_hash tailq fully local
  rte_mempool: make mempool tailq fully local
  rte_lpm: make lpm tailq fully local
  rte_lpm6: make lpm6 tailq fully local

 app/test/test_tailq.c                     | 33 ++++++++--------
 lib/librte_eal/common/eal_common_tailqs.c |  2 +-
 lib/librte_eal/common/include/rte_tailq.h |  9 +++--
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 14 ++++++-
 lib/librte_hash/rte_fbk_hash.c            | 66 ++++++++++++++++++++++++-------
 lib/librte_hash/rte_fbk_hash.h            |  3 --
 lib/librte_hash/rte_hash.c                | 54 ++++++++++++++++++++-----
 lib/librte_hash/rte_hash.h                |  2 -
 lib/librte_lpm/rte_lpm.c                  | 54 ++++++++++++++++++++-----
 lib/librte_lpm/rte_lpm.h                  |  2 -
 lib/librte_lpm/rte_lpm6.c                 | 55 ++++++++++++++++++++------
 lib/librte_mempool/Makefile               |  3 +-
 lib/librte_mempool/rte_mempool.c          | 37 ++++++++++++-----
 lib/librte_mempool/rte_mempool.h          |  2 -
 lib/librte_ring/Makefile                  |  4 +-
 lib/librte_ring/rte_ring.c                | 33 ++++++++++++----
 lib/librte_ring/rte_ring.h                |  2 -
 17 files changed, 278 insertions(+), 97 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 1/7] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 2/7] rte_ring: make ring tailq completely local Anatoly Burakov
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 app/test/test_tailq.c                     | 33 ++++++++++++++++---------------
 lib/librte_eal/common/eal_common_tailqs.c |  2 +-
 lib/librte_eal/common/include/rte_tailq.h |  9 +++++----
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index 67da009..c9b53ee 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -52,16 +52,16 @@
 
 #define DEFAULT_TAILQ (RTE_TAILQ_NUM)
 
-static struct rte_dummy d_elem;
+static struct rte_tailq_entry d_elem;
 
 static int
 test_tailq_create(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 	unsigned i;
 
 	/* create a first tailq and check its non-null */
-	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error allocating dummy_q0\n");
 
@@ -70,13 +70,14 @@ test_tailq_create(void)
 	TAILQ_INSERT_TAIL(d_head, &d_elem, next);
 
 	/* try allocating dummy_q0 again, and check for failure */
-	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head) == NULL)
+	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head) == NULL)
 		do_return("Error, non-null result returned when attemption to "
 				"re-allocate a tailq\n");
 
 	/* now fill up the tailq slots available and check we get an error */
 	for (i = RTE_TAILQ_NUM; i < RTE_MAX_TAILQ; i++){
-		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i, rte_dummy_head)) == NULL)
+		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i,
+				rte_tailq_entry_head)) == NULL)
 			break;
 	}
 
@@ -91,10 +92,10 @@ static int
 test_tailq_lookup(void)
 {
 	/* run successful  test - check result is found */
-	struct rte_dummy_head *d_head;
-	struct rte_dummy *d_ptr;
+	struct rte_tailq_entry_head *d_head;
+	struct rte_tailq_entry *d_ptr;
 
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error with tailq lookup\n");
 
@@ -104,7 +105,7 @@ test_tailq_lookup(void)
 					"expected element not found\n");
 
 	/* now try a bad/error lookup */
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Error, lookup does not return NULL for bad tailq name\n");
 
@@ -115,7 +116,7 @@ test_tailq_lookup(void)
 static int
 test_tailq_deprecated(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 
 	/* since TAILQ_RESERVE is not able to create new tailqs,
 	 * we should find an existing one (IOW, RTE_TAILQ_RESERVE behaves identical
@@ -123,29 +124,29 @@ test_tailq_deprecated(void)
 	 *
 	 * PCI_RESOURCE_LIST tailq is guaranteed to
 	 * be present in any DPDK app. */
-	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
-	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
 	/* try doing that with non-existent names */
-	d_head = RTE_TAILQ_RESERVE("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
 	/* try doing the same with NULL names */
-	d_head = RTE_TAILQ_RESERVE(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index f294a58..db9a185 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -118,7 +118,7 @@ rte_dump_tailq(FILE *f)
 	rte_rwlock_read_lock(&mcfg->qlock);
 	for (i=0; i < RTE_MAX_TAILQ; i++) {
 		const struct rte_tailq_head *tailq = &mcfg->tailq_head[i];
-		const struct rte_dummy_head *head = &tailq->tailq_head;
+		const struct rte_tailq_entry_head *head = &tailq->tailq_head;
 
 		fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n", i,
 		       (rte_tailq_names[i] != NULL ? rte_tailq_names[i]:"nil"),
diff --git a/lib/librte_eal/common/include/rte_tailq.h b/lib/librte_eal/common/include/rte_tailq.h
index d084d9a..b34e5ed 100644
--- a/lib/librte_eal/common/include/rte_tailq.h
+++ b/lib/librte_eal/common/include/rte_tailq.h
@@ -48,11 +48,12 @@ extern "C" {
 #include <stdio.h>
 
 /** dummy structure type used by the rte_tailq APIs */
-struct rte_dummy {
-	TAILQ_ENTRY(rte_dummy) next; /**< Pointer entries for a tailq list */
+struct rte_tailq_entry {
+	TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */
+	void *data; /**< Pointer to the data referenced by this tailq entry */
 };
 /** dummy */
-TAILQ_HEAD(rte_dummy_head, rte_dummy);
+TAILQ_HEAD(rte_tailq_entry_head, rte_tailq_entry);
 
 #define RTE_TAILQ_NAMESIZE 32
 
@@ -65,7 +66,7 @@ TAILQ_HEAD(rte_dummy_head, rte_dummy);
  * a multi-process app to find already-created elements in shared memory.
  */
 struct rte_tailq_head {
-	struct rte_dummy_head tailq_head; /**< NOTE: must be first element */
+	struct rte_tailq_entry_head tailq_head; /**< NOTE: must be first element */
 };
 
 /**
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 2/7] rte_ring: make ring tailq completely local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 1/7] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 3/7] rte_hash: make rte_hash tailq fully local Anatoly Burakov
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 14 +++++++++++--
 lib/librte_ring/Makefile                  |  4 ++--
 lib/librte_ring/rte_ring.c                | 33 +++++++++++++++++++++++--------
 lib/librte_ring/rte_ring.h                |  2 --
 4 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
index 4ad76a7..69e5ea6 100644
--- a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
+++ b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
@@ -50,6 +50,7 @@
 #include <rte_errno.h>
 #include <rte_ring.h>
 #include <rte_mempool.h>
+#include <rte_malloc.h>
 #include <rte_common.h>
 #include <rte_ivshmem.h>
 #include <rte_tailq_elem.h>
@@ -101,7 +102,7 @@ static int memseg_idx;
 static int pagesz;
 
 /* Tailq heads to add rings to */
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /*
  * Utility functions
@@ -754,6 +755,7 @@ rte_eal_ivshmem_obj_init(void)
 	struct ivshmem_segment * seg;
 	struct rte_memzone * mz;
 	struct rte_ring * r;
+	struct rte_tailq_entry *te;
 	unsigned i, ms, idx;
 	uint64_t offset;
 
@@ -819,7 +821,15 @@ rte_eal_ivshmem_obj_init(void)
 
 		r = (struct rte_ring*) (mz->addr_64);
 
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+		te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+		if (te == NULL) {
+			RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n");
+			return -1;
+		}
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 
 		RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr);
 	}
diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile
index 550507d..2380a43 100644
--- a/lib/librte_ring/Makefile
+++ b/lib/librte_ring/Makefile
@@ -42,7 +42,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h
 
-# this lib needs eal
-DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal
+# this lib needs eal and rte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 2fe4024..d2ff3fe 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -75,6 +75,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
@@ -89,7 +90,7 @@
 
 #include "rte_ring.h"
 
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /* true if x is a power of 2 */
 #define POWEROF2(x) ((((x)-1) & (x)) == 0)
@@ -155,6 +156,7 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 {
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	struct rte_ring *r;
+	struct rte_tailq_entry *te;
 	const struct rte_memzone *mz;
 	ssize_t ring_size;
 	int mz_flags = 0;
@@ -173,6 +175,13 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		return NULL;
 	}
 
+	te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
 	rte_snprintf(mz_name, sizeof(mz_name), "%s%s", RTE_RING_MZ_PREFIX, name);
 
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +195,14 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		/* no need to check return value here, we already checked the
 		 * arguments above */
 		rte_ring_init(r, name, count, flags);
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 	} else {
 		r = NULL;
 		RTE_LOG(ERR, RING, "Cannot reserve memory\n");
+		rte_free(te);
 	}
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
@@ -272,7 +285,7 @@ rte_ring_dump(FILE *f, const struct rte_ring *r)
 void
 rte_ring_list_dump(FILE *f)
 {
-	const struct rte_ring *mp;
+	const struct rte_tailq_entry *te;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialised tail queue */
@@ -284,8 +297,8 @@ rte_ring_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(mp, ring_list, next) {
-		rte_ring_dump(f, mp);
+	TAILQ_FOREACH(te, ring_list, next) {
+		rte_ring_dump(f, (struct rte_ring *) te->data);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -295,7 +308,8 @@ rte_ring_list_dump(FILE *f)
 struct rte_ring *
 rte_ring_lookup(const char *name)
 {
-	struct rte_ring *r;
+	struct rte_tailq_entry *te;
+	struct rte_ring *r = NULL;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialized tail queue */
@@ -307,15 +321,18 @@ rte_ring_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(r, ring_list, next) {
+	TAILQ_FOREACH(te, ring_list, next) {
+		r = (struct rte_ring *) te->data;
 		if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (r == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return r;
 }
diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h
index 4f3e20f..3920830 100644
--- a/lib/librte_ring/rte_ring.h
+++ b/lib/librte_ring/rte_ring.h
@@ -138,8 +138,6 @@ struct rte_ring_debug_stats {
  * a problem.
  */
 struct rte_ring {
-	TAILQ_ENTRY(rte_ring) next;      /**< Next in list. */
-
 	char name[RTE_RING_NAMESIZE];    /**< Name of the ring. */
 	int flags;                       /**< Flags supplied at creation. */
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 3/7] rte_hash: make rte_hash tailq fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 1/7] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 2/7] rte_ring: make ring tailq completely local Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 4/7] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_hash/rte_hash.c | 54 ++++++++++++++++++++++++++++++++++++++--------
 lib/librte_hash/rte_hash.h |  2 --
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c
index d4221a8..a89ea44 100644
--- a/lib/librte_hash/rte_hash.c
+++ b/lib/librte_hash/rte_hash.c
@@ -60,7 +60,7 @@
 #include "rte_hash.h"
 
 
-TAILQ_HEAD(rte_hash_list, rte_hash);
+TAILQ_HEAD(rte_hash_list, rte_tailq_entry);
 
 /* Macro to enable/disable run-time checking of function parameters */
 #if defined(RTE_LIBRTE_HASH_DEBUG)
@@ -141,24 +141,29 @@ find_first(uint32_t sig, const uint32_t *sig_bucket, uint32_t num_sigs)
 struct rte_hash *
 rte_hash_find_existing(const char *name)
 {
-	struct rte_hash *h;
+	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_hash_list *hash_list;
 
 	/* check that we have an initialised tail queue */
-	if ((hash_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+	if ((hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -166,6 +171,7 @@ struct rte_hash *
 rte_hash_create(const struct rte_hash_parameters *params)
 {
 	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t num_buckets, sig_bucket_size, key_size,
 		hash_tbl_size, sig_tbl_size, key_tbl_size, mem_size;
 	char hash_name[RTE_HASH_NAMESIZE];
@@ -212,17 +218,25 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (h != NULL)
+	if (te != NULL)
+		goto exit;
+
+	te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "tailq entry allocation failed\n");
 		goto exit;
+	}
 
 	h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size,
 					   CACHE_LINE_SIZE, params->socket_id);
 	if (h == NULL) {
 		RTE_LOG(ERR, HASH, "memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -242,7 +256,9 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	h->hash_func = (params->hash_func == NULL) ?
 		DEFAULT_HASH_FUNC : params->hash_func;
 
-	TAILQ_INSERT_TAIL(hash_list, h, next);
+	te->data = (void *) h;
+
+	TAILQ_INSERT_TAIL(hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -253,11 +269,31 @@ exit:
 void
 rte_hash_free(struct rte_hash *h)
 {
+	struct rte_tailq_entry *te;
+	struct rte_hash_list *hash_list;
+
 	if (h == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_HASH, rte_hash_list, h);
+	/* check that we have an initialised tail queue */
+	if ((hash_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, hash_list, next) {
+		if (te->data == (void *) h)
+			break;
+	}
+
+	if (te == NULL)
+		return;
+
+	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_HASH, rte_hash_list, te);
 	rte_free(h);
+	rte_free(te);
 }
 
 static inline int32_t
diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h
index 5228e3a..2ecaf1a 100644
--- a/lib/librte_hash/rte_hash.h
+++ b/lib/librte_hash/rte_hash.h
@@ -86,8 +86,6 @@ struct rte_hash_parameters {
 
 /** A hash table structure. */
 struct rte_hash {
-	TAILQ_ENTRY(rte_hash) next;/**< Next in list. */
-
 	char name[RTE_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total table entries. */
 	uint32_t bucket_entries;	/**< Bucket entries. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 4/7] rte_fbk_hash: make rte_fbk_hash tailq fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (2 preceding siblings ...)
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 3/7] rte_hash: make rte_hash tailq fully local Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 5/7] rte_mempool: make mempool " Anatoly Burakov
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_hash/rte_fbk_hash.c | 66 +++++++++++++++++++++++++++++++++---------
 lib/librte_hash/rte_fbk_hash.h |  3 --
 2 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index 4d67554..e566f48 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -54,7 +54,7 @@
 
 #include "rte_fbk_hash.h"
 
-TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
+TAILQ_HEAD(rte_fbk_hash_list, rte_tailq_entry);
 
 /**
  * Performs a lookup for an existing hash table, and returns a pointer to
@@ -69,24 +69,29 @@ TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
 struct rte_fbk_hash_table *
 rte_fbk_hash_find_existing(const char *name)
 {
-	struct rte_fbk_hash_table *h;
+	struct rte_fbk_hash_table *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_fbk_hash_list *fbk_hash_list;
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		h = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -104,6 +109,7 @@ struct rte_fbk_hash_table *
 rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 {
 	struct rte_fbk_hash_table *ht = NULL;
+	struct rte_tailq_entry *te;
 	char hash_name[RTE_FBK_HASH_NAMESIZE];
 	const uint32_t mem_size =
 			sizeof(*ht) + (sizeof(ht->t[0]) * params->entries);
@@ -112,7 +118,8 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -134,20 +141,28 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(ht, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		ht = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (ht != NULL)
+	if (te != NULL)
+		goto exit;
+
+	te = rte_zmalloc("FBK_HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate tailq entry\n");
 		goto exit;
+	}
 
 	/* Allocate memory for table. */
-	ht = (struct rte_fbk_hash_table *)rte_malloc_socket(hash_name, mem_size,
+	ht = (struct rte_fbk_hash_table *)rte_zmalloc_socket(hash_name, mem_size,
 			0, params->socket_id);
-	if (ht == NULL)
+	if (ht == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate fbk hash table\n");
+		rte_free(te);
 		goto exit;
-
-	memset(ht, 0, mem_size);
+	}
 
 	/* Set up hash table context. */
 	rte_snprintf(ht->name, sizeof(ht->name), "%s", params->name);
@@ -169,7 +184,9 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 		ht->init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT;
 	}
 
-	TAILQ_INSERT_TAIL(fbk_hash_list, ht, next);
+	te->data = (void *) ht;
+
+	TAILQ_INSERT_TAIL(fbk_hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +203,31 @@ exit:
 void
 rte_fbk_hash_free(struct rte_fbk_hash_table *ht)
 {
+	struct rte_tailq_entry *te;
+	struct rte_fbk_hash_list *fbk_hash_list;
+
 	if (ht == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list, ht);
+	/* check that we have an initialised tail queue */
+	if ((fbk_hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		if (te->data == (void *) ht)
+			break;
+	}
+
+	if (te == NULL)
+		return;
+
+	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list, te);
 	rte_free(ht);
+	rte_free(te);
 }
 
diff --git a/lib/librte_hash/rte_fbk_hash.h b/lib/librte_hash/rte_fbk_hash.h
index 4d1a316..3d229bf 100644
--- a/lib/librte_hash/rte_fbk_hash.h
+++ b/lib/librte_hash/rte_fbk_hash.h
@@ -103,11 +103,8 @@ union rte_fbk_hash_entry {
 };
 
 
-
 /** The four-byte key hash table structure. */
 struct rte_fbk_hash_table {
-	TAILQ_ENTRY(rte_fbk_hash_table) next;	/**< Linked list. */
-
 	char name[RTE_FBK_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total number of entries. */
 	uint32_t entries_per_bucket;	/**< Number of entries in a bucket. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 5/7] rte_mempool: make mempool tailq fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (3 preceding siblings ...)
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 4/7] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 6/7] rte_lpm: make lpm " Anatoly Burakov
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_mempool/Makefile      |  3 ++-
 lib/librte_mempool/rte_mempool.c | 37 ++++++++++++++++++++++++++++---------
 lib/librte_mempool/rte_mempool.h |  2 --
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile
index c79b306..9939e10 100644
--- a/lib/librte_mempool/Makefile
+++ b/lib/librte_mempool/Makefile
@@ -44,7 +44,8 @@ endif
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
 
-# this lib needs eal
+# this lib needs eal, rte_ring and rte_malloc
 DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal lib/librte_ring
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 7eebf7f..736e854 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -45,6 +45,7 @@
 #include <rte_debug.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_atomic.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
@@ -60,7 +61,7 @@
 
 #include "rte_mempool.h"
 
-TAILQ_HEAD(rte_mempool_list, rte_mempool);
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
 
 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
 
@@ -404,6 +405,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	char rg_name[RTE_RING_NAMESIZE];
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_ring *r;
 	const struct rte_memzone *mz;
 	size_t mempool_size;
@@ -501,6 +503,13 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 		}
 	}
 
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		goto exit;
+	}
+
 	/*
 	 * If user provided an external memory buffer, then use it to
 	 * store mempool objects. Otherwise reserve memzone big enough to
@@ -527,8 +536,10 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	 * no more memory: in this case we loose previously reserved
 	 * space for the as we cannot free it
 	 */
-	if (mz == NULL)
+	if (mz == NULL) {
+		rte_free(te);
 		goto exit;
+	}
 
 	if (rte_eal_has_hugepages()) {
 		startaddr = (void*)mz->addr;
@@ -587,7 +598,9 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 
 	mempool_populate(mp, n, 1, obj_init, obj_init_arg);
 
-	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp);
+	te->data = (void *) mp;
+
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
@@ -812,6 +825,7 @@ void
 rte_mempool_list_dump(FILE *f)
 {
 	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -822,7 +836,8 @@ rte_mempool_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		rte_mempool_dump(f, mp);
 	}
 
@@ -834,6 +849,7 @@ struct rte_mempool *
 rte_mempool_lookup(const char *name)
 {
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -844,15 +860,18 @@ rte_mempool_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	if (mp == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return mp;
 }
@@ -860,7 +879,7 @@ rte_mempool_lookup(const char *name)
 void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 		      void *arg)
 {
-	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te = NULL;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -871,8 +890,8 @@ void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
-		(*func)(mp, arg);
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
index e5a0b13..95f19f9 100644
--- a/lib/librte_mempool/rte_mempool.h
+++ b/lib/librte_mempool/rte_mempool.h
@@ -143,8 +143,6 @@ struct rte_mempool_objsz {
  * The RTE mempool structure.
  */
 struct rte_mempool {
-	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
-
 	char name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
 	struct rte_ring *ring;           /**< Ring to store objects. */
 	phys_addr_t phys_addr;           /**< Phys. addr. of mempool struct. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 6/7] rte_lpm: make lpm tailq fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (4 preceding siblings ...)
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 5/7] rte_mempool: make mempool " Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 7/7] rte_lpm6: make lpm6 " Anatoly Burakov
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_lpm/rte_lpm.c | 54 ++++++++++++++++++++++++++++++++++++++++--------
 lib/librte_lpm/rte_lpm.h |  2 --
 2 files changed, 45 insertions(+), 11 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index 592750e..18a0cc0 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -56,7 +56,7 @@
 
 #include "rte_lpm.h"
 
-TAILQ_HEAD(rte_lpm_list, rte_lpm);
+TAILQ_HEAD(rte_lpm_list, rte_tailq_entry);
 
 #define MAX_DEPTH_TBL24 24
 
@@ -118,24 +118,29 @@ depth_to_range(uint8_t depth)
 struct rte_lpm *
 rte_lpm_find_existing(const char *name)
 {
-	struct rte_lpm *l;
+	struct rte_lpm *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm *) te->data;
 		if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -149,6 +154,7 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 {
 	char mem_name[RTE_LPM_NAMESIZE];
 	struct rte_lpm *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t mem_size;
 	struct rte_lpm_list *lpm_list;
 
@@ -176,18 +182,27 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
 		goto exit;
 
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size,
 			CACHE_LINE_SIZE, socket_id);
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -195,7 +210,9 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	lpm->max_rules = max_rules;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -209,12 +226,31 @@ exit:
 void
 rte_lpm_free(struct rte_lpm *lpm)
 {
+	struct rte_lpm_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM, rte_lpm_list, lpm);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL)
+		return;
+
+	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM, rte_lpm_list, te);
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h
index d35565d..308f5ef 100644
--- a/lib/librte_lpm/rte_lpm.h
+++ b/lib/librte_lpm/rte_lpm.h
@@ -132,8 +132,6 @@ struct rte_lpm_rule_info {
 
 /** @internal LPM structure. */
 struct rte_lpm {
-	TAILQ_ENTRY(rte_lpm) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
 	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 7/7] rte_lpm6: make lpm6 tailq fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (5 preceding siblings ...)
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 6/7] rte_lpm: make lpm " Anatoly Burakov
@ 2014-06-13 15:29 ` Anatoly Burakov
  2014-06-17  9:57 ` [dpdk-dev] [PATCH 0/7] Make DPDK tailqs " Burakov, Anatoly
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
  8 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-13 15:29 UTC (permalink / raw)
  To: dev

---
 lib/librte_lpm/rte_lpm6.c | 55 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 56c74a1..36cb9fc 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -77,7 +77,7 @@ enum valid_flag {
 	VALID
 };
 
-TAILQ_HEAD(rte_lpm6_list, rte_lpm6);
+TAILQ_HEAD(rte_lpm6_list, rte_tailq_entry);
 
 /** Tbl entry structure. It is the same for both tbl24 and tbl8 */
 struct rte_lpm6_tbl_entry {
@@ -99,8 +99,6 @@ struct rte_lpm6_rule {
 
 /** LPM6 structure. */
 struct rte_lpm6 {
-	TAILQ_ENTRY(rte_lpm6) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM6_NAMESIZE];    /**< Name of the lpm. */
 	uint32_t max_rules;              /**< Max number of rules. */
@@ -149,6 +147,7 @@ rte_lpm6_create(const char *name, int socket_id,
 {
 	char mem_name[RTE_LPM6_NAMESIZE];
 	struct rte_lpm6 *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint64_t mem_size, rules_size;
 	struct rte_lpm6_list *lpm_list;
 
@@ -179,19 +178,28 @@ rte_lpm6_create(const char *name, int socket_id,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* Guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
 		goto exit;
 
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM6_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry!\n");
+		goto exit;
+	}
+
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm6 *)rte_zmalloc_socket(mem_name, (size_t)mem_size,
 			CACHE_LINE_SIZE, socket_id);
 
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -201,6 +209,7 @@ rte_lpm6_create(const char *name, int socket_id,
 	if (lpm->rules_tbl == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
 		rte_free(lpm);
+		rte_free(te);
 		goto exit;
 	}
 
@@ -209,7 +218,9 @@ rte_lpm6_create(const char *name, int socket_id,
 	lpm->number_tbl8s = config->number_tbl8s;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -223,7 +234,8 @@ exit:
 struct rte_lpm6 *
 rte_lpm6_find_existing(const char *name)
 {
-	struct rte_lpm6 *l;
+	struct rte_lpm6 *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm6_list *lpm_list;
 
 	/* Check that we have an initialised tail queue */
@@ -234,14 +246,17 @@ rte_lpm6_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, l->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -252,13 +267,31 @@ rte_lpm6_find_existing(const char *name)
 void
 rte_lpm6_free(struct rte_lpm6 *lpm)
 {
+	struct rte_lpm6_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM6, rte_lpm6_list, lpm);
-	rte_free(lpm->rules_tbl);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm6_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL)
+		return;
+
+	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM6, rte_lpm6_list, te);
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (6 preceding siblings ...)
  2014-06-13 15:29 ` [dpdk-dev] [PATCH 7/7] rte_lpm6: make lpm6 " Anatoly Burakov
@ 2014-06-17  9:57 ` Burakov, Anatoly
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
  8 siblings, 0 replies; 44+ messages in thread
From: Burakov, Anatoly @ 2014-06-17  9:57 UTC (permalink / raw)
  To: Burakov, Anatoly, dev

Found a few races, a v2 will be submitted shortly.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Anatoly Burakov
> Sent: Friday, June 13, 2014 4:29 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local

Best regards,
Anatoly Burakov
DPDK SW Engineer

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 0/9] Make DPDK tailqs fully local
  2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
                   ` (7 preceding siblings ...)
  2014-06-17  9:57 ` [dpdk-dev] [PATCH 0/7] Make DPDK tailqs " Burakov, Anatoly
@ 2014-06-17 15:35 ` Anatoly Burakov
  2014-06-17 15:35   ` [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
                     ` (9 more replies)
  8 siblings, 10 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:35 UTC (permalink / raw)
  To: dev

This issue was reported by OVS-DPDK project, and the fix should go to
upstream DPDK. This is not memnic-related - this is to do with
DPDK's rte_ivshmem library.

Every DPDK data structure has a corresponding TAILQ reserved for it in
the runtime config file. Those TAILQs are fully local to the process,
however most data structures contain pointers to next entry in the
TAILQ.

Since the data structures such as rings are shared in their entirety,
those TAILQ pointers are shared as well. Meaning that, after a
successful rte_ring creation, the tailq_next pointer of the last
ring in the TAILQ will be updated with a pointer to a ring which may
not be present in the address space of another process (i.e. a ring
that may be host-local or guest-local, and not shared over IVSHMEM).
Any successive ring create/lookup on the other side of IVSHMEM will
result in trying to dereference an invalid pointer.

This patchset fixes this problem by creating a default tailq entry
that may be used by any data structure that chooses to use TAILQs.
This default TAILQ entry will consist of a tailq_next/tailq_prev
pointers, and an opaque pointer to arbitrary data. All TAILQ
pointers from data structures themselves will be removed and
replaced by those generic TAILQ entries, thus fixing the problem
of potentially exposing local address space to shared structures.

Technically, only rte_ring structure require modification, because
IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
but for consistency's sake other TAILQ-based data structures were
adapted as well.

v2 changes:
* fixed race conditions in *_free operations
* fixed multiprocess support for malloc heaps
* added similar changes for acl
* rebased on top of e88b42f818bc1a6d4ce6cb70371b66e37fa34f7d

Anatoly Burakov (9):
  eal: map shared config into exact same address as primary process
  rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  rte_ring: make ring tailq fully local
  rte_hash: make rte_hash tailq fully local
  rte_fbk_hash: make rte_fbk_hash tailq fully local
  rte_mempool: make mempool tailq fully local
  rte_lpm: make lpm tailq fully local
  rte_lpm6: make lpm6 tailq fully local
  rte_acl: make acl tailq fully local

 app/test/test_tailq.c                             | 33 +++++-----
 lib/librte_acl/acl.h                              |  1 -
 lib/librte_acl/rte_acl.c                          | 74 ++++++++++++++++++-----
 lib/librte_eal/common/eal_common_tailqs.c         |  2 +-
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++
 lib/librte_eal/common/include/rte_tailq.h         |  9 +--
 lib/librte_eal/linuxapp/eal/eal.c                 | 31 ++++++++--
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c         | 17 +++++-
 lib/librte_hash/rte_fbk_hash.c                    | 73 +++++++++++++++++-----
 lib/librte_hash/rte_fbk_hash.h                    |  3 -
 lib/librte_hash/rte_hash.c                        | 61 ++++++++++++++++---
 lib/librte_hash/rte_hash.h                        |  2 -
 lib/librte_lpm/rte_lpm.c                          | 65 ++++++++++++++++----
 lib/librte_lpm/rte_lpm.h                          |  2 -
 lib/librte_lpm/rte_lpm6.c                         | 62 +++++++++++++++----
 lib/librte_mempool/Makefile                       |  3 +-
 lib/librte_mempool/rte_mempool.c                  | 37 +++++++++---
 lib/librte_mempool/rte_mempool.h                  |  2 -
 lib/librte_ring/Makefile                          |  4 +-
 lib/librte_ring/rte_ring.c                        | 33 +++++++---
 lib/librte_ring/rte_ring.h                        |  2 -
 21 files changed, 402 insertions(+), 119 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
@ 2014-06-17 15:35   ` Anatoly Burakov
  2014-06-17 16:29     ` Ananyev, Konstantin
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
                     ` (8 subsequent siblings)
  9 siblings, 1 reply; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:35 UTC (permalink / raw)
  To: dev

Shared config is shared across primary and secondary processes.
However,when using rte_malloc, the malloc elements keep references to
the heap inside themselves. This heap reference might not be referencing
a local heap because the heap reference points to the heap of whatever
process has allocated that malloc element. Therefore, there can be
situations when malloc elements in a given heap actually reference
different addresses for the same heap - depending on which process has
allocated the element. This can lead to segmentation faults when dealing
with malloc elements allocated on the same heap by different processes.

To fix this problem, heaps will now have the same addresses across
processes. In order to achieve that, a new field in a shared mem_config
(a structure that holds the heaps, and which is shared across processes)
was added to keep the address of where this config is mapped in the
primary process.

Secondary process will now map the config in two stages - first, it'll
map it into an arbitrary address and read the address the primary
process has allocated for the shared config. Then, the config is
unmapped and re-mapped using the address previously read.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++++
 lib/librte_eal/linuxapp/eal/eal.c                 | 31 +++++++++++++++++++----
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 30ce6fc..d6359e5 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -89,6 +89,11 @@ struct rte_mem_config {
 
 	/* Heaps of Malloc per socket */
 	struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];
+
+	/* address of mem_config in primary process. used to map shared config into
+	 * exact same address the primary process maps it.
+	 */
+	uint64_t mem_cfg_addr;
 } __attribute__((__packed__));
 
 
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 6994303..fedd82f 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -239,6 +239,11 @@ rte_eal_config_create(void)
 	}
 	memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
 	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+
+	/* store address of the config in the config itself so that secondary
+	 * processes could later map the config into this exact location */
+	rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
+
 }
 
 /* attach to an existing shared memory config */
@@ -246,6 +251,8 @@ static void
 rte_eal_config_attach(void)
 {
 	void *rte_mem_cfg_addr;
+	struct rte_mem_config *mem_config;
+
 	const char *pathname = eal_runtime_config_path();
 
 	if (internal_config.no_shconf)
@@ -257,13 +264,27 @@ rte_eal_config_attach(void)
 			rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
 	}
 
-	rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
-				PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
-	close(mem_cfg_fd);
-	if (rte_mem_cfg_addr == MAP_FAILED)
+	/* map it as read-only first */
+	mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
+			PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
+	if (mem_config == MAP_FAILED)
 		rte_panic("Cannot mmap memory for rte_config\n");
 
-	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+	/* store address used by primary process */
+	rte_mem_cfg_addr = (void *) (uintptr_t) mem_config->mem_cfg_addr;
+
+	/* unmap the config */
+	munmap(mem_config, sizeof(*mem_config));
+
+	/* map the config again, with the proper virtual address */
+	mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
+			sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
+			mem_cfg_fd, 0);
+	if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
+		rte_panic("Cannot mmap memory for rte_config\n");
+	close(mem_cfg_fd);
+
+	rte_config.mem_config = mem_config;
 }
 
 /* Detect if we are a primary or a secondary process */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
  2014-06-17 15:35   ` [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
                     ` (7 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 app/test/test_tailq.c                     | 33 ++++++++++++++++---------------
 lib/librte_eal/common/eal_common_tailqs.c |  2 +-
 lib/librte_eal/common/include/rte_tailq.h |  9 +++++----
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index 67da009..c9b53ee 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -52,16 +52,16 @@
 
 #define DEFAULT_TAILQ (RTE_TAILQ_NUM)
 
-static struct rte_dummy d_elem;
+static struct rte_tailq_entry d_elem;
 
 static int
 test_tailq_create(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 	unsigned i;
 
 	/* create a first tailq and check its non-null */
-	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error allocating dummy_q0\n");
 
@@ -70,13 +70,14 @@ test_tailq_create(void)
 	TAILQ_INSERT_TAIL(d_head, &d_elem, next);
 
 	/* try allocating dummy_q0 again, and check for failure */
-	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head) == NULL)
+	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head) == NULL)
 		do_return("Error, non-null result returned when attemption to "
 				"re-allocate a tailq\n");
 
 	/* now fill up the tailq slots available and check we get an error */
 	for (i = RTE_TAILQ_NUM; i < RTE_MAX_TAILQ; i++){
-		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i, rte_dummy_head)) == NULL)
+		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i,
+				rte_tailq_entry_head)) == NULL)
 			break;
 	}
 
@@ -91,10 +92,10 @@ static int
 test_tailq_lookup(void)
 {
 	/* run successful  test - check result is found */
-	struct rte_dummy_head *d_head;
-	struct rte_dummy *d_ptr;
+	struct rte_tailq_entry_head *d_head;
+	struct rte_tailq_entry *d_ptr;
 
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error with tailq lookup\n");
 
@@ -104,7 +105,7 @@ test_tailq_lookup(void)
 					"expected element not found\n");
 
 	/* now try a bad/error lookup */
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Error, lookup does not return NULL for bad tailq name\n");
 
@@ -115,7 +116,7 @@ test_tailq_lookup(void)
 static int
 test_tailq_deprecated(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 
 	/* since TAILQ_RESERVE is not able to create new tailqs,
 	 * we should find an existing one (IOW, RTE_TAILQ_RESERVE behaves identical
@@ -123,29 +124,29 @@ test_tailq_deprecated(void)
 	 *
 	 * PCI_RESOURCE_LIST tailq is guaranteed to
 	 * be present in any DPDK app. */
-	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
-	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
 	/* try doing that with non-existent names */
-	d_head = RTE_TAILQ_RESERVE("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
 	/* try doing the same with NULL names */
-	d_head = RTE_TAILQ_RESERVE(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index f294a58..db9a185 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -118,7 +118,7 @@ rte_dump_tailq(FILE *f)
 	rte_rwlock_read_lock(&mcfg->qlock);
 	for (i=0; i < RTE_MAX_TAILQ; i++) {
 		const struct rte_tailq_head *tailq = &mcfg->tailq_head[i];
-		const struct rte_dummy_head *head = &tailq->tailq_head;
+		const struct rte_tailq_entry_head *head = &tailq->tailq_head;
 
 		fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n", i,
 		       (rte_tailq_names[i] != NULL ? rte_tailq_names[i]:"nil"),
diff --git a/lib/librte_eal/common/include/rte_tailq.h b/lib/librte_eal/common/include/rte_tailq.h
index d084d9a..b34e5ed 100644
--- a/lib/librte_eal/common/include/rte_tailq.h
+++ b/lib/librte_eal/common/include/rte_tailq.h
@@ -48,11 +48,12 @@ extern "C" {
 #include <stdio.h>
 
 /** dummy structure type used by the rte_tailq APIs */
-struct rte_dummy {
-	TAILQ_ENTRY(rte_dummy) next; /**< Pointer entries for a tailq list */
+struct rte_tailq_entry {
+	TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */
+	void *data; /**< Pointer to the data referenced by this tailq entry */
 };
 /** dummy */
-TAILQ_HEAD(rte_dummy_head, rte_dummy);
+TAILQ_HEAD(rte_tailq_entry_head, rte_tailq_entry);
 
 #define RTE_TAILQ_NAMESIZE 32
 
@@ -65,7 +66,7 @@ TAILQ_HEAD(rte_dummy_head, rte_dummy);
  * a multi-process app to find already-created elements in shared memory.
  */
 struct rte_tailq_head {
-	struct rte_dummy_head tailq_head; /**< NOTE: must be first element */
+	struct rte_tailq_entry_head tailq_head; /**< NOTE: must be first element */
 };
 
 /**
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 3/9] rte_ring: make ring tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
  2014-06-17 15:35   ` [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 4/9] rte_hash: make rte_hash " Anatoly Burakov
                     ` (6 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 ++++++++++++++--
 lib/librte_ring/Makefile                  |  4 ++--
 lib/librte_ring/rte_ring.c                | 33 +++++++++++++++++++++++--------
 lib/librte_ring/rte_ring.h                |  2 --
 4 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
index 4ad76a7..fa5f4e3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
+++ b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
@@ -50,6 +50,7 @@
 #include <rte_errno.h>
 #include <rte_ring.h>
 #include <rte_mempool.h>
+#include <rte_malloc.h>
 #include <rte_common.h>
 #include <rte_ivshmem.h>
 #include <rte_tailq_elem.h>
@@ -101,7 +102,7 @@ static int memseg_idx;
 static int pagesz;
 
 /* Tailq heads to add rings to */
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /*
  * Utility functions
@@ -754,6 +755,7 @@ rte_eal_ivshmem_obj_init(void)
 	struct ivshmem_segment * seg;
 	struct rte_memzone * mz;
 	struct rte_ring * r;
+	struct rte_tailq_entry *te;
 	unsigned i, ms, idx;
 	uint64_t offset;
 
@@ -808,6 +810,8 @@ rte_eal_ivshmem_obj_init(void)
 		mcfg->memzone_idx++;
 	}
 
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
 	/* find rings */
 	for (i = 0; i < mcfg->memzone_idx; i++) {
 		mz = &mcfg->memzone[i];
@@ -819,10 +823,19 @@ rte_eal_ivshmem_obj_init(void)
 
 		r = (struct rte_ring*) (mz->addr_64);
 
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+		te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+		if (te == NULL) {
+			RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n");
+			return -1;
+		}
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 
 		RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr);
 	}
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 #ifdef RTE_LIBRTE_IVSHMEM_DEBUG
 	rte_memzone_dump(stdout);
diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile
index 550507d..2380a43 100644
--- a/lib/librte_ring/Makefile
+++ b/lib/librte_ring/Makefile
@@ -42,7 +42,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h
 
-# this lib needs eal
-DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal
+# this lib needs eal and rte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 2fe4024..d2ff3fe 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -75,6 +75,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
@@ -89,7 +90,7 @@
 
 #include "rte_ring.h"
 
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /* true if x is a power of 2 */
 #define POWEROF2(x) ((((x)-1) & (x)) == 0)
@@ -155,6 +156,7 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 {
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	struct rte_ring *r;
+	struct rte_tailq_entry *te;
 	const struct rte_memzone *mz;
 	ssize_t ring_size;
 	int mz_flags = 0;
@@ -173,6 +175,13 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		return NULL;
 	}
 
+	te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
 	rte_snprintf(mz_name, sizeof(mz_name), "%s%s", RTE_RING_MZ_PREFIX, name);
 
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +195,14 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		/* no need to check return value here, we already checked the
 		 * arguments above */
 		rte_ring_init(r, name, count, flags);
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 	} else {
 		r = NULL;
 		RTE_LOG(ERR, RING, "Cannot reserve memory\n");
+		rte_free(te);
 	}
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
@@ -272,7 +285,7 @@ rte_ring_dump(FILE *f, const struct rte_ring *r)
 void
 rte_ring_list_dump(FILE *f)
 {
-	const struct rte_ring *mp;
+	const struct rte_tailq_entry *te;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialised tail queue */
@@ -284,8 +297,8 @@ rte_ring_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(mp, ring_list, next) {
-		rte_ring_dump(f, mp);
+	TAILQ_FOREACH(te, ring_list, next) {
+		rte_ring_dump(f, (struct rte_ring *) te->data);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -295,7 +308,8 @@ rte_ring_list_dump(FILE *f)
 struct rte_ring *
 rte_ring_lookup(const char *name)
 {
-	struct rte_ring *r;
+	struct rte_tailq_entry *te;
+	struct rte_ring *r = NULL;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialized tail queue */
@@ -307,15 +321,18 @@ rte_ring_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(r, ring_list, next) {
+	TAILQ_FOREACH(te, ring_list, next) {
+		r = (struct rte_ring *) te->data;
 		if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (r == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return r;
 }
diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h
index 4f3e20f..3920830 100644
--- a/lib/librte_ring/rte_ring.h
+++ b/lib/librte_ring/rte_ring.h
@@ -138,8 +138,6 @@ struct rte_ring_debug_stats {
  * a problem.
  */
 struct rte_ring {
-	TAILQ_ENTRY(rte_ring) next;      /**< Next in list. */
-
 	char name[RTE_RING_NAMESIZE];    /**< Name of the ring. */
 	int flags;                       /**< Flags supplied at creation. */
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 4/9] rte_hash: make rte_hash tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (2 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
                     ` (5 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++-------
 lib/librte_hash/rte_hash.h |  2 --
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c
index d4221a8..eea5c01 100644
--- a/lib/librte_hash/rte_hash.c
+++ b/lib/librte_hash/rte_hash.c
@@ -60,7 +60,7 @@
 #include "rte_hash.h"
 
 
-TAILQ_HEAD(rte_hash_list, rte_hash);
+TAILQ_HEAD(rte_hash_list, rte_tailq_entry);
 
 /* Macro to enable/disable run-time checking of function parameters */
 #if defined(RTE_LIBRTE_HASH_DEBUG)
@@ -141,24 +141,29 @@ find_first(uint32_t sig, const uint32_t *sig_bucket, uint32_t num_sigs)
 struct rte_hash *
 rte_hash_find_existing(const char *name)
 {
-	struct rte_hash *h;
+	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_hash_list *hash_list;
 
 	/* check that we have an initialised tail queue */
-	if ((hash_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+	if ((hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -166,6 +171,7 @@ struct rte_hash *
 rte_hash_create(const struct rte_hash_parameters *params)
 {
 	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t num_buckets, sig_bucket_size, key_size,
 		hash_tbl_size, sig_tbl_size, key_tbl_size, mem_size;
 	char hash_name[RTE_HASH_NAMESIZE];
@@ -212,17 +218,25 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (h != NULL)
+	if (te != NULL)
+		goto exit;
+
+	te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "tailq entry allocation failed\n");
 		goto exit;
+	}
 
 	h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size,
 					   CACHE_LINE_SIZE, params->socket_id);
 	if (h == NULL) {
 		RTE_LOG(ERR, HASH, "memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -242,7 +256,9 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	h->hash_func = (params->hash_func == NULL) ?
 		DEFAULT_HASH_FUNC : params->hash_func;
 
-	TAILQ_INSERT_TAIL(hash_list, h, next);
+	te->data = (void *) h;
+
+	TAILQ_INSERT_TAIL(hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -253,11 +269,38 @@ exit:
 void
 rte_hash_free(struct rte_hash *h)
 {
+	struct rte_tailq_entry *te;
+	struct rte_hash_list *hash_list;
+
 	if (h == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_HASH, rte_hash_list, h);
+	/* check that we have an initialised tail queue */
+	if ((hash_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, hash_list, next) {
+		if (te->data == (void *) h)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(h);
+	rte_free(te);
 }
 
 static inline int32_t
diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h
index 5228e3a..2ecaf1a 100644
--- a/lib/librte_hash/rte_hash.h
+++ b/lib/librte_hash/rte_hash.h
@@ -86,8 +86,6 @@ struct rte_hash_parameters {
 
 /** A hash table structure. */
 struct rte_hash {
-	TAILQ_ENTRY(rte_hash) next;/**< Next in list. */
-
 	char name[RTE_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total table entries. */
 	uint32_t bucket_entries;	/**< Bucket entries. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 5/9] rte_fbk_hash: make rte_fbk_hash tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (3 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 4/9] rte_hash: make rte_hash " Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 6/9] rte_mempool: make mempool " Anatoly Burakov
                     ` (4 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++--------
 lib/librte_hash/rte_fbk_hash.h |  3 --
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index 4d67554..1356cf4 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -54,7 +54,7 @@
 
 #include "rte_fbk_hash.h"
 
-TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
+TAILQ_HEAD(rte_fbk_hash_list, rte_tailq_entry);
 
 /**
  * Performs a lookup for an existing hash table, and returns a pointer to
@@ -69,24 +69,29 @@ TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
 struct rte_fbk_hash_table *
 rte_fbk_hash_find_existing(const char *name)
 {
-	struct rte_fbk_hash_table *h;
+	struct rte_fbk_hash_table *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_fbk_hash_list *fbk_hash_list;
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		h = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -104,6 +109,7 @@ struct rte_fbk_hash_table *
 rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 {
 	struct rte_fbk_hash_table *ht = NULL;
+	struct rte_tailq_entry *te;
 	char hash_name[RTE_FBK_HASH_NAMESIZE];
 	const uint32_t mem_size =
 			sizeof(*ht) + (sizeof(ht->t[0]) * params->entries);
@@ -112,7 +118,8 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -134,20 +141,28 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(ht, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		ht = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (ht != NULL)
+	if (te != NULL)
 		goto exit;
 
+	te = rte_zmalloc("FBK_HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory for table. */
-	ht = (struct rte_fbk_hash_table *)rte_malloc_socket(hash_name, mem_size,
+	ht = (struct rte_fbk_hash_table *)rte_zmalloc_socket(hash_name, mem_size,
 			0, params->socket_id);
-	if (ht == NULL)
+	if (ht == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate fbk hash table\n");
+		rte_free(te);
 		goto exit;
-
-	memset(ht, 0, mem_size);
+	}
 
 	/* Set up hash table context. */
 	rte_snprintf(ht->name, sizeof(ht->name), "%s", params->name);
@@ -169,7 +184,9 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 		ht->init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT;
 	}
 
-	TAILQ_INSERT_TAIL(fbk_hash_list, ht, next);
+	te->data = (void *) ht;
+
+	TAILQ_INSERT_TAIL(fbk_hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +203,38 @@ exit:
 void
 rte_fbk_hash_free(struct rte_fbk_hash_table *ht)
 {
+	struct rte_tailq_entry *te;
+	struct rte_fbk_hash_list *fbk_hash_list;
+
 	if (ht == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list, ht);
+	/* check that we have an initialised tail queue */
+	if ((fbk_hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		if (te->data == (void *) ht)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(fbk_hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(ht);
+	rte_free(te);
 }
 
diff --git a/lib/librte_hash/rte_fbk_hash.h b/lib/librte_hash/rte_fbk_hash.h
index 4d1a316..3d229bf 100644
--- a/lib/librte_hash/rte_fbk_hash.h
+++ b/lib/librte_hash/rte_fbk_hash.h
@@ -103,11 +103,8 @@ union rte_fbk_hash_entry {
 };
 
 
-
 /** The four-byte key hash table structure. */
 struct rte_fbk_hash_table {
-	TAILQ_ENTRY(rte_fbk_hash_table) next;	/**< Linked list. */
-
 	char name[RTE_FBK_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total number of entries. */
 	uint32_t entries_per_bucket;	/**< Number of entries in a bucket. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 6/9] rte_mempool: make mempool tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (4 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 7/9] rte_lpm: make lpm " Anatoly Burakov
                     ` (3 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_mempool/Makefile      |  3 ++-
 lib/librte_mempool/rte_mempool.c | 37 ++++++++++++++++++++++++++++---------
 lib/librte_mempool/rte_mempool.h |  2 --
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile
index c79b306..9939e10 100644
--- a/lib/librte_mempool/Makefile
+++ b/lib/librte_mempool/Makefile
@@ -44,7 +44,8 @@ endif
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
 
-# this lib needs eal
+# this lib needs eal, rte_ring and rte_malloc
 DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal lib/librte_ring
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 7eebf7f..736e854 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -45,6 +45,7 @@
 #include <rte_debug.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_atomic.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
@@ -60,7 +61,7 @@
 
 #include "rte_mempool.h"
 
-TAILQ_HEAD(rte_mempool_list, rte_mempool);
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
 
 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
 
@@ -404,6 +405,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	char rg_name[RTE_RING_NAMESIZE];
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_ring *r;
 	const struct rte_memzone *mz;
 	size_t mempool_size;
@@ -501,6 +503,13 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 		}
 	}
 
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		goto exit;
+	}
+
 	/*
 	 * If user provided an external memory buffer, then use it to
 	 * store mempool objects. Otherwise reserve memzone big enough to
@@ -527,8 +536,10 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	 * no more memory: in this case we loose previously reserved
 	 * space for the as we cannot free it
 	 */
-	if (mz == NULL)
+	if (mz == NULL) {
+		rte_free(te);
 		goto exit;
+	}
 
 	if (rte_eal_has_hugepages()) {
 		startaddr = (void*)mz->addr;
@@ -587,7 +598,9 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 
 	mempool_populate(mp, n, 1, obj_init, obj_init_arg);
 
-	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp);
+	te->data = (void *) mp;
+
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
@@ -812,6 +825,7 @@ void
 rte_mempool_list_dump(FILE *f)
 {
 	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -822,7 +836,8 @@ rte_mempool_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		rte_mempool_dump(f, mp);
 	}
 
@@ -834,6 +849,7 @@ struct rte_mempool *
 rte_mempool_lookup(const char *name)
 {
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -844,15 +860,18 @@ rte_mempool_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	if (mp == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return mp;
 }
@@ -860,7 +879,7 @@ rte_mempool_lookup(const char *name)
 void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 		      void *arg)
 {
-	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te = NULL;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -871,8 +890,8 @@ void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
-		(*func)(mp, arg);
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
index e5a0b13..95f19f9 100644
--- a/lib/librte_mempool/rte_mempool.h
+++ b/lib/librte_mempool/rte_mempool.h
@@ -143,8 +143,6 @@ struct rte_mempool_objsz {
  * The RTE mempool structure.
  */
 struct rte_mempool {
-	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
-
 	char name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
 	struct rte_ring *ring;           /**< Ring to store objects. */
 	phys_addr_t phys_addr;           /**< Phys. addr. of mempool struct. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 7/9] rte_lpm: make lpm tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (5 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 6/9] rte_mempool: make mempool " Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
                     ` (2 subsequent siblings)
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++--------
 lib/librte_lpm/rte_lpm.h |  2 --
 2 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index 592750e..6a49d43 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -56,7 +56,7 @@
 
 #include "rte_lpm.h"
 
-TAILQ_HEAD(rte_lpm_list, rte_lpm);
+TAILQ_HEAD(rte_lpm_list, rte_tailq_entry);
 
 #define MAX_DEPTH_TBL24 24
 
@@ -118,24 +118,29 @@ depth_to_range(uint8_t depth)
 struct rte_lpm *
 rte_lpm_find_existing(const char *name)
 {
-	struct rte_lpm *l;
+	struct rte_lpm *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm *) te->data;
 		if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -149,12 +154,13 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 {
 	char mem_name[RTE_LPM_NAMESIZE];
 	struct rte_lpm *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t mem_size;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -176,18 +182,27 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
 		goto exit;
 
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size,
 			CACHE_LINE_SIZE, socket_id);
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -195,7 +210,9 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	lpm->max_rules = max_rules;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -209,12 +226,38 @@ exit:
 void
 rte_lpm_free(struct rte_lpm *lpm)
 {
+	struct rte_lpm_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM, rte_lpm_list, lpm);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h
index d35565d..308f5ef 100644
--- a/lib/librte_lpm/rte_lpm.h
+++ b/lib/librte_lpm/rte_lpm.h
@@ -132,8 +132,6 @@ struct rte_lpm_rule_info {
 
 /** @internal LPM structure. */
 struct rte_lpm {
-	TAILQ_ENTRY(rte_lpm) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
 	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 8/9] rte_lpm6: make lpm6 tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (6 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 7/9] rte_lpm: make lpm " Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 9/9] rte_acl: make acl " Anatoly Burakov
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 56c74a1..73b48d0 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -77,7 +77,7 @@ enum valid_flag {
 	VALID
 };
 
-TAILQ_HEAD(rte_lpm6_list, rte_lpm6);
+TAILQ_HEAD(rte_lpm6_list, rte_tailq_entry);
 
 /** Tbl entry structure. It is the same for both tbl24 and tbl8 */
 struct rte_lpm6_tbl_entry {
@@ -99,8 +99,6 @@ struct rte_lpm6_rule {
 
 /** LPM6 structure. */
 struct rte_lpm6 {
-	TAILQ_ENTRY(rte_lpm6) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM6_NAMESIZE];    /**< Name of the lpm. */
 	uint32_t max_rules;              /**< Max number of rules. */
@@ -149,6 +147,7 @@ rte_lpm6_create(const char *name, int socket_id,
 {
 	char mem_name[RTE_LPM6_NAMESIZE];
 	struct rte_lpm6 *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint64_t mem_size, rules_size;
 	struct rte_lpm6_list *lpm_list;
 
@@ -179,12 +178,20 @@ rte_lpm6_create(const char *name, int socket_id,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* Guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
+		goto exit;
+
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM6_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry!\n");
 		goto exit;
+	}
 
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm6 *)rte_zmalloc_socket(mem_name, (size_t)mem_size,
@@ -192,6 +199,7 @@ rte_lpm6_create(const char *name, int socket_id,
 
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -201,6 +209,7 @@ rte_lpm6_create(const char *name, int socket_id,
 	if (lpm->rules_tbl == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
 		rte_free(lpm);
+		rte_free(te);
 		goto exit;
 	}
 
@@ -209,7 +218,9 @@ rte_lpm6_create(const char *name, int socket_id,
 	lpm->number_tbl8s = config->number_tbl8s;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -223,7 +234,8 @@ exit:
 struct rte_lpm6 *
 rte_lpm6_find_existing(const char *name)
 {
-	struct rte_lpm6 *l;
+	struct rte_lpm6 *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm6_list *lpm_list;
 
 	/* Check that we have an initialised tail queue */
@@ -234,14 +246,17 @@ rte_lpm6_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, l->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -252,13 +267,38 @@ rte_lpm6_find_existing(const char *name)
 void
 rte_lpm6_free(struct rte_lpm6 *lpm)
 {
+	struct rte_lpm6_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM6, rte_lpm6_list, lpm);
-	rte_free(lpm->rules_tbl);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm6_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 9/9] rte_acl: make acl tailq fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (7 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
@ 2014-06-17 15:36   ` Anatoly Burakov
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
  9 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-17 15:36 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_acl/acl.h     |  1 -
 lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/lib/librte_acl/acl.h b/lib/librte_acl/acl.h
index e6d7985..b9d63fd 100644
--- a/lib/librte_acl/acl.h
+++ b/lib/librte_acl/acl.h
@@ -149,7 +149,6 @@ struct rte_acl_bld_trie {
 };
 
 struct rte_acl_ctx {
-	TAILQ_ENTRY(rte_acl_ctx) next;    /**< Next in list. */
 	char                name[RTE_ACL_NAMESIZE];
 	/** Name of the ACL context. */
 	int32_t             socket_id;
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 129a41f..3b47ab6 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -36,13 +36,14 @@
 
 #define	BIT_SIZEOF(x)	(sizeof(x) * CHAR_BIT)
 
-TAILQ_HEAD(rte_acl_list, rte_acl_ctx);
+TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
 
 struct rte_acl_ctx *
 rte_acl_find_existing(const char *name)
 {
-	struct rte_acl_ctx *ctx;
+	struct rte_acl_ctx *ctx = NULL;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -52,27 +53,55 @@ rte_acl_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (ctx == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return ctx;
 }
 
 void
 rte_acl_free(struct rte_acl_ctx *ctx)
 {
+	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
+
 	if (ctx == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_ACL, rte_acl_list, ctx);
+	/* check that we have an initialised tail queue */
+	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
+	if (acl_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, acl_list, next) {
+		if (te->data == (void *) ctx)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(acl_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 	rte_free(ctx->mem);
 	rte_free(ctx);
+	rte_free(te);
 }
 
 struct rte_acl_ctx *
@@ -81,6 +110,7 @@ rte_acl_create(const struct rte_acl_param *param)
 	size_t sz;
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 	char name[sizeof(ctx->name)];
 
 	/* check that we have an initialised tail queue */
@@ -105,15 +135,31 @@ rte_acl_create(const struct rte_acl_param *param)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* if we already have one with that name */
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 
 	/* if ACL with such name doesn't exist, then create a new one. */
-	if (ctx == NULL && (ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE,
-			param->socket_id)) != NULL) {
+	if (te == NULL) {
+		ctx = NULL;
+		te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0);
+
+		if (te == NULL) {
+			RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n");
+			goto exit;
+		}
+
+		ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE, param->socket_id);
 
+		if (ctx == NULL) {
+			RTE_LOG(ERR, ACL,
+				"allocation of %zu bytes on socket %d for %s failed\n",
+				sz, param->socket_id, name);
+			rte_free(te);
+			goto exit;
+		}
 		/* init new allocated context. */
 		ctx->rules = ctx + 1;
 		ctx->max_rules = param->max_rule_num;
@@ -121,14 +167,12 @@ rte_acl_create(const struct rte_acl_param *param)
 		ctx->socket_id = param->socket_id;
 		rte_snprintf(ctx->name, sizeof(ctx->name), "%s", param->name);
 
-		TAILQ_INSERT_TAIL(acl_list, ctx, next);
+		te->data = (void *) ctx;
 
-	} else if (ctx == NULL) {
-		RTE_LOG(ERR, ACL,
-			"allocation of %zu bytes on socket %d for %s failed\n",
-			sz, param->socket_id, name);
+		TAILQ_INSERT_TAIL(acl_list, te, next);
 	}
 
+exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 	return ctx;
 }
@@ -232,6 +276,7 @@ rte_acl_list_dump(void)
 {
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -241,7 +286,8 @@ rte_acl_list_dump(void)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx *) te->data;
 		rte_acl_dump(ctx);
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process
  2014-06-17 15:35   ` [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
@ 2014-06-17 16:29     ` Ananyev, Konstantin
  2014-06-18  9:25       ` Burakov, Anatoly
  0 siblings, 1 reply; 44+ messages in thread
From: Ananyev, Konstantin @ 2014-06-17 16:29 UTC (permalink / raw)
  To: Burakov, Anatoly, dev

Hi Anatoly

> 
> Shared config is shared across primary and secondary processes.
> However,when using rte_malloc, the malloc elements keep references to
> the heap inside themselves. This heap reference might not be referencing
> a local heap because the heap reference points to the heap of whatever
> process has allocated that malloc element. Therefore, there can be
> situations when malloc elements in a given heap actually reference
> different addresses for the same heap - depending on which process has
> allocated the element. This can lead to segmentation faults when dealing
> with malloc elements allocated on the same heap by different processes.
> 
> To fix this problem, heaps will now have the same addresses across
> processes. In order to achieve that, a new field in a shared mem_config
> (a structure that holds the heaps, and which is shared across processes)
> was added to keep the address of where this config is mapped in the
> primary process.
> 
> Secondary process will now map the config in two stages - first, it'll
> map it into an arbitrary address and read the address the primary
> process has allocated for the shared config. Then, the config is
> unmapped and re-mapped using the address previously read.
> 
> Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
> ---
>  lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++++
>  lib/librte_eal/linuxapp/eal/eal.c                 | 31 +++++++++++++++++++----
>  2 files changed, 31 insertions(+), 5 deletions(-)
> 
> diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
> index 30ce6fc..d6359e5 100644
> --- a/lib/librte_eal/common/include/rte_eal_memconfig.h
> +++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
> @@ -89,6 +89,11 @@ struct rte_mem_config {
> 
>  	/* Heaps of Malloc per socket */
>  	struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];
> +
> +	/* address of mem_config in primary process. used to map shared config into
> +	 * exact same address the primary process maps it.
> +	 */
> +	uint64_t mem_cfg_addr;
>  } __attribute__((__packed__));
> 
> 
> diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
> index 6994303..fedd82f 100644
> --- a/lib/librte_eal/linuxapp/eal/eal.c
> +++ b/lib/librte_eal/linuxapp/eal/eal.c
> @@ -239,6 +239,11 @@ rte_eal_config_create(void)
>  	}
>  	memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
>  	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
> +
> +	/* store address of the config in the config itself so that secondary
> +	 * processes could later map the config into this exact location */
> +	rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
> +
>  }
> 
>  /* attach to an existing shared memory config */
> @@ -246,6 +251,8 @@ static void
>  rte_eal_config_attach(void)
>  {
>  	void *rte_mem_cfg_addr;
> +	struct rte_mem_config *mem_config;
> +
>  	const char *pathname = eal_runtime_config_path();
> 
>  	if (internal_config.no_shconf)
> @@ -257,13 +264,27 @@ rte_eal_config_attach(void)
>  			rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
>  	}
> 
> -	rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
> -				PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
> -	close(mem_cfg_fd);
> -	if (rte_mem_cfg_addr == MAP_FAILED)
> +	/* map it as read-only first */
> +	mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
> +			PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
> +	if (mem_config == MAP_FAILED)
>  		rte_panic("Cannot mmap memory for rte_config\n");
> 
> -	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
> +	/* store address used by primary process */
> +	rte_mem_cfg_addr = (void *) (uintptr_t) mem_config->mem_cfg_addr;
> +
> +	/* unmap the config */
> +	munmap(mem_config, sizeof(*mem_config));
> +
> +	/* map the config again, with the proper virtual address */
> +	mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
> +			sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
> +			mem_cfg_fd, 0);
> +	if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
> +		rte_panic("Cannot mmap memory for rte_config\n");
> +	close(mem_cfg_fd);
> +
> +	rte_config.mem_config = mem_config;
>  }
> 
>  /* Detect if we are a primary or a secondary process */
> --

I think we introduce a race window here.
If secondary process would do first mmap() before rte_config.mem_config->mem_cfg_addr was properly set by primary process,
then it will try to do second mmap() with wrong address.
I think we need to do second mmap() straight after rte_eal_mcfg_wait_complete(), or even just inside it.

Konstantin  

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process
  2014-06-17 16:29     ` Ananyev, Konstantin
@ 2014-06-18  9:25       ` Burakov, Anatoly
  0 siblings, 0 replies; 44+ messages in thread
From: Burakov, Anatoly @ 2014-06-18  9:25 UTC (permalink / raw)
  To: Ananyev, Konstantin, dev

Hi Konstantin,

> I think we introduce a race window here.
> If secondary process would do first mmap() before rte_config.mem_config-
> >mem_cfg_addr was properly set by primary process, then it will try to do
> second mmap() with wrong address.
> I think we need to do second mmap() straight after
> rte_eal_mcfg_wait_complete(), or even just inside it.

Acknowledged, will respin.

Best regards,
Anatoly Burakov
DPDK SW Engineer

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs fully local
  2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
                     ` (8 preceding siblings ...)
  2014-06-17 15:36   ` [dpdk-dev] [PATCH 9/9] rte_acl: make acl " Anatoly Burakov
@ 2014-06-18 11:27   ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
                       ` (10 more replies)
  9 siblings, 11 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev

This issue was reported by OVS-DPDK project, and the fix should go to
upstream DPDK. This is not memnic-related - this is to do with
DPDK's rte_ivshmem library.

Every DPDK data structure has a corresponding TAILQ reserved for it in
the runtime config file. Those TAILQs are fully local to the process,
however most data structures contain pointers to next entry in the
TAILQ.

Since the data structures such as rings are shared in their entirety,
those TAILQ pointers are shared as well. Meaning that, after a
successful rte_ring creation, the tailq_next pointer of the last
ring in the TAILQ will be updated with a pointer to a ring which may
not be present in the address space of another process (i.e. a ring
that may be host-local or guest-local, and not shared over IVSHMEM).
Any successive ring create/lookup on the other side of IVSHMEM will
result in trying to dereference an invalid pointer.

This patchset fixes this problem by creating a default tailq entry
that may be used by any data structure that chooses to use TAILQs.
This default TAILQ entry will consist of a tailq_next/tailq_prev
pointers, and an opaque pointer to arbitrary data. All TAILQ
pointers from data structures themselves will be removed and
replaced by those generic TAILQ entries, thus fixing the problem
of potentially exposing local address space to shared structures.

Technically, only rte_ring structure require modification, because
IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
but for consistency's sake other TAILQ-based data structures were
adapted as well.

v2 changes:
* fixed race conditions in *_free operations
* fixed multiprocess support for malloc heaps
* added similar changes for acl
* rebased on top of e88b42f818bc1a6d4ce6cb70371b66e37fa34f7d

v3 changes:
* fixed race reported by Konstantin Ananyev (introduced in v2)

Anatoly Burakov (9):
  eal: map shared config into exact same address as primary process
  rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  rte_ring: make ring tailq fully local
  rte_hash: make rte_hash tailq fully local
  rte_fbk_hash: make rte_fbk_hash tailq fully local
  rte_mempool: make mempool tailq fully local
  rte_lpm: make lpm tailq fully local
  rte_lpm6: make lpm6 tailq fully local
  rte_acl: make acl tailq fully local

 app/test/test_tailq.c                             | 33 +++++-----
 lib/librte_acl/acl.h                              |  1 -
 lib/librte_acl/rte_acl.c                          | 74 ++++++++++++++++++-----
 lib/librte_eal/common/eal_common_tailqs.c         |  2 +-
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++
 lib/librte_eal/common/include/rte_tailq.h         |  9 +--
 lib/librte_eal/linuxapp/eal/eal.c                 | 44 ++++++++++++--
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c         | 17 +++++-
 lib/librte_hash/rte_fbk_hash.c                    | 73 +++++++++++++++++-----
 lib/librte_hash/rte_fbk_hash.h                    |  3 -
 lib/librte_hash/rte_hash.c                        | 61 ++++++++++++++++---
 lib/librte_hash/rte_hash.h                        |  2 -
 lib/librte_lpm/rte_lpm.c                          | 65 ++++++++++++++++----
 lib/librte_lpm/rte_lpm.h                          |  2 -
 lib/librte_lpm/rte_lpm6.c                         | 62 +++++++++++++++----
 lib/librte_mempool/Makefile                       |  3 +-
 lib/librte_mempool/rte_mempool.c                  | 37 +++++++++---
 lib/librte_mempool/rte_mempool.h                  |  2 -
 lib/librte_ring/Makefile                          |  4 +-
 lib/librte_ring/rte_ring.c                        | 33 +++++++---
 lib/librte_ring/rte_ring.h                        |  2 -
 21 files changed, 415 insertions(+), 119 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 1/9] eal: map shared config into exact same address as primary process
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev

Shared config is shared across primary and secondary processes.
However,when using rte_malloc, the malloc elements keep references to
the heap inside themselves. This heap reference might not be referencing
a local heap because the heap reference points to the heap of whatever
process has allocated that malloc element. Therefore, there can be
situations when malloc elements in a given heap actually reference
different addresses for the same heap - depending on which process has
allocated the element. This can lead to segmentation faults when dealing
with malloc elements allocated on the same heap by different processes.

To fix this problem, heaps will now have the same addresses across
processes. In order to achieve that, a new field in a shared mem_config
(a structure that holds the heaps, and which is shared across processes)
was added to keep the address of where this config is mapped in the
primary process.

Secondary process will now map the config in two stages - first, it'll
map it into an arbitrary address and read the address the primary
process has allocated for the shared config. Then, the config is
unmapped and re-mapped using the address previously read.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 +++
 lib/librte_eal/linuxapp/eal/eal.c                 | 44 ++++++++++++++++++++---
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 30ce6fc..d6359e5 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -89,6 +89,11 @@ struct rte_mem_config {
 
 	/* Heaps of Malloc per socket */
 	struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];
+
+	/* address of mem_config in primary process. used to map shared config into
+	 * exact same address the primary process maps it.
+	 */
+	uint64_t mem_cfg_addr;
 } __attribute__((__packed__));
 
 
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index 6994303..fee375c 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -239,13 +239,19 @@ rte_eal_config_create(void)
 	}
 	memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
 	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+
+	/* store address of the config in the config itself so that secondary
+	 * processes could later map the config into this exact location */
+	rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
+
 }
 
 /* attach to an existing shared memory config */
 static void
 rte_eal_config_attach(void)
 {
-	void *rte_mem_cfg_addr;
+	struct rte_mem_config *mem_config;
+
 	const char *pathname = eal_runtime_config_path();
 
 	if (internal_config.no_shconf)
@@ -257,13 +263,40 @@ rte_eal_config_attach(void)
 			rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
 	}
 
-	rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
-				PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
+	/* map it as read-only first */
+	mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
+			PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
+	if (mem_config == MAP_FAILED)
+		rte_panic("Cannot mmap memory for rte_config\n");
+
+	rte_config.mem_config = mem_config;
+}
+
+/* reattach the shared config at exact memory location primary process has it */
+static void
+rte_eal_config_reattach(void)
+{
+	struct rte_mem_config *mem_config;
+	void *rte_mem_cfg_addr;
+
+	if (internal_config.no_shconf)
+		return;
+
+	/* save the address primary process has mapped shared config to */
+	rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr;
+
+	/* unmap original config */
+	munmap(rte_config.mem_config, sizeof(struct rte_mem_config));
+
+	/* remap the config at proper address */
+	mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
+			sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
+			mem_cfg_fd, 0);
 	close(mem_cfg_fd);
-	if (rte_mem_cfg_addr == MAP_FAILED)
+	if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
 		rte_panic("Cannot mmap memory for rte_config\n");
 
-	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+	rte_config.mem_config = mem_config;
 }
 
 /* Detect if we are a primary or a secondary process */
@@ -301,6 +334,7 @@ rte_config_init(void)
 	case RTE_PROC_SECONDARY:
 		rte_eal_config_attach();
 		rte_eal_mcfg_wait_complete(rte_config.mem_config);
+		rte_eal_config_reattach();
 		break;
 	case RTE_PROC_AUTO:
 	case RTE_PROC_INVALID:
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 app/test/test_tailq.c                     | 33 ++++++++++++++++---------------
 lib/librte_eal/common/eal_common_tailqs.c |  2 +-
 lib/librte_eal/common/include/rte_tailq.h |  9 +++++----
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index 67da009..c9b53ee 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -52,16 +52,16 @@
 
 #define DEFAULT_TAILQ (RTE_TAILQ_NUM)
 
-static struct rte_dummy d_elem;
+static struct rte_tailq_entry d_elem;
 
 static int
 test_tailq_create(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 	unsigned i;
 
 	/* create a first tailq and check its non-null */
-	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error allocating dummy_q0\n");
 
@@ -70,13 +70,14 @@ test_tailq_create(void)
 	TAILQ_INSERT_TAIL(d_head, &d_elem, next);
 
 	/* try allocating dummy_q0 again, and check for failure */
-	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head) == NULL)
+	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head) == NULL)
 		do_return("Error, non-null result returned when attemption to "
 				"re-allocate a tailq\n");
 
 	/* now fill up the tailq slots available and check we get an error */
 	for (i = RTE_TAILQ_NUM; i < RTE_MAX_TAILQ; i++){
-		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i, rte_dummy_head)) == NULL)
+		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i,
+				rte_tailq_entry_head)) == NULL)
 			break;
 	}
 
@@ -91,10 +92,10 @@ static int
 test_tailq_lookup(void)
 {
 	/* run successful  test - check result is found */
-	struct rte_dummy_head *d_head;
-	struct rte_dummy *d_ptr;
+	struct rte_tailq_entry_head *d_head;
+	struct rte_tailq_entry *d_ptr;
 
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error with tailq lookup\n");
 
@@ -104,7 +105,7 @@ test_tailq_lookup(void)
 					"expected element not found\n");
 
 	/* now try a bad/error lookup */
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Error, lookup does not return NULL for bad tailq name\n");
 
@@ -115,7 +116,7 @@ test_tailq_lookup(void)
 static int
 test_tailq_deprecated(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 
 	/* since TAILQ_RESERVE is not able to create new tailqs,
 	 * we should find an existing one (IOW, RTE_TAILQ_RESERVE behaves identical
@@ -123,29 +124,29 @@ test_tailq_deprecated(void)
 	 *
 	 * PCI_RESOURCE_LIST tailq is guaranteed to
 	 * be present in any DPDK app. */
-	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
-	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
 	/* try doing that with non-existent names */
-	d_head = RTE_TAILQ_RESERVE("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
 	/* try doing the same with NULL names */
-	d_head = RTE_TAILQ_RESERVE(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index f294a58..db9a185 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -118,7 +118,7 @@ rte_dump_tailq(FILE *f)
 	rte_rwlock_read_lock(&mcfg->qlock);
 	for (i=0; i < RTE_MAX_TAILQ; i++) {
 		const struct rte_tailq_head *tailq = &mcfg->tailq_head[i];
-		const struct rte_dummy_head *head = &tailq->tailq_head;
+		const struct rte_tailq_entry_head *head = &tailq->tailq_head;
 
 		fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n", i,
 		       (rte_tailq_names[i] != NULL ? rte_tailq_names[i]:"nil"),
diff --git a/lib/librte_eal/common/include/rte_tailq.h b/lib/librte_eal/common/include/rte_tailq.h
index d084d9a..b34e5ed 100644
--- a/lib/librte_eal/common/include/rte_tailq.h
+++ b/lib/librte_eal/common/include/rte_tailq.h
@@ -48,11 +48,12 @@ extern "C" {
 #include <stdio.h>
 
 /** dummy structure type used by the rte_tailq APIs */
-struct rte_dummy {
-	TAILQ_ENTRY(rte_dummy) next; /**< Pointer entries for a tailq list */
+struct rte_tailq_entry {
+	TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */
+	void *data; /**< Pointer to the data referenced by this tailq entry */
 };
 /** dummy */
-TAILQ_HEAD(rte_dummy_head, rte_dummy);
+TAILQ_HEAD(rte_tailq_entry_head, rte_tailq_entry);
 
 #define RTE_TAILQ_NAMESIZE 32
 
@@ -65,7 +66,7 @@ TAILQ_HEAD(rte_dummy_head, rte_dummy);
  * a multi-process app to find already-created elements in shared memory.
  */
 struct rte_tailq_head {
-	struct rte_dummy_head tailq_head; /**< NOTE: must be first element */
+	struct rte_tailq_entry_head tailq_head; /**< NOTE: must be first element */
 };
 
 /**
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 3/9] rte_ring: make ring tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 4/9] rte_hash: make rte_hash " Anatoly Burakov
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 ++++++++++++++--
 lib/librte_ring/Makefile                  |  4 ++--
 lib/librte_ring/rte_ring.c                | 33 +++++++++++++++++++++++--------
 lib/librte_ring/rte_ring.h                |  2 --
 4 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
index 4ad76a7..fa5f4e3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
+++ b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
@@ -50,6 +50,7 @@
 #include <rte_errno.h>
 #include <rte_ring.h>
 #include <rte_mempool.h>
+#include <rte_malloc.h>
 #include <rte_common.h>
 #include <rte_ivshmem.h>
 #include <rte_tailq_elem.h>
@@ -101,7 +102,7 @@ static int memseg_idx;
 static int pagesz;
 
 /* Tailq heads to add rings to */
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /*
  * Utility functions
@@ -754,6 +755,7 @@ rte_eal_ivshmem_obj_init(void)
 	struct ivshmem_segment * seg;
 	struct rte_memzone * mz;
 	struct rte_ring * r;
+	struct rte_tailq_entry *te;
 	unsigned i, ms, idx;
 	uint64_t offset;
 
@@ -808,6 +810,8 @@ rte_eal_ivshmem_obj_init(void)
 		mcfg->memzone_idx++;
 	}
 
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
 	/* find rings */
 	for (i = 0; i < mcfg->memzone_idx; i++) {
 		mz = &mcfg->memzone[i];
@@ -819,10 +823,19 @@ rte_eal_ivshmem_obj_init(void)
 
 		r = (struct rte_ring*) (mz->addr_64);
 
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+		te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+		if (te == NULL) {
+			RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n");
+			return -1;
+		}
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 
 		RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr);
 	}
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 #ifdef RTE_LIBRTE_IVSHMEM_DEBUG
 	rte_memzone_dump(stdout);
diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile
index 550507d..2380a43 100644
--- a/lib/librte_ring/Makefile
+++ b/lib/librte_ring/Makefile
@@ -42,7 +42,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h
 
-# this lib needs eal
-DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal
+# this lib needs eal and rte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 2fe4024..d2ff3fe 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -75,6 +75,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
@@ -89,7 +90,7 @@
 
 #include "rte_ring.h"
 
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /* true if x is a power of 2 */
 #define POWEROF2(x) ((((x)-1) & (x)) == 0)
@@ -155,6 +156,7 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 {
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	struct rte_ring *r;
+	struct rte_tailq_entry *te;
 	const struct rte_memzone *mz;
 	ssize_t ring_size;
 	int mz_flags = 0;
@@ -173,6 +175,13 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		return NULL;
 	}
 
+	te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
 	rte_snprintf(mz_name, sizeof(mz_name), "%s%s", RTE_RING_MZ_PREFIX, name);
 
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +195,14 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		/* no need to check return value here, we already checked the
 		 * arguments above */
 		rte_ring_init(r, name, count, flags);
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 	} else {
 		r = NULL;
 		RTE_LOG(ERR, RING, "Cannot reserve memory\n");
+		rte_free(te);
 	}
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
@@ -272,7 +285,7 @@ rte_ring_dump(FILE *f, const struct rte_ring *r)
 void
 rte_ring_list_dump(FILE *f)
 {
-	const struct rte_ring *mp;
+	const struct rte_tailq_entry *te;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialised tail queue */
@@ -284,8 +297,8 @@ rte_ring_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(mp, ring_list, next) {
-		rte_ring_dump(f, mp);
+	TAILQ_FOREACH(te, ring_list, next) {
+		rte_ring_dump(f, (struct rte_ring *) te->data);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -295,7 +308,8 @@ rte_ring_list_dump(FILE *f)
 struct rte_ring *
 rte_ring_lookup(const char *name)
 {
-	struct rte_ring *r;
+	struct rte_tailq_entry *te;
+	struct rte_ring *r = NULL;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialized tail queue */
@@ -307,15 +321,18 @@ rte_ring_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(r, ring_list, next) {
+	TAILQ_FOREACH(te, ring_list, next) {
+		r = (struct rte_ring *) te->data;
 		if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (r == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return r;
 }
diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h
index 4f3e20f..3920830 100644
--- a/lib/librte_ring/rte_ring.h
+++ b/lib/librte_ring/rte_ring.h
@@ -138,8 +138,6 @@ struct rte_ring_debug_stats {
  * a problem.
  */
 struct rte_ring {
-	TAILQ_ENTRY(rte_ring) next;      /**< Next in list. */
-
 	char name[RTE_RING_NAMESIZE];    /**< Name of the ring. */
 	int flags;                       /**< Flags supplied at creation. */
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 4/9] rte_hash: make rte_hash tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (2 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++-------
 lib/librte_hash/rte_hash.h |  2 --
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c
index d4221a8..eea5c01 100644
--- a/lib/librte_hash/rte_hash.c
+++ b/lib/librte_hash/rte_hash.c
@@ -60,7 +60,7 @@
 #include "rte_hash.h"
 
 
-TAILQ_HEAD(rte_hash_list, rte_hash);
+TAILQ_HEAD(rte_hash_list, rte_tailq_entry);
 
 /* Macro to enable/disable run-time checking of function parameters */
 #if defined(RTE_LIBRTE_HASH_DEBUG)
@@ -141,24 +141,29 @@ find_first(uint32_t sig, const uint32_t *sig_bucket, uint32_t num_sigs)
 struct rte_hash *
 rte_hash_find_existing(const char *name)
 {
-	struct rte_hash *h;
+	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_hash_list *hash_list;
 
 	/* check that we have an initialised tail queue */
-	if ((hash_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+	if ((hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -166,6 +171,7 @@ struct rte_hash *
 rte_hash_create(const struct rte_hash_parameters *params)
 {
 	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t num_buckets, sig_bucket_size, key_size,
 		hash_tbl_size, sig_tbl_size, key_tbl_size, mem_size;
 	char hash_name[RTE_HASH_NAMESIZE];
@@ -212,17 +218,25 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (h != NULL)
+	if (te != NULL)
+		goto exit;
+
+	te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "tailq entry allocation failed\n");
 		goto exit;
+	}
 
 	h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size,
 					   CACHE_LINE_SIZE, params->socket_id);
 	if (h == NULL) {
 		RTE_LOG(ERR, HASH, "memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -242,7 +256,9 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	h->hash_func = (params->hash_func == NULL) ?
 		DEFAULT_HASH_FUNC : params->hash_func;
 
-	TAILQ_INSERT_TAIL(hash_list, h, next);
+	te->data = (void *) h;
+
+	TAILQ_INSERT_TAIL(hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -253,11 +269,38 @@ exit:
 void
 rte_hash_free(struct rte_hash *h)
 {
+	struct rte_tailq_entry *te;
+	struct rte_hash_list *hash_list;
+
 	if (h == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_HASH, rte_hash_list, h);
+	/* check that we have an initialised tail queue */
+	if ((hash_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, hash_list, next) {
+		if (te->data == (void *) h)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(h);
+	rte_free(te);
 }
 
 static inline int32_t
diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h
index 5228e3a..2ecaf1a 100644
--- a/lib/librte_hash/rte_hash.h
+++ b/lib/librte_hash/rte_hash.h
@@ -86,8 +86,6 @@ struct rte_hash_parameters {
 
 /** A hash table structure. */
 struct rte_hash {
-	TAILQ_ENTRY(rte_hash) next;/**< Next in list. */
-
 	char name[RTE_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total table entries. */
 	uint32_t bucket_entries;	/**< Bucket entries. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 5/9] rte_fbk_hash: make rte_fbk_hash tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (3 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 4/9] rte_hash: make rte_hash " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 6/9] rte_mempool: make mempool " Anatoly Burakov
                       ` (5 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++--------
 lib/librte_hash/rte_fbk_hash.h |  3 --
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index 4d67554..1356cf4 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -54,7 +54,7 @@
 
 #include "rte_fbk_hash.h"
 
-TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
+TAILQ_HEAD(rte_fbk_hash_list, rte_tailq_entry);
 
 /**
  * Performs a lookup for an existing hash table, and returns a pointer to
@@ -69,24 +69,29 @@ TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
 struct rte_fbk_hash_table *
 rte_fbk_hash_find_existing(const char *name)
 {
-	struct rte_fbk_hash_table *h;
+	struct rte_fbk_hash_table *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_fbk_hash_list *fbk_hash_list;
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		h = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -104,6 +109,7 @@ struct rte_fbk_hash_table *
 rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 {
 	struct rte_fbk_hash_table *ht = NULL;
+	struct rte_tailq_entry *te;
 	char hash_name[RTE_FBK_HASH_NAMESIZE];
 	const uint32_t mem_size =
 			sizeof(*ht) + (sizeof(ht->t[0]) * params->entries);
@@ -112,7 +118,8 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -134,20 +141,28 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(ht, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		ht = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (ht != NULL)
+	if (te != NULL)
 		goto exit;
 
+	te = rte_zmalloc("FBK_HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory for table. */
-	ht = (struct rte_fbk_hash_table *)rte_malloc_socket(hash_name, mem_size,
+	ht = (struct rte_fbk_hash_table *)rte_zmalloc_socket(hash_name, mem_size,
 			0, params->socket_id);
-	if (ht == NULL)
+	if (ht == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate fbk hash table\n");
+		rte_free(te);
 		goto exit;
-
-	memset(ht, 0, mem_size);
+	}
 
 	/* Set up hash table context. */
 	rte_snprintf(ht->name, sizeof(ht->name), "%s", params->name);
@@ -169,7 +184,9 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 		ht->init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT;
 	}
 
-	TAILQ_INSERT_TAIL(fbk_hash_list, ht, next);
+	te->data = (void *) ht;
+
+	TAILQ_INSERT_TAIL(fbk_hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +203,38 @@ exit:
 void
 rte_fbk_hash_free(struct rte_fbk_hash_table *ht)
 {
+	struct rte_tailq_entry *te;
+	struct rte_fbk_hash_list *fbk_hash_list;
+
 	if (ht == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list, ht);
+	/* check that we have an initialised tail queue */
+	if ((fbk_hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		if (te->data == (void *) ht)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(fbk_hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(ht);
+	rte_free(te);
 }
 
diff --git a/lib/librte_hash/rte_fbk_hash.h b/lib/librte_hash/rte_fbk_hash.h
index 4d1a316..3d229bf 100644
--- a/lib/librte_hash/rte_fbk_hash.h
+++ b/lib/librte_hash/rte_fbk_hash.h
@@ -103,11 +103,8 @@ union rte_fbk_hash_entry {
 };
 
 
-
 /** The four-byte key hash table structure. */
 struct rte_fbk_hash_table {
-	TAILQ_ENTRY(rte_fbk_hash_table) next;	/**< Linked list. */
-
 	char name[RTE_FBK_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total number of entries. */
 	uint32_t entries_per_bucket;	/**< Number of entries in a bucket. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 6/9] rte_mempool: make mempool tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (4 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 7/9] rte_lpm: make lpm " Anatoly Burakov
                       ` (4 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_mempool/Makefile      |  3 ++-
 lib/librte_mempool/rte_mempool.c | 37 ++++++++++++++++++++++++++++---------
 lib/librte_mempool/rte_mempool.h |  2 --
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile
index c79b306..9939e10 100644
--- a/lib/librte_mempool/Makefile
+++ b/lib/librte_mempool/Makefile
@@ -44,7 +44,8 @@ endif
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
 
-# this lib needs eal
+# this lib needs eal, rte_ring and rte_malloc
 DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal lib/librte_ring
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 7eebf7f..736e854 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -45,6 +45,7 @@
 #include <rte_debug.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_atomic.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
@@ -60,7 +61,7 @@
 
 #include "rte_mempool.h"
 
-TAILQ_HEAD(rte_mempool_list, rte_mempool);
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
 
 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
 
@@ -404,6 +405,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	char rg_name[RTE_RING_NAMESIZE];
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_ring *r;
 	const struct rte_memzone *mz;
 	size_t mempool_size;
@@ -501,6 +503,13 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 		}
 	}
 
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		goto exit;
+	}
+
 	/*
 	 * If user provided an external memory buffer, then use it to
 	 * store mempool objects. Otherwise reserve memzone big enough to
@@ -527,8 +536,10 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	 * no more memory: in this case we loose previously reserved
 	 * space for the as we cannot free it
 	 */
-	if (mz == NULL)
+	if (mz == NULL) {
+		rte_free(te);
 		goto exit;
+	}
 
 	if (rte_eal_has_hugepages()) {
 		startaddr = (void*)mz->addr;
@@ -587,7 +598,9 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 
 	mempool_populate(mp, n, 1, obj_init, obj_init_arg);
 
-	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp);
+	te->data = (void *) mp;
+
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
@@ -812,6 +825,7 @@ void
 rte_mempool_list_dump(FILE *f)
 {
 	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -822,7 +836,8 @@ rte_mempool_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		rte_mempool_dump(f, mp);
 	}
 
@@ -834,6 +849,7 @@ struct rte_mempool *
 rte_mempool_lookup(const char *name)
 {
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -844,15 +860,18 @@ rte_mempool_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	if (mp == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return mp;
 }
@@ -860,7 +879,7 @@ rte_mempool_lookup(const char *name)
 void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 		      void *arg)
 {
-	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te = NULL;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -871,8 +890,8 @@ void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
-		(*func)(mp, arg);
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
index e5a0b13..95f19f9 100644
--- a/lib/librte_mempool/rte_mempool.h
+++ b/lib/librte_mempool/rte_mempool.h
@@ -143,8 +143,6 @@ struct rte_mempool_objsz {
  * The RTE mempool structure.
  */
 struct rte_mempool {
-	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
-
 	char name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
 	struct rte_ring *ring;           /**< Ring to store objects. */
 	phys_addr_t phys_addr;           /**< Phys. addr. of mempool struct. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 7/9] rte_lpm: make lpm tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (5 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 6/9] rte_mempool: make mempool " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++--------
 lib/librte_lpm/rte_lpm.h |  2 --
 2 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index 592750e..6a49d43 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -56,7 +56,7 @@
 
 #include "rte_lpm.h"
 
-TAILQ_HEAD(rte_lpm_list, rte_lpm);
+TAILQ_HEAD(rte_lpm_list, rte_tailq_entry);
 
 #define MAX_DEPTH_TBL24 24
 
@@ -118,24 +118,29 @@ depth_to_range(uint8_t depth)
 struct rte_lpm *
 rte_lpm_find_existing(const char *name)
 {
-	struct rte_lpm *l;
+	struct rte_lpm *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm *) te->data;
 		if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -149,12 +154,13 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 {
 	char mem_name[RTE_LPM_NAMESIZE];
 	struct rte_lpm *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t mem_size;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -176,18 +182,27 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
 		goto exit;
 
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size,
 			CACHE_LINE_SIZE, socket_id);
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -195,7 +210,9 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	lpm->max_rules = max_rules;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -209,12 +226,38 @@ exit:
 void
 rte_lpm_free(struct rte_lpm *lpm)
 {
+	struct rte_lpm_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM, rte_lpm_list, lpm);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h
index d35565d..308f5ef 100644
--- a/lib/librte_lpm/rte_lpm.h
+++ b/lib/librte_lpm/rte_lpm.h
@@ -132,8 +132,6 @@ struct rte_lpm_rule_info {
 
 /** @internal LPM structure. */
 struct rte_lpm {
-	TAILQ_ENTRY(rte_lpm) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
 	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 8/9] rte_lpm6: make lpm6 tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (6 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 7/9] rte_lpm: make lpm " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 9/9] rte_acl: make acl " Anatoly Burakov
                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 56c74a1..73b48d0 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -77,7 +77,7 @@ enum valid_flag {
 	VALID
 };
 
-TAILQ_HEAD(rte_lpm6_list, rte_lpm6);
+TAILQ_HEAD(rte_lpm6_list, rte_tailq_entry);
 
 /** Tbl entry structure. It is the same for both tbl24 and tbl8 */
 struct rte_lpm6_tbl_entry {
@@ -99,8 +99,6 @@ struct rte_lpm6_rule {
 
 /** LPM6 structure. */
 struct rte_lpm6 {
-	TAILQ_ENTRY(rte_lpm6) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM6_NAMESIZE];    /**< Name of the lpm. */
 	uint32_t max_rules;              /**< Max number of rules. */
@@ -149,6 +147,7 @@ rte_lpm6_create(const char *name, int socket_id,
 {
 	char mem_name[RTE_LPM6_NAMESIZE];
 	struct rte_lpm6 *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint64_t mem_size, rules_size;
 	struct rte_lpm6_list *lpm_list;
 
@@ -179,12 +178,20 @@ rte_lpm6_create(const char *name, int socket_id,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* Guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
+		goto exit;
+
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM6_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry!\n");
 		goto exit;
+	}
 
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm6 *)rte_zmalloc_socket(mem_name, (size_t)mem_size,
@@ -192,6 +199,7 @@ rte_lpm6_create(const char *name, int socket_id,
 
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -201,6 +209,7 @@ rte_lpm6_create(const char *name, int socket_id,
 	if (lpm->rules_tbl == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
 		rte_free(lpm);
+		rte_free(te);
 		goto exit;
 	}
 
@@ -209,7 +218,9 @@ rte_lpm6_create(const char *name, int socket_id,
 	lpm->number_tbl8s = config->number_tbl8s;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -223,7 +234,8 @@ exit:
 struct rte_lpm6 *
 rte_lpm6_find_existing(const char *name)
 {
-	struct rte_lpm6 *l;
+	struct rte_lpm6 *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm6_list *lpm_list;
 
 	/* Check that we have an initialised tail queue */
@@ -234,14 +246,17 @@ rte_lpm6_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, l->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -252,13 +267,38 @@ rte_lpm6_find_existing(const char *name)
 void
 rte_lpm6_free(struct rte_lpm6 *lpm)
 {
+	struct rte_lpm6_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM6, rte_lpm6_list, lpm);
-	rte_free(lpm->rules_tbl);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm6_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH v3 9/9] rte_acl: make acl tailq fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (7 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
@ 2014-06-18 11:27     ` Anatoly Burakov
  2014-06-18 14:21     ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Ananyev, Konstantin
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-18 11:27 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_acl/acl.h     |  1 -
 lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/lib/librte_acl/acl.h b/lib/librte_acl/acl.h
index e6d7985..b9d63fd 100644
--- a/lib/librte_acl/acl.h
+++ b/lib/librte_acl/acl.h
@@ -149,7 +149,6 @@ struct rte_acl_bld_trie {
 };
 
 struct rte_acl_ctx {
-	TAILQ_ENTRY(rte_acl_ctx) next;    /**< Next in list. */
 	char                name[RTE_ACL_NAMESIZE];
 	/** Name of the ACL context. */
 	int32_t             socket_id;
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 129a41f..3b47ab6 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -36,13 +36,14 @@
 
 #define	BIT_SIZEOF(x)	(sizeof(x) * CHAR_BIT)
 
-TAILQ_HEAD(rte_acl_list, rte_acl_ctx);
+TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
 
 struct rte_acl_ctx *
 rte_acl_find_existing(const char *name)
 {
-	struct rte_acl_ctx *ctx;
+	struct rte_acl_ctx *ctx = NULL;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -52,27 +53,55 @@ rte_acl_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (ctx == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return ctx;
 }
 
 void
 rte_acl_free(struct rte_acl_ctx *ctx)
 {
+	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
+
 	if (ctx == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_ACL, rte_acl_list, ctx);
+	/* check that we have an initialised tail queue */
+	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
+	if (acl_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, acl_list, next) {
+		if (te->data == (void *) ctx)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(acl_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 	rte_free(ctx->mem);
 	rte_free(ctx);
+	rte_free(te);
 }
 
 struct rte_acl_ctx *
@@ -81,6 +110,7 @@ rte_acl_create(const struct rte_acl_param *param)
 	size_t sz;
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 	char name[sizeof(ctx->name)];
 
 	/* check that we have an initialised tail queue */
@@ -105,15 +135,31 @@ rte_acl_create(const struct rte_acl_param *param)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* if we already have one with that name */
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 
 	/* if ACL with such name doesn't exist, then create a new one. */
-	if (ctx == NULL && (ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE,
-			param->socket_id)) != NULL) {
+	if (te == NULL) {
+		ctx = NULL;
+		te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0);
+
+		if (te == NULL) {
+			RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n");
+			goto exit;
+		}
+
+		ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE, param->socket_id);
 
+		if (ctx == NULL) {
+			RTE_LOG(ERR, ACL,
+				"allocation of %zu bytes on socket %d for %s failed\n",
+				sz, param->socket_id, name);
+			rte_free(te);
+			goto exit;
+		}
 		/* init new allocated context. */
 		ctx->rules = ctx + 1;
 		ctx->max_rules = param->max_rule_num;
@@ -121,14 +167,12 @@ rte_acl_create(const struct rte_acl_param *param)
 		ctx->socket_id = param->socket_id;
 		rte_snprintf(ctx->name, sizeof(ctx->name), "%s", param->name);
 
-		TAILQ_INSERT_TAIL(acl_list, ctx, next);
+		te->data = (void *) ctx;
 
-	} else if (ctx == NULL) {
-		RTE_LOG(ERR, ACL,
-			"allocation of %zu bytes on socket %d for %s failed\n",
-			sz, param->socket_id, name);
+		TAILQ_INSERT_TAIL(acl_list, te, next);
 	}
 
+exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 	return ctx;
 }
@@ -232,6 +276,7 @@ rte_acl_list_dump(void)
 {
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -241,7 +286,8 @@ rte_acl_list_dump(void)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx *) te->data;
 		rte_acl_dump(ctx);
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (8 preceding siblings ...)
  2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 9/9] rte_acl: make acl " Anatoly Burakov
@ 2014-06-18 14:21     ` Ananyev, Konstantin
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
  10 siblings, 0 replies; 44+ messages in thread
From: Ananyev, Konstantin @ 2014-06-18 14:21 UTC (permalink / raw)
  To: Burakov, Anatoly, dev



> This issue was reported by OVS-DPDK project, and the fix should go to
> upstream DPDK. This is not memnic-related - this is to do with
> DPDK's rte_ivshmem library.
> 
> Every DPDK data structure has a corresponding TAILQ reserved for it in
> the runtime config file. Those TAILQs are fully local to the process,
> however most data structures contain pointers to next entry in the
> TAILQ.
> 
> Since the data structures such as rings are shared in their entirety,
> those TAILQ pointers are shared as well. Meaning that, after a
> successful rte_ring creation, the tailq_next pointer of the last
> ring in the TAILQ will be updated with a pointer to a ring which may
> not be present in the address space of another process (i.e. a ring
> that may be host-local or guest-local, and not shared over IVSHMEM).
> Any successive ring create/lookup on the other side of IVSHMEM will
> result in trying to dereference an invalid pointer.
> 
> This patchset fixes this problem by creating a default tailq entry
> that may be used by any data structure that chooses to use TAILQs.
> This default TAILQ entry will consist of a tailq_next/tailq_prev
> pointers, and an opaque pointer to arbitrary data. All TAILQ
> pointers from data structures themselves will be removed and
> replaced by those generic TAILQ entries, thus fixing the problem
> of potentially exposing local address space to shared structures.
> 
> Technically, only rte_ring structure require modification, because
> IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
> but for consistency's sake other TAILQ-based data structures were
> adapted as well.
> 
> v2 changes:
> * fixed race conditions in *_free operations
> * fixed multiprocess support for malloc heaps
> * added similar changes for acl
> * rebased on top of e88b42f818bc1a6d4ce6cb70371b66e37fa34f7d
> 
> v3 changes:
> * fixed race reported by Konstantin Ananyev (introduced in v2)
> 
> Anatoly Burakov (9):
>   eal: map shared config into exact same address as primary process
>   rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
>   rte_ring: make ring tailq fully local
>   rte_hash: make rte_hash tailq fully local
>   rte_fbk_hash: make rte_fbk_hash tailq fully local
>   rte_mempool: make mempool tailq fully local
>   rte_lpm: make lpm tailq fully local
>   rte_lpm6: make lpm6 tailq fully local
>   rte_acl: make acl tailq fully local
> 
>  app/test/test_tailq.c                             | 33 +++++-----
>  lib/librte_acl/acl.h                              |  1 -
>  lib/librte_acl/rte_acl.c                          | 74 ++++++++++++++++++-----
>  lib/librte_eal/common/eal_common_tailqs.c         |  2 +-
>  lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++
>  lib/librte_eal/common/include/rte_tailq.h         |  9 +--
>  lib/librte_eal/linuxapp/eal/eal.c                 | 44 ++++++++++++--
>  lib/librte_eal/linuxapp/eal/eal_ivshmem.c         | 17 +++++-
>  lib/librte_hash/rte_fbk_hash.c                    | 73 +++++++++++++++++-----
>  lib/librte_hash/rte_fbk_hash.h                    |  3 -
>  lib/librte_hash/rte_hash.c                        | 61 ++++++++++++++++---
>  lib/librte_hash/rte_hash.h                        |  2 -
>  lib/librte_lpm/rte_lpm.c                          | 65 ++++++++++++++++----
>  lib/librte_lpm/rte_lpm.h                          |  2 -
>  lib/librte_lpm/rte_lpm6.c                         | 62 +++++++++++++++----
>  lib/librte_mempool/Makefile                       |  3 +-
>  lib/librte_mempool/rte_mempool.c                  | 37 +++++++++---
>  lib/librte_mempool/rte_mempool.h                  |  2 -
>  lib/librte_ring/Makefile                          |  4 +-
>  lib/librte_ring/rte_ring.c                        | 33 +++++++---
>  lib/librte_ring/rte_ring.h                        |  2 -
>  21 files changed, 415 insertions(+), 119 deletions(-)
> 
> --

Acked-by: Konstantin Ananyev <konstantin.ananyev@intel.com>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 00/10] Make DPDK tailqs fully local
  2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
                       ` (9 preceding siblings ...)
  2014-06-18 14:21     ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Ananyev, Konstantin
@ 2014-06-20 15:42     ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 01/10] eal: map shared config into exact same address as primary process Anatoly Burakov
                         ` (10 more replies)
  10 siblings, 11 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev

This issue was reported by OVS-DPDK project, and the fix should go to
upstream DPDK. This is not memnic-related - this is to do with
DPDK's rte_ivshmem library.

Every DPDK data structure has a corresponding TAILQ reserved for it in
the runtime config file. Those TAILQs are fully local to the process,
however most data structures contain pointers to next entry in the
TAILQ.

Since the data structures such as rings are shared in their entirety,
those TAILQ pointers are shared as well. Meaning that, after a
successful rte_ring creation, the tailq_next pointer of the last
ring in the TAILQ will be updated with a pointer to a ring which may
not be present in the address space of another process (i.e. a ring
that may be host-local or guest-local, and not shared over IVSHMEM).
Any successive ring create/lookup on the other side of IVSHMEM will
result in trying to dereference an invalid pointer.

This patchset fixes this problem by creating a default tailq entry
that may be used by any data structure that chooses to use TAILQs.
This default TAILQ entry will consist of a tailq_next/tailq_prev
pointers, and an opaque pointer to arbitrary data. All TAILQ
pointers from data structures themselves will be removed and
replaced by those generic TAILQ entries, thus fixing the problem
of potentially exposing local address space to shared structures.

Technically, only rte_ring structure require modification, because
IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
but for consistency's sake other TAILQ-based data structures were
adapted as well.

As part of this patchset, rte_malloc is also fixed to properly support
multiprocess malloc and free. Previously, if the memory was malloc'd
and freed in different processes, this could lead to segmentation
faults due to different heap pointers in malloc elements themselves.
This is fixed by making shared config to be mapped at the same
addresses in both primary and secondary processes, so that the heap
pointers in malloc elements are always valid, whatever process is
doing malloc or free.

The mapping address for the shared config is also now set with the
base-virtaddr flag, mapping the config file just before the start
address for the hugepages.

v2 changes:
* fixed race conditions in *_free operations
* fixed multiprocess support for malloc heaps
* added similar changes for acl
* rebased on top of e88b42f818bc1a6d4ce6cb70371b66e37fa34f7d

v3 changes:
* fixed race reported by Konstantin Ananyev (introduced in v2)

v4 changes:
* rte_mem_config mapping address is now also set by --base-virtaddr

Anatoly Burakov (10):
  eal: map shared config into exact same address as primary process
  eal: use --base-virtaddr for mapping rte_config as well
  rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  rte_ring: make ring tailq fully local
  rte_hash: make rte_hash tailq fully local
  rte_fbk_hash: make rte_fbk_hash tailq fully local
  rte_mempool: make mempool tailq fully local
  rte_lpm: make lpm tailq fully local
  rte_lpm6: make lpm6 tailq fully local
  rte_acl: make acl tailq fully local

 app/test/test_tailq.c                             | 33 +++++-----
 lib/librte_acl/acl.h                              |  1 -
 lib/librte_acl/rte_acl.c                          | 74 ++++++++++++++++++-----
 lib/librte_eal/common/eal_common_tailqs.c         |  2 +-
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 ++
 lib/librte_eal/common/include/rte_tailq.h         |  9 +--
 lib/librte_eal/linuxapp/eal/eal.c                 | 54 +++++++++++++++--
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c         | 17 +++++-
 lib/librte_hash/rte_fbk_hash.c                    | 73 +++++++++++++++++-----
 lib/librte_hash/rte_fbk_hash.h                    |  3 -
 lib/librte_hash/rte_hash.c                        | 61 ++++++++++++++++---
 lib/librte_hash/rte_hash.h                        |  2 -
 lib/librte_lpm/rte_lpm.c                          | 65 ++++++++++++++++----
 lib/librte_lpm/rte_lpm.h                          |  2 -
 lib/librte_lpm/rte_lpm6.c                         | 62 +++++++++++++++----
 lib/librte_mempool/Makefile                       |  3 +-
 lib/librte_mempool/rte_mempool.c                  | 37 +++++++++---
 lib/librte_mempool/rte_mempool.h                  |  2 -
 lib/librte_ring/Makefile                          |  4 +-
 lib/librte_ring/rte_ring.c                        | 33 +++++++---
 lib/librte_ring/rte_ring.h                        |  2 -
 21 files changed, 424 insertions(+), 120 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 01/10] eal: map shared config into exact same address as primary process
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 02/10] eal: use --base-virtaddr for mapping rte_config as well Anatoly Burakov
                         ` (9 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev

Shared config is shared across primary and secondary processes.
However,when using rte_malloc, the malloc elements keep references to
the heap inside themselves. This heap reference might not be referencing
a local heap because the heap reference points to the heap of whatever
process has allocated that malloc element. Therefore, there can be
situations when malloc elements in a given heap actually reference
different addresses for the same heap - depending on which process has
allocated the element. This can lead to segmentation faults when dealing
with malloc elements allocated on the same heap by different processes.

To fix this problem, heaps will now have the same addresses across
processes. In order to achieve that, a new field in a shared mem_config
(a structure that holds the heaps, and which is shared across processes)
was added to keep the address of where this config is mapped in the
primary process.

Secondary process will now map the config in two stages - first, it'll
map it into an arbitrary address and read the address the primary
process has allocated for the shared config. Then, the config is
unmapped and re-mapped using the address previously read.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/common/include/rte_eal_memconfig.h |  5 +++
 lib/librte_eal/linuxapp/eal/eal.c                 | 44 ++++++++++++++++++++---
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/lib/librte_eal/common/include/rte_eal_memconfig.h b/lib/librte_eal/common/include/rte_eal_memconfig.h
index 30ce6fc..d6359e5 100644
--- a/lib/librte_eal/common/include/rte_eal_memconfig.h
+++ b/lib/librte_eal/common/include/rte_eal_memconfig.h
@@ -89,6 +89,11 @@ struct rte_mem_config {
 
 	/* Heaps of Malloc per socket */
 	struct malloc_heap malloc_heaps[RTE_MAX_NUMA_NODES];
+
+	/* address of mem_config in primary process. used to map shared config into
+	 * exact same address the primary process maps it.
+	 */
+	uint64_t mem_cfg_addr;
 } __attribute__((__packed__));
 
 
diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index d204387..ecb7664 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -239,13 +239,19 @@ rte_eal_config_create(void)
 	}
 	memcpy(rte_mem_cfg_addr, &early_mem_config, sizeof(early_mem_config));
 	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+
+	/* store address of the config in the config itself so that secondary
+	 * processes could later map the config into this exact location */
+	rte_config.mem_config->mem_cfg_addr = (uintptr_t) rte_mem_cfg_addr;
+
 }
 
 /* attach to an existing shared memory config */
 static void
 rte_eal_config_attach(void)
 {
-	void *rte_mem_cfg_addr;
+	struct rte_mem_config *mem_config;
+
 	const char *pathname = eal_runtime_config_path();
 
 	if (internal_config.no_shconf)
@@ -257,13 +263,40 @@ rte_eal_config_attach(void)
 			rte_panic("Cannot open '%s' for rte_mem_config\n", pathname);
 	}
 
-	rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
-				PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
+	/* map it as read-only first */
+	mem_config = (struct rte_mem_config *) mmap(NULL, sizeof(*mem_config),
+			PROT_READ, MAP_SHARED, mem_cfg_fd, 0);
+	if (mem_config == MAP_FAILED)
+		rte_panic("Cannot mmap memory for rte_config\n");
+
+	rte_config.mem_config = mem_config;
+}
+
+/* reattach the shared config at exact memory location primary process has it */
+static void
+rte_eal_config_reattach(void)
+{
+	struct rte_mem_config *mem_config;
+	void *rte_mem_cfg_addr;
+
+	if (internal_config.no_shconf)
+		return;
+
+	/* save the address primary process has mapped shared config to */
+	rte_mem_cfg_addr = (void *) (uintptr_t) rte_config.mem_config->mem_cfg_addr;
+
+	/* unmap original config */
+	munmap(rte_config.mem_config, sizeof(struct rte_mem_config));
+
+	/* remap the config at proper address */
+	mem_config = (struct rte_mem_config *) mmap(rte_mem_cfg_addr,
+			sizeof(*mem_config), PROT_READ | PROT_WRITE, MAP_SHARED,
+			mem_cfg_fd, 0);
 	close(mem_cfg_fd);
-	if (rte_mem_cfg_addr == MAP_FAILED)
+	if (mem_config == MAP_FAILED || mem_config != rte_mem_cfg_addr)
 		rte_panic("Cannot mmap memory for rte_config\n");
 
-	rte_config.mem_config = (struct rte_mem_config *) rte_mem_cfg_addr;
+	rte_config.mem_config = mem_config;
 }
 
 /* Detect if we are a primary or a secondary process */
@@ -301,6 +334,7 @@ rte_config_init(void)
 	case RTE_PROC_SECONDARY:
 		rte_eal_config_attach();
 		rte_eal_mcfg_wait_complete(rte_config.mem_config);
+		rte_eal_config_reattach();
 		break;
 	case RTE_PROC_AUTO:
 	case RTE_PROC_INVALID:
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 02/10] eal: use --base-virtaddr for mapping rte_config as well
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 01/10] eal: map shared config into exact same address as primary process Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 03/10] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
                         ` (8 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev

Use --base-virtaddr to set the address of rte_config file along with
start address of the hugepages. Since the user would likely expect
the hugepages to be starting at the specified address, the specified
address will likely be rounded to either 2M or 1G. So, in order to
not waste space, we subtract the length of the config (and align it
on page boundary) from the base virtual address and map the config
just before the hugepages.

Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c
index ecb7664..32cec25 100644
--- a/lib/librte_eal/linuxapp/eal/eal.c
+++ b/lib/librte_eal/linuxapp/eal/eal.c
@@ -212,6 +212,14 @@ rte_eal_config_create(void)
 	if (internal_config.no_shconf)
 		return;
 
+	/* map the config before hugepage address so that we don't waste a page */
+	if (internal_config.base_virtaddr != 0)
+		rte_mem_cfg_addr = (void *) 
+			RTE_ALIGN_FLOOR(internal_config.base_virtaddr -
+			sizeof(struct rte_mem_config), sysconf (_SC_PAGE_SIZE));
+	else
+		rte_mem_cfg_addr = NULL;
+
 	if (mem_cfg_fd < 0){
 		mem_cfg_fd = open(pathname, O_RDWR | O_CREAT, 0660);
 		if (mem_cfg_fd < 0)
@@ -231,7 +239,7 @@ rte_eal_config_create(void)
 				"process running?\n", pathname);
 	}
 
-	rte_mem_cfg_addr = mmap(NULL, sizeof(*rte_config.mem_config),
+	rte_mem_cfg_addr = mmap(rte_mem_cfg_addr, sizeof(*rte_config.mem_config),
 				PROT_READ | PROT_WRITE, MAP_SHARED, mem_cfg_fd, 0);
 
 	if (rte_mem_cfg_addr == MAP_FAILED){
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 03/10] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 01/10] eal: map shared config into exact same address as primary process Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 02/10] eal: use --base-virtaddr for mapping rte_config as well Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 04/10] rte_ring: make ring tailq fully local Anatoly Burakov
                         ` (7 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 app/test/test_tailq.c                     | 33 ++++++++++++++++---------------
 lib/librte_eal/common/eal_common_tailqs.c |  2 +-
 lib/librte_eal/common/include/rte_tailq.h |  9 +++++----
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/app/test/test_tailq.c b/app/test/test_tailq.c
index 67da009..c9b53ee 100644
--- a/app/test/test_tailq.c
+++ b/app/test/test_tailq.c
@@ -52,16 +52,16 @@
 
 #define DEFAULT_TAILQ (RTE_TAILQ_NUM)
 
-static struct rte_dummy d_elem;
+static struct rte_tailq_entry d_elem;
 
 static int
 test_tailq_create(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 	unsigned i;
 
 	/* create a first tailq and check its non-null */
-	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error allocating dummy_q0\n");
 
@@ -70,13 +70,14 @@ test_tailq_create(void)
 	TAILQ_INSERT_TAIL(d_head, &d_elem, next);
 
 	/* try allocating dummy_q0 again, and check for failure */
-	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_dummy_head) == NULL)
+	if (RTE_TAILQ_RESERVE_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head) == NULL)
 		do_return("Error, non-null result returned when attemption to "
 				"re-allocate a tailq\n");
 
 	/* now fill up the tailq slots available and check we get an error */
 	for (i = RTE_TAILQ_NUM; i < RTE_MAX_TAILQ; i++){
-		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i, rte_dummy_head)) == NULL)
+		if ((d_head = RTE_TAILQ_RESERVE_BY_IDX(i,
+				rte_tailq_entry_head)) == NULL)
 			break;
 	}
 
@@ -91,10 +92,10 @@ static int
 test_tailq_lookup(void)
 {
 	/* run successful  test - check result is found */
-	struct rte_dummy_head *d_head;
-	struct rte_dummy *d_ptr;
+	struct rte_tailq_entry_head *d_head;
+	struct rte_tailq_entry *d_ptr;
 
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(DEFAULT_TAILQ, rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error with tailq lookup\n");
 
@@ -104,7 +105,7 @@ test_tailq_lookup(void)
 					"expected element not found\n");
 
 	/* now try a bad/error lookup */
-	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP_BY_IDX(RTE_MAX_TAILQ, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Error, lookup does not return NULL for bad tailq name\n");
 
@@ -115,7 +116,7 @@ test_tailq_lookup(void)
 static int
 test_tailq_deprecated(void)
 {
-	struct rte_dummy_head *d_head;
+	struct rte_tailq_entry_head *d_head;
 
 	/* since TAILQ_RESERVE is not able to create new tailqs,
 	 * we should find an existing one (IOW, RTE_TAILQ_RESERVE behaves identical
@@ -123,29 +124,29 @@ test_tailq_deprecated(void)
 	 *
 	 * PCI_RESOURCE_LIST tailq is guaranteed to
 	 * be present in any DPDK app. */
-	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
-	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("PCI_RESOURCE_LIST", rte_tailq_entry_head);
 	if (d_head == NULL)
 		do_return("Error finding PCI_RESOURCE_LIST\n");
 
 	/* try doing that with non-existent names */
-	d_head = RTE_TAILQ_RESERVE("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP("random name", rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP("random name", rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("Non-existent tailq found!\n");
 
 	/* try doing the same with NULL names */
-	d_head = RTE_TAILQ_RESERVE(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_RESERVE(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
-	d_head = RTE_TAILQ_LOOKUP(NULL, rte_dummy_head);
+	d_head = RTE_TAILQ_LOOKUP(NULL, rte_tailq_entry_head);
 	if (d_head != NULL)
 		do_return("NULL tailq found!\n");
 
diff --git a/lib/librte_eal/common/eal_common_tailqs.c b/lib/librte_eal/common/eal_common_tailqs.c
index f294a58..db9a185 100644
--- a/lib/librte_eal/common/eal_common_tailqs.c
+++ b/lib/librte_eal/common/eal_common_tailqs.c
@@ -118,7 +118,7 @@ rte_dump_tailq(FILE *f)
 	rte_rwlock_read_lock(&mcfg->qlock);
 	for (i=0; i < RTE_MAX_TAILQ; i++) {
 		const struct rte_tailq_head *tailq = &mcfg->tailq_head[i];
-		const struct rte_dummy_head *head = &tailq->tailq_head;
+		const struct rte_tailq_entry_head *head = &tailq->tailq_head;
 
 		fprintf(f, "Tailq %u: qname:<%s>, tqh_first:%p, tqh_last:%p\n", i,
 		       (rte_tailq_names[i] != NULL ? rte_tailq_names[i]:"nil"),
diff --git a/lib/librte_eal/common/include/rte_tailq.h b/lib/librte_eal/common/include/rte_tailq.h
index d084d9a..b34e5ed 100644
--- a/lib/librte_eal/common/include/rte_tailq.h
+++ b/lib/librte_eal/common/include/rte_tailq.h
@@ -48,11 +48,12 @@ extern "C" {
 #include <stdio.h>
 
 /** dummy structure type used by the rte_tailq APIs */
-struct rte_dummy {
-	TAILQ_ENTRY(rte_dummy) next; /**< Pointer entries for a tailq list */
+struct rte_tailq_entry {
+	TAILQ_ENTRY(rte_tailq_entry) next; /**< Pointer entries for a tailq list */
+	void *data; /**< Pointer to the data referenced by this tailq entry */
 };
 /** dummy */
-TAILQ_HEAD(rte_dummy_head, rte_dummy);
+TAILQ_HEAD(rte_tailq_entry_head, rte_tailq_entry);
 
 #define RTE_TAILQ_NAMESIZE 32
 
@@ -65,7 +66,7 @@ TAILQ_HEAD(rte_dummy_head, rte_dummy);
  * a multi-process app to find already-created elements in shared memory.
  */
 struct rte_tailq_head {
-	struct rte_dummy_head tailq_head; /**< NOTE: must be first element */
+	struct rte_tailq_entry_head tailq_head; /**< NOTE: must be first element */
 };
 
 /**
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 04/10] rte_ring: make ring tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (2 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 03/10] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 05/10] rte_hash: make rte_hash " Anatoly Burakov
                         ` (6 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_eal/linuxapp/eal/eal_ivshmem.c | 17 ++++++++++++++--
 lib/librte_ring/Makefile                  |  4 ++--
 lib/librte_ring/rte_ring.c                | 33 +++++++++++++++++++++++--------
 lib/librte_ring/rte_ring.h                |  2 --
 4 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
index 4ad76a7..fa5f4e3 100644
--- a/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
+++ b/lib/librte_eal/linuxapp/eal/eal_ivshmem.c
@@ -50,6 +50,7 @@
 #include <rte_errno.h>
 #include <rte_ring.h>
 #include <rte_mempool.h>
+#include <rte_malloc.h>
 #include <rte_common.h>
 #include <rte_ivshmem.h>
 #include <rte_tailq_elem.h>
@@ -101,7 +102,7 @@ static int memseg_idx;
 static int pagesz;
 
 /* Tailq heads to add rings to */
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /*
  * Utility functions
@@ -754,6 +755,7 @@ rte_eal_ivshmem_obj_init(void)
 	struct ivshmem_segment * seg;
 	struct rte_memzone * mz;
 	struct rte_ring * r;
+	struct rte_tailq_entry *te;
 	unsigned i, ms, idx;
 	uint64_t offset;
 
@@ -808,6 +810,8 @@ rte_eal_ivshmem_obj_init(void)
 		mcfg->memzone_idx++;
 	}
 
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
 	/* find rings */
 	for (i = 0; i < mcfg->memzone_idx; i++) {
 		mz = &mcfg->memzone[i];
@@ -819,10 +823,19 @@ rte_eal_ivshmem_obj_init(void)
 
 		r = (struct rte_ring*) (mz->addr_64);
 
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+		te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+		if (te == NULL) {
+			RTE_LOG(ERR, EAL, "Cannot allocate ring tailq entry!\n");
+			return -1;
+		}
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 
 		RTE_LOG(DEBUG, EAL, "Found ring: '%s' at %p\n", r->name, mz->addr);
 	}
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 #ifdef RTE_LIBRTE_IVSHMEM_DEBUG
 	rte_memzone_dump(stdout);
diff --git a/lib/librte_ring/Makefile b/lib/librte_ring/Makefile
index 550507d..2380a43 100644
--- a/lib/librte_ring/Makefile
+++ b/lib/librte_ring/Makefile
@@ -42,7 +42,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_RING) := rte_ring.c
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_RING)-include := rte_ring.h
 
-# this lib needs eal
-DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal
+# this lib needs eal and rte_malloc
+DEPDIRS-$(CONFIG_RTE_LIBRTE_RING) += lib/librte_eal lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_ring/rte_ring.c b/lib/librte_ring/rte_ring.c
index 2fe4024..d2ff3fe 100644
--- a/lib/librte_ring/rte_ring.c
+++ b/lib/librte_ring/rte_ring.c
@@ -75,6 +75,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
 #include <rte_eal.h>
@@ -89,7 +90,7 @@
 
 #include "rte_ring.h"
 
-TAILQ_HEAD(rte_ring_list, rte_ring);
+TAILQ_HEAD(rte_ring_list, rte_tailq_entry);
 
 /* true if x is a power of 2 */
 #define POWEROF2(x) ((((x)-1) & (x)) == 0)
@@ -155,6 +156,7 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 {
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	struct rte_ring *r;
+	struct rte_tailq_entry *te;
 	const struct rte_memzone *mz;
 	ssize_t ring_size;
 	int mz_flags = 0;
@@ -173,6 +175,13 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		return NULL;
 	}
 
+	te = rte_zmalloc("RING_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, RING, "Cannot reserve memory for tailq\n");
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
 	rte_snprintf(mz_name, sizeof(mz_name), "%s%s", RTE_RING_MZ_PREFIX, name);
 
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +195,14 @@ rte_ring_create(const char *name, unsigned count, int socket_id,
 		/* no need to check return value here, we already checked the
 		 * arguments above */
 		rte_ring_init(r, name, count, flags);
-		TAILQ_INSERT_TAIL(ring_list, r, next);
+
+		te->data = (void *) r;
+
+		TAILQ_INSERT_TAIL(ring_list, te, next);
 	} else {
 		r = NULL;
 		RTE_LOG(ERR, RING, "Cannot reserve memory\n");
+		rte_free(te);
 	}
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
@@ -272,7 +285,7 @@ rte_ring_dump(FILE *f, const struct rte_ring *r)
 void
 rte_ring_list_dump(FILE *f)
 {
-	const struct rte_ring *mp;
+	const struct rte_tailq_entry *te;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialised tail queue */
@@ -284,8 +297,8 @@ rte_ring_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(mp, ring_list, next) {
-		rte_ring_dump(f, mp);
+	TAILQ_FOREACH(te, ring_list, next) {
+		rte_ring_dump(f, (struct rte_ring *) te->data);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -295,7 +308,8 @@ rte_ring_list_dump(FILE *f)
 struct rte_ring *
 rte_ring_lookup(const char *name)
 {
-	struct rte_ring *r;
+	struct rte_tailq_entry *te;
+	struct rte_ring *r = NULL;
 	struct rte_ring_list *ring_list;
 
 	/* check that we have an initialized tail queue */
@@ -307,15 +321,18 @@ rte_ring_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
 
-	TAILQ_FOREACH(r, ring_list, next) {
+	TAILQ_FOREACH(te, ring_list, next) {
+		r = (struct rte_ring *) te->data;
 		if (strncmp(name, r->name, RTE_RING_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (r == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return r;
 }
diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h
index 4f3e20f..3920830 100644
--- a/lib/librte_ring/rte_ring.h
+++ b/lib/librte_ring/rte_ring.h
@@ -138,8 +138,6 @@ struct rte_ring_debug_stats {
  * a problem.
  */
 struct rte_ring {
-	TAILQ_ENTRY(rte_ring) next;      /**< Next in list. */
-
 	char name[RTE_RING_NAMESIZE];    /**< Name of the ring. */
 	int flags;                       /**< Flags supplied at creation. */
 
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 05/10] rte_hash: make rte_hash tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (3 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 04/10] rte_ring: make ring tailq fully local Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 06/10] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
                         ` (5 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++-------
 lib/librte_hash/rte_hash.h |  2 --
 2 files changed, 52 insertions(+), 11 deletions(-)

diff --git a/lib/librte_hash/rte_hash.c b/lib/librte_hash/rte_hash.c
index d4221a8..eea5c01 100644
--- a/lib/librte_hash/rte_hash.c
+++ b/lib/librte_hash/rte_hash.c
@@ -60,7 +60,7 @@
 #include "rte_hash.h"
 
 
-TAILQ_HEAD(rte_hash_list, rte_hash);
+TAILQ_HEAD(rte_hash_list, rte_tailq_entry);
 
 /* Macro to enable/disable run-time checking of function parameters */
 #if defined(RTE_LIBRTE_HASH_DEBUG)
@@ -141,24 +141,29 @@ find_first(uint32_t sig, const uint32_t *sig_bucket, uint32_t num_sigs)
 struct rte_hash *
 rte_hash_find_existing(const char *name)
 {
-	struct rte_hash *h;
+	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_hash_list *hash_list;
 
 	/* check that we have an initialised tail queue */
-	if ((hash_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+	if ((hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -166,6 +171,7 @@ struct rte_hash *
 rte_hash_create(const struct rte_hash_parameters *params)
 {
 	struct rte_hash *h = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t num_buckets, sig_bucket_size, key_size,
 		hash_tbl_size, sig_tbl_size, key_tbl_size, mem_size;
 	char hash_name[RTE_HASH_NAMESIZE];
@@ -212,17 +218,25 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(h, hash_list, next) {
+	TAILQ_FOREACH(te, hash_list, next) {
+		h = (struct rte_hash *) te->data;
 		if (strncmp(params->name, h->name, RTE_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (h != NULL)
+	if (te != NULL)
+		goto exit;
+
+	te = rte_zmalloc("HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "tailq entry allocation failed\n");
 		goto exit;
+	}
 
 	h = (struct rte_hash *)rte_zmalloc_socket(hash_name, mem_size,
 					   CACHE_LINE_SIZE, params->socket_id);
 	if (h == NULL) {
 		RTE_LOG(ERR, HASH, "memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -242,7 +256,9 @@ rte_hash_create(const struct rte_hash_parameters *params)
 	h->hash_func = (params->hash_func == NULL) ?
 		DEFAULT_HASH_FUNC : params->hash_func;
 
-	TAILQ_INSERT_TAIL(hash_list, h, next);
+	te->data = (void *) h;
+
+	TAILQ_INSERT_TAIL(hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -253,11 +269,38 @@ exit:
 void
 rte_hash_free(struct rte_hash *h)
 {
+	struct rte_tailq_entry *te;
+	struct rte_hash_list *hash_list;
+
 	if (h == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_HASH, rte_hash_list, h);
+	/* check that we have an initialised tail queue */
+	if ((hash_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_HASH, rte_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, hash_list, next) {
+		if (te->data == (void *) h)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(h);
+	rte_free(te);
 }
 
 static inline int32_t
diff --git a/lib/librte_hash/rte_hash.h b/lib/librte_hash/rte_hash.h
index 5228e3a..2ecaf1a 100644
--- a/lib/librte_hash/rte_hash.h
+++ b/lib/librte_hash/rte_hash.h
@@ -86,8 +86,6 @@ struct rte_hash_parameters {
 
 /** A hash table structure. */
 struct rte_hash {
-	TAILQ_ENTRY(rte_hash) next;/**< Next in list. */
-
 	char name[RTE_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total table entries. */
 	uint32_t bucket_entries;	/**< Bucket entries. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 06/10] rte_fbk_hash: make rte_fbk_hash tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (4 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 05/10] rte_hash: make rte_hash " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 07/10] rte_mempool: make mempool " Anatoly Burakov
                         ` (4 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++--------
 lib/librte_hash/rte_fbk_hash.h |  3 --
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/lib/librte_hash/rte_fbk_hash.c b/lib/librte_hash/rte_fbk_hash.c
index 4d67554..1356cf4 100644
--- a/lib/librte_hash/rte_fbk_hash.c
+++ b/lib/librte_hash/rte_fbk_hash.c
@@ -54,7 +54,7 @@
 
 #include "rte_fbk_hash.h"
 
-TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
+TAILQ_HEAD(rte_fbk_hash_list, rte_tailq_entry);
 
 /**
  * Performs a lookup for an existing hash table, and returns a pointer to
@@ -69,24 +69,29 @@ TAILQ_HEAD(rte_fbk_hash_list, rte_fbk_hash_table);
 struct rte_fbk_hash_table *
 rte_fbk_hash_find_existing(const char *name)
 {
-	struct rte_fbk_hash_table *h;
+	struct rte_fbk_hash_table *h = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_fbk_hash_list *fbk_hash_list;
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(h, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		h = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(name, h->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-	if (h == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return h;
 }
 
@@ -104,6 +109,7 @@ struct rte_fbk_hash_table *
 rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 {
 	struct rte_fbk_hash_table *ht = NULL;
+	struct rte_tailq_entry *te;
 	char hash_name[RTE_FBK_HASH_NAMESIZE];
 	const uint32_t mem_size =
 			sizeof(*ht) + (sizeof(ht->t[0]) * params->entries);
@@ -112,7 +118,8 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 
 	/* check that we have an initialised tail queue */
 	if ((fbk_hash_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list)) == NULL) {
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -134,20 +141,28 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(ht, fbk_hash_list, next) {
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		ht = (struct rte_fbk_hash_table *) te->data;
 		if (strncmp(params->name, ht->name, RTE_FBK_HASH_NAMESIZE) == 0)
 			break;
 	}
-	if (ht != NULL)
+	if (te != NULL)
 		goto exit;
 
+	te = rte_zmalloc("FBK_HASH_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory for table. */
-	ht = (struct rte_fbk_hash_table *)rte_malloc_socket(hash_name, mem_size,
+	ht = (struct rte_fbk_hash_table *)rte_zmalloc_socket(hash_name, mem_size,
 			0, params->socket_id);
-	if (ht == NULL)
+	if (ht == NULL) {
+		RTE_LOG(ERR, HASH, "Failed to allocate fbk hash table\n");
+		rte_free(te);
 		goto exit;
-
-	memset(ht, 0, mem_size);
+	}
 
 	/* Set up hash table context. */
 	rte_snprintf(ht->name, sizeof(ht->name), "%s", params->name);
@@ -169,7 +184,9 @@ rte_fbk_hash_create(const struct rte_fbk_hash_params *params)
 		ht->init_val = RTE_FBK_HASH_INIT_VAL_DEFAULT;
 	}
 
-	TAILQ_INSERT_TAIL(fbk_hash_list, ht, next);
+	te->data = (void *) ht;
+
+	TAILQ_INSERT_TAIL(fbk_hash_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -186,10 +203,38 @@ exit:
 void
 rte_fbk_hash_free(struct rte_fbk_hash_table *ht)
 {
+	struct rte_tailq_entry *te;
+	struct rte_fbk_hash_list *fbk_hash_list;
+
 	if (ht == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_FBK_HASH, rte_fbk_hash_list, ht);
+	/* check that we have an initialised tail queue */
+	if ((fbk_hash_list =
+			RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_FBK_HASH,
+					rte_fbk_hash_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find out tailq entry */
+	TAILQ_FOREACH(te, fbk_hash_list, next) {
+		if (te->data == (void *) ht)
+			break;
+	}
+
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(fbk_hash_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(ht);
+	rte_free(te);
 }
 
diff --git a/lib/librte_hash/rte_fbk_hash.h b/lib/librte_hash/rte_fbk_hash.h
index 4d1a316..3d229bf 100644
--- a/lib/librte_hash/rte_fbk_hash.h
+++ b/lib/librte_hash/rte_fbk_hash.h
@@ -103,11 +103,8 @@ union rte_fbk_hash_entry {
 };
 
 
-
 /** The four-byte key hash table structure. */
 struct rte_fbk_hash_table {
-	TAILQ_ENTRY(rte_fbk_hash_table) next;	/**< Linked list. */
-
 	char name[RTE_FBK_HASH_NAMESIZE];	/**< Name of the hash. */
 	uint32_t entries;		/**< Total number of entries. */
 	uint32_t entries_per_bucket;	/**< Number of entries in a bucket. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 07/10] rte_mempool: make mempool tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (5 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 06/10] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 08/10] rte_lpm: make lpm " Anatoly Burakov
                         ` (3 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_mempool/Makefile      |  3 ++-
 lib/librte_mempool/rte_mempool.c | 37 ++++++++++++++++++++++++++++---------
 lib/librte_mempool/rte_mempool.h |  2 --
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/lib/librte_mempool/Makefile b/lib/librte_mempool/Makefile
index c79b306..9939e10 100644
--- a/lib/librte_mempool/Makefile
+++ b/lib/librte_mempool/Makefile
@@ -44,7 +44,8 @@ endif
 # install includes
 SYMLINK-$(CONFIG_RTE_LIBRTE_MEMPOOL)-include := rte_mempool.h
 
-# this lib needs eal
+# this lib needs eal, rte_ring and rte_malloc
 DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_eal lib/librte_ring
+DEPDIRS-$(CONFIG_RTE_LIBRTE_MEMPOOL) += lib/librte_malloc
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_mempool/rte_mempool.c b/lib/librte_mempool/rte_mempool.c
index 7eebf7f..736e854 100644
--- a/lib/librte_mempool/rte_mempool.c
+++ b/lib/librte_mempool/rte_mempool.c
@@ -45,6 +45,7 @@
 #include <rte_debug.h>
 #include <rte_memory.h>
 #include <rte_memzone.h>
+#include <rte_malloc.h>
 #include <rte_atomic.h>
 #include <rte_launch.h>
 #include <rte_tailq.h>
@@ -60,7 +61,7 @@
 
 #include "rte_mempool.h"
 
-TAILQ_HEAD(rte_mempool_list, rte_mempool);
+TAILQ_HEAD(rte_mempool_list, rte_tailq_entry);
 
 #define CACHE_FLUSHTHRESH_MULTIPLIER 1.5
 
@@ -404,6 +405,7 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	char mz_name[RTE_MEMZONE_NAMESIZE];
 	char rg_name[RTE_RING_NAMESIZE];
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_ring *r;
 	const struct rte_memzone *mz;
 	size_t mempool_size;
@@ -501,6 +503,13 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 		}
 	}
 
+	/* try to allocate tailq entry */
+	te = rte_zmalloc("MEMPOOL_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, MEMPOOL, "Cannot allocate tailq entry!\n");
+		goto exit;
+	}
+
 	/*
 	 * If user provided an external memory buffer, then use it to
 	 * store mempool objects. Otherwise reserve memzone big enough to
@@ -527,8 +536,10 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 	 * no more memory: in this case we loose previously reserved
 	 * space for the as we cannot free it
 	 */
-	if (mz == NULL)
+	if (mz == NULL) {
+		rte_free(te);
 		goto exit;
+	}
 
 	if (rte_eal_has_hugepages()) {
 		startaddr = (void*)mz->addr;
@@ -587,7 +598,9 @@ rte_mempool_xmem_create(const char *name, unsigned n, unsigned elt_size,
 
 	mempool_populate(mp, n, 1, obj_init, obj_init_arg);
 
-	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, mp);
+	te->data = (void *) mp;
+
+	RTE_EAL_TAILQ_INSERT_TAIL(RTE_TAILQ_MEMPOOL, rte_mempool_list, te);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_MEMPOOL_RWLOCK);
@@ -812,6 +825,7 @@ void
 rte_mempool_list_dump(FILE *f)
 {
 	const struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -822,7 +836,8 @@ rte_mempool_list_dump(FILE *f)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		rte_mempool_dump(f, mp);
 	}
 
@@ -834,6 +849,7 @@ struct rte_mempool *
 rte_mempool_lookup(const char *name)
 {
 	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -844,15 +860,18 @@ rte_mempool_lookup(const char *name)
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
+	TAILQ_FOREACH(te, mempool_list, next) {
+		mp = (struct rte_mempool *) te->data;
 		if (strncmp(name, mp->name, RTE_MEMPOOL_NAMESIZE) == 0)
 			break;
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	if (mp == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return mp;
 }
@@ -860,7 +879,7 @@ rte_mempool_lookup(const char *name)
 void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 		      void *arg)
 {
-	struct rte_mempool *mp = NULL;
+	struct rte_tailq_entry *te = NULL;
 	struct rte_mempool_list *mempool_list;
 
 	if ((mempool_list =
@@ -871,8 +890,8 @@ void rte_mempool_walk(void (*func)(const struct rte_mempool *, void *),
 
 	rte_rwlock_read_lock(RTE_EAL_MEMPOOL_RWLOCK);
 
-	TAILQ_FOREACH(mp, mempool_list, next) {
-		(*func)(mp, arg);
+	TAILQ_FOREACH(te, mempool_list, next) {
+		(*func)((struct rte_mempool *) te->data, arg);
 	}
 
 	rte_rwlock_read_unlock(RTE_EAL_MEMPOOL_RWLOCK);
diff --git a/lib/librte_mempool/rte_mempool.h b/lib/librte_mempool/rte_mempool.h
index e5a0b13..95f19f9 100644
--- a/lib/librte_mempool/rte_mempool.h
+++ b/lib/librte_mempool/rte_mempool.h
@@ -143,8 +143,6 @@ struct rte_mempool_objsz {
  * The RTE mempool structure.
  */
 struct rte_mempool {
-	TAILQ_ENTRY(rte_mempool) next;   /**< Next in list. */
-
 	char name[RTE_MEMPOOL_NAMESIZE]; /**< Name of mempool. */
 	struct rte_ring *ring;           /**< Ring to store objects. */
 	phys_addr_t phys_addr;           /**< Phys. addr. of mempool struct. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 08/10] rte_lpm: make lpm tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (6 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 07/10] rte_mempool: make mempool " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 09/10] rte_lpm6: make lpm6 " Anatoly Burakov
                         ` (2 subsequent siblings)
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++--------
 lib/librte_lpm/rte_lpm.h |  2 --
 2 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm.c b/lib/librte_lpm/rte_lpm.c
index 35209c3..1ee4e96 100644
--- a/lib/librte_lpm/rte_lpm.c
+++ b/lib/librte_lpm/rte_lpm.c
@@ -56,7 +56,7 @@
 
 #include "rte_lpm.h"
 
-TAILQ_HEAD(rte_lpm_list, rte_lpm);
+TAILQ_HEAD(rte_lpm_list, rte_tailq_entry);
 
 #define MAX_DEPTH_TBL24 24
 
@@ -118,24 +118,29 @@ depth_to_range(uint8_t depth)
 struct rte_lpm *
 rte_lpm_find_existing(const char *name)
 {
-	struct rte_lpm *l;
+	struct rte_lpm *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm *) te->data;
 		if (strncmp(name, l->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -149,12 +154,13 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 {
 	char mem_name[RTE_LPM_NAMESIZE];
 	struct rte_lpm *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint32_t mem_size;
 	struct rte_lpm_list *lpm_list;
 
 	/* check that we have an initialised tail queue */
-	if ((lpm_list =
-	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+	if ((lpm_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM,
+			rte_lpm_list)) == NULL) {
 		rte_errno = E_RTE_NO_TAILQ;
 		return NULL;
 	}
@@ -176,18 +182,27 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
 		goto exit;
 
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry\n");
+		goto exit;
+	}
+
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm *)rte_zmalloc_socket(mem_name, mem_size,
 			CACHE_LINE_SIZE, socket_id);
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -195,7 +210,9 @@ rte_lpm_create(const char *name, int socket_id, int max_rules,
 	lpm->max_rules = max_rules;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -209,12 +226,38 @@ exit:
 void
 rte_lpm_free(struct rte_lpm *lpm)
 {
+	struct rte_lpm_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM, rte_lpm_list, lpm);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
diff --git a/lib/librte_lpm/rte_lpm.h b/lib/librte_lpm/rte_lpm.h
index 840d871..62d7736 100644
--- a/lib/librte_lpm/rte_lpm.h
+++ b/lib/librte_lpm/rte_lpm.h
@@ -132,8 +132,6 @@ struct rte_lpm_rule_info {
 
 /** @internal LPM structure. */
 struct rte_lpm {
-	TAILQ_ENTRY(rte_lpm) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM_NAMESIZE];        /**< Name of the lpm. */
 	int mem_location; /**< @deprecated @see RTE_LPM_HEAP and RTE_LPM_MEMZONE. */
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 09/10] rte_lpm6: make lpm6 tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (7 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 08/10] rte_lpm: make lpm " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 10/10] rte_acl: make acl " Anatoly Burakov
  2014-07-22 22:12       ` [dpdk-dev] [PATCH 00/10] Make DPDK tailqs " Thomas Monjalon
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 51 insertions(+), 11 deletions(-)

diff --git a/lib/librte_lpm/rte_lpm6.c b/lib/librte_lpm/rte_lpm6.c
index 32690cb..8072534 100644
--- a/lib/librte_lpm/rte_lpm6.c
+++ b/lib/librte_lpm/rte_lpm6.c
@@ -77,7 +77,7 @@ enum valid_flag {
 	VALID
 };
 
-TAILQ_HEAD(rte_lpm6_list, rte_lpm6);
+TAILQ_HEAD(rte_lpm6_list, rte_tailq_entry);
 
 /** Tbl entry structure. It is the same for both tbl24 and tbl8 */
 struct rte_lpm6_tbl_entry {
@@ -99,8 +99,6 @@ struct rte_lpm6_rule {
 
 /** LPM6 structure. */
 struct rte_lpm6 {
-	TAILQ_ENTRY(rte_lpm6) next;      /**< Next in list. */
-
 	/* LPM metadata. */
 	char name[RTE_LPM6_NAMESIZE];    /**< Name of the lpm. */
 	uint32_t max_rules;              /**< Max number of rules. */
@@ -149,6 +147,7 @@ rte_lpm6_create(const char *name, int socket_id,
 {
 	char mem_name[RTE_LPM6_NAMESIZE];
 	struct rte_lpm6 *lpm = NULL;
+	struct rte_tailq_entry *te;
 	uint64_t mem_size, rules_size;
 	struct rte_lpm6_list *lpm_list;
 
@@ -179,12 +178,20 @@ rte_lpm6_create(const char *name, int socket_id,
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* Guarantee there's no existing */
-	TAILQ_FOREACH(lpm, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		lpm = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, lpm->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
-	if (lpm != NULL)
+	if (te != NULL)
+		goto exit;
+
+	/* allocate tailq entry */
+	te = rte_zmalloc("LPM6_TAILQ_ENTRY", sizeof(*te), 0);
+	if (te == NULL) {
+		RTE_LOG(ERR, LPM, "Failed to allocate tailq entry!\n");
 		goto exit;
+	}
 
 	/* Allocate memory to store the LPM data structures. */
 	lpm = (struct rte_lpm6 *)rte_zmalloc_socket(mem_name, (size_t)mem_size,
@@ -192,6 +199,7 @@ rte_lpm6_create(const char *name, int socket_id,
 
 	if (lpm == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
+		rte_free(te);
 		goto exit;
 	}
 
@@ -201,6 +209,7 @@ rte_lpm6_create(const char *name, int socket_id,
 	if (lpm->rules_tbl == NULL) {
 		RTE_LOG(ERR, LPM, "LPM memory allocation failed\n");
 		rte_free(lpm);
+		rte_free(te);
 		goto exit;
 	}
 
@@ -209,7 +218,9 @@ rte_lpm6_create(const char *name, int socket_id,
 	lpm->number_tbl8s = config->number_tbl8s;
 	rte_snprintf(lpm->name, sizeof(lpm->name), "%s", name);
 
-	TAILQ_INSERT_TAIL(lpm_list, lpm, next);
+	te->data = (void *) lpm;
+
+	TAILQ_INSERT_TAIL(lpm_list, te, next);
 
 exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
@@ -223,7 +234,8 @@ exit:
 struct rte_lpm6 *
 rte_lpm6_find_existing(const char *name)
 {
-	struct rte_lpm6 *l;
+	struct rte_lpm6 *l = NULL;
+	struct rte_tailq_entry *te;
 	struct rte_lpm6_list *lpm_list;
 
 	/* Check that we have an initialised tail queue */
@@ -234,14 +246,17 @@ rte_lpm6_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(l, lpm_list, next) {
+	TAILQ_FOREACH(te, lpm_list, next) {
+		l = (struct rte_lpm6 *) te->data;
 		if (strncmp(name, l->name, RTE_LPM6_NAMESIZE) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (l == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 
 	return l;
 }
@@ -252,13 +267,38 @@ rte_lpm6_find_existing(const char *name)
 void
 rte_lpm6_free(struct rte_lpm6 *lpm)
 {
+	struct rte_lpm6_list *lpm_list;
+	struct rte_tailq_entry *te;
+
 	/* Check user arguments. */
 	if (lpm == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_LPM6, rte_lpm6_list, lpm);
-	rte_free(lpm->rules_tbl);
+	/* check that we have an initialised tail queue */
+	if ((lpm_list =
+	     RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_LPM, rte_lpm6_list)) == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, lpm_list, next) {
+		if (te->data == (void *) lpm)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(lpm_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+
 	rte_free(lpm);
+	rte_free(te);
 }
 
 /*
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [dpdk-dev] [PATCH 10/10] rte_acl: make acl tailq fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (8 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 09/10] rte_lpm6: make lpm6 " Anatoly Burakov
@ 2014-06-20 15:42       ` Anatoly Burakov
  2014-07-22 22:12       ` [dpdk-dev] [PATCH 00/10] Make DPDK tailqs " Thomas Monjalon
  10 siblings, 0 replies; 44+ messages in thread
From: Anatoly Burakov @ 2014-06-20 15:42 UTC (permalink / raw)
  To: dev


Signed-off-by: Anatoly Burakov <anatoly.burakov@intel.com>
---
 lib/librte_acl/acl.h     |  1 -
 lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/lib/librte_acl/acl.h b/lib/librte_acl/acl.h
index e6d7985..b9d63fd 100644
--- a/lib/librte_acl/acl.h
+++ b/lib/librte_acl/acl.h
@@ -149,7 +149,6 @@ struct rte_acl_bld_trie {
 };
 
 struct rte_acl_ctx {
-	TAILQ_ENTRY(rte_acl_ctx) next;    /**< Next in list. */
 	char                name[RTE_ACL_NAMESIZE];
 	/** Name of the ACL context. */
 	int32_t             socket_id;
diff --git a/lib/librte_acl/rte_acl.c b/lib/librte_acl/rte_acl.c
index 129a41f..3b47ab6 100644
--- a/lib/librte_acl/rte_acl.c
+++ b/lib/librte_acl/rte_acl.c
@@ -36,13 +36,14 @@
 
 #define	BIT_SIZEOF(x)	(sizeof(x) * CHAR_BIT)
 
-TAILQ_HEAD(rte_acl_list, rte_acl_ctx);
+TAILQ_HEAD(rte_acl_list, rte_tailq_entry);
 
 struct rte_acl_ctx *
 rte_acl_find_existing(const char *name)
 {
-	struct rte_acl_ctx *ctx;
+	struct rte_acl_ctx *ctx = NULL;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -52,27 +53,55 @@ rte_acl_find_existing(const char *name)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
 
-	if (ctx == NULL)
+	if (te == NULL) {
 		rte_errno = ENOENT;
+		return NULL;
+	}
 	return ctx;
 }
 
 void
 rte_acl_free(struct rte_acl_ctx *ctx)
 {
+	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
+
 	if (ctx == NULL)
 		return;
 
-	RTE_EAL_TAILQ_REMOVE(RTE_TAILQ_ACL, rte_acl_list, ctx);
+	/* check that we have an initialised tail queue */
+	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
+	if (acl_list == NULL) {
+		rte_errno = E_RTE_NO_TAILQ;
+		return;
+	}
+
+	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
+
+	/* find our tailq entry */
+	TAILQ_FOREACH(te, acl_list, next) {
+		if (te->data == (void *) ctx)
+			break;
+	}
+	if (te == NULL) {
+		rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
+		return;
+	}
+
+	TAILQ_REMOVE(acl_list, te, next);
+
+	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 
 	rte_free(ctx->mem);
 	rte_free(ctx);
+	rte_free(te);
 }
 
 struct rte_acl_ctx *
@@ -81,6 +110,7 @@ rte_acl_create(const struct rte_acl_param *param)
 	size_t sz;
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 	char name[sizeof(ctx->name)];
 
 	/* check that we have an initialised tail queue */
@@ -105,15 +135,31 @@ rte_acl_create(const struct rte_acl_param *param)
 	rte_rwlock_write_lock(RTE_EAL_TAILQ_RWLOCK);
 
 	/* if we already have one with that name */
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx*) te->data;
 		if (strncmp(param->name, ctx->name, sizeof(ctx->name)) == 0)
 			break;
 	}
 
 	/* if ACL with such name doesn't exist, then create a new one. */
-	if (ctx == NULL && (ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE,
-			param->socket_id)) != NULL) {
+	if (te == NULL) {
+		ctx = NULL;
+		te = rte_zmalloc("ACL_TAILQ_ENTRY", sizeof(*te), 0);
+
+		if (te == NULL) {
+			RTE_LOG(ERR, ACL, "Cannot allocate tailq entry!\n");
+			goto exit;
+		}
+
+		ctx = rte_zmalloc_socket(name, sz, CACHE_LINE_SIZE, param->socket_id);
 
+		if (ctx == NULL) {
+			RTE_LOG(ERR, ACL,
+				"allocation of %zu bytes on socket %d for %s failed\n",
+				sz, param->socket_id, name);
+			rte_free(te);
+			goto exit;
+		}
 		/* init new allocated context. */
 		ctx->rules = ctx + 1;
 		ctx->max_rules = param->max_rule_num;
@@ -121,14 +167,12 @@ rte_acl_create(const struct rte_acl_param *param)
 		ctx->socket_id = param->socket_id;
 		rte_snprintf(ctx->name, sizeof(ctx->name), "%s", param->name);
 
-		TAILQ_INSERT_TAIL(acl_list, ctx, next);
+		te->data = (void *) ctx;
 
-	} else if (ctx == NULL) {
-		RTE_LOG(ERR, ACL,
-			"allocation of %zu bytes on socket %d for %s failed\n",
-			sz, param->socket_id, name);
+		TAILQ_INSERT_TAIL(acl_list, te, next);
 	}
 
+exit:
 	rte_rwlock_write_unlock(RTE_EAL_TAILQ_RWLOCK);
 	return ctx;
 }
@@ -232,6 +276,7 @@ rte_acl_list_dump(void)
 {
 	struct rte_acl_ctx *ctx;
 	struct rte_acl_list *acl_list;
+	struct rte_tailq_entry *te;
 
 	/* check that we have an initialised tail queue */
 	acl_list = RTE_TAILQ_LOOKUP_BY_IDX(RTE_TAILQ_ACL, rte_acl_list);
@@ -241,7 +286,8 @@ rte_acl_list_dump(void)
 	}
 
 	rte_rwlock_read_lock(RTE_EAL_TAILQ_RWLOCK);
-	TAILQ_FOREACH(ctx, acl_list, next) {
+	TAILQ_FOREACH(te, acl_list, next) {
+		ctx = (struct rte_acl_ctx *) te->data;
 		rte_acl_dump(ctx);
 	}
 	rte_rwlock_read_unlock(RTE_EAL_TAILQ_RWLOCK);
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [dpdk-dev] [PATCH 00/10] Make DPDK tailqs fully local
  2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
                         ` (9 preceding siblings ...)
  2014-06-20 15:42       ` [dpdk-dev] [PATCH 10/10] rte_acl: make acl " Anatoly Burakov
@ 2014-07-22 22:12       ` Thomas Monjalon
  10 siblings, 0 replies; 44+ messages in thread
From: Thomas Monjalon @ 2014-07-22 22:12 UTC (permalink / raw)
  To: Anatoly Burakov; +Cc: dev

2014-06-20 16:42, Anatoly Burakov:
> This issue was reported by OVS-DPDK project, and the fix should go to
> upstream DPDK. This is not memnic-related - this is to do with
> DPDK's rte_ivshmem library.
> 
> Every DPDK data structure has a corresponding TAILQ reserved for it in
> the runtime config file. Those TAILQs are fully local to the process,
> however most data structures contain pointers to next entry in the
> TAILQ.
> 
> Since the data structures such as rings are shared in their entirety,
> those TAILQ pointers are shared as well. Meaning that, after a
> successful rte_ring creation, the tailq_next pointer of the last
> ring in the TAILQ will be updated with a pointer to a ring which may
> not be present in the address space of another process (i.e. a ring
> that may be host-local or guest-local, and not shared over IVSHMEM).
> Any successive ring create/lookup on the other side of IVSHMEM will
> result in trying to dereference an invalid pointer.
> 
> This patchset fixes this problem by creating a default tailq entry
> that may be used by any data structure that chooses to use TAILQs.
> This default TAILQ entry will consist of a tailq_next/tailq_prev
> pointers, and an opaque pointer to arbitrary data. All TAILQ
> pointers from data structures themselves will be removed and
> replaced by those generic TAILQ entries, thus fixing the problem
> of potentially exposing local address space to shared structures.
> 
> Technically, only rte_ring structure require modification, because
> IVSHMEM is only using memzones (which aren't in TAILQs) and rings,
> but for consistency's sake other TAILQ-based data structures were
> adapted as well.
> 
> As part of this patchset, rte_malloc is also fixed to properly support
> multiprocess malloc and free. Previously, if the memory was malloc'd
> and freed in different processes, this could lead to segmentation
> faults due to different heap pointers in malloc elements themselves.
> This is fixed by making shared config to be mapped at the same
> addresses in both primary and secondary processes, so that the heap
> pointers in malloc elements are always valid, whatever process is
> doing malloc or free.
> 
> The mapping address for the shared config is also now set with the
> base-virtaddr flag, mapping the config file just before the start
> address for the hugepages.
> 
> v2 changes:
> * fixed race conditions in *_free operations
> * fixed multiprocess support for malloc heaps
> * added similar changes for acl
> * rebased on top of e88b42f818bc1a6d4ce6cb70371b66e37fa34f7d
> 
> v3 changes:
> * fixed race reported by Konstantin Ananyev (introduced in v2)
> 
> v4 changes:
> * rte_mem_config mapping address is now also set by --base-virtaddr
> 
> Anatoly Burakov (10):
>   eal: map shared config into exact same address as primary process
>   eal: use --base-virtaddr for mapping rte_config as well
>   rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
>   rte_ring: make ring tailq fully local
>   rte_hash: make rte_hash tailq fully local
>   rte_fbk_hash: make rte_fbk_hash tailq fully local
>   rte_mempool: make mempool tailq fully local
>   rte_lpm: make lpm tailq fully local
>   rte_lpm6: make lpm6 tailq fully local
>   rte_acl: make acl tailq fully local

Applied for version 1.7.1.

Thanks
-- 
Thomas

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2014-07-22 22:11 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-13 15:29 [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 1/7] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 2/7] rte_ring: make ring tailq completely local Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 3/7] rte_hash: make rte_hash tailq fully local Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 4/7] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 5/7] rte_mempool: make mempool " Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 6/7] rte_lpm: make lpm " Anatoly Burakov
2014-06-13 15:29 ` [dpdk-dev] [PATCH 7/7] rte_lpm6: make lpm6 " Anatoly Burakov
2014-06-17  9:57 ` [dpdk-dev] [PATCH 0/7] Make DPDK tailqs " Burakov, Anatoly
2014-06-17 15:35 ` [dpdk-dev] [PATCH 0/9] " Anatoly Burakov
2014-06-17 15:35   ` [dpdk-dev] [PATCH 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
2014-06-17 16:29     ` Ananyev, Konstantin
2014-06-18  9:25       ` Burakov, Anatoly
2014-06-17 15:36   ` [dpdk-dev] [PATCH 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 4/9] rte_hash: make rte_hash " Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 6/9] rte_mempool: make mempool " Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 7/9] rte_lpm: make lpm " Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
2014-06-17 15:36   ` [dpdk-dev] [PATCH 9/9] rte_acl: make acl " Anatoly Burakov
2014-06-18 11:27   ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 1/9] eal: map shared config into exact same address as primary process Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 2/9] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 3/9] rte_ring: make ring tailq fully local Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 4/9] rte_hash: make rte_hash " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 5/9] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 6/9] rte_mempool: make mempool " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 7/9] rte_lpm: make lpm " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 8/9] rte_lpm6: make lpm6 " Anatoly Burakov
2014-06-18 11:27     ` [dpdk-dev] [PATCH v3 9/9] rte_acl: make acl " Anatoly Burakov
2014-06-18 14:21     ` [dpdk-dev] [PATCH v3 0/9] Make DPDK tailqs " Ananyev, Konstantin
2014-06-20 15:42     ` [dpdk-dev] [PATCH 00/10] " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 01/10] eal: map shared config into exact same address as primary process Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 02/10] eal: use --base-virtaddr for mapping rte_config as well Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 03/10] rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 04/10] rte_ring: make ring tailq fully local Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 05/10] rte_hash: make rte_hash " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 06/10] rte_fbk_hash: make rte_fbk_hash " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 07/10] rte_mempool: make mempool " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 08/10] rte_lpm: make lpm " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 09/10] rte_lpm6: make lpm6 " Anatoly Burakov
2014-06-20 15:42       ` [dpdk-dev] [PATCH 10/10] rte_acl: make acl " Anatoly Burakov
2014-07-22 22:12       ` [dpdk-dev] [PATCH 00/10] Make DPDK tailqs " Thomas Monjalon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).