From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 8A4E142E2C;
	Sun,  9 Jul 2023 15:09:16 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id D2276410FA;
	Sun,  9 Jul 2023 15:08:55 +0200 (CEST)
Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255])
 by mails.dpdk.org (Postfix) with ESMTP id 0C1F9410FA
 for <dev@dpdk.org>; Sun,  9 Jul 2023 15:08:48 +0200 (CEST)
Received: from dggpeml100024.china.huawei.com (unknown [172.30.72.53])
 by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4QzS9q450lz1FDWW;
 Sun,  9 Jul 2023 21:08:15 +0800 (CST)
Received: from localhost.localdomain (10.50.163.32) by
 dggpeml100024.china.huawei.com (7.185.36.115) with Microsoft SMTP Server
 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id
 15.1.2507.27; Sun, 9 Jul 2023 21:08:46 +0800
From: Chengwen Feng <fengchengwen@huawei.com>
To: <thomas@monjalon.net>, <david.marchand@redhat.com>
CC: <dev@dpdk.org>, <mb@smartsharesystems.com>, <anatoly.burakov@intel.com>,
 <dmitry.kozliuk@gmail.com>, <jerinjacobk@gmail.com>, <hofors@lysator.liu.se>, 
 <stephen@networkplumber.org>
Subject: [PATCH v15 1/6] memarea: introduce memarea library
Date: Sun, 9 Jul 2023 13:00:36 +0000
Message-ID: <20230709130041.8736-2-fengchengwen@huawei.com>
X-Mailer: git-send-email 2.17.1
In-Reply-To: <20230709130041.8736-1-fengchengwen@huawei.com>
References: <20220721044648.6817-1-fengchengwen@huawei.com>
 <20230709130041.8736-1-fengchengwen@huawei.com>
MIME-Version: 1.0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 8bit
X-Originating-IP: [10.50.163.32]
X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To
 dggpeml100024.china.huawei.com (7.185.36.115)
X-CFilter-Loop: Reflected
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

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

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',
-- 
2.17.1