From: Shani Peretz <shperetz@nvidia.com>
To: <dev@dpdk.org>
Cc: <rasland@nvidia.com>, Shani Peretz <shperetz@nvidia.com>,
Bing Zhao <bingz@nvidia.com>,
Dariusz Sosnowski <dsosnowski@nvidia.com>,
"Viacheslav Ovsiienko" <viacheslavo@nvidia.com>,
Ori Kam <orika@nvidia.com>, Suanming Mou <suanmingm@nvidia.com>,
Matan Azrad <matan@nvidia.com>
Subject: [PATCH 2/2] net/mlx5: added a bitmap that tracks ipool allocs and frees
Date: Mon, 24 Mar 2025 10:18:24 +0200 [thread overview]
Message-ID: <20250324081825.231395-3-shperetz@nvidia.com> (raw)
In-Reply-To: <20250324081825.231395-1-shperetz@nvidia.com>
The bitmap goal is to prevent double allocations and deallocations in
per core cache mode.
This validation occurs only in debug mode, ensuring it doesn't
impact performance.
Signed-off-by: Shani Peretz <shperetz@nvidia.com>
Acked-by: Bing Zhao <bingz@nvidia.com>
---
drivers/net/mlx5/mlx5_utils.c | 103 +++++++++++++++++++++++++++++++++-
drivers/net/mlx5/mlx5_utils.h | 12 ++++
2 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/drivers/net/mlx5/mlx5_utils.c b/drivers/net/mlx5/mlx5_utils.c
index b92ac44540..f8cd7bc043 100644
--- a/drivers/net/mlx5/mlx5_utils.c
+++ b/drivers/net/mlx5/mlx5_utils.c
@@ -121,6 +121,9 @@ mlx5_ipool_create(struct mlx5_indexed_pool_config *cfg)
pool->free_list = TRUNK_INVALID;
rte_spinlock_init(&pool->lcore_lock);
+#ifdef POOL_DEBUG
+ rte_spinlock_init(&pool->cache_validator.lock);
+#endif
DRV_LOG_IPOOL(INFO, "lcore id %d: pool %s: per core cache mode %s",
rte_lcore_id(), pool->cfg.type, pool->cfg.per_core_cache != 0 ? "on" : "off");
return pool;
@@ -229,6 +232,55 @@ mlx5_ipool_update_global_cache(struct mlx5_indexed_pool *pool, int cidx)
return lc;
}
+#ifdef POOL_DEBUG
+static void
+mlx5_ipool_grow_bmp(struct mlx5_indexed_pool *pool, uint32_t new_size)
+{
+ struct rte_bitmap *old_bmp = NULL;
+ void *old_bmp_mem = NULL;
+ uint32_t old_size = 0;
+ uint32_t i, bmp_mem_size;
+
+ if (pool->cache_validator.bmp_mem && pool->cache_validator.bmp) {
+ old_bmp = pool->cache_validator.bmp;
+ old_size = pool->cache_validator.bmp_size;
+ old_bmp_mem = pool->cache_validator.bmp_mem;
+ }
+
+ if (unlikely(new_size <= old_size))
+ return;
+
+ pool->cache_validator.bmp_size = new_size;
+ bmp_mem_size = rte_bitmap_get_memory_footprint(new_size);
+
+ pool->cache_validator.bmp_mem = pool->cfg.malloc(MLX5_MEM_ZERO, bmp_mem_size,
+ RTE_CACHE_LINE_SIZE,
+ rte_socket_id());
+ if (unlikely(!pool->cache_validator.bmp_mem)) {
+ DRV_LOG_IPOOL(ERR, "Unable to allocate memory for a new bitmap");
+ return;
+ }
+
+ pool->cache_validator.bmp = rte_bitmap_init_with_all_set(pool->cache_validator.bmp_size,
+ pool->cache_validator.bmp_mem,
+ bmp_mem_size);
+ if (unlikely(!pool->cache_validator.bmp)) {
+ DRV_LOG(ERR, "Unable to allocate memory for a new bitmap");
+ pool->cfg.free(pool->cache_validator.bmp_mem);
+ return;
+ }
+
+ if (old_bmp && old_bmp_mem) {
+ for (i = 0; i < old_size; i++) {
+ if (rte_bitmap_get(old_bmp, i) == 0)
+ rte_bitmap_clear(pool->cache_validator.bmp, i);
+ }
+ rte_bitmap_free(old_bmp);
+ pool->cfg.free(old_bmp_mem);
+ }
+}
+#endif
+
static uint32_t
mlx5_ipool_allocate_from_global(struct mlx5_indexed_pool *pool, int cidx)
{
@@ -413,6 +465,50 @@ mlx5_ipool_get_cache(struct mlx5_indexed_pool *pool, uint32_t idx)
return entry;
}
+#ifdef POOL_DEBUG
+static void
+mlx5_ipool_validate_malloc_cache(struct mlx5_indexed_pool *pool, uint32_t idx)
+{
+ rte_spinlock_lock(&pool->cache_validator.lock);
+ uint32_t entry_idx = idx - 1;
+ uint32_t allocated_size = pool->gc->n_trunk_valid *
+ mlx5_trunk_size_get(pool, pool->n_trunk_valid);
+
+ if (!pool->cache_validator.bmp)
+ mlx5_ipool_grow_bmp(pool, allocated_size);
+
+ if (pool->cache_validator.bmp_size < allocated_size)
+ mlx5_ipool_grow_bmp(pool, allocated_size);
+
+ if (rte_bitmap_get(pool->cache_validator.bmp, entry_idx) == 0) {
+ DRV_LOG_IPOOL(ERR, "lcore id %d: pool %s: detected double malloc idx: %d",
+ rte_lcore_id(), pool->cfg.type, idx);
+ MLX5_ASSERT(0);
+ }
+ rte_bitmap_clear(pool->cache_validator.bmp, entry_idx);
+ rte_spinlock_unlock(&pool->cache_validator.lock);
+}
+
+static void
+mlx5_ipool_validate_free_cache(struct mlx5_indexed_pool *pool, uint32_t idx)
+{
+ rte_spinlock_lock(&pool->cache_validator.lock);
+ uint32_t entry_idx = idx - 1;
+
+ if (!pool->gc || !pool->cache_validator.bmp) {
+ rte_spinlock_unlock(&pool->cache_validator.lock);
+ return;
+ }
+
+ if (rte_bitmap_get(pool->cache_validator.bmp, entry_idx) != 0) {
+ DRV_LOG_IPOOL(ERR, "lcore id %d: pool %s: detected double free of index %d",
+ rte_lcore_id(), pool->cfg.type, idx);
+ MLX5_ASSERT(0);
+ }
+ rte_bitmap_set(pool->cache_validator.bmp, entry_idx);
+ rte_spinlock_unlock(&pool->cache_validator.lock);
+}
+#endif
static void *
_mlx5_ipool_malloc_cache(struct mlx5_indexed_pool *pool, int cidx,
@@ -455,11 +551,11 @@ mlx5_ipool_malloc_cache(struct mlx5_indexed_pool *pool, uint32_t *idx)
rte_spinlock_unlock(&pool->lcore_lock);
#ifdef POOL_DEBUG
++pool->n_entry;
+ mlx5_ipool_validate_malloc_cache(pool, *idx);
DRV_LOG_IPOOL(DEBUG, "lcore id %d: pool %s: allocated entry %d lcore %d, "
"current cache size %d, total allocated entries %d.", rte_lcore_id(),
pool->cfg.type, *idx, cidx, pool->cache[cidx]->len, pool->n_entry);
#endif
-
return entry;
}
@@ -471,6 +567,11 @@ _mlx5_ipool_free_cache(struct mlx5_indexed_pool *pool, int cidx, uint32_t idx)
uint32_t reclaim_num = 0;
MLX5_ASSERT(idx);
+
+#ifdef POOL_DEBUG
+ mlx5_ipool_validate_free_cache(pool, idx);
+#endif
+
/*
* When index was allocated on core A but freed on core B. In this
* case check if local cache on core B was allocated before.
diff --git a/drivers/net/mlx5/mlx5_utils.h b/drivers/net/mlx5/mlx5_utils.h
index 68dcda5c4d..c65839c5d9 100644
--- a/drivers/net/mlx5/mlx5_utils.h
+++ b/drivers/net/mlx5/mlx5_utils.h
@@ -259,6 +259,15 @@ struct mlx5_ipool_per_lcore {
uint32_t idx[]; /**< Cache objects. */
};
+#ifdef POOL_DEBUG
+struct mlx5_ipool_cache_validation {
+ rte_spinlock_t lock;
+ uint32_t bmp_size;
+ struct rte_bitmap *bmp;
+ void *bmp_mem;
+};
+#endif
+
struct mlx5_indexed_pool {
struct mlx5_indexed_pool_config cfg; /* Indexed pool configuration. */
rte_spinlock_t rsz_lock; /* Pool lock for multiple thread usage. */
@@ -279,6 +288,9 @@ struct mlx5_indexed_pool {
struct rte_bitmap *ibmp;
void *bmp_mem;
/* Allocate objects bitmap. Use during flush. */
+#ifdef POOL_DEBUG
+ struct mlx5_ipool_cache_validation cache_validator;
+#endif
};
};
#ifdef POOL_DEBUG
--
2.34.1
prev parent reply other threads:[~2025-03-24 8:19 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-24 8:18 [PATCH 0/2] add debug capabilities to ipool Shani Peretz
2025-03-24 8:18 ` [PATCH 1/2] net/mlx5: add ipool debug capabilities Shani Peretz
2025-03-24 8:18 ` Shani Peretz [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250324081825.231395-3-shperetz@nvidia.com \
--to=shperetz@nvidia.com \
--cc=bingz@nvidia.com \
--cc=dev@dpdk.org \
--cc=dsosnowski@nvidia.com \
--cc=matan@nvidia.com \
--cc=orika@nvidia.com \
--cc=rasland@nvidia.com \
--cc=suanmingm@nvidia.com \
--cc=viacheslavo@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).