[dpdk-dev,01/37] pipeline: add pipeline table action APIs

Message ID 20180309182426.135278-2-jasvinder.singh@intel.com (mailing list archive)
State Superseded, archived
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail apply patch file failure

Commit Message

Jasvinder Singh March 9, 2018, 6:23 p.m. UTC
  This API provides a common set of actions for pipeline tables to speed up
application development.

Each match-action rule added to a pipeline table has associated data
that stores the action context. This data is input to the table
action handler called for every input packet that hits the rule as
part of the table lookup during the pipeline execution.

The pipeline library allows the user to define his own table
actions by providing customized table action handlers (table
lookup) and complete freedom of setting the rules and their data
(table rule add/delete). While the user can still follow this
process, this API is intended to provide a quicker development
alternative for a set of predefined actions.

The typical steps to use this API are:
* Define a table action profile.
* Instantiate the table action profile to create table action objects.
* Use the table action object to generate the pipeline table action
  handlers (invoked by the pipeline table lookup operation).
* Use the table action object to generate the rule data (for the
  pipeline table rule add operation) based on given action parameters.
* Use the table action object to read action data (e.g. stats counters)
  for any given rule.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
---
 doc/api/doxy-api-index.md                    |   1 +
 lib/librte_pipeline/Makefile                 |   3 +-
 lib/librte_pipeline/meson.build              |   5 +-
 lib/librte_pipeline/rte_pipeline_version.map |  13 ++
 lib/librte_pipeline/rte_table_action.c       | 278 +++++++++++++++++++++++++++
 lib/librte_pipeline/rte_table_action.h       | 224 +++++++++++++++++++++
 6 files changed, 521 insertions(+), 3 deletions(-)
 create mode 100644 lib/librte_pipeline/rte_table_action.c
 create mode 100644 lib/librte_pipeline/rte_table_action.h
  

Comments

Jasvinder Singh March 12, 2018, 5:25 p.m. UTC | #1
Refactored the IP pipeline application. As result, the code base
size (lines of code) reduces by ~60%.

1. Moved table actions into the librte_pipeline library. As result,
   the pre-fabricated pipelines from the application pipeline folder
   were removed. The flexibility is greatly improved, as now any
   action can be combined with any match (i.e. table type), which
   was not possible before.

2. Removed configuration file as the initialization method. Now
   all the pipelines are set up and assigned to threads through
   CLI commands for improved flexibility.

3. Replaced the local CLI with remote CLI. Any standard TCP
   client (e.g. telnet, netcat) can now connect to the app,
   send request as command string through the network and wait
   for the response string before pushing the next command.
   Results in better flexibility and automation.

v2:
- split the patch that removes the existing pipeline components
  into multiple patches.
- fix checkpatch errors.

Jasvinder Singh (44):
  pipeline: add pipeline table action APIs
  pipeline: get pipeline table action params
  pipeline: add traffic metering action
  pipeline: add traffic manager action
  pipeline: add packet encapsulation action
  pipeline: add nat action
  pipeline: add ttl update action
  pipeline: add statistics read action
  pipeline: add timestamp action
  ip_pipeline: remove passthrough pipeline
  ip_pipeline: remove routing pipeline
  ip_pipeline: remove flow classification pipeline
  ip_pipeline: remove flow actions pipeline
  ip_pipeline: remove firewall pipeline
  ip_pipeline: remove master pipeline
  ip_pipeline: remove config
  ip_pipeline: rework and improvements
  ip_pipeline: add cli interface
  ip_pipeline: add mempool object for pipeline
  ip_pipeline: add link object
  ip_pipeline: add software queue object
  ip_pipeline: add traffic manager object
  ip_pipeline: add tap object
  ip_pipeline: add kni object
  ip_pipeline: add action profile object
  ip_pipeline: add pipeline object
  ip_pipeline: add threads
  ip_pipeline: add thread runtime
  ip_pipeline: add cli to enable and disable pipeline
  ip_pipeline: add cli to enable and disable pipeline port
  ip_pipeline: add cli to read pipeline port and table stats
  ip_pipeline: add cli for pipeline table entries
  ip_pipeline: add cli to delete pipeline table entry
  ip_pipeline: add cli to read pipeline table entry stats
  ip_pipeline: add cli to configure meter profile
  ip_pipeline: add cli to read meter stats
  ip_pipeline: add cli to update dscp table
  ip_pipeline: add cli to read ttl stats
  ip_pipeline: add l2fwd example
  ip_pipeline: add KNI port example
  ip_pipeline: add TAP port example
  ip_pipeline: add route example
  ip_pipeline: add firewall example
  ip_pipeline: add flow classification example

 doc/api/doxy-api-index.md                          |    1 +
 examples/ip_pipeline/Makefile                      |   49 +-
 examples/ip_pipeline/action.c                      |  165 +
 examples/ip_pipeline/action.h                      |   44 +
 examples/ip_pipeline/app.h                         | 1401 -------
 examples/ip_pipeline/cli.c                         | 4261 ++++++++++++++++++++
 examples/ip_pipeline/cli.h                         |   18 +
 examples/ip_pipeline/common.h                      |   12 +
 examples/ip_pipeline/config/action.cfg             |   68 -
 examples/ip_pipeline/config/action.sh              |  119 -
 examples/ip_pipeline/config/action.txt             |    8 -
 examples/ip_pipeline/config/diagram-generator.py   |  317 --
 .../ip_pipeline/config/edge_router_downstream.cfg  |   97 -
 .../ip_pipeline/config/edge_router_downstream.sh   |   13 -
 .../ip_pipeline/config/edge_router_upstream.cfg    |  124 -
 .../ip_pipeline/config/edge_router_upstream.sh     |   33 -
 examples/ip_pipeline/config/firewall.cfg           |   68 -
 examples/ip_pipeline/config/firewall.sh            |   13 -
 examples/ip_pipeline/config/firewall.txt           |    9 -
 examples/ip_pipeline/config/flow.cfg               |   72 -
 examples/ip_pipeline/config/flow.sh                |   25 -
 examples/ip_pipeline/config/flow.txt               |   17 -
 examples/ip_pipeline/config/ip_pipeline.cfg        |    9 -
 examples/ip_pipeline/config/ip_pipeline.sh         |    5 -
 examples/ip_pipeline/config/kni.cfg                |   67 -
 examples/ip_pipeline/config/l2fwd.cfg              |   58 -
 examples/ip_pipeline/config/l3fwd.cfg              |   68 -
 examples/ip_pipeline/config/l3fwd.sh               |   33 -
 examples/ip_pipeline/config/l3fwd_arp.cfg          |   70 -
 examples/ip_pipeline/config/l3fwd_arp.sh           |   43 -
 examples/ip_pipeline/config/network_layers.cfg     |  227 --
 examples/ip_pipeline/config/network_layers.sh      |   79 -
 .../ip_pipeline/config/pipeline-to-core-mapping.py |  906 -----
 examples/ip_pipeline/config/tap.cfg                |   64 -
 examples/ip_pipeline/config/tm_profile.cfg         |  105 -
 examples/ip_pipeline/config_check.c                |  488 ---
 examples/ip_pipeline/config_parse.c                | 3395 ----------------
 examples/ip_pipeline/config_parse_tm.c             |  419 --
 examples/ip_pipeline/conn.c                        |  326 ++
 examples/ip_pipeline/conn.h                        |   47 +
 examples/ip_pipeline/cpu_core_map.c                |  471 ---
 examples/ip_pipeline/cpu_core_map.h                |   40 -
 examples/ip_pipeline/examples/firewall.cli         |   59 +
 examples/ip_pipeline/examples/flow.cli             |   60 +
 examples/ip_pipeline/examples/kni.cli              |   69 +
 examples/ip_pipeline/examples/l2fwd.cli            |   53 +
 examples/ip_pipeline/examples/route.cli            |   60 +
 examples/ip_pipeline/examples/tap.cli              |   66 +
 examples/ip_pipeline/{pipeline => }/hash_func.h    |    3 +-
 .../ip_pipeline/{pipeline => }/hash_func_arm64.h   |    0
 examples/ip_pipeline/init.c                        | 1927 ---------
 examples/ip_pipeline/kni.c                         |  167 +
 examples/ip_pipeline/kni.h                         |   44 +
 examples/ip_pipeline/link.c                        |  268 ++
 examples/ip_pipeline/link.h                        |   63 +
 examples/ip_pipeline/main.c                        |  253 +-
 examples/ip_pipeline/mempool.c                     |   81 +
 examples/ip_pipeline/mempool.h                     |   40 +
 examples/ip_pipeline/meson.build                   |   36 +-
 examples/ip_pipeline/parser.c                      |   16 +-
 examples/ip_pipeline/parser.h                      |    8 +
 examples/ip_pipeline/pipeline.c                    |  930 +++++
 examples/ip_pipeline/pipeline.h                    |  373 +-
 .../ip_pipeline/pipeline/pipeline_actions_common.h |  202 -
 examples/ip_pipeline/pipeline/pipeline_common_be.c |  176 -
 examples/ip_pipeline/pipeline/pipeline_common_be.h |  134 -
 examples/ip_pipeline/pipeline/pipeline_common_fe.c | 1455 -------
 examples/ip_pipeline/pipeline/pipeline_common_fe.h |  231 --
 examples/ip_pipeline/pipeline/pipeline_firewall.c  | 1421 -------
 examples/ip_pipeline/pipeline/pipeline_firewall.h  |   60 -
 .../ip_pipeline/pipeline/pipeline_firewall_be.c    |  856 ----
 .../ip_pipeline/pipeline/pipeline_firewall_be.h    |  147 -
 .../ip_pipeline/pipeline/pipeline_flow_actions.c   | 1286 ------
 .../ip_pipeline/pipeline/pipeline_flow_actions.h   |   60 -
 .../pipeline/pipeline_flow_actions_be.c            |  983 -----
 .../pipeline/pipeline_flow_actions_be.h            |  139 -
 .../pipeline/pipeline_flow_classification.c        | 1878 ---------
 .../pipeline/pipeline_flow_classification.h        |  106 -
 .../pipeline/pipeline_flow_classification_be.c     |  723 ----
 .../pipeline/pipeline_flow_classification_be.h     |  113 -
 examples/ip_pipeline/pipeline/pipeline_master.c    |   20 -
 examples/ip_pipeline/pipeline/pipeline_master.h    |   12 -
 examples/ip_pipeline/pipeline/pipeline_master_be.c |  141 -
 examples/ip_pipeline/pipeline/pipeline_master_be.h |   12 -
 .../ip_pipeline/pipeline/pipeline_passthrough.c    |   45 -
 .../ip_pipeline/pipeline/pipeline_passthrough.h    |   12 -
 .../ip_pipeline/pipeline/pipeline_passthrough_be.c |  929 -----
 .../ip_pipeline/pipeline/pipeline_passthrough_be.h |   44 -
 examples/ip_pipeline/pipeline/pipeline_routing.c   | 1613 --------
 examples/ip_pipeline/pipeline/pipeline_routing.h   |   71 -
 .../ip_pipeline/pipeline/pipeline_routing_be.c     | 1966 ---------
 .../ip_pipeline/pipeline/pipeline_routing_be.h     |  283 --
 examples/ip_pipeline/pipeline_be.h                 |  322 --
 examples/ip_pipeline/swq.c                         |   74 +
 examples/ip_pipeline/swq.h                         |   37 +
 examples/ip_pipeline/tap.c                         |   97 +
 examples/ip_pipeline/tap.h                         |   29 +
 examples/ip_pipeline/thread.c                      | 2485 +++++++++++-
 examples/ip_pipeline/thread.h                      |   75 +-
 examples/ip_pipeline/thread_fe.c                   |  457 ---
 examples/ip_pipeline/thread_fe.h                   |   72 -
 examples/ip_pipeline/tmgr.c                        |  227 ++
 examples/ip_pipeline/tmgr.h                        |   70 +
 lib/librte_pipeline/Makefile                       |    6 +-
 lib/librte_pipeline/meson.build                    |    7 +-
 lib/librte_pipeline/rte_pipeline_version.map       |   21 +
 lib/librte_pipeline/rte_table_action.c             | 2086 ++++++++++
 lib/librte_pipeline/rte_table_action.h             |  853 ++++
 108 files changed, 13248 insertions(+), 27218 deletions(-)
 create mode 100644 examples/ip_pipeline/action.c
 create mode 100644 examples/ip_pipeline/action.h
 delete mode 100644 examples/ip_pipeline/app.h
 create mode 100644 examples/ip_pipeline/cli.c
 create mode 100644 examples/ip_pipeline/cli.h
 create mode 100644 examples/ip_pipeline/common.h
 delete mode 100644 examples/ip_pipeline/config/action.cfg
 delete mode 100644 examples/ip_pipeline/config/action.sh
 delete mode 100644 examples/ip_pipeline/config/action.txt
 delete mode 100755 examples/ip_pipeline/config/diagram-generator.py
 delete mode 100644 examples/ip_pipeline/config/edge_router_downstream.cfg
 delete mode 100644 examples/ip_pipeline/config/edge_router_downstream.sh
 delete mode 100644 examples/ip_pipeline/config/edge_router_upstream.cfg
 delete mode 100644 examples/ip_pipeline/config/edge_router_upstream.sh
 delete mode 100644 examples/ip_pipeline/config/firewall.cfg
 delete mode 100644 examples/ip_pipeline/config/firewall.sh
 delete mode 100644 examples/ip_pipeline/config/firewall.txt
 delete mode 100644 examples/ip_pipeline/config/flow.cfg
 delete mode 100644 examples/ip_pipeline/config/flow.sh
 delete mode 100644 examples/ip_pipeline/config/flow.txt
 delete mode 100644 examples/ip_pipeline/config/ip_pipeline.cfg
 delete mode 100644 examples/ip_pipeline/config/ip_pipeline.sh
 delete mode 100644 examples/ip_pipeline/config/kni.cfg
 delete mode 100644 examples/ip_pipeline/config/l2fwd.cfg
 delete mode 100644 examples/ip_pipeline/config/l3fwd.cfg
 delete mode 100644 examples/ip_pipeline/config/l3fwd.sh
 delete mode 100644 examples/ip_pipeline/config/l3fwd_arp.cfg
 delete mode 100644 examples/ip_pipeline/config/l3fwd_arp.sh
 delete mode 100644 examples/ip_pipeline/config/network_layers.cfg
 delete mode 100644 examples/ip_pipeline/config/network_layers.sh
 delete mode 100755 examples/ip_pipeline/config/pipeline-to-core-mapping.py
 delete mode 100644 examples/ip_pipeline/config/tap.cfg
 delete mode 100644 examples/ip_pipeline/config/tm_profile.cfg
 delete mode 100644 examples/ip_pipeline/config_check.c
 delete mode 100644 examples/ip_pipeline/config_parse.c
 delete mode 100644 examples/ip_pipeline/config_parse_tm.c
 create mode 100644 examples/ip_pipeline/conn.c
 create mode 100644 examples/ip_pipeline/conn.h
 delete mode 100644 examples/ip_pipeline/cpu_core_map.c
 delete mode 100644 examples/ip_pipeline/cpu_core_map.h
 create mode 100644 examples/ip_pipeline/examples/firewall.cli
 create mode 100644 examples/ip_pipeline/examples/flow.cli
 create mode 100644 examples/ip_pipeline/examples/kni.cli
 create mode 100644 examples/ip_pipeline/examples/l2fwd.cli
 create mode 100644 examples/ip_pipeline/examples/route.cli
 create mode 100644 examples/ip_pipeline/examples/tap.cli
 rename examples/ip_pipeline/{pipeline => }/hash_func.h (99%)
 rename examples/ip_pipeline/{pipeline => }/hash_func_arm64.h (100%)
 delete mode 100644 examples/ip_pipeline/init.c
 create mode 100644 examples/ip_pipeline/kni.c
 create mode 100644 examples/ip_pipeline/kni.h
 create mode 100644 examples/ip_pipeline/link.c
 create mode 100644 examples/ip_pipeline/link.h
 create mode 100644 examples/ip_pipeline/mempool.c
 create mode 100644 examples/ip_pipeline/mempool.h
 create mode 100644 examples/ip_pipeline/pipeline.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_actions_common.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.h
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.c
 delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.h
 delete mode 100644 examples/ip_pipeline/pipeline_be.h
 create mode 100644 examples/ip_pipeline/swq.c
 create mode 100644 examples/ip_pipeline/swq.h
 create mode 100644 examples/ip_pipeline/tap.c
 create mode 100644 examples/ip_pipeline/tap.h
 delete mode 100644 examples/ip_pipeline/thread_fe.c
 delete mode 100644 examples/ip_pipeline/thread_fe.h
 create mode 100644 examples/ip_pipeline/tmgr.c
 create mode 100644 examples/ip_pipeline/tmgr.h
 create mode 100644 lib/librte_pipeline/rte_table_action.c
 create mode 100644 lib/librte_pipeline/rte_table_action.h
  

Patch

diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index d77f205..e24b70e 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:
     [array]            (@ref rte_table_array.h),
     [stub]             (@ref rte_table_stub.h)
   * [pipeline]         (@ref rte_pipeline.h)
+    [table_action].....(@ref rte_table_action.h)
 
 - **basic**:
   [approx fraction]    (@ref rte_approx.h),
diff --git a/lib/librte_pipeline/Makefile b/lib/librte_pipeline/Makefile
index e94fbc0..e8c43c7 100644
--- a/lib/librte_pipeline/Makefile
+++ b/lib/librte_pipeline/Makefile
@@ -21,8 +21,9 @@  LIBABIVER := 3
 # all source are stored in SRCS-y
 #
 SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := rte_pipeline.c
+SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rte_table_action.c
 
 # install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_PIPELINE)-include += rte_pipeline.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_PIPELINE)-include += rte_pipeline.h rte_table_action.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_pipeline/meson.build b/lib/librte_pipeline/meson.build
index a35b622..4dda560 100644
--- a/lib/librte_pipeline/meson.build
+++ b/lib/librte_pipeline/meson.build
@@ -2,6 +2,7 @@ 
 # Copyright(c) 2017 Intel Corporation
 
 version = 3
-sources = files('rte_pipeline.c')
-headers = files('rte_pipeline.h')
+allow_experimental_apis = true
+sources = files('rte_pipeline.c', 'rte_table_action.c')
+headers = files('rte_pipeline.h', 'rte_table_action.h')
 deps += ['port', 'table']
diff --git a/lib/librte_pipeline/rte_pipeline_version.map b/lib/librte_pipeline/rte_pipeline_version.map
index e4ee154..4bc414c 100644
--- a/lib/librte_pipeline/rte_pipeline_version.map
+++ b/lib/librte_pipeline/rte_pipeline_version.map
@@ -45,3 +45,16 @@  DPDK_16.04 {
 	rte_pipeline_ah_packet_drop;
 
 } DPDK_2.2;
+
+EXPERIMENTAL {
+	global:
+
+	rte_table_action_apply;
+	rte_table_action_create;
+	rte_table_action_free;
+	rte_table_action_profile_action_register;
+	rte_table_action_profile_create;
+	rte_table_action_profile_free;
+	rte_table_action_profile_freeze;
+
+} DPDK_16.04;
diff --git a/lib/librte_pipeline/rte_table_action.c b/lib/librte_pipeline/rte_table_action.c
new file mode 100644
index 0000000..45e22a4
--- /dev/null
+++ b/lib/librte_pipeline/rte_table_action.c
@@ -0,0 +1,278 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <rte_malloc.h>
+
+#include <rte_common.h>
+#include <rte_malloc.h>
+
+#include "rte_table_action.h"
+
+/**
+ * RTE_TABLE_ACTION_FWD
+ */
+#define fwd_data rte_pipeline_table_entry
+
+static int
+fwd_apply(struct fwd_data *data,
+	struct rte_table_action_fwd_params *p)
+{
+	data->action = p->action;
+
+	if (p->action == RTE_PIPELINE_ACTION_PORT)
+		data->port_id = p->id;
+
+	if (p->action == RTE_PIPELINE_ACTION_TABLE)
+		data->table_id = p->id;
+
+	return 0;
+}
+
+/**
+ * Action profile
+ */
+static int
+action_valid(enum rte_table_action_type action)
+{
+	switch (action) {
+	case RTE_TABLE_ACTION_FWD:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+
+#define RTE_TABLE_ACTION_MAX                                   64
+
+struct ap_config {
+	uint64_t action_mask;
+	struct rte_table_action_common_config common;
+};
+
+static size_t
+action_cfg_size(enum rte_table_action_type action)
+{
+	switch (action) {
+	default:
+		return 0;
+	}
+}
+
+static void*
+action_cfg_get(struct ap_config *ap_config __rte_unused,
+	enum rte_table_action_type type)
+{
+	switch (type) {
+	default:
+		return NULL;
+	}
+}
+
+static void
+action_cfg_set(struct ap_config *ap_config,
+	enum rte_table_action_type type,
+	void *action_cfg)
+{
+	void *dst = action_cfg_get(ap_config, type);
+
+	if (dst)
+		memcpy(dst, action_cfg, action_cfg_size(type));
+
+	ap_config->action_mask |= 1LLU << type;
+}
+
+struct ap_data {
+	size_t offset[RTE_TABLE_ACTION_MAX];
+	size_t total_size;
+};
+
+static size_t
+action_data_size(enum rte_table_action_type action,
+	struct ap_config *ap_config __rte_unused)
+{
+	switch (action) {
+	case RTE_TABLE_ACTION_FWD:
+		return sizeof(struct fwd_data);
+
+	default:
+		return 0;
+	}
+}
+
+
+static void
+action_data_offset_set(struct ap_data *ap_data,
+	struct ap_config *ap_config)
+{
+	uint64_t action_mask = ap_config->action_mask;
+	size_t offset;
+	enum rte_table_action_type action;
+
+	memset(ap_data->offset, 0, sizeof(ap_data->offset));
+
+	offset = 0;
+	for (action = 0; action < RTE_TABLE_ACTION_MAX; action++)
+		if (action_mask & (1LLU << action)) {
+			ap_data->offset[action] = offset;
+			offset += action_data_size(action, ap_config);
+		}
+
+	ap_data->total_size = offset;
+}
+
+struct rte_table_action_profile {
+	struct ap_config cfg;
+	struct ap_data data;
+	int frozen;
+};
+
+struct rte_table_action_profile *
+rte_table_action_profile_create(struct rte_table_action_common_config *common)
+{
+	struct rte_table_action_profile *ap;
+
+	/* Check input arguments */
+	if (common == NULL)
+		return NULL;
+
+	/* Memory allocation */
+	ap = calloc(1, sizeof(struct rte_table_action_profile));
+	if (ap == NULL)
+		return NULL;
+
+	/* Initialization */
+	memcpy(&ap->cfg.common, common, sizeof(*common));
+
+	return ap;
+}
+
+
+int
+rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
+	enum rte_table_action_type type,
+	void *action_config)
+{
+	/* Check input arguments */
+	if ((profile == NULL) ||
+		profile->frozen ||
+		(action_valid(type) == 0) ||
+		(profile->cfg.action_mask & (1LLU << type)) ||
+		((action_cfg_size(type) == 0) && action_config) ||
+		(action_cfg_size(type) && (action_config == NULL)))
+		return -EINVAL;
+
+	/* Action enable */
+	action_cfg_set(&profile->cfg, type, action_config);
+
+	return 0;
+}
+
+int
+rte_table_action_profile_freeze(struct rte_table_action_profile *profile)
+{
+	if (profile->frozen)
+		return -EBUSY;
+
+	profile->cfg.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
+	action_data_offset_set(&profile->data, &profile->cfg);
+	profile->frozen = 1;
+
+	return 0;
+}
+
+int
+rte_table_action_profile_free(struct rte_table_action_profile *profile)
+{
+	if (profile == NULL)
+		return 0;
+
+	free(profile);
+	return 0;
+}
+
+struct rte_table_action {
+	struct ap_config cfg;
+	struct ap_data data;
+};
+
+struct rte_table_action *
+rte_table_action_create(struct rte_table_action_profile *profile,
+	uint32_t socket_id)
+{
+	struct rte_table_action *action;
+
+	/* Check input arguments */
+	if ((profile == NULL) ||
+		(profile->frozen == 0))
+		return NULL;
+
+	/* Memory allocation */
+	action = rte_zmalloc_socket(NULL,
+		sizeof(struct rte_table_action),
+		RTE_CACHE_LINE_SIZE,
+		socket_id);
+	if (action == NULL)
+		return NULL;
+
+	/* Initialization */
+	memcpy(&action->cfg, &profile->cfg, sizeof(profile->cfg));
+	memcpy(&action->data, &profile->data, sizeof(profile->data));
+
+	return action;
+}
+
+static __rte_always_inline void *
+action_data_get(void *data,
+	struct rte_table_action *action,
+	enum rte_table_action_type type)
+{
+	size_t offset = action->data.offset[type];
+	uint8_t *data_bytes = data;
+
+	return &data_bytes[offset];
+}
+
+int
+rte_table_action_apply(struct rte_table_action *action,
+	void *data,
+	enum rte_table_action_type type,
+	void *action_params)
+{
+	void *action_data;
+
+	/* Check input arguments */
+	if ((action == NULL) ||
+		(data == NULL) ||
+		(action_valid(type) == 0) ||
+		((action->cfg.action_mask & (1LLU << type)) == 0) ||
+		(action_params == NULL))
+		return -EINVAL;
+
+	/* Data update */
+	action_data = action_data_get(data, action, type);
+
+	switch (type) {
+	case RTE_TABLE_ACTION_FWD:
+		return fwd_apply(action_data,
+			action_params);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+int
+rte_table_action_free(struct rte_table_action *action)
+{
+	if (action == NULL)
+		return 0;
+
+	rte_free(action);
+
+	return 0;
+}
\ No newline at end of file
diff --git a/lib/librte_pipeline/rte_table_action.h b/lib/librte_pipeline/rte_table_action.h
new file mode 100644
index 0000000..da7f12c
--- /dev/null
+++ b/lib/librte_pipeline/rte_table_action.h
@@ -0,0 +1,224 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Intel Corporation
+ */
+
+#ifndef __INCLUDE_RTE_TABLE_ACTION_H__
+#define __INCLUDE_RTE_TABLE_ACTION_H__
+
+/**
+ * @file
+ * RTE Pipeline Table Actions
+ *
+ * This API provides a common set of actions for pipeline tables to speed up
+ * application development.
+ *
+ * Each match-action rule added to a pipeline table has associated data that
+ * stores the action context. This data is input to the table action handler
+ * called for every input packet that hits the rule as part of the table lookup
+ * during the pipeline execution. The pipeline library allows the user to define
+ * his own table actions by providing customized table action handlers (table
+ * lookup) and complete freedom of setting the rules and their data (table rule
+ * add/delete). While the user can still follow this process, this API is
+ * intended to provide a quicker development alternative for a set of predefined
+ * actions.
+ *
+ * The typical steps to use this API are:
+ *  - Define a table action profile. This is a configuration template that can
+ *    potentially be shared by multiple tables from the same or different
+ *    pipelines, with different tables from the same pipeline likely to use
+ *    different action profiles. For every table using a given action profile,
+ *    the profile defines the set of actions and the action configuration to be
+ *    implemented for all the table rules. API functions:
+ *    rte_table_action_profile_create(),
+ *    rte_table_action_profile_action_register(),
+ *    rte_table_action_profile_freeze().
+ *
+ *  - Instantiate the table action profile to create table action objects. Each
+ *    pipeline table has its own table action object. API functions:
+ *    rte_table_action_create().
+ *
+ *  - Use the table action object to generate the pipeline table action handlers
+ *    (invoked by the pipeline table lookup operation). API functions:
+ *    rte_table_action_table_params_get().
+ *
+ *  - Use the table action object to generate the rule data (for the pipeline
+ *    table rule add operation) based on given action parameters. API functions:
+ *    rte_table_action_apply().
+ *
+ *  - Use the table action object to read action data (e.g. stats counters) for
+ *    any given rule. API functions: rte_table_action_XYZ_read().
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include <rte_compat.h>
+
+#include "rte_pipeline.h"
+
+/** Table actions. */
+enum rte_table_action_type {
+	/** Forward to next pipeline table, output port or drop. */
+	RTE_TABLE_ACTION_FWD = 0,
+};
+
+/** Common action configuration (per table action profile). */
+struct rte_table_action_common_config {
+	/** Input packet Internet Protocol (IP) version. Non-zero for IPv4, zero
+	 * for IPv6.
+	 */
+	int ip_version;
+
+	/** IP header offset within the input packet buffer. Offset 0 points to
+	 * the first byte of the MBUF structure.
+	 */
+	uint32_t ip_offset;
+};
+
+/**
+ * RTE_TABLE_ACTION_FWD
+ */
+/** Forward action parameters (per table rule). */
+struct rte_table_action_fwd_params {
+	/** Forward action. */
+	enum rte_pipeline_action action;
+
+	/** Pipeline table ID or output port ID. */
+	uint32_t id;
+};
+
+/**
+ * Table action profile.
+ */
+struct rte_table_action_profile;
+
+/**
+ * Table action profile create.
+ *
+ * @param[in] common
+ *   Common action configuration.
+ * @return
+ *   Table action profile handle on success, NULL otherwise.
+ */
+struct rte_table_action_profile * __rte_experimental
+rte_table_action_profile_create(struct rte_table_action_common_config *common);
+
+/**
+ * Table action profile free.
+ *
+ * @param[in] profile
+ *   Table profile action handle (needs to be valid).
+ * @return
+ *   Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_profile_free(struct rte_table_action_profile *profile);
+
+/**
+ * Table action profile action register.
+ *
+ * @param[in] profile
+ *   Table profile action handle (needs to be valid and not in frozen state).
+ * @param[in] type
+ *   Specific table action to be registered for *profile*.
+ * @param[in] action_config
+ *   Configuration for the *type* action.
+ *   If struct rte_table_action_*type*_config is defined by the Table Action
+ *   API, it needs to point to a valid instance of this structure, otherwise it
+ *   needs to be set to NULL.
+ * @return
+ *   Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_profile_action_register(struct rte_table_action_profile *profile,
+	enum rte_table_action_type type,
+	void *action_config);
+
+/**
+ * Table action profile freeze.
+ *
+ * Once this function is called successfully, the given profile enters the
+ * frozen state with the following immediate effects: no more actions can be
+ * registered for this profile, so the profile can be instantiated to create
+ * table action objects.
+ *
+ * @param[in] profile
+ *   Table profile action handle (needs to be valid and not in frozen state).
+ * @return
+ *   Zero on success, non-zero error code otherwise.
+ *
+ * @see rte_table_action_create()
+ */
+int __rte_experimental
+rte_table_action_profile_freeze(struct rte_table_action_profile *profile);
+
+/**
+ * Table action.
+ */
+struct rte_table_action;
+
+/**
+ * Table action create.
+ *
+ * Instantiates the given table action profile to create a table action object.
+ *
+ * @param[in] profile
+ *   Table profile action handle (needs to be valid and in frozen state).
+ * @param[in] socket_id
+ *   CPU socket ID where the internal data structures required by the new table
+ *   action object should be allocated.
+ * @return
+ *   Handle to table action object on success, NULL on error.
+ *
+ * @see rte_table_action_create()
+ */
+struct rte_table_action * __rte_experimental
+rte_table_action_create(struct rte_table_action_profile *profile,
+	uint32_t socket_id);
+
+/**
+ * Table action free.
+ *
+ * @param[in] action
+ *   Handle to table action object (needs to be valid).
+ * @return
+ *   Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_free(struct rte_table_action *action);
+
+/**
+ * Table action apply.
+ *
+ * @param[in] action
+ *   Handle to table action object (needs to be valid).
+ * @param[in] data
+ *   Data byte array (typically table rule data) to apply action *type* on.
+ * @param[in] type
+ *   Specific table action previously registered for the table action profile of
+ *   the *action* object.
+ * @param[in] action_params
+ *   Parameters for the *type* action.
+ *   If struct rte_table_action_*type*_params is defined by the Table Action
+ *   API, it needs to point to a valid instance of this structure, otherwise it
+ *   needs to be set to NULL.
+ * @return
+ *   Zero on success, non-zero error code otherwise.
+ */
+int __rte_experimental
+rte_table_action_apply(struct rte_table_action *action,
+	void *data,
+	enum rte_table_action_type type,
+	void *action_params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCLUDE_RTE_TABLE_ACTION_H__ */