+/**
+ * This function allocates non-initialized memory entry from pool.
+ * In NUMA systems, the memory entry allocated resides on the same
+ * NUMA socket as the core that calls this function.
+ *
+ * Memory entry is allocated from memory trunk, no alignment.
+ *
+ * @param pool
+ * Pointer to indexed memory entry pool.
+ * No initialization required.
+ * @param[out] idx
+ * Pointer to memory to save allocated index.
+ * Memory index always positive value.
+ * @return
+ * - Pointer to the allocated memory entry.
+ * - NULL on error. Not enough memory, or invalid arguments.
+ */
+void *mlx5_ipool_malloc(struct mlx5_indexed_pool *pool, uint32_t *idx);
+
+/**
+ * This function allocates zero initialized memory entry from pool.
+ * In NUMA systems, the memory entry allocated resides on the same
+ * NUMA socket as the core that calls this function.
+ *
+ * Memory entry is allocated from memory trunk, no alignment.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ * No initialization required.
+ * @param[out] idx
+ * Pointer to memory to save allocated index.
+ * Memory index always positive value.
+ * @return
+ * - Pointer to the allocated memory entry .
+ * - NULL on error. Not enough memory, or invalid arguments.
+ */
+void *mlx5_ipool_zmalloc(struct mlx5_indexed_pool *pool, uint32_t *idx);
+
+/**
+ * This function frees indexed memory entry to pool.
+ * Caller has to make sure that the index is allocated from same pool.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ * @param idx
+ * Allocated memory entry index.
+ */
+void mlx5_ipool_free(struct mlx5_indexed_pool *pool, uint32_t idx);
+
+/**
+ * This function returns pointer of indexed memory entry from index.
+ * Caller has to make sure that the index is valid, and allocated
+ * from same pool.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ * @param idx
+ * Allocated memory index.
+ * @return
+ * - Pointer to indexed memory entry.
+ */
+void *mlx5_ipool_get(struct mlx5_indexed_pool *pool, uint32_t idx);
+
+/**
+ * This function creates indexed memory pool.
+ * Caller has to configure the configuration accordingly.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ * @param cfg
+ * Allocated memory index.
+ */
+struct mlx5_indexed_pool *
+mlx5_ipool_create(struct mlx5_indexed_pool_config *cfg);
+
+/**
+ * This function releases all resources of pool.
+ * Caller has to make sure that all indexes and memories allocated
+ * from this pool not referenced anymore.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ * @return
+ * - non-zero value on error.
+ * - 0 on success.
+ */
+int mlx5_ipool_destroy(struct mlx5_indexed_pool *pool);
+
+/**
+ * This function dumps debug info of pool.
+ *
+ * @param pool
+ * Pointer to indexed memory pool.
+ */
+void mlx5_ipool_dump(struct mlx5_indexed_pool *pool);
+
+/*
+ * Macros for linked list based on indexed memory.
+ * Example data structure:
+ * struct Foo {
+ * ILIST_ENTRY(uint16_t) next;
+ * ...
+ * }
+ *
+ */
+#define ILIST_ENTRY(type) \
+struct { \
+ type prev; /* Index of previous element. */ \
+ type next; /* Index of next element. */ \
+}
+
+#define ILIST_INSERT(pool, head, idx, elem, field) \
+ do { \
+ typeof(elem) peer; \
+ MLX5_ASSERT((elem) && (idx)); \
+ (elem)->field.next = *(head); \
+ (elem)->field.prev = 0; \
+ if (*(head)) { \
+ (peer) = mlx5_ipool_get(pool, *(head)); \
+ if (peer) \
+ (peer)->field.prev = (idx); \
+ } \
+ *(head) = (idx); \
+ } while (0)
+
+#define ILIST_REMOVE(pool, head, idx, elem, field) \
+ do { \
+ typeof(elem) peer; \
+ MLX5_ASSERT(elem); \
+ MLX5_ASSERT(head); \
+ if ((elem)->field.prev) { \
+ (peer) = mlx5_ipool_get \
+ (pool, (elem)->field.prev); \
+ if (peer) \
+ (peer)->field.next = (elem)->field.next;\
+ } \
+ if ((elem)->field.next) { \
+ (peer) = mlx5_ipool_get \
+ (pool, (elem)->field.next); \
+ if (peer) \
+ (peer)->field.prev = (elem)->field.prev;\
+ } \
+ if (*(head) == (idx)) \
+ *(head) = (elem)->field.next; \
+ } while (0)
+
+#define ILIST_FOREACH(pool, head, idx, elem, field) \
+ for ((idx) = (head), (elem) = \
+ (idx) ? mlx5_ipool_get(pool, (idx)) : NULL; (elem); \
+ idx = (elem)->field.next, (elem) = \
+ (idx) ? mlx5_ipool_get(pool, idx) : NULL)
+
+/* Single index list. */
+#define SILIST_ENTRY(type) \
+struct { \
+ type next; /* Index of next element. */ \
+}
+
+#define SILIST_INSERT(head, idx, elem, field) \
+ do { \
+ MLX5_ASSERT((elem) && (idx)); \
+ (elem)->field.next = *(head); \
+ *(head) = (idx); \
+ } while (0)
+
+#define SILIST_FOREACH(pool, head, idx, elem, field) \
+ for ((idx) = (head), (elem) = \
+ (idx) ? mlx5_ipool_get(pool, (idx)) : NULL; (elem); \
+ idx = (elem)->field.next, (elem) = \
+ (idx) ? mlx5_ipool_get(pool, idx) : NULL)
+