diff --git a/MAINTAINERS b/MAINTAINERS
index 4800f6884..aa40cc92b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1462,6 +1462,11 @@ F: examples/bpf/
 F: app/test/test_bpf.c
 F: doc/guides/prog_guide/bpf_lib.rst
 
+Graph - EXPERIMENTAL
+M: Jerin Jacob <jerinj@marvell.com>
+M: Kiran Kumar K <kirankumark@marvell.com>
+F: lib/librte_graph/
+
 
 Test Applications
 -----------------
diff --git a/config/common_base b/config/common_base
index c31175f9d..32f982136 100644
--- a/config/common_base
+++ b/config/common_base
@@ -1074,6 +1074,13 @@ CONFIG_RTE_LIBRTE_BPF_ELF=n
 #
 CONFIG_RTE_LIBRTE_IPSEC=y
 
+#
+# Compile librte_graph
+#
+CONFIG_RTE_LIBRTE_GRAPH=y
+CONFIG_RTE_GRAPH_BURST_SIZE=256
+CONFIG_RTE_LIBRTE_GRAPH_STATS=y
+
 #
 # Compile the test application
 #
diff --git a/config/rte_config.h b/config/rte_config.h
index d30786bc0..e9201fd46 100644
--- a/config/rte_config.h
+++ b/config/rte_config.h
@@ -98,6 +98,10 @@
 /* KNI defines */
 #define RTE_KNI_PREEMPT_DEFAULT 1
 
+/* rte_graph defines */
+#define RTE_GRAPH_BURST_SIZE 256
+#define RTE_LIBRTE_GRAPH_STATS 1
+
 /****** driver defines ********/
 
 /* QuickAssist device */
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index dff496be0..5cc50f750 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -159,6 +159,7 @@ The public API headers are grouped by topics:
   * [pipeline]         (@ref rte_pipeline.h)
     [port_in_action]   (@ref rte_port_in_action.h)
     [table_action]     (@ref rte_table_action.h)
+  * [graph]            (@ref rte_graph.h):
 
 - **basic**:
   [approx fraction]    (@ref rte_approx.h),
diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
index 65e8146be..e3b7f54f8 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -33,6 +33,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/lib/librte_eventdev \
                           @TOPDIR@/lib/librte_fib \
                           @TOPDIR@/lib/librte_flow_classify \
+                          @TOPDIR@/lib/librte_graph \
                           @TOPDIR@/lib/librte_gro \
                           @TOPDIR@/lib/librte_gso \
                           @TOPDIR@/lib/librte_hash \
diff --git a/lib/Makefile b/lib/Makefile
index 46b91ae1a..1f572b659 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -119,6 +119,9 @@ DEPDIRS-librte_telemetry := librte_eal librte_metrics librte_ethdev
 DIRS-$(CONFIG_RTE_LIBRTE_RCU) += librte_rcu
 DEPDIRS-librte_rcu := librte_eal
 
+DIRS-$(CONFIG_RTE_LIBRTE_GRAPH) += librte_graph
+DEPDIRS-librte_graph := librte_eal
+
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUX),y)
 DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni
 endif
diff --git a/lib/librte_graph/Makefile b/lib/librte_graph/Makefile
new file mode 100644
index 000000000..26fe514f3
--- /dev/null
+++ b/lib/librte_graph/Makefile
@@ -0,0 +1,22 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2020 Marvell International Ltd.
+#
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_graph.a
+
+CFLAGS += -O3 -DALLOW_EXPERIMENTAL_API
+CFLAGS += $(WERROR_FLAGS)
+LDLIBS += -lrte_eal
+
+EXPORT_MAP := rte_graph_version.map
+
+# all source are stored in SRCS-y
+SRCS-$(CONFIG_RTE_LIBRTE_GRAPH) += graph.c
+
+# install header files
+SYMLINK-$(CONFIG_RTE_LIBRTE_GRAPH)-include += rte_graph.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_graph/graph.c b/lib/librte_graph/graph.c
new file mode 100644
index 000000000..a55bf443a
--- /dev/null
+++ b/lib/librte_graph/graph.c
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#include "rte_graph.h"
diff --git a/lib/librte_graph/meson.build b/lib/librte_graph/meson.build
new file mode 100644
index 000000000..455cf2ba5
--- /dev/null
+++ b/lib/librte_graph/meson.build
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2020 Marvell International Ltd.
+#
+
+name = 'graph'
+
+sources = files('graph.c')
+headers = files('rte_graph.h')
+allow_experimental_apis = true
+
+deps += ['eal']
diff --git a/lib/librte_graph/rte_graph.h b/lib/librte_graph/rte_graph.h
new file mode 100644
index 000000000..862f51dde
--- /dev/null
+++ b/lib/librte_graph/rte_graph.h
@@ -0,0 +1,785 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2020 Marvell International Ltd.
+ */
+
+#ifndef _RTE_GRAPH_H_
+#define _RTE_GRAPH_H_
+
+/**
+ * @file rte_graph.h
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Graph architecture abstracts the data processing functions as
+ * "node" and "link" them together to create a complex "graph" to enable
+ * reusable/modular data processing functions.
+ *
+ * This API enables graph framework operations such as create, lookup,
+ * dump and destroy on graph and node operations such as clone,
+ * edge update, and edge shrink, etc. The API also allows to create the stats
+ * cluster to monitor per graph and per node stats.
+ *
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include <rte_common.h>
+#include <rte_compat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_GRAPH_NAMESIZE 64 /**< Max length of graph name. */
+#define RTE_NODE_NAMESIZE 64  /**< Max length of node name. */
+#define RTE_GRAPH_OFF_INVALID UINT32_MAX /**< Invalid graph offset. */
+#define RTE_NODE_ID_INVALID UINT32_MAX   /**< Invalid node id. */
+#define RTE_EDGE_ID_INVALID UINT16_MAX   /**< Invalid edge id. */
+#define RTE_GRAPH_ID_INVALID UINT16_MAX  /**< Invalid graph id. */
+#define RTE_GRAPH_FENCE 0xdeadbeef12345678ULL /**< Graph fence data. */
+
+typedef uint32_t rte_graph_off_t;  /**< Graph offset type. */
+typedef uint32_t rte_node_t;       /**< Node id type. */
+typedef uint16_t rte_edge_t;       /**< Edge id type. */
+typedef uint16_t rte_graph_t;      /**< Graph id type. */
+
+/** Burst size in terms of log2 */
+#if RTE_GRAPH_BURST_SIZE == 1
+#define RTE_GRAPH_BURST_SIZE_LOG2 0  /**< Object burst size of 1. */
+#elif RTE_GRAPH_BURST_SIZE == 2
+#define RTE_GRAPH_BURST_SIZE_LOG2 1  /**< Object burst size of 2. */
+#elif RTE_GRAPH_BURST_SIZE == 4
+#define RTE_GRAPH_BURST_SIZE_LOG2 2  /**< Object burst size of 4. */
+#elif RTE_GRAPH_BURST_SIZE == 8
+#define RTE_GRAPH_BURST_SIZE_LOG2 3  /**< Object burst size of 8. */
+#elif RTE_GRAPH_BURST_SIZE == 16
+#define RTE_GRAPH_BURST_SIZE_LOG2 4  /**< Object burst size of 16. */
+#elif RTE_GRAPH_BURST_SIZE == 32
+#define RTE_GRAPH_BURST_SIZE_LOG2 5  /**< Object burst size of 32. */
+#elif RTE_GRAPH_BURST_SIZE == 64
+#define RTE_GRAPH_BURST_SIZE_LOG2 6  /**< Object burst size of 64. */
+#elif RTE_GRAPH_BURST_SIZE == 128
+#define RTE_GRAPH_BURST_SIZE_LOG2 7  /**< Object burst size of 128. */
+#elif RTE_GRAPH_BURST_SIZE == 256
+#define RTE_GRAPH_BURST_SIZE_LOG2 8  /**< Object burst size of 256. */
+#else
+#error "Unsupported burst size"
+#endif
+
+/* Forward declaration */
+struct rte_node;  /**< Node data */
+struct rte_graph; /**< Graph data */
+struct rte_graph_cluster_stats;      /**< Stats for Cluster of graphs */
+struct rte_graph_cluster_node_stats; /**< Node stats within cluster of graphs */
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Node process function.
+ *
+ * The function invoked when the worker thread walks on nodes using
+ * rte_graph_walk().
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ * @param objs
+ *   Pointer to an array of objects to be processed.
+ * @param nb_objs
+ *   Number of objects in the array.
+ *
+ * @return
+ *   Number of objects processed.
+ *
+ * @see rte_graph_walk()
+ *
+ */
+typedef uint16_t (*rte_node_process_t)(struct rte_graph *graph,
+				       struct rte_node *node, void **objs,
+				       uint16_t nb_objs);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Node initialization function.
+ *
+ * The function invoked when the user creates the graph using rte_graph_create()
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ *
+ * @return
+ *   - 0: Success.
+ *   -<0: Failure.
+ *
+ * @see rte_graph_create()
+ */
+typedef int (*rte_node_init_t)(const struct rte_graph *graph,
+			       struct rte_node *node);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Node finalization function.
+ *
+ * The function invoked when the user destroys the graph using
+ * rte_graph_destroy().
+ *
+ * @param graph
+ *   Pointer to the graph object.
+ * @param node
+ *   Pointer to the node object.
+ *
+ * @see rte_graph_destroy()
+ */
+typedef void (*rte_node_fini_t)(const struct rte_graph *graph,
+				struct rte_node *node);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Graph cluster stats callback.
+ *
+ * @param is_first
+ *   Flag to denote that stats are of the first node.
+ * @param is_last
+ *   Flag to denote that stats are of the last node.
+ * @param cookie
+ *   Cookie supplied during stats creation.
+ * @param stats
+ *   Node cluster stats data.
+ *
+ * @return
+ *   - 0: Success.
+ *   -<0: Failure.
+ */
+typedef int (*rte_graph_cluster_stats_cb_t)(bool is_first, bool is_last,
+	     void *cookie, const struct rte_graph_cluster_node_stats *stats);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Structure to hold configuration parameters for creating the graph.
+ *
+ * @see rte_graph_create()
+ */
+struct rte_graph_param {
+	int socket_id; /**< Socket id where memory is allocated. */
+	uint16_t nb_node_patterns;  /**< Number of node patterns. */
+	const char **node_patterns;
+	/**< Array of node patterns based on shell pattern. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Structure to hold configuration parameters for graph cluster stats create.
+ *
+ * @see rte_graph_cluster_stats_create()
+ */
+struct rte_graph_cluster_stats_param {
+	int socket_id;
+	/**< Socket id where memory is allocated */
+	rte_graph_cluster_stats_cb_t fn;
+	/**< Stats print callback function. NULL value allowed, in that case,
+	 *   default print stat function used.
+	 */
+	RTE_STD_C11
+	union {
+		void *cookie;
+		FILE *f; /**< File pointer to dump the stats when fn == NULL. */
+	};
+	uint16_t nb_graph_patterns;  /**< Number of graph patterns. */
+	const char **graph_patterns;
+	/**< Array of graph patterns based on shell pattern. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Node cluster stats data structure.
+ *
+ * @see struct rte_graph_cluster_stats_param::fn
+ */
+struct rte_graph_cluster_node_stats {
+	uint64_t ts;	    /**< Current timestamp. */
+	uint64_t calls;	    /**< Current number of calls made. */
+	uint64_t objs;      /**< Current number of objs processed. */
+	uint64_t cycles;    /**< Current number of cycles. */
+
+	uint64_t prev_ts;	/**< Previous call timestamp. */
+	uint64_t prev_calls;	/**< Previous number of calls. */
+	uint64_t prev_objs;	/**< Previous number of processed objs. */
+	uint64_t prev_cycles;	/**< Previous number of cycles. */
+
+	uint64_t realloc_count; /**< Realloc count. */
+
+	rte_node_t id;	/**< Node identifier of stats. */
+	uint64_t hz;	/**< Cycles per seconds. */
+	char name[RTE_NODE_NAMESIZE];	/**< Name of the node. */
+} __rte_cache_aligned;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Structure defines the node registration parameters.
+ *
+ * @see __rte_node_register(), RTE_NODE_REGISTER()
+ */
+struct rte_node_register {
+	char name[RTE_NODE_NAMESIZE]; /**< Name of the node. */
+	uint64_t flags;		      /**< Node configuration flag. */
+#define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */
+	rte_node_process_t process; /**< Node process function. */
+	rte_node_init_t init;       /**< Node init function. */
+	rte_node_fini_t fini;       /**< Node fini function. */
+	rte_node_t id;		    /**< Node Identifier. */
+	rte_node_t parent_id;       /**< Identifier of parent node. */
+	rte_edge_t nb_edges;        /**< Number of edges from this node. */
+	const char *next_nodes[];   /**< Names of next nodes. */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create Graph.
+ *
+ * Create memory reel, detect loops and find isolated nodes.
+ *
+ * @param name
+ *   Unique name for this graph.
+ * @param prm
+ *   Graph parameter, includes node names and count to be included
+ *   in this graph.
+ *
+ * @return
+ *   Unique graph id on success, RTE_GRAPH_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_graph_t rte_graph_create(const char *name, struct rte_graph_param *prm);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Destroy Graph.
+ *
+ * Free Graph memory reel.
+ *
+ * @param name
+ *   Name of the graph to destroy.
+ *
+ * @return
+ *   0 on success, error otherwise.
+ */
+__rte_experimental
+rte_graph_t rte_graph_destroy(const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get graph id from graph name.
+ *
+ * @param name
+ *   Name of the graph to get id.
+ *
+ * @return
+ *   Graph id on success, RTE_GRAPH_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_graph_t rte_graph_from_name(const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get graph name from graph id.
+ *
+ * @param id
+ *   id of the graph to get name.
+ *
+ * @return
+ *   Graph name on success, NULL otherwise.
+ */
+__rte_experimental
+char *rte_graph_id_to_name(rte_graph_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Export the graph as graph viz dot file
+ *
+ * @param name
+ *   Name of the graph to export.
+ * @param f
+ *   File pointer to export the graph.
+ *
+ * @return
+ *   0 on success, error otherwise.
+ */
+__rte_experimental
+rte_graph_t rte_graph_export(const char *name, FILE *f);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get graph object from its name.
+ *
+ * Typical usage of this API to get graph objects in the worker thread and
+ * followed calling rte_graph_walk() in a loop.
+ *
+ * @param name
+ *   Name of the graph.
+ *
+ * @return
+ *   Graph pointer on success, NULL otherwise.
+ *
+ * @see rte_graph_walk()
+ */
+__rte_experimental
+struct rte_graph *rte_graph_lookup(const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get maximum number of graph available.
+ *
+ * @return
+ *   Maximum graph count on success, RTE_GRAPH_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_graph_t rte_graph_max_count(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Dump the graph information to file.
+ *
+ * @param f
+ *   File pointer to dump graph info.
+ * @param id
+ *   Graph id to get graph info.
+ */
+__rte_experimental
+void rte_graph_dump(FILE *f, rte_graph_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Dump all graphs information to file
+ *
+ * @param f
+ *   File pointer to dump graph info.
+ */
+__rte_experimental
+void rte_graph_list_dump(FILE *f);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Dump graph information along with node info to file
+ *
+ * @param f
+ *   File pointer to dump graph info.
+ * @param graph
+ *   Graph pointer to get graph info.
+ * @param all
+ *   true to dump nodes in the graph.
+ */
+__rte_experimental
+void rte_graph_obj_dump(FILE *f, struct rte_graph *graph, bool all);
+
+/** Macro to browse rte_node object after the graph creation */
+#define rte_graph_foreach_node(count, off, graph, node)                        \
+	for (count = 0, off = graph->nodes_start,                              \
+	     node = RTE_PTR_ADD(graph, off);                                   \
+	     count < graph->nb_nodes;                                          \
+	     off = node->next, node = RTE_PTR_ADD(graph, off), count++)
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get node object with in graph from id.
+ *
+ * @param graph_id
+ *   Graph id to get node pointer from.
+ * @param node_id
+ *   Node id to get node pointer.
+ *
+ * @return
+ *   Node pointer on success, NULL otherwise.
+ */
+__rte_experimental
+struct rte_node *rte_graph_node_get(rte_graph_t graph_id, uint32_t node_id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get node pointer with in graph from name.
+ *
+ * @param graph
+ *   Graph name to get node pointer from.
+ * @param name
+ *   Node name to get the node pointer.
+ *
+ * @return
+ *   Node pointer on success, NULL otherwise.
+ */
+__rte_experimental
+struct rte_node *rte_graph_node_get_by_name(const char *graph,
+					    const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create graph stats cluster to aggregate runtime node stats.
+ *
+ * @param prm
+ *   Parameters including file pointer to dump stats,
+ *   Graph pattern to create cluster and callback function.
+ *
+ * @return
+ *   Valid pointer on success, NULL otherwise.
+ */
+__rte_experimental
+struct rte_graph_cluster_stats *rte_graph_cluster_stats_create(
+			const struct rte_graph_cluster_stats_param *prm);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Destroy cluster stats.
+ *
+ * @param stat
+ *    Valid cluster pointer to destroy.
+ */
+__rte_experimental
+void rte_graph_cluster_stats_destroy(struct rte_graph_cluster_stats *stat);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get stats to application.
+ *
+ * @param[out] stat
+ *   Cluster status.
+ * @param skip_cb
+ *   true to skip callback function invocation.
+ */
+__rte_experimental
+void rte_graph_cluster_stats_get(struct rte_graph_cluster_stats *stat,
+				 bool skip_cb);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Reset cluster stats to zero.
+ *
+ * @param stat
+ *   Valid cluster stats pointer.
+ */
+__rte_experimental
+void rte_graph_cluster_stats_reset(struct rte_graph_cluster_stats *stat);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Register new packet processing node. Nodes can be registered
+ * dynamically via this call or statically via the RTE_NODE_REGISTER
+ * macro.
+ *
+ * @param node
+ *   Valid node pointer with name, process function and next_nodes.
+ *
+ * @return
+ *   Valid node id on success, RTE_NODE_ID_INVALID otherwise.
+ *
+ * @see RTE_NODE_REGISTER()
+ */
+__rte_experimental
+rte_node_t __rte_node_register(const struct rte_node_register *node);
+
+/**
+ * Register a static node.
+ *
+ * The static node is registered through the constructor scheme, thereby, it can
+ * be used in a multi-process scenario.
+ *
+ * @param node
+ *   Valid node pointer with name, process function, and next_nodes.
+ */
+#define RTE_NODE_REGISTER(node)                                                \
+	RTE_INIT(rte_node_register_##node)                                     \
+	{                                                                      \
+		node.parent_id = RTE_NODE_ID_INVALID;                          \
+		node.id = __rte_node_register(&node);                          \
+	}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Clone a node from static node(node created from RTE_NODE_REGISTER).
+ *
+ * @param id
+ *   Static node id to clone from.
+ * @param name
+ *   Name of the new node. The library prepends the parent node name to the
+ * user-specified name. The final node name will be,
+ * "parent node name" + "-" + name.
+ *
+ * @return
+ *   Valid node id on success, RTE_NODE_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_node_t rte_node_clone(rte_node_t id, const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get node id from node name.
+ *
+ * @param name
+ *   Valid node name. In the case of the cloned node, the name will be
+ * "parent node name" + "-" + name.
+ *
+ * @return
+ *   Valid node id on success, RTE_NODE_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_node_t rte_node_from_name(const char *name);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get node name from node id.
+ *
+ * @param id
+ *   Valid node id.
+ *
+ * @return
+ *   Valid node name on success, NULL otherwise.
+ */
+__rte_experimental
+char *rte_node_id_to_name(rte_node_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get the number of edges for a node from node id.
+ *
+ * @param id
+ *   Valid node id.
+ *
+ * @return
+ *   Valid edge count on success, RTE_EDGE_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_edge_t rte_node_edge_count(rte_node_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Update the edges for a node from node id.
+ *
+ * @param id
+ *   Valid node id.
+ * @param from
+ *   Index to update the edges from. RTE_EDGE_ID_INVALID is valid,
+ * in that case, it will be added to the end of the list.
+ * @param next_nodes
+ *   Name of the edges to update.
+ * @param nb_edges
+ *   Number of edges to update.
+ *
+ * @return
+ *   Valid edge count on success, 0 otherwise.
+ */
+__rte_experimental
+rte_edge_t rte_node_edge_update(rte_node_t id, rte_edge_t from,
+				const char **next_nodes, uint16_t nb_edges);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Shrink the edges to a given size.
+ *
+ * @param id
+ *   Valid node id.
+ * @param size
+ *   New size to shrink the edges.
+ *
+ * @return
+ *   New size on success, RTE_EDGE_ID_INVALID otherwise.
+ */
+__rte_experimental
+rte_edge_t rte_node_edge_shrink(rte_node_t id, rte_edge_t size);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get the edge names from a given node.
+ *
+ * @param id
+ *   Valid node id.
+ * @param[out] next_nodes
+ *   Buffer to copy the edge names. The NULL value is allowed in that case,
+ * the function returns the size of the array that needs to be allocated.
+ *
+ * @return
+ *   When next_nodes == NULL, it returns the size of the array else
+ *  number of item copied.
+ */
+__rte_experimental
+rte_node_t rte_node_edge_get(rte_node_t id, char *next_nodes[]);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get maximum nodes created so far.
+ *
+ * @return
+ *   Maximum nodes count on success, 0 otherwise.
+ */
+__rte_experimental
+rte_node_t rte_node_max_count(void);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Dump node info to file.
+ *
+ * @param f
+ *   File pointer to dump the node info.
+ * @param id
+ *   Node id to get the info.
+ */
+__rte_experimental
+void rte_node_dump(FILE *f, rte_node_t id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Dump all node info to file.
+ *
+ * @param f
+ *   File pointer to dump the node info.
+ */
+__rte_experimental
+void rte_node_list_dump(FILE *f);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Test the validity of node id.
+ *
+ * @param id
+ *   Node id to check.
+ *
+ * @return
+ *   1 if valid id, 0 otherwise.
+ */
+static __rte_always_inline int
+rte_node_is_invalid(rte_node_t id)
+{
+	return (id == RTE_NODE_ID_INVALID);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Test the validity of edge id.
+ *
+ * @param id
+ *   Edge node id to check.
+ *
+ * @return
+ *   1 if valid id, 0 otherwise.
+ */
+static __rte_always_inline int
+rte_edge_is_invalid(rte_edge_t id)
+{
+	return (id == RTE_EDGE_ID_INVALID);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Test the validity of graph id.
+ *
+ * @param id
+ *   Graph id to check.
+ *
+ * @return
+ *   1 if valid id, 0 otherwise.
+ */
+static __rte_always_inline int
+rte_graph_is_invalid(rte_graph_t id)
+{
+	return (id == RTE_GRAPH_ID_INVALID);
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Test stats feature support.
+ *
+ * @return
+ *   1 if stats enabled, 0 otherwise.
+ */
+static __rte_always_inline int
+rte_graph_has_stats_feature(void)
+{
+#ifdef RTE_LIBRTE_GRAPH_STATS
+	return RTE_LIBRTE_GRAPH_STATS;
+#else
+	return 0;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_GRAPH_H_ */
diff --git a/lib/librte_graph/rte_graph_version.map b/lib/librte_graph/rte_graph_version.map
new file mode 100644
index 000000000..55ef35df5
--- /dev/null
+++ b/lib/librte_graph/rte_graph_version.map
@@ -0,0 +1,3 @@
+EXPERIMENTAL {
+
+};
diff --git a/lib/meson.build b/lib/meson.build
index 9c3cc55d5..c43d86bb9 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -30,7 +30,7 @@ libraries = [
 	# add pkt framework libs which use other libs from above
 	'port', 'table', 'pipeline',
 	# flow_classify lib depends on pkt framework table lib
-	'flow_classify', 'bpf', 'telemetry']
+	'flow_classify', 'bpf', 'graph', 'telemetry']
 
 if is_windows
 	libraries = ['kvargs','eal'] # only supported libraries for windows
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index d295ca0a5..b1195f09a 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -98,6 +98,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED)          += -lrte_sched
 _LDLIBS-$(CONFIG_RTE_LIBRTE_RCU)            += -lrte_rcu
+_LDLIBS-$(CONFIG_RTE_LIBRTE_GRAPH)          += -lrte_graph
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUX),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI)            += -lrte_kni
