[v15,1/6] memarea: introduce memarea library

Message ID 20230709130041.8736-2-fengchengwen@huawei.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers
Series introduce memarea library |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

fengchengwen July 9, 2023, 1 p.m. UTC
  The memarea library is an allocator of variable-size object which based
on a memory region.

This patch provides rte_memarea_create() and rte_memarea_destroy() API.

Signed-off-by: Chengwen Feng <fengchengwen@huawei.com>
Reviewed-by: Dongdong Liu <liudongdong3@huawei.com>
Acked-by: Morten Brørup <mb@smartsharesystems.com>
---
 MAINTAINERS                            |   5 +
 doc/api/doxy-api-index.md              |   3 +-
 doc/api/doxy-api.conf.in               |   1 +
 doc/guides/prog_guide/index.rst        |   1 +
 doc/guides/prog_guide/memarea_lib.rst  |  48 ++++++
 doc/guides/rel_notes/release_23_07.rst |   6 +
 lib/memarea/memarea_private.h          |  86 ++++++++++
 lib/memarea/meson.build                |  10 ++
 lib/memarea/rte_memarea.c              | 215 +++++++++++++++++++++++++
 lib/memarea/rte_memarea.h              | 137 ++++++++++++++++
 lib/memarea/version.map                |  12 ++
 lib/meson.build                        |   1 +
 12 files changed, 524 insertions(+), 1 deletion(-)
 create mode 100644 doc/guides/prog_guide/memarea_lib.rst
 create mode 100644 lib/memarea/memarea_private.h
 create mode 100644 lib/memarea/meson.build
 create mode 100644 lib/memarea/rte_memarea.c
 create mode 100644 lib/memarea/rte_memarea.h
 create mode 100644 lib/memarea/version.map
  

Comments

Stephen Hemminger July 9, 2023, 7:46 p.m. UTC | #1
On Sun, 9 Jul 2023 13:00:36 +0000
Chengwen Feng <fengchengwen@huawei.com> wrote:

> +struct rte_memarea_param {
> +	char name[RTE_MEMAREA_NAMESIZE]; /**< Name of memarea. */
> +	enum rte_memarea_source source;  /**< Memory source of memarea. */
> +	enum rte_memarea_algorithm alg;  /**< Memory management algorithm. */
> +	/** Total size (bytes) of memarea, it should not be less be 1024. */
> +	size_t total_sz;
> +	/** Indicates whether the memarea API should be MT-safe. */
> +	uint32_t mt_safe : 1;
> +	union {
> +		/** The initialization parameters if the source is set to be
> +		 * RTE_MEMAREA_SOURCE_HEAP.
> +		 */
> +		struct {
> +			/** Socket from which to apply for memarea's memory. */
> +			int socket_id;
> +		} heap;
> +		/** The initialization parameters if the source is set to be
> +		 * RTE_MEMAREA_SOURCE_MEMAREA.
> +		 */
> +		struct {
> +			/** Source memarea which to apply for this memarea's
> +			 * memory from.
> +			 */
> +			struct rte_memarea *src;
> +		} ma;
> +	};
> +};

FYI - since this data structure has holes in it. Given the current API you can
not assume that those holes are zero and try to reuse them later.

One alternative would to put in explicit reserved fields and check for zero
if you want to add more bits later.
  

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 1c3be16a91..93de0876f1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1612,6 +1612,11 @@  F: app/test/test_lpm*
 F: app/test/test_func_reentrancy.c
 F: app/test/test_xmmt_ops.h
 
+Memarea - EXPERIMENTAL
+M: Chengwen Feng <fengchengwen@huawei.com>
+F: lib/memarea
+F: doc/guides/prog_guide/memarea_lib.rst
+
 Membership - EXPERIMENTAL
 M: Yipeng Wang <yipeng1.wang@intel.com>
 M: Sameh Gobriel <sameh.gobriel@intel.com>
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 3bc8778981..5c32913f92 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -65,7 +65,8 @@  The public API headers are grouped by topics:
   [memzone](@ref rte_memzone.h),
   [mempool](@ref rte_mempool.h),
   [malloc](@ref rte_malloc.h),
-  [memcpy](@ref rte_memcpy.h)
+  [memcpy](@ref rte_memcpy.h),
+  [memarea](@ref rte_memarea.h)
 
 - **timers**:
   [cycles](@ref rte_cycles.h),
diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
index 1a4210b948..1f35d8483e 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -54,6 +54,7 @@  INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/lib/latencystats \
                           @TOPDIR@/lib/lpm \
                           @TOPDIR@/lib/mbuf \
+                          @TOPDIR@/lib/memarea \
                           @TOPDIR@/lib/member \
                           @TOPDIR@/lib/mempool \
                           @TOPDIR@/lib/meter \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index d89cd3edb6..aa8eebe256 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -38,6 +38,7 @@  Programmer's Guide
     hash_lib
     toeplitz_hash_lib
     efd_lib
+    memarea_lib
     member_lib
     lpm_lib
     lpm6_lib
diff --git a/doc/guides/prog_guide/memarea_lib.rst b/doc/guides/prog_guide/memarea_lib.rst
new file mode 100644
index 0000000000..bf19090294
--- /dev/null
+++ b/doc/guides/prog_guide/memarea_lib.rst
@@ -0,0 +1,48 @@ 
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2023 HiSilicon Limited
+
+Memarea Library
+===============
+
+Introduction
+------------
+
+The memarea library provides an allocator of variable-size objects, it is
+oriented towards the application layer, providing 'region-based memory
+management' function [1].
+
+The main features are as follows:
+
+* The memory region can be initialized from the following memory sources:
+
+  - HEAP: e.g. invoke ``rte_malloc_socket``.
+
+  - LIBC: e.g. invoke posix_memalign.
+
+  - Another memarea: it can be allocated from another memarea.
+
+* It supports MT-safe as long as it's specified at creation time.
+
+* The address returned by the allocator is align to 8B.
+
+Library API Overview
+--------------------
+
+The ``rte_memarea_create()`` function is used to create a memarea, the function
+returns the pointer to the created memarea or ``NULL`` if the creation failed.
+
+The ``rte_memarea_destroy()`` function is used to destroy a memarea.
+
+Debug Mode
+----------
+
+In debug mode, cookies are added at the beginning and end of objects, it will
+help debugging buffer overflows.
+
+Debug mode is disabled by default, but can be enabled by setting
+``RTE_LIBRTE_MEMAREA_DEBUG`` in ``config/rte_config.h``.
+
+Reference
+---------
+
+[1] https://en.wikipedia.org/wiki/Region-based_memory_management
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index dcfd692425..ccef40e8cb 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -206,6 +206,12 @@  New Features
 
   See the :doc:`../tools/dmaperf` for more details.
 
+* **Added memarea library.**
+
+  The memarea library is an allocator of variable-size objects, it is oriented
+  towards the application layer, providing 'region-based memory management'
+  function.
+
 
 Removed Items
 -------------
diff --git a/lib/memarea/memarea_private.h b/lib/memarea/memarea_private.h
new file mode 100644
index 0000000000..61dc518777
--- /dev/null
+++ b/lib/memarea/memarea_private.h
@@ -0,0 +1,86 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 HiSilicon Limited
+ */
+
+#ifndef MEMAREA_PRIVATE_H
+#define MEMAREA_PRIVATE_H
+
+#include <rte_memarea.h>
+
+#define MEMAREA_MINIMUM_TOTAL_SIZE	1024
+
+#define MEMAREA_OBJECT_SIZE_ALIGN	8
+
+#define MEMAREA_OBJECT_HEADER_AVAILABLE_COOKIE	0xbeef1234beef1234ULL
+#define MEMAREA_OBJECT_HEADER_ALLOCATED_COOKIE	0x12345678abcdef12ULL
+#define MEMAREA_OBJECT_TRAILER_COOKIE		0xabcd1234abcd5678ULL
+
+#define MEMAREA_OBJECT_IS_ALLOCATED(hdr)	(TAILQ_NEXT((hdr), avail_next) == (void *)-1)
+#define MEMAREA_OBJECT_MARK_ALLOCATED(hdr)	(TAILQ_NEXT((hdr), avail_next) = (void *)-1)
+
+#ifdef RTE_LIBRTE_MEMAREA_DEBUG
+#define MEMAREA_OBJECT_GET_SIZE(hdr) \
+		((uintptr_t)TAILQ_NEXT((hdr), obj_next) - (uintptr_t)(hdr) - \
+		 sizeof(struct memarea_objhdr) - sizeof(struct memarea_objtlr))
+#else
+#define MEMAREA_OBJECT_GET_SIZE(hdr) \
+		((uintptr_t)TAILQ_NEXT((hdr), obj_next) - (uintptr_t)(hdr) - \
+		 sizeof(struct memarea_objhdr))
+#endif
+
+struct memarea_objhdr {
+	/** The obj_next will form obj_lsit. */
+	TAILQ_ENTRY(memarea_objhdr) obj_next;
+	/** If the object is available, the avail_next will link in avail_list.
+	 * If the object has been allocated, the avail_next.tqe_next is -1.
+	 */
+	TAILQ_ENTRY(memarea_objhdr) avail_next;
+#ifdef RTE_LIBRTE_MEMAREA_DEBUG
+	uint64_t                    cookie; /**< Debug cookie */
+#endif
+};
+
+#ifdef RTE_LIBRTE_MEMAREA_DEBUG
+struct memarea_objtlr {
+	uint64_t cookie; /**< Debug cookie */
+};
+#endif
+
+TAILQ_HEAD(memarea_objhdr_list, memarea_objhdr);
+
+struct rte_memarea {
+	struct rte_memarea_param   init;
+	rte_spinlock_t             lock;
+	void                      *area_base;
+	struct memarea_objhdr     *guard_hdr;
+	/** The obj_list is an address ascending ordered linked list:
+	 *             ----------------------               --------------
+	 *             |      object-1      |               |  object-1  |
+	 * obj_list -> |~~~~~~~~~~~~~~~~~~~~|  data-region  |~~~~~~~~~~~~|
+	 *        ---> | tailq | hdr-cookie |               | tlr-cookie |
+	 *        |    ----------------------               --------------
+	 *        |
+	 *        |    ----------------------               --------------
+	 *        |    |      object-2      |               |  object-2  |
+	 *        ---> |~~~~~~~~~~~~~~~~~~~~|  data-region  |~~~~~~~~~~~~|
+	 *        ---> | tailq | hdr-cookie |               | tlr-cookie |
+	 *        |     ----------------------               --------------
+	 *        ...
+	 *        ...  more objects.
+	 *        ...
+	 *        |    ----------------------
+	 *        |    |    object-guard    |
+	 *        ---> |~~~~~~~~~~~~~~~~~~~~|
+	 *             | tailq | hdr-cookie |
+	 *             ----------------------
+	 * Note: the last object is the guard object, which has no data-region
+	 *       and no tailer cookie.
+	 **/
+	struct memarea_objhdr_list obj_list;
+	/** The avail_list is an unordered linked list. This list will hold the
+	 * objects which are available(means can be used to allocate).
+	 */
+	struct memarea_objhdr_list avail_list;
+} __rte_cache_aligned;
+
+#endif /* MEMAREA_PRIVATE_H */
diff --git a/lib/memarea/meson.build b/lib/memarea/meson.build
new file mode 100644
index 0000000000..5d2632a38e
--- /dev/null
+++ b/lib/memarea/meson.build
@@ -0,0 +1,10 @@ 
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 HiSilicon Limited
+
+sources = files(
+        'rte_memarea.c',
+)
+headers = files(
+        'rte_memarea.h',
+)
+deps += []
diff --git a/lib/memarea/rte_memarea.c b/lib/memarea/rte_memarea.c
new file mode 100644
index 0000000000..70ac08a572
--- /dev/null
+++ b/lib/memarea/rte_memarea.c
@@ -0,0 +1,215 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 HiSilicon Limited
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rte_common.h>
+#include <rte_errno.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_spinlock.h>
+
+#include "rte_memarea.h"
+#include "memarea_private.h"
+
+RTE_LOG_REGISTER_DEFAULT(rte_memarea_logtype, INFO);
+#define RTE_MEMAREA_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, rte_memarea_logtype, \
+		"MEMAREA: %s(): " fmt "\n", __func__, ## args)
+
+static int
+memarea_check_param(const struct rte_memarea_param *init)
+{
+	size_t len;
+
+	if (init == NULL) {
+		RTE_MEMAREA_LOG(ERR, "init param is NULL!");
+		return -EINVAL;
+	}
+
+	len = strnlen(init->name, RTE_MEMAREA_NAMESIZE);
+	if (len == 0 || len >= RTE_MEMAREA_NAMESIZE) {
+		RTE_MEMAREA_LOG(ERR, "name size: %zu invalid!", len);
+		return -EINVAL;
+	}
+
+	if (init->source != RTE_MEMAREA_SOURCE_HEAP &&
+	    init->source != RTE_MEMAREA_SOURCE_LIBC &&
+	    init->source != RTE_MEMAREA_SOURCE_MEMAREA) {
+		RTE_MEMAREA_LOG(ERR, "%s source: %d not supported!",
+			init->name, init->source);
+		return -EINVAL;
+	}
+
+	if (init->total_sz < MEMAREA_MINIMUM_TOTAL_SIZE) {
+		RTE_MEMAREA_LOG(ERR, "%s total-size: %zu too small!",
+			init->name, init->total_sz);
+		return -EINVAL;
+	}
+
+	if (init->source == RTE_MEMAREA_SOURCE_MEMAREA && init->ma.src == NULL) {
+		RTE_MEMAREA_LOG(ERR, "%s source memarea is NULL!", init->name);
+		return -EINVAL;
+	}
+
+	if (init->alg != RTE_MEMAREA_ALGORITHM_NEXTFIT) {
+		RTE_MEMAREA_LOG(ERR, "%s algorithm: %d not supported!",
+			init->name, init->alg);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void *
+memarea_alloc_from_libc(size_t size)
+{
+#ifdef RTE_EXEC_ENV_WINDOWS
+	return _aligned_malloc(size, RTE_CACHE_LINE_SIZE);
+#else
+	void *ptr = NULL;
+	int ret;
+	ret = posix_memalign(&ptr, RTE_CACHE_LINE_SIZE, size);
+	if (ret != 0)
+		return NULL;
+	return ptr;
+ #endif
+}
+
+static void *
+memarea_alloc_area(const struct rte_memarea_param *init)
+{
+	void *ptr = NULL;
+
+	if (init->source == RTE_MEMAREA_SOURCE_HEAP)
+		ptr = rte_malloc_socket(NULL, init->total_sz, RTE_CACHE_LINE_SIZE,
+					init->heap.socket_id);
+	else if (init->source == RTE_MEMAREA_SOURCE_LIBC)
+		ptr = memarea_alloc_from_libc(init->total_sz);
+
+	return ptr;
+}
+
+static void
+memarea_free_area(const struct rte_memarea_param *init, void *ptr)
+{
+	if (init->source == RTE_MEMAREA_SOURCE_HEAP)
+		rte_free(ptr);
+	else if (init->source == RTE_MEMAREA_SOURCE_LIBC)
+		free(ptr);
+}
+
+/**
+ * Set cookie.
+ *
+ * @param status
+ *   - 0: object is set to be available, but don't set tailer cookie.
+ *   - 1: object is set to be allocated, but don't set tailer cookie.
+ *   - 2: object is new split, the header cookie will set to be available,
+ *        the tailer cookie of the previous object will be set.
+ *   - 3: object is new split, the header cookie will set to be allocated,
+ *        the tailer cookie of the previous object will be set.
+ *   - 4: object is to be merged, it will no longer exist. the header cookie
+ *        is cleared and the tailer cookie of the previous object is cleared.
+ */
+static inline void
+memarea_set_cookie(struct memarea_objhdr *hdr, int status)
+{
+#ifdef RTE_LIBRTE_MEMAREA_DEBUG
+	struct memarea_objtlr *tlr;
+
+	if (status == 0) {
+		hdr->cookie = MEMAREA_OBJECT_HEADER_AVAILABLE_COOKIE;
+	} else if (status == 1) {
+		hdr->cookie = MEMAREA_OBJECT_HEADER_ALLOCATED_COOKIE;
+	} else if (status == 2) {
+		hdr->cookie = MEMAREA_OBJECT_HEADER_AVAILABLE_COOKIE;
+		tlr = RTE_PTR_SUB(hdr, sizeof(struct memarea_objtlr));
+		tlr->cookie = MEMAREA_OBJECT_TRAILER_COOKIE;
+	} else if (status == 3) {
+		hdr->cookie = MEMAREA_OBJECT_HEADER_ALLOCATED_COOKIE;
+		tlr = RTE_PTR_SUB(hdr, sizeof(struct memarea_objtlr));
+		tlr->cookie = MEMAREA_OBJECT_TRAILER_COOKIE;
+	} else if (status == 4) {
+		hdr->cookie = 0;
+		tlr = RTE_PTR_SUB(hdr, sizeof(struct memarea_objtlr));
+		tlr->cookie = 0;
+	}
+#else
+	RTE_SET_USED(hdr);
+	RTE_SET_USED(status);
+#endif
+}
+
+struct rte_memarea *
+rte_memarea_create(const struct rte_memarea_param *init)
+{
+	struct memarea_objhdr *hdr, *guard_hdr;
+	struct rte_memarea *ma;
+	size_t align_sz;
+	void *ptr;
+	int ret;
+
+	/** 1st: check parameter valid. */
+	ret = memarea_check_param(init);
+	if (ret != 0) {
+		rte_errno = -ret;
+		return NULL;
+	}
+
+	/** 2nd: alloc the memarea data region. */
+	ptr = memarea_alloc_area(init);
+	if (ptr == NULL) {
+		RTE_MEMAREA_LOG(ERR, "%s alloc memory area fail!", init->name);
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	/** 3rd: alloc the memare management struct. */
+	ma = rte_zmalloc(NULL, sizeof(struct rte_memarea), RTE_CACHE_LINE_SIZE);
+	if (ma == NULL) {
+		memarea_free_area(init, ptr);
+		RTE_MEMAREA_LOG(ERR, "%s alloc management object fail!", init->name);
+		rte_errno = ENOMEM;
+		return NULL;
+	}
+
+	/** 4th: backup init parameter, initialize the lock and list. */
+	ma->init = *init;
+	rte_spinlock_init(&ma->lock);
+	TAILQ_INIT(&ma->obj_list);
+	TAILQ_INIT(&ma->avail_list);
+
+	/** 5th: initialize the first object and last guard object. */
+	hdr = ptr;
+	align_sz = RTE_ALIGN_FLOOR(init->total_sz, MEMAREA_OBJECT_SIZE_ALIGN);
+	guard_hdr = RTE_PTR_ADD(ptr, align_sz - sizeof(struct memarea_objhdr));
+	ma->area_base = ptr;
+	ma->guard_hdr = guard_hdr;
+
+	/** 5.1: hook the first object to both obj_list and avail_list. */
+	TAILQ_INSERT_TAIL(&ma->obj_list, hdr, obj_next);
+	TAILQ_INSERT_TAIL(&ma->avail_list, hdr, avail_next);
+	memarea_set_cookie(hdr, 0);
+
+	/** 5.2: hook the guard object to only obj_list. */
+	memset(guard_hdr, 0, sizeof(struct memarea_objhdr));
+	TAILQ_INSERT_AFTER(&ma->obj_list, hdr, guard_hdr, obj_next);
+	MEMAREA_OBJECT_MARK_ALLOCATED(guard_hdr);
+	memarea_set_cookie(guard_hdr, 3);
+
+	return ma;
+}
+
+void
+rte_memarea_destroy(struct rte_memarea *ma)
+{
+	if (ma == NULL) {
+		rte_errno = EINVAL;
+		return;
+	}
+	memarea_free_area(&ma->init, ma->area_base);
+	rte_free(ma);
+}
diff --git a/lib/memarea/rte_memarea.h b/lib/memarea/rte_memarea.h
new file mode 100644
index 0000000000..e2921ad83b
--- /dev/null
+++ b/lib/memarea/rte_memarea.h
@@ -0,0 +1,137 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 HiSilicon Limited
+ */
+
+#ifndef RTE_MEMAREA_H
+#define RTE_MEMAREA_H
+
+/**
+ * @file
+ * RTE Memarea.
+ *
+ * The memarea is an allocator of variable-size object which based on a memory
+ * region. It has the following features:
+ *
+ * - The memory region can be initialized from the following memory sources:
+ *   1. HEAP: e.g. invoke rte_malloc_xxx family.
+ *   2. LIBC: e.g. invoke posix_memalign.
+ *   3. Another memarea: it can be allocated from another memarea.
+ *
+ * - It supports MT-safe as long as it's specified at creation time. If not
+ *   specified, all the functions of the memarea API are lock-free, and assume
+ *   to not be invoked in parallel on different logical cores to work on the
+ *   same memarea.
+ *
+ * - The address returned by the allocator is align to 8B.
+ *
+ * @note The current implementation is a minimum set and does not support
+ * multiple-process.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_MEMAREA_NAMESIZE	64
+
+/**
+ * Memarea memory source.
+ */
+enum rte_memarea_source {
+	/** Memory source comes from rte_malloc_xxx memory. */
+	RTE_MEMAREA_SOURCE_HEAP,
+	/** Memory source comes from libc. */
+	RTE_MEMAREA_SOURCE_LIBC,
+	/** Memory source comes from another memarea. */
+	RTE_MEMAREA_SOURCE_MEMAREA,
+};
+
+/**
+ * Memarea memory management algorithm.
+ */
+enum rte_memarea_algorithm {
+	/** The default management algorithm is a variant of the next fit
+	 * algorithm. It uses a free-list to apply for memory and uses an
+	 * object-list in ascending order of address to support merging
+	 * upon free.
+	 */
+	RTE_MEMAREA_ALGORITHM_NEXTFIT,
+};
+
+struct rte_memarea;
+
+/**
+ * Memarea creation parameters.
+ */
+struct rte_memarea_param {
+	char name[RTE_MEMAREA_NAMESIZE]; /**< Name of memarea. */
+	enum rte_memarea_source source;  /**< Memory source of memarea. */
+	enum rte_memarea_algorithm alg;  /**< Memory management algorithm. */
+	/** Total size (bytes) of memarea, it should not be less be 1024. */
+	size_t total_sz;
+	/** Indicates whether the memarea API should be MT-safe. */
+	uint32_t mt_safe : 1;
+	union {
+		/** The initialization parameters if the source is set to be
+		 * RTE_MEMAREA_SOURCE_HEAP.
+		 */
+		struct {
+			/** Socket from which to apply for memarea's memory. */
+			int socket_id;
+		} heap;
+		/** The initialization parameters if the source is set to be
+		 * RTE_MEMAREA_SOURCE_MEMAREA.
+		 */
+		struct {
+			/** Source memarea which to apply for this memarea's
+			 * memory from.
+			 */
+			struct rte_memarea *src;
+		} ma;
+	};
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create memarea.
+ *
+ * Create one new memarea.
+ *
+ * @param init
+ *   The init parameter of memarea.
+ *
+ * @return
+ *   Non-NULL on success. Otherwise NULL is returned (the rte_errno is set).
+ */
+__rte_experimental
+struct rte_memarea *rte_memarea_create(const struct rte_memarea_param *init);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy memarea.
+ *
+ * Destroy the memarea.
+ *
+ * @param ma
+ *   The pointer of memarea.
+ *
+ * @note The rte_errno is set if destroy failed.
+ */
+__rte_experimental
+void rte_memarea_destroy(struct rte_memarea *ma);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RTE_MEMAREA_H */
diff --git a/lib/memarea/version.map b/lib/memarea/version.map
new file mode 100644
index 0000000000..f36a04d7cf
--- /dev/null
+++ b/lib/memarea/version.map
@@ -0,0 +1,12 @@ 
+EXPERIMENTAL {
+	global:
+
+	rte_memarea_create;
+	rte_memarea_destroy;
+
+	local: *;
+};
+
+INTERNAL {
+	local: *;
+};
diff --git a/lib/meson.build b/lib/meson.build
index fac2f52cad..36821e7007 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -42,6 +42,7 @@  libraries = [
         'kni',
         'latencystats',
         'lpm',
+        'memarea',
         'member',
         'pcapng',
         'power',