Make DPDK tailqs fully local
cover Make DPDK tailqs fully local
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(-)
Signature · 1 line
1.8.1.4
A message that is not in the archive (sent off-list or not yet received): cover.1402672392.git.anatoly.burakov-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
PATCH 1/7 rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
--- 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(-)
app/test/test_tailq.c +17 -16
@@ -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 inttest_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" );
lib/librte_eal/common/eal_common_tailqs.c +1 -1
@@ -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"),
lib/librte_eal/common/include/rte_tailq.h +5 -4
@@ -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 */ };/**
Signature · 1 line
1.8.1.4
PATCH 2/7 rte_ring: make ring tailq completely local
In reply to a message not in the archive--- 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(-)
lib/librte_eal/linuxapp/eal/eal_ivshmem.c +12 -2
@@ -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); }
lib/librte_ring/Makefile +2 -2
@@ -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
lib/librte_ring/rte_ring.c +25 -8
@@ -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; }
lib/librte_ring/rte_ring.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 3/7 rte_hash: make rte_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_hash.c | 54 ++++++++++++++++++++++++++++++++++++++-------- lib/librte_hash/rte_hash.h | 2 -- 2 files changed, 45 insertions(+), 11 deletions(-)
lib/librte_hash/rte_hash.c +45 -9
@@ -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
lib/librte_hash/rte_hash.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 4/7 rte_fbk_hash: make rte_fbk_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_fbk_hash.c | 66 +++++++++++++++++++++++++++++++++--------- lib/librte_hash/rte_fbk_hash.h | 3 -- 2 files changed, 52 insertions(+), 17 deletions(-)
lib/librte_hash/rte_fbk_hash.c +52 -14
@@ -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); }
lib/librte_hash/rte_fbk_hash.h +0 -3
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 5/7 rte_mempool: make mempool tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_mempool/Makefile +2 -1
@@ -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
lib/librte_mempool/rte_mempool.c +28 -9
@@ -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 );
lib/librte_mempool/rte_mempool.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 6/7 rte_lpm: make lpm tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm.c | 54 ++++++++++++++++++++++++++++++++++++++++-------- lib/librte_lpm/rte_lpm.h | 2 -- 2 files changed, 45 insertions(+), 11 deletions(-)
lib/librte_lpm/rte_lpm.c +45 -9
@@ -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); }/*
lib/librte_lpm/rte_lpm.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 7/7 rte_lpm6: make lpm6 tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm6.c | 55 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 11 deletions(-)
lib/librte_lpm/rte_lpm6.c +44 -11
@@ -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); }/*
Signature · 1 line
1.8.1.4
Found a few races, a v2 will be submitted shortly.
Quoted 5 lines
-----Original Message-----
From: dev [mailto:[email protected]] On Behalf Of Anatoly Burakov
Sent: Friday, June 13, 2014 4:29 PM
To: [email protected]
Subject: [dpdk-dev] [PATCH 0/7] Make DPDK tailqs fully local
Best regards,
Anatoly Burakov
DPDK SW Engineer
cover Make DPDK tailqs fully local
In reply to a message not in the archiveThis 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(-)
Signature · 1 line
1.8.1.4
A message that is not in the archive (sent off-list or not yet received): cover.1403084449.git.anatoly.burakov-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Ananyev, Konstantin
Acked-byQuoted 76 lines
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_ivshmemlibrary.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_ringcreation, thetailq_nextpointer 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_ringstructure 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*_freeoperations
* fixed multiprocess support for malloc heaps
* added similar changes for acl
* rebased on top ofe88b42f818bc1a6d4ce6cb70371b66e37fa34f7dv3 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: changerte_dummytorte_tailq_entry, add data pointer
rte_ring: make ring tailq fully local
rte_hash: makerte_hashtailq fully local
rte_fbk_hash: makerte_fbk_hashtailq 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 localapp/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(-)
Quoted 1 line
--
cover Make DPDK tailqs fully local
In reply to a message not in the archiveThis 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(-)
Signature · 1 line
1.8.1.4
PATCH 1/10 eal: map shared config into exact same address as primary process
In reply to a message not in the archiveShared 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.
--- 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(-)
lib/librte_eal/common/include/rte_eal_memconfig.h +5 -0
@@ -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__));
lib/librte_eal/linuxapp/eal/eal.c +39 -5
71 lines not on this page · raw message
Signature · 1 line
1.8.1.4
PATCH 2/10 eal: use --base-virtaddr for mapping rte_config as well
In reply to a message not in the archiveUse --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.
--- lib/librte_eal/linuxapp/eal/eal.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
lib/librte_eal/linuxapp/eal/eal.c +9 -1
@@ -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 ){
Signature · 1 line
1.8.1.4
PATCH 3/10 rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
In reply to a message not in the archive--- 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(-)
app/test/test_tailq.c +17 -16
@@ -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 inttest_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" );
lib/librte_eal/common/eal_common_tailqs.c +1 -1
@@ -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"),
lib/librte_eal/common/include/rte_tailq.h +5 -4
@@ -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 */ };/**
Signature · 1 line
1.8.1.4
PATCH 4/10 rte_ring: make ring tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_eal/linuxapp/eal/eal_ivshmem.c +15 -2
@@ -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);
lib/librte_ring/Makefile +2 -2
@@ -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
lib/librte_ring/rte_ring.c +25 -8
@@ -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; }
lib/librte_ring/rte_ring.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 5/10 rte_hash: make rte_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++------- lib/librte_hash/rte_hash.h | 2 -- 2 files changed, 52 insertions(+), 11 deletions(-)
lib/librte_hash/rte_hash.c +52 -9
@@ -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
lib/librte_hash/rte_hash.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 6/10 rte_fbk_hash: make rte_fbk_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++-------- lib/librte_hash/rte_fbk_hash.h | 3 -- 2 files changed, 59 insertions(+), 17 deletions(-)
lib/librte_hash/rte_fbk_hash.c +59 -14
@@ -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); }
lib/librte_hash/rte_fbk_hash.h +0 -3
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 7/10 rte_mempool: make mempool tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_mempool/Makefile +2 -1
@@ -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
lib/librte_mempool/rte_mempool.c +28 -9
@@ -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 );
lib/librte_mempool/rte_mempool.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 8/10 rte_lpm: make lpm tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++-------- lib/librte_lpm/rte_lpm.h | 2 -- 2 files changed, 54 insertions(+), 13 deletions(-)
lib/librte_lpm/rte_lpm.c +54 -11
@@ -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); }/*
lib/librte_lpm/rte_lpm.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 9/10 rte_lpm6: make lpm6 tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-)
lib/librte_lpm/rte_lpm6.c +51 -11
@@ -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); }/*
Signature · 1 line
1.8.1.4
PATCH 10/10 rte_acl: make acl tailq fully local
In reply to a message not in the archive--- lib/librte_acl/acl.h | 1 - lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 15 deletions(-)
lib/librte_acl/acl.h +0 -1
@@ -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;
lib/librte_acl/rte_acl.c +60 -14
148 lines not on this page · raw message
Signature · 1 line
1.8.1.4
PATCH 1/9 eal: map shared config into exact same address as primary process
In reply to a message not in the archiveShared 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.
--- 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(-)
lib/librte_eal/common/include/rte_eal_memconfig.h +5 -0
@@ -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__));
lib/librte_eal/linuxapp/eal/eal.c +26 -5
@@ -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 voidrte_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 */
Signature · 1 line
1.8.1.4
A message that is not in the archive (sent off-list or not yet received): fb3aaffcd381dcd174677d763d59cc80171faa90.1403018971.git.anatoly.burakov-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
Re: [PATCH 1/9] eal: map shared config into exact same address as primary process
Hi Anatoly
Quoted 93 lines
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 <[email protected]>--- 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(-)lib/librte_eal/common/include/rte_eal_memconfig.h +5
-0@@ -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__));lib/librte_eal/linuxapp/eal/eal.c +20
-5@@ -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 voidrte_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,
lib/librte_eal/linuxapp/eal/eal.c rte_eal_config_attach(void)
Quoted 10 lines
lib/librte_eal/linuxapp/eal/eal.c +6
-1+ 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
A message that is not in the archive (sent off-list or not yet received): 2601191342CEEE43887BDE71AB9772580EFB7832-kPTMFJFq+rEu0RiL9chJVbfspsVTdybXVpNB7YpNyf8@public.gmane.org
Re: [PATCH 1/9] eal: map shared config into exact same address as primary process
Hi Konstantin,
Quoted 6 lines
I think we introduce a race window here.
If secondary process would do firstmmap()before rte_config.mem_config-Quoted 1 line
mem_cfg_addrwas properly set by primary process, then it will try to dosecond
mmap()with wrong address.
I think we need to do secondmmap()straight afterrte_eal_mcfg_wait_complete(), or even just inside it.
Acknowledged, will respin.
Best regards,
Anatoly Burakov
DPDK SW Engineer
PATCH 2/9 rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
In reply to a message not in the archive--- 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(-)
app/test/test_tailq.c +17 -16
@@ -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 inttest_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" );
lib/librte_eal/common/eal_common_tailqs.c +1 -1
@@ -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"),
lib/librte_eal/common/include/rte_tailq.h +5 -4
@@ -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 */ };/**
Signature · 1 line
1.8.1.4
PATCH 3/9 rte_ring: make ring tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_eal/linuxapp/eal/eal_ivshmem.c +15 -2
@@ -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);
lib/librte_ring/Makefile +2 -2
@@ -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
lib/librte_ring/rte_ring.c +25 -8
@@ -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; }
lib/librte_ring/rte_ring.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 4/9 rte_hash: make rte_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++------- lib/librte_hash/rte_hash.h | 2 -- 2 files changed, 52 insertions(+), 11 deletions(-)
lib/librte_hash/rte_hash.c +52 -9
@@ -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
lib/librte_hash/rte_hash.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 5/9 rte_fbk_hash: make rte_fbk_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++-------- lib/librte_hash/rte_fbk_hash.h | 3 -- 2 files changed, 59 insertions(+), 17 deletions(-)
lib/librte_hash/rte_fbk_hash.c +59 -14
@@ -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); }
lib/librte_hash/rte_fbk_hash.h +0 -3
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 6/9 rte_mempool: make mempool tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_mempool/Makefile +2 -1
@@ -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
lib/librte_mempool/rte_mempool.c +28 -9
@@ -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 );
lib/librte_mempool/rte_mempool.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 7/9 rte_lpm: make lpm tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++-------- lib/librte_lpm/rte_lpm.h | 2 -- 2 files changed, 54 insertions(+), 13 deletions(-)
lib/librte_lpm/rte_lpm.c +54 -11
@@ -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); }/*
lib/librte_lpm/rte_lpm.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH 8/9 rte_lpm6: make lpm6 tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-)
lib/librte_lpm/rte_lpm6.c +51 -11
@@ -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); }/*
Signature · 1 line
1.8.1.4
PATCH 9/9 rte_acl: make acl tailq fully local
In reply to a message not in the archive--- lib/librte_acl/acl.h | 1 - lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 15 deletions(-)
lib/librte_acl/acl.h +0 -1
@@ -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;
lib/librte_acl/rte_acl.c +60 -14
148 lines not on this page · raw message
Signature · 1 line
1.8.1.4
A message that is not in the archive (sent off-list or not yet received): cover.1403018971.git.anatoly.burakov-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
v3 cover Make DPDK tailqs fully local
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(-)
Signature · 1 line
1.8.1.4
A message that is not in the archive (sent off-list or not yet received): cover.1403277437.git.anatoly.burakov-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org
2014-06-20 16:42, Anatoly Burakov:
Quoted 56 lines
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_ivshmemlibrary.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_ringcreation, thetailq_nextpointer 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_ringstructure 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_mallocis 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*_freeoperations
* fixed multiprocess support for malloc heaps
* added similar changes for acl
* rebased on top ofe88b42f818bc1a6d4ce6cb70371b66e37fa34f7dv3 changes:
* fixed race reported by Konstantin Ananyev (introduced in v2)v4 changes:
*rte_mem_configmapping address is now also set by --base-virtaddr
Quoted 11 lines
Anatoly Burakov (10):
eal: map shared config into exact same address as primary process
eal: use --base-virtaddr for mappingrte_configas well
rte_tailq: changerte_dummytorte_tailq_entry, add data pointer
rte_ring: make ring tailq fully local
rte_hash: makerte_hashtailq fully local
rte_fbk_hash: makerte_fbk_hashtailq 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
Signature · 1 line
Thomas
PATCH v3 1/9 eal: map shared config into exact same address as primary process
In reply to a message not in the archiveShared 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.
--- 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(-)
lib/librte_eal/common/include/rte_eal_memconfig.h +5 -0
@@ -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__));
lib/librte_eal/linuxapp/eal/eal.c +39 -5
71 lines not on this page · raw message
Signature · 1 line
1.8.1.4
PATCH v3 2/9 rte_tailq: change rte_dummy to rte_tailq_entry, add data pointer
In reply to a message not in the archive--- 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(-)
app/test/test_tailq.c +17 -16
@@ -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 inttest_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" );
lib/librte_eal/common/eal_common_tailqs.c +1 -1
@@ -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"),
lib/librte_eal/common/include/rte_tailq.h +5 -4
@@ -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 */ };/**
Signature · 1 line
1.8.1.4
PATCH v3 3/9 rte_ring: make ring tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_eal/linuxapp/eal/eal_ivshmem.c +15 -2
@@ -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);
lib/librte_ring/Makefile +2 -2
@@ -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
lib/librte_ring/rte_ring.c +25 -8
@@ -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; }
lib/librte_ring/rte_ring.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH v3 4/9 rte_hash: make rte_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_hash.c | 61 +++++++++++++++++++++++++++++++++++++++------- lib/librte_hash/rte_hash.h | 2 -- 2 files changed, 52 insertions(+), 11 deletions(-)
lib/librte_hash/rte_hash.c +52 -9
@@ -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
lib/librte_hash/rte_hash.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH v3 5/9 rte_fbk_hash: make rte_fbk_hash tailq fully local
In reply to a message not in the archive--- lib/librte_hash/rte_fbk_hash.c | 73 ++++++++++++++++++++++++++++++++++-------- lib/librte_hash/rte_fbk_hash.h | 3 -- 2 files changed, 59 insertions(+), 17 deletions(-)
lib/librte_hash/rte_fbk_hash.c +59 -14
@@ -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); }
lib/librte_hash/rte_fbk_hash.h +0 -3
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH v3 6/9 rte_mempool: make mempool tailq fully local
In reply to a message not in the archive--- 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(-)
lib/librte_mempool/Makefile +2 -1
@@ -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
lib/librte_mempool/rte_mempool.c +28 -9
@@ -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 );
lib/librte_mempool/rte_mempool.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH v3 7/9 rte_lpm: make lpm tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm.c | 65 ++++++++++++++++++++++++++++++++++++++++-------- lib/librte_lpm/rte_lpm.h | 2 -- 2 files changed, 54 insertions(+), 13 deletions(-)
lib/librte_lpm/rte_lpm.c +54 -11
@@ -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); }/*
lib/librte_lpm/rte_lpm.h +0 -2
@@ -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. */
Signature · 1 line
1.8.1.4
PATCH v3 8/9 rte_lpm6: make lpm6 tailq fully local
In reply to a message not in the archive--- lib/librte_lpm/rte_lpm6.c | 62 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 11 deletions(-)
lib/librte_lpm/rte_lpm6.c +51 -11
@@ -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); }/*
Signature · 1 line
1.8.1.4
PATCH v3 9/9 rte_acl: make acl tailq fully local
In reply to a message not in the archive--- lib/librte_acl/acl.h | 1 - lib/librte_acl/rte_acl.c | 74 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 60 insertions(+), 15 deletions(-)
lib/librte_acl/acl.h +0 -1
@@ -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;
lib/librte_acl/rte_acl.c +60 -14
148 lines not on this page · raw message
Signature · 1 line
1.8.1.4