+ return l + r;
+}
+
+/** Maximum size of string for naming the hlist table. */
+#define MLX5_HLIST_NAMESIZE 32
+
+/**
+ * Structure of the entry in the hash list, user should define its own struct
+ * that contains this in order to store the data. The 'key' is 64-bits right
+ * now and its user's responsibility to guarantee there is no collision.
+ */
+struct mlx5_hlist_entry {
+ LIST_ENTRY(mlx5_hlist_entry) next; /* entry pointers in the list. */
+ uint64_t key; /* user defined 'key', could be the hash signature. */
+};
+
+/** Structure for hash head. */
+LIST_HEAD(mlx5_hlist_head, mlx5_hlist_entry);
+
+/** Type of function that is used to handle the data before freeing. */
+typedef void (*mlx5_hlist_destroy_callback_fn)(void *p, void *ctx);
+
+/**
+ * Type of function for user defined matching.
+ *
+ * @param entry
+ * The entry in the list.
+ * @param ctx
+ * The pointer to new entry context.
+ *
+ * @return
+ * 0 if matching, -1 otherwise.
+ */
+typedef int (*mlx5_hlist_match_callback_fn)(struct mlx5_hlist_entry *entry,
+ void *ctx);
+
+/** hash list table structure */
+struct mlx5_hlist {
+ char name[MLX5_HLIST_NAMESIZE]; /**< Name of the hash list. */
+ /**< number of heads, need to be power of 2. */
+ uint32_t table_sz;
+ /**< mask to get the index of the list heads. */
+ uint32_t mask;
+ struct mlx5_hlist_head heads[]; /**< list head arrays. */
+};
+
+/**
+ * Create a hash list table, the user can specify the list heads array size
+ * of the table, now the size should be a power of 2 in order to get better
+ * distribution for the entries. Each entry is a part of the whole data element
+ * and the caller should be responsible for the data element's allocation and
+ * cleanup / free. Key of each entry will be calculated with CRC in order to
+ * generate a little fairer distribution.
+ *
+ * @param name
+ * Name of the hash list(optional).
+ * @param size
+ * Heads array size of the hash list.
+ *
+ * @return
+ * Pointer of the hash list table created, NULL on failure.
+ */
+struct mlx5_hlist *mlx5_hlist_create(const char *name, uint32_t size);
+
+/**
+ * Search an entry matching the key.
+ *
+ * @param h
+ * Pointer to the hast list table.
+ * @param key
+ * Key for the searching entry.
+ *
+ * @return
+ * Pointer of the hlist entry if found, NULL otherwise.
+ */
+struct mlx5_hlist_entry *mlx5_hlist_lookup(struct mlx5_hlist *h, uint64_t key);
+
+/**
+ * Insert an entry to the hash list table, the entry is only part of whole data
+ * element and a 64B key is used for matching. User should construct the key or
+ * give a calculated hash signature and guarantee there is no collision.
+ *
+ * @param h
+ * Pointer to the hast list table.
+ * @param entry
+ * Entry to be inserted into the hash list table.
+ *
+ * @return
+ * - zero for success.
+ * - -EEXIST if the entry is already inserted.
+ */
+int mlx5_hlist_insert(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry);
+
+/**
+ * Extended routine to search an entry matching the context with
+ * user defined match function.
+ *
+ * @param h
+ * Pointer to the hast list table.
+ * @param key
+ * Key for the searching entry.
+ * @param cb
+ * Callback function to match the node with context.
+ * @param ctx
+ * Common context parameter used by callback function.
+ *
+ * @return
+ * Pointer of the hlist entry if found, NULL otherwise.
+ */
+struct mlx5_hlist_entry *mlx5_hlist_lookup_ex(struct mlx5_hlist *h,
+ uint64_t key,
+ mlx5_hlist_match_callback_fn cb,
+ void *ctx);
+
+/**
+ * Extended routine to insert an entry to the list with key collisions.
+ *
+ * For the list have key collision, the extra user defined match function
+ * allows node with same key will be inserted.
+ *
+ * @param h
+ * Pointer to the hast list table.
+ * @param entry
+ * Entry to be inserted into the hash list table.
+ * @param cb
+ * Callback function to match the node with context.
+ * @param ctx
+ * Common context parameter used by callback function.
+ *
+ * @return
+ * - zero for success.
+ * - -EEXIST if the entry is already inserted.
+ */
+int mlx5_hlist_insert_ex(struct mlx5_hlist *h, struct mlx5_hlist_entry *entry,
+ mlx5_hlist_match_callback_fn cb, void *ctx);
+
+/**
+ * Remove an entry from the hash list table. User should guarantee the validity
+ * of the entry.
+ *
+ * @param h
+ * Pointer to the hast list table. (not used)
+ * @param entry
+ * Entry to be removed from the hash list table.
+ */
+void mlx5_hlist_remove(struct mlx5_hlist *h __rte_unused,
+ struct mlx5_hlist_entry *entry);
+
+/**
+ * Destroy the hash list table, all the entries already inserted into the lists
+ * will be handled by the callback function provided by the user (including
+ * free if needed) before the table is freed.
+ *
+ * @param h
+ * Pointer to the hast list table.
+ * @param cb
+ * Callback function for each inserted entry when destroying the hash list.
+ * @param ctx
+ * Common context parameter used by callback function for each entry.
+ */
+void mlx5_hlist_destroy(struct mlx5_hlist *h,
+ mlx5_hlist_destroy_callback_fn cb, void *ctx);
+
+/**
+ * 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);
+
+/**
+ * This function allocates new empty Three-level table.
+ *
+ * @param type
+ * The l3t can set as word, double word, quad word or pointer with index.
+ *
+ * @return
+ * - Pointer to the allocated l3t.
+ * - NULL on error. Not enough memory, or invalid arguments.
+ */
+struct mlx5_l3t_tbl *mlx5_l3t_create(enum mlx5_l3t_type type);
+
+/**
+ * This function destroys Three-level table.
+ *
+ * @param tbl
+ * Pointer to the l3t.
+ */
+void mlx5_l3t_destroy(struct mlx5_l3t_tbl *tbl);
+
+/**
+ * This function gets the index entry from Three-level table.
+ *
+ * @param tbl
+ * Pointer to the l3t.
+ * @param idx
+ * Index to the entry.
+ * @param data
+ * Pointer to the memory which saves the entry data.
+ * When function call returns 0, data contains the entry data get from
+ * l3t.
+ * When function call returns -1, data is not modified.
+ *
+ * @return
+ * 0 if success, -1 on error.
+ */
+
+uint32_t mlx5_l3t_get_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx,
+ union mlx5_l3t_data *data);
+/**
+ * This function clears the index entry from Three-level table.
+ *
+ * @param tbl
+ * Pointer to the l3t.
+ * @param idx
+ * Index to the entry.
+ */
+void mlx5_l3t_clear_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx);
+
+/**
+ * This function gets the index entry from Three-level table.
+ *
+ * @param tbl
+ * Pointer to the l3t.
+ * @param idx
+ * Index to the entry.
+ * @param data
+ * Pointer to the memory which contains the entry data save to l3t.
+ *
+ * @return
+ * 0 if success, -1 on error.
+ */
+uint32_t mlx5_l3t_set_entry(struct mlx5_l3t_tbl *tbl, uint32_t idx,
+ union mlx5_l3t_data *data);
+
+/*
+ * 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. */ \