All of lore.kernel.org
 help / color / mirror / Atom feed
From: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
To: dev@dpdk.org
Cc: jasvinder.singh@intel.com, yogesh.jangra@intel.com
Subject: [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline
Date: Thu,  4 Aug 2022 16:58:25 +0000	[thread overview]
Message-ID: <20220804165839.1074817-8-cristian.dumitrescu@intel.com> (raw)
In-Reply-To: <20220804165839.1074817-1-cristian.dumitrescu@intel.com>

Replace the legacy pipeline support with support for the SWX pipeline.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |    1 -
 drivers/net/softnic/rte_eth_softnic.c         |    6 -
 drivers/net/softnic/rte_eth_softnic_action.c  |  423 ---
 drivers/net/softnic/rte_eth_softnic_cli.c     |   16 +-
 .../net/softnic/rte_eth_softnic_internals.h   |  502 +---
 .../net/softnic/rte_eth_softnic_pipeline.c    |  988 +------
 drivers/net/softnic/rte_eth_softnic_thread.c  | 2594 +----------------
 7 files changed, 216 insertions(+), 4314 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_action.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 91f1f3220f..f0cfc6dc17 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -10,7 +10,6 @@ sources = files(
         'conn.c',
         'parser.c',
         'rte_eth_softnic.c',
-        'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index eb97ae7185..a940952c7a 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -160,8 +160,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	/* Firmware */
 	softnic_pipeline_disable_all(p);
 	softnic_pipeline_free(p);
-	softnic_table_action_profile_free(p);
-	softnic_port_in_action_profile_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
@@ -180,8 +178,6 @@ pmd_free(struct pmd_internals *p)
 
 	softnic_thread_free(p);
 	softnic_pipeline_free(p);
-	softnic_table_action_profile_free(p);
-	softnic_port_in_action_profile_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
@@ -261,8 +257,6 @@ pmd_init(struct pmd_params *params)
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_port_in_action_profile_init(p);
-	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
 
 	status = softnic_thread_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_action.c b/drivers/net/softnic/rte_eth_softnic_action.c
deleted file mode 100644
index 33be9552a6..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_action.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_string_fns.h>
-#include <rte_table_hash_func.h>
-
-#include "rte_eth_softnic_internals.h"
-
-/**
- * Input port
- */
-int
-softnic_port_in_action_profile_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->port_in_action_profile_list);
-
-	return 0;
-}
-
-void
-softnic_port_in_action_profile_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_port_in_action_profile *profile;
-
-		profile = TAILQ_FIRST(&p->port_in_action_profile_list);
-		if (profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->port_in_action_profile_list, profile, node);
-		free(profile);
-	}
-}
-
-struct softnic_port_in_action_profile *
-softnic_port_in_action_profile_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_port_in_action_profile *profile;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(profile, &p->port_in_action_profile_list, node)
-		if (strcmp(profile->name, name) == 0)
-			return profile;
-
-	return NULL;
-}
-
-struct softnic_port_in_action_profile *
-softnic_port_in_action_profile_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_port_in_action_profile_params *params)
-{
-	struct softnic_port_in_action_profile *profile;
-	struct rte_port_in_action_profile *ap;
-	int status;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_port_in_action_profile_find(p, name) ||
-		params == NULL)
-		return NULL;
-
-	if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) &&
-		params->lb.f_hash == NULL) {
-		switch (params->lb.key_size) {
-		case  8:
-			params->lb.f_hash = rte_table_hash_crc_key8;
-			break;
-
-		case 16:
-			params->lb.f_hash = rte_table_hash_crc_key16;
-			break;
-
-		case 24:
-			params->lb.f_hash = rte_table_hash_crc_key24;
-			break;
-
-		case 32:
-			params->lb.f_hash = rte_table_hash_crc_key32;
-			break;
-
-		case 40:
-			params->lb.f_hash = rte_table_hash_crc_key40;
-			break;
-
-		case 48:
-			params->lb.f_hash = rte_table_hash_crc_key48;
-			break;
-
-		case 56:
-			params->lb.f_hash = rte_table_hash_crc_key56;
-			break;
-
-		case 64:
-			params->lb.f_hash = rte_table_hash_crc_key64;
-			break;
-
-		default:
-			return NULL;
-		}
-
-		params->lb.seed = 0;
-	}
-
-	/* Resource */
-	ap = rte_port_in_action_profile_create(0);
-	if (ap == NULL)
-		return NULL;
-
-	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) {
-		status = rte_port_in_action_profile_action_register(ap,
-			RTE_PORT_IN_ACTION_FLTR,
-			&params->fltr);
-
-		if (status) {
-			rte_port_in_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) {
-		status = rte_port_in_action_profile_action_register(ap,
-			RTE_PORT_IN_ACTION_LB,
-			&params->lb);
-
-		if (status) {
-			rte_port_in_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	status = rte_port_in_action_profile_freeze(ap);
-	if (status) {
-		rte_port_in_action_profile_free(ap);
-		return NULL;
-	}
-
-	/* Node allocation */
-	profile = calloc(1, sizeof(struct softnic_port_in_action_profile));
-	if (profile == NULL) {
-		rte_port_in_action_profile_free(ap);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(profile->name, name, sizeof(profile->name));
-	memcpy(&profile->params, params, sizeof(*params));
-	profile->ap = ap;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->port_in_action_profile_list, profile, node);
-
-	return profile;
-}
-
-/**
- * Table
- */
-int
-softnic_table_action_profile_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->table_action_profile_list);
-
-	return 0;
-}
-
-void
-softnic_table_action_profile_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_table_action_profile *profile;
-
-		profile = TAILQ_FIRST(&p->table_action_profile_list);
-		if (profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->table_action_profile_list, profile, node);
-		rte_table_action_profile_free(profile->ap);
-		free(profile);
-	}
-}
-
-struct softnic_table_action_profile *
-softnic_table_action_profile_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_table_action_profile *profile;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(profile, &p->table_action_profile_list, node)
-		if (strcmp(profile->name, name) == 0)
-			return profile;
-
-	return NULL;
-}
-
-struct softnic_table_action_profile *
-softnic_table_action_profile_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_table_action_profile_params *params)
-{
-	struct softnic_table_action_profile *profile;
-	struct rte_table_action_profile *ap;
-	int status;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_table_action_profile_find(p, name) ||
-		params == NULL ||
-		((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0))
-		return NULL;
-
-	if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) &&
-		params->lb.f_hash == NULL) {
-		switch (params->lb.key_size) {
-		case 8:
-			params->lb.f_hash = rte_table_hash_crc_key8;
-			break;
-
-		case 16:
-			params->lb.f_hash = rte_table_hash_crc_key16;
-			break;
-
-		case 24:
-			params->lb.f_hash = rte_table_hash_crc_key24;
-			break;
-
-		case 32:
-			params->lb.f_hash = rte_table_hash_crc_key32;
-			break;
-
-		case 40:
-			params->lb.f_hash = rte_table_hash_crc_key40;
-			break;
-
-		case 48:
-			params->lb.f_hash = rte_table_hash_crc_key48;
-			break;
-
-		case 56:
-			params->lb.f_hash = rte_table_hash_crc_key56;
-			break;
-
-		case 64:
-			params->lb.f_hash = rte_table_hash_crc_key64;
-			break;
-
-		default:
-			return NULL;
-		}
-
-		params->lb.seed = 0;
-	}
-
-	/* Resource */
-	ap = rte_table_action_profile_create(&params->common);
-	if (ap == NULL)
-		return NULL;
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_FWD,
-			NULL);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_LB,
-			&params->lb);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_MTR,
-			&params->mtr);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_TM,
-			&params->tm);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_ENCAP,
-			&params->encap);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_NAT,
-			&params->nat);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_TTL,
-			&params->ttl);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_STATS,
-			&params->stats);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_TIME,
-			NULL);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_TAG,
-			NULL);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_DECAP,
-			NULL);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	if (params->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
-		status = rte_table_action_profile_action_register(ap,
-			RTE_TABLE_ACTION_SYM_CRYPTO,
-			&params->sym_crypto);
-
-		if (status) {
-			rte_table_action_profile_free(ap);
-			return NULL;
-		}
-	}
-
-	status = rte_table_action_profile_freeze(ap);
-	if (status) {
-		rte_table_action_profile_free(ap);
-		return NULL;
-	}
-
-	/* Node allocation */
-	profile = calloc(1, sizeof(struct softnic_table_action_profile));
-	if (profile == NULL) {
-		rte_table_action_profile_free(ap);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(profile->name, name, sizeof(profile->name));
-	memcpy(&profile->params, params, sizeof(*params));
-	profile->ap = ap;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->table_action_profile_list, profile, node);
-
-	return profile;
-}
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index abe275ec83..2b00b65c6c 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -196,6 +196,7 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 	size_t out_size)
 {
 	char *pipeline_name;
+	struct pipeline *p;
 	uint32_t thread_id;
 	int status;
 
@@ -215,13 +216,18 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 	}
 
 	pipeline_name = tokens[3];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
 
 	if (strcmp(tokens[4], "enable") != 0) {
 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
 		return;
 	}
 
-	status = softnic_thread_pipeline_enable(softnic, thread_id, pipeline_name);
+	status = softnic_thread_pipeline_enable(softnic, thread_id, p);
 	if (status) {
 		snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
 		return;
@@ -239,6 +245,7 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	size_t out_size)
 {
 	char *pipeline_name;
+	struct pipeline *p;
 	uint32_t thread_id;
 	int status;
 
@@ -258,13 +265,18 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	}
 
 	pipeline_name = tokens[3];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
 
 	if (strcmp(tokens[4], "disable") != 0) {
 		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
 		return;
 	}
 
-	status = softnic_thread_pipeline_disable(softnic, thread_id, pipeline_name);
+	status = softnic_thread_pipeline_disable(softnic, thread_id, p);
 	if (status) {
 		snprintf(out, out_size, MSG_CMD_FAIL,
 			"thread pipeline disable");
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index df74c1fbdc..d817883a39 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -13,9 +13,8 @@
 #include <rte_mbuf.h>
 #include <rte_ring.h>
 #include <rte_ethdev.h>
-#include <rte_port_in_action.h>
-#include <rte_table_action.h>
-#include <rte_pipeline.h>
+#include <rte_swx_pipeline.h>
+#include <rte_swx_ctl.h>
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
@@ -89,207 +88,18 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * Input port action
- */
-struct softnic_port_in_action_profile_params {
-	uint64_t action_mask;
-	struct rte_port_in_action_fltr_config fltr;
-	struct rte_port_in_action_lb_config lb;
-};
-
-struct softnic_port_in_action_profile {
-	TAILQ_ENTRY(softnic_port_in_action_profile) node;
-	char name[NAME_SIZE];
-	struct softnic_port_in_action_profile_params params;
-	struct rte_port_in_action_profile *ap;
-};
-
-TAILQ_HEAD(softnic_port_in_action_profile_list, softnic_port_in_action_profile);
-
-/**
- * Table action
- */
-struct softnic_table_action_profile_params {
-	uint64_t action_mask;
-	struct rte_table_action_common_config common;
-	struct rte_table_action_lb_config lb;
-	struct rte_table_action_mtr_config mtr;
-	struct rte_table_action_tm_config tm;
-	struct rte_table_action_encap_config encap;
-	struct rte_table_action_nat_config nat;
-	struct rte_table_action_ttl_config ttl;
-	struct rte_table_action_stats_config stats;
-	struct rte_table_action_sym_crypto_config sym_crypto;
-};
-
-struct softnic_table_action_profile {
-	TAILQ_ENTRY(softnic_table_action_profile) node;
-	char name[NAME_SIZE];
-	struct softnic_table_action_profile_params params;
-	struct rte_table_action_profile *ap;
-};
-
-TAILQ_HEAD(softnic_table_action_profile_list, softnic_table_action_profile);
-
-struct softnic_table_meter_profile {
-	TAILQ_ENTRY(softnic_table_meter_profile) node;
-	uint32_t meter_profile_id;
-	struct rte_table_action_meter_profile profile;
-};
-
-TAILQ_HEAD(softnic_table_meter_profile_list,
-	softnic_table_meter_profile);
-
 /**
  * Pipeline
  */
-struct pipeline_params {
-	uint32_t timer_period_ms;
-	uint32_t offset_port_id;
-};
-
-enum softnic_port_in_type {
-	PORT_IN_RXQ,
-	PORT_IN_SWQ,
-	PORT_IN_SOURCE,
-};
-
-struct softnic_port_in_params {
-	/* Read */
-	enum softnic_port_in_type type;
-	char dev_name[NAME_SIZE];
-	union {
-		struct {
-			uint16_t queue_id;
-		} rxq;
-
-		struct {
-			const char *mempool_name;
-			const char *file_name;
-			uint32_t n_bytes_per_pkt;
-		} source;
-	};
-	uint32_t burst_size;
-
-	/* Action */
-	char action_profile_name[NAME_SIZE];
-};
-
-enum softnic_port_out_type {
-	PORT_OUT_TXQ,
-	PORT_OUT_SWQ,
-	PORT_OUT_SINK,
-};
-
-struct softnic_port_out_params {
-	enum softnic_port_out_type type;
-	char dev_name[NAME_SIZE];
-	union {
-		struct {
-			uint16_t queue_id;
-		} txq;
-
-		struct {
-			const char *file_name;
-			uint32_t max_n_pkts;
-		} sink;
-	};
-	uint32_t burst_size;
-	int retry;
-	uint32_t n_retries;
-};
-
-enum softnic_table_type {
-	TABLE_ACL,
-	TABLE_ARRAY,
-	TABLE_HASH,
-	TABLE_LPM,
-	TABLE_STUB,
-};
-
-struct softnic_table_acl_params {
-	uint32_t n_rules;
-	uint32_t ip_header_offset;
-	int ip_version;
-};
-
-struct softnic_table_array_params {
-	uint32_t n_keys;
-	uint32_t key_offset;
-};
-
-#ifndef TABLE_RULE_MATCH_SIZE_MAX
-#define TABLE_RULE_MATCH_SIZE_MAX                          256
-#endif
-
-struct softnic_table_hash_params {
-	uint32_t n_keys;
-	uint32_t key_offset;
-	uint32_t key_size;
-	uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
-	uint32_t n_buckets;
-	int extendable_bucket;
-};
-
-struct softnic_table_lpm_params {
-	uint32_t n_rules;
-	uint32_t key_offset;
-	uint32_t key_size;
-};
-
-struct softnic_table_params {
-	/* Match */
-	enum softnic_table_type match_type;
-	union {
-		struct softnic_table_acl_params acl;
-		struct softnic_table_array_params array;
-		struct softnic_table_hash_params hash;
-		struct softnic_table_lpm_params lpm;
-	} match;
-
-	/* Action */
-	char action_profile_name[NAME_SIZE];
-};
-
-struct softnic_port_in {
-	struct softnic_port_in_params params;
-	struct softnic_port_in_action_profile *ap;
-	struct rte_port_in_action *a;
-};
-
-struct softnic_port_out {
-	struct softnic_port_out_params params;
-};
-
-struct softnic_table {
-	struct softnic_table_params params;
-	struct softnic_table_action_profile *ap;
-	struct rte_table_action *a;
-	struct rte_table_action_dscp_table dscp_table;
-	struct softnic_table_meter_profile_list meter_profiles;
-};
-
 struct pipeline {
 	TAILQ_ENTRY(pipeline) node;
 	char name[NAME_SIZE];
 
-	struct rte_pipeline *p;
-	struct pipeline_params params;
-	struct softnic_port_in port_in[RTE_PIPELINE_PORT_IN_MAX];
-	struct softnic_port_out port_out[RTE_PIPELINE_PORT_OUT_MAX];
-	struct softnic_table table[RTE_PIPELINE_TABLE_MAX];
-	uint32_t n_ports_in;
-	uint32_t n_ports_out;
-	uint32_t n_tables;
-
-	struct rte_ring *msgq_req;
-	struct rte_ring *msgq_rsp;
-	uint32_t timer_period_ms;
+	struct rte_swx_pipeline *p;
+	struct rte_swx_ctl_pipeline *ctl;
 
 	int enabled;
 	uint32_t thread_id;
-	uint32_t cpu_id;
 };
 
 TAILQ_HEAD(pipeline_list, pipeline);
@@ -309,6 +119,15 @@ TAILQ_HEAD(pipeline_list, pipeline);
 #define THREAD_TIMER_PERIOD_MS                             100
 #endif
 
+/* Pipeline instruction quanta: Needs to be big enough to do some meaningful
+ * work, but not too big to avoid starving any other pipelines mapped to the
+ * same thread. For a pipeline that executes 10 instructions per packet, a
+ * quanta of 1000 instructions equates to processing 100 packets.
+ */
+#ifndef PIPELINE_INSTR_QUANTA
+#define PIPELINE_INSTR_QUANTA                              1000
+#endif
+
 /**
  * Main thread: data plane thread context
  */
@@ -322,37 +141,14 @@ struct softnic_thread {
 /**
  * Data plane threads: context
  */
-#ifndef TABLE_RULE_ACTION_SIZE_MAX
-#define TABLE_RULE_ACTION_SIZE_MAX                         2048
-#endif
-
-struct softnic_table_data {
-	struct rte_table_action *a;
-};
-
-struct pipeline_data {
-	struct rte_pipeline *p;
-	struct softnic_table_data table_data[RTE_PIPELINE_TABLE_MAX];
-	uint32_t n_tables;
-
-	struct rte_ring *msgq_req;
-	struct rte_ring *msgq_rsp;
-	uint64_t timer_period; /* Measured in CPU cycles. */
-	uint64_t time_next;
-
-	uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX];
-};
-
 struct softnic_thread_data {
-	struct rte_pipeline *p[THREAD_PIPELINES_MAX];
+	struct rte_swx_pipeline *p[THREAD_PIPELINES_MAX];
 	uint32_t n_pipelines;
 
-	struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX];
 	struct rte_ring *msgq_req;
 	struct rte_ring *msgq_rsp;
 	uint64_t timer_period; /* Measured in CPU cycles. */
 	uint64_t time_next;
-	uint64_t time_next_min;
 	uint64_t iter;
 } __rte_cache_aligned;
 
@@ -367,8 +163,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_port_in_action_profile_list port_in_action_profile_list;
-	struct softnic_table_action_profile_list table_action_profile_list;
 	struct pipeline_list pipeline_list;
 	struct softnic_thread thread[RTE_MAX_LCORE];
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
@@ -447,42 +241,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * Input port action
- */
-int
-softnic_port_in_action_profile_init(struct pmd_internals *p);
-
-void
-softnic_port_in_action_profile_free(struct pmd_internals *p);
-
-struct softnic_port_in_action_profile *
-softnic_port_in_action_profile_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_port_in_action_profile *
-softnic_port_in_action_profile_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_port_in_action_profile_params *params);
-
-/**
- * Table action
- */
-int
-softnic_table_action_profile_init(struct pmd_internals *p);
-
-void
-softnic_table_action_profile_free(struct pmd_internals *p);
-
-struct softnic_table_action_profile *
-softnic_table_action_profile_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_table_action_profile *
-softnic_table_action_profile_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_table_action_profile_params *params);
-
 /**
  * Pipeline
  */
@@ -504,228 +262,9 @@ softnic_pipeline_find(struct pmd_internals *p, const char *name);
 struct pipeline *
 softnic_pipeline_create(struct pmd_internals *p,
 	const char *name,
-	struct pipeline_params *params);
-
-int
-softnic_pipeline_port_in_create(struct pmd_internals *p,
-	const char *pipeline_name,
-	struct softnic_port_in_params *params,
-	int enabled);
-
-int
-softnic_pipeline_port_in_connect_to_table(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t port_id,
-	uint32_t table_id);
-
-int
-softnic_pipeline_port_out_create(struct pmd_internals *p,
-	const char *pipeline_name,
-	struct softnic_port_out_params *params);
-
-int
-softnic_pipeline_port_out_find(struct pmd_internals *softnic,
-		const char *pipeline_name,
-		const char *name,
-		uint32_t *port_id);
-
-int
-softnic_pipeline_table_create(struct pmd_internals *p,
-	const char *pipeline_name,
-	struct softnic_table_params *params);
-
-struct softnic_table_meter_profile *
-softnic_pipeline_table_meter_profile_find(struct softnic_table *table,
-	uint32_t meter_profile_id);
-
-struct softnic_table_rule_match_acl {
-	int ip_version;
-
-	RTE_STD_C11
-	union {
-		struct {
-			uint32_t sa;
-			uint32_t da;
-		} ipv4;
-
-		struct {
-			uint8_t sa[16];
-			uint8_t da[16];
-		} ipv6;
-	};
-
-	uint32_t sa_depth;
-	uint32_t da_depth;
-	uint16_t sp0;
-	uint16_t sp1;
-	uint16_t dp0;
-	uint16_t dp1;
-	uint8_t proto;
-	uint8_t proto_mask;
-	uint32_t priority;
-};
-
-struct softnic_table_rule_match_array {
-	uint32_t pos;
-};
-
-struct softnic_table_rule_match_hash {
-	uint8_t key[TABLE_RULE_MATCH_SIZE_MAX];
-};
-
-struct softnic_table_rule_match_lpm {
-	int ip_version;
-
-	RTE_STD_C11
-	union {
-		uint32_t ipv4;
-		uint8_t ipv6[16];
-	};
-
-	uint8_t depth;
-};
-
-struct softnic_table_rule_match {
-	enum softnic_table_type match_type;
-
-	union {
-		struct softnic_table_rule_match_acl acl;
-		struct softnic_table_rule_match_array array;
-		struct softnic_table_rule_match_hash hash;
-		struct softnic_table_rule_match_lpm lpm;
-	} match;
-};
-
-#ifndef SYM_CRYPTO_MAX_KEY_SIZE
-#define SYM_CRYPTO_MAX_KEY_SIZE		(256)
-#endif
-struct softnic_table_rule_action {
-	uint64_t action_mask;
-	struct rte_table_action_fwd_params fwd;
-	struct rte_table_action_lb_params lb;
-	struct rte_table_action_mtr_params mtr;
-	struct rte_table_action_tm_params tm;
-	struct rte_table_action_encap_params encap;
-	struct rte_table_action_nat_params nat;
-	struct rte_table_action_ttl_params ttl;
-	struct rte_table_action_stats_params stats;
-	struct rte_table_action_time_params time;
-	struct rte_table_action_tag_params tag;
-	struct rte_table_action_decap_params decap;
-	struct rte_table_action_sym_crypto_params sym_crypto;
-	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
-};
-
-int
-softnic_pipeline_port_in_stats_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t port_id,
-	struct rte_pipeline_port_in_stats *stats,
-	int clear);
-
-int
-softnic_pipeline_port_in_enable(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t port_id);
-
-int
-softnic_pipeline_port_in_disable(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t port_id);
-
-int
-softnic_pipeline_port_out_stats_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t port_id,
-	struct rte_pipeline_port_out_stats *stats,
-	int clear);
-
-int
-softnic_pipeline_table_stats_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct rte_pipeline_table_stats *stats,
-	int clear);
-
-int
-softnic_pipeline_table_rule_add(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match,
-	struct softnic_table_rule_action *action,
-	void **data);
-
-int
-softnic_pipeline_table_rule_add_bulk(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match,
-	struct softnic_table_rule_action *action,
-	void **data,
-	uint32_t *n_rules);
-
-int
-softnic_pipeline_table_rule_add_default(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_action *action,
-	void **data);
-
-int
-softnic_pipeline_table_rule_delete(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match);
-
-int
-softnic_pipeline_table_rule_delete_default(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id);
-
-int
-softnic_pipeline_table_rule_stats_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	struct rte_table_action_stats_counters *stats,
-	int clear);
-
-int
-softnic_pipeline_table_mtr_profile_add(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint32_t meter_profile_id,
-	struct rte_table_action_meter_profile *profile);
-
-int
-softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint32_t meter_profile_id);
-
-int
-softnic_pipeline_table_rule_mtr_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	uint32_t tc_mask,
-	struct rte_table_action_mtr_counters *stats,
-	int clear);
-
-int
-softnic_pipeline_table_dscp_table_update(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint64_t dscp_mask,
-	struct rte_table_action_dscp_table *dscp_table);
-
-int
-softnic_pipeline_table_rule_ttl_read(struct pmd_internals *p,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	struct rte_table_action_ttl_counters *stats,
-	int clear);
+	const char *lib_file_name,
+	const char *iospec_file_name,
+	int numa_node);
 
 /**
  * Thread
@@ -739,12 +278,15 @@ softnic_thread_free(struct pmd_internals *p);
 int
 softnic_thread_pipeline_enable(struct pmd_internals *p,
 	uint32_t thread_id,
-	const char *pipeline_name);
+	struct pipeline *pipeline);
 
 int
 softnic_thread_pipeline_disable(struct pmd_internals *p,
 	uint32_t thread_id,
-	const char *pipeline_name);
+	struct pipeline *pipeline);
+
+void
+softnic_thread_pipeline_disable_all(struct pmd_internals *p);
 
 /**
  * CLI
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 7a2828b785..76570b2cb3 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -6,35 +6,10 @@
 #include <string.h>
 
 #include <rte_common.h>
-#include <rte_ip.h>
-#include <rte_tcp.h>
-
 #include <rte_string_fns.h>
-#include <rte_port_ethdev.h>
-#include <rte_port_ring.h>
-#include <rte_port_source_sink.h>
-#include <rte_port_fd.h>
-#include <rte_port_sched.h>
-#include <rte_port_sym_crypto.h>
-
-#include <rte_table_acl.h>
-#include <rte_table_array.h>
-#include <rte_table_hash.h>
-#include <rte_table_hash_func.h>
-#include <rte_table_lpm.h>
-#include <rte_table_lpm_ipv6.h>
-#include <rte_table_stub.h>
 
 #include "rte_eth_softnic_internals.h"
 
-#ifndef PIPELINE_MSGQ_SIZE
-#define PIPELINE_MSGQ_SIZE                                 64
-#endif
-
-#ifndef TABLE_LPM_NUMBER_TBL8
-#define TABLE_LPM_NUMBER_TBL8                              256
-#endif
-
 int
 softnic_pipeline_init(struct pmd_internals *p)
 {
@@ -43,44 +18,19 @@ softnic_pipeline_init(struct pmd_internals *p)
 	return 0;
 }
 
-static void
-softnic_pipeline_table_free(struct softnic_table *table)
-{
-	for ( ; ; ) {
-		struct softnic_table_meter_profile *mp;
-
-		mp = TAILQ_FIRST(&table->meter_profiles);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&table->meter_profiles, mp, node);
-		free(mp);
-	}
-}
-
 void
 softnic_pipeline_free(struct pmd_internals *p)
 {
 	for ( ; ; ) {
 		struct pipeline *pipeline;
-		uint32_t table_id;
 
 		pipeline = TAILQ_FIRST(&p->pipeline_list);
 		if (pipeline == NULL)
 			break;
 
 		TAILQ_REMOVE(&p->pipeline_list, pipeline, node);
-
-		for (table_id = 0; table_id < pipeline->n_tables; table_id++) {
-			struct softnic_table *table =
-				&pipeline->table[table_id];
-
-			softnic_pipeline_table_free(table);
-		}
-
-		rte_ring_free(pipeline->msgq_req);
-		rte_ring_free(pipeline->msgq_rsp);
-		rte_pipeline_free(pipeline->p);
+		rte_swx_ctl_pipeline_free(pipeline->ctl);
+		rte_swx_pipeline_free(pipeline->p);
 		free(pipeline);
 	}
 }
@@ -94,7 +44,7 @@ softnic_pipeline_disable_all(struct pmd_internals *p)
 		if (pipeline->enabled)
 			softnic_thread_pipeline_disable(p,
 				pipeline->thread_id,
-				pipeline->name);
+				pipeline);
 }
 
 uint32_t
@@ -126,850 +76,170 @@ softnic_pipeline_find(struct pmd_internals *p,
 	return NULL;
 }
 
-struct pipeline *
-softnic_pipeline_create(struct pmd_internals *softnic,
-	const char *name,
-	struct pipeline_params *params)
-{
-	char resource_name[NAME_MAX];
-	struct rte_pipeline_params pp;
-	struct pipeline *pipeline;
-	struct rte_pipeline *p;
-	struct rte_ring *msgq_req;
-	struct rte_ring *msgq_rsp;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_pipeline_find(softnic, name) ||
-		params == NULL ||
-		params->timer_period_ms == 0)
-		return NULL;
-
-	/* Resource create */
-	snprintf(resource_name, sizeof(resource_name), "%s-%s-REQ",
-		softnic->params.name,
-		name);
-
-	msgq_req = rte_ring_create(resource_name,
-		PIPELINE_MSGQ_SIZE,
-		softnic->params.cpu_id,
-		RING_F_SP_ENQ | RING_F_SC_DEQ);
-	if (msgq_req == NULL)
-		return NULL;
-
-	snprintf(resource_name, sizeof(resource_name), "%s-%s-RSP",
-		softnic->params.name,
-		name);
-
-	msgq_rsp = rte_ring_create(resource_name,
-		PIPELINE_MSGQ_SIZE,
-		softnic->params.cpu_id,
-		RING_F_SP_ENQ | RING_F_SC_DEQ);
-	if (msgq_rsp == NULL) {
-		rte_ring_free(msgq_req);
-		return NULL;
-	}
-
-	snprintf(resource_name, sizeof(resource_name), "%s_%s",
-		softnic->params.name,
-		name);
-
-	pp.name = resource_name;
-	pp.socket_id = (int)softnic->params.cpu_id;
-	pp.offset_port_id = params->offset_port_id;
-
-	p = rte_pipeline_create(&pp);
-	if (p == NULL) {
-		rte_ring_free(msgq_rsp);
-		rte_ring_free(msgq_req);
-		return NULL;
-	}
-
-	/* Node allocation */
-	pipeline = calloc(1, sizeof(struct pipeline));
-	if (pipeline == NULL) {
-		rte_pipeline_free(p);
-		rte_ring_free(msgq_rsp);
-		rte_ring_free(msgq_req);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(pipeline->name, name, sizeof(pipeline->name));
-	pipeline->p = p;
-	memcpy(&pipeline->params, params, sizeof(*params));
-	pipeline->n_ports_in = 0;
-	pipeline->n_ports_out = 0;
-	pipeline->n_tables = 0;
-	pipeline->msgq_req = msgq_req;
-	pipeline->msgq_rsp = msgq_rsp;
-	pipeline->timer_period_ms = params->timer_period_ms;
-	pipeline->enabled = 0;
-	pipeline->cpu_id = softnic->params.cpu_id;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node);
-
-	return pipeline;
-}
+#ifndef MAX_LINE_LENGTH
+#define MAX_LINE_LENGTH 2048
+#endif
 
-int
-softnic_pipeline_port_in_create(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	struct softnic_port_in_params *params,
-	int enabled)
+/* The Soft NIC device internal resources such as mempools, rings or pipelines are globally visible,
+ * hence they need to have globally unique names. In order to apply the same configuration scripts
+ * unmodified to all the Soft NIC devices that instantiate the same program, the pipeline I/O
+ * configuration files are silently translated internally to prefix the name of the above resources
+ * with the Soft NIC device name, thus making the resource names globally unique.
+ */
+static int
+iospec_translate(struct pmd_internals *softnic __rte_unused,
+		 const char *file_in_name,
+		 const char *file_out_name)
 {
-	struct rte_pipeline_port_in_params p;
-
-	union {
-		struct rte_port_ethdev_reader_params ethdev;
-		struct rte_port_ring_reader_params ring;
-		struct rte_port_sched_reader_params sched;
-		struct rte_port_fd_reader_params fd;
-		struct rte_port_source_params source;
-	} pp;
+	FILE *fi = NULL, *fo = NULL;
+	char *line = NULL;
+	int status = 0;
 
-	struct pipeline *pipeline;
-	struct softnic_port_in *port_in;
-	struct softnic_port_in_action_profile *ap;
-	struct rte_port_in_action *action;
-	uint32_t port_id;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-	memset(&pp, 0, sizeof(pp));
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		params == NULL ||
-		params->burst_size == 0 ||
-		params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return -1;
-
-	ap = NULL;
-	if (strlen(params->action_profile_name)) {
-		ap = softnic_port_in_action_profile_find(softnic,
-			params->action_profile_name);
-		if (ap == NULL)
-			return -1;
+	/* File open. */
+	fi = fopen(file_in_name, "r");
+	fo = fopen(file_out_name, "w");
+	if (!fi || !fo) {
+		status = -EIO;
+		goto free;
 	}
 
-	switch (params->type) {
-	case PORT_IN_RXQ:
-	{
-		struct softnic_link *link;
-
-		link = softnic_link_find(softnic, params->dev_name);
-		if (link == NULL)
-			return -1;
-
-		if (params->rxq.queue_id >= link->n_rxq)
-			return -1;
-
-		pp.ethdev.port_id = link->port_id;
-		pp.ethdev.queue_id = params->rxq.queue_id;
-
-		p.ops = &rte_port_ethdev_reader_ops;
-		p.arg_create = &pp.ethdev;
-		break;
+	/* Memory allocation. */
+	line = malloc(MAX_LINE_LENGTH);
+	if (!line) {
+		status = -ENOMEM;
+		goto free;
 	}
 
-	case PORT_IN_SWQ:
-	{
-		struct softnic_swq *swq;
-
-		swq = softnic_swq_find(softnic, params->dev_name);
-		if (swq == NULL)
-			return -1;
-
-		pp.ring.ring = swq->r;
-
-		p.ops = &rte_port_ring_reader_ops;
-		p.arg_create = &pp.ring;
-		break;
-	}
+	/* Read from the input file and write to the output file. */
+	for ( ; ; ) {
+		char *ptr = line;
+		uint32_t n_tokens;
+		int flag = 0;
 
-	case PORT_IN_SOURCE:
-	{
-		struct softnic_mempool *mempool;
+		/* Read next line. */
+		if (!fgets(line, MAX_LINE_LENGTH, fi))
+			break;
 
-		mempool = softnic_mempool_find(softnic, params->source.mempool_name);
-		if (mempool == NULL)
-			return -1;
+		/* Parse the line into tokens. */
+		for (n_tokens = 0; ; n_tokens++) {
+			char *token;
 
-		pp.source.mempool = mempool->m;
-		pp.source.file_name = params->source.file_name;
-		pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt;
+			/* Read token. */
+			token = strtok_r(ptr, " \f\n\r\t\v", &ptr);
+			if (!token)
+				break;
 
-		p.ops = &rte_port_source_ops;
-		p.arg_create = &pp.source;
-		break;
-	}
+			/* Handle comments. */
+			if (!n_tokens &&
+			    ((token[0] == '#') ||
+			     (token[0] == ';') ||
+			     ((token[0] == '/') && (token[1] == '/'))))
+				break;
 
-	default:
-		return -1;
-	}
+			/* Process token. */
+			if (flag) {
+				fprintf(fo, "%s_%s ", softnic->params.name, token);
+				flag = 0;
+				continue;
+			}
 
-	p.burst_size = params->burst_size;
+			if (!strcmp(token, "mempool") ||
+			    !strcmp(token, "ring")) {
+				flag = 1;
+				fprintf(fo, "%s ", token);
+				continue;
+			}
 
-	/* Resource create */
-	action = NULL;
-	p.f_action = NULL;
-	p.arg_ah = NULL;
-
-	if (ap) {
-		action = rte_port_in_action_create(ap->ap,
-			softnic->params.cpu_id);
-		if (action == NULL)
-			return -1;
-
-		status = rte_port_in_action_params_get(action,
-			&p);
-		if (status) {
-			rte_port_in_action_free(action);
-			return -1;
+			/* Default action: write token. */
+			fprintf(fo, "%s ", token);
 		}
-	}
-
-	status = rte_pipeline_port_in_create(pipeline->p,
-		&p,
-		&port_id);
-	if (status) {
-		rte_port_in_action_free(action);
-		return -1;
-	}
-
-	if (enabled)
-		rte_pipeline_port_in_enable(pipeline->p, port_id);
-
-	/* Pipeline */
-	port_in = &pipeline->port_in[pipeline->n_ports_in];
-	memcpy(&port_in->params, params, sizeof(*params));
-	port_in->ap = ap;
-	port_in->a = action;
-	pipeline->n_ports_in++;
-
-	return 0;
-}
-
-int
-softnic_pipeline_port_in_connect_to_table(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t port_id,
-	uint32_t table_id)
-{
-	struct pipeline *pipeline;
-	int status;
 
-	/* Check input params */
-	if (pipeline_name == NULL)
-		return -1;
+		/* Handle empty or comment lines. */
+		if (!n_tokens)
+			continue;
 
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL ||
-		port_id >= pipeline->n_ports_in ||
-		table_id >= pipeline->n_tables)
-		return -1;
+		/* Write newline. */
+		fprintf(fo, "\n");
+	}
 
-	/* Resource */
-	status = rte_pipeline_port_in_connect_to_table(pipeline->p,
-		port_id,
-		table_id);
+free:
+	/* Memory free. */
+	free(line);
 
+	/* File close. */
+	if (fi)
+		fclose(fi);
+	if (fo)
+		fclose(fo);
 	return status;
 }
 
-int
-softnic_pipeline_port_out_create(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	struct softnic_port_out_params *params)
+struct pipeline *
+softnic_pipeline_create(struct pmd_internals *softnic,
+	const char *name,
+	const char *lib_file_name,
+	const char *iospec_file_name,
+	int numa_node)
 {
-	struct rte_pipeline_port_out_params p;
-
-	union {
-		struct rte_port_ethdev_writer_params ethdev;
-		struct rte_port_ring_writer_params ring;
-		struct rte_port_sched_writer_params sched;
-		struct rte_port_fd_writer_params fd;
-		struct rte_port_sink_params sink;
-	} pp;
-
-	union {
-		struct rte_port_ethdev_writer_nodrop_params ethdev;
-		struct rte_port_ring_writer_nodrop_params ring;
-		struct rte_port_fd_writer_nodrop_params fd;
-	} pp_nodrop;
-
-	struct pipeline *pipeline;
-	struct softnic_port_out *port_out;
-	uint32_t port_id;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-	memset(&pp, 0, sizeof(pp));
-	memset(&pp_nodrop, 0, sizeof(pp_nodrop));
+	char global_name[NAME_MAX];
+	FILE *iospec_file = NULL;
+	struct pipeline *pipeline = NULL;
+	struct rte_swx_pipeline *p = NULL;
+	struct rte_swx_ctl_pipeline *ctl = NULL;
+	int status = 0;
 
 	/* Check input params */
-	if (pipeline_name == NULL ||
-		params == NULL ||
-		params->burst_size == 0 ||
-		params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return -1;
-
-	switch (params->type) {
-	case PORT_OUT_TXQ:
-	{
-		struct softnic_link *link;
-
-		link = softnic_link_find(softnic, params->dev_name);
-		if (link == NULL)
-			return -1;
-
-		if (params->txq.queue_id >= link->n_txq)
-			return -1;
-
-		pp.ethdev.port_id = link->port_id;
-		pp.ethdev.queue_id = params->txq.queue_id;
-		pp.ethdev.tx_burst_sz = params->burst_size;
-
-		pp_nodrop.ethdev.port_id = link->port_id;
-		pp_nodrop.ethdev.queue_id = params->txq.queue_id;
-		pp_nodrop.ethdev.tx_burst_sz = params->burst_size;
-		pp_nodrop.ethdev.n_retries = params->n_retries;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_ethdev_writer_ops;
-			p.arg_create = &pp.ethdev;
-		} else {
-			p.ops = &rte_port_ethdev_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.ethdev;
-		}
-		break;
-	}
-
-	case PORT_OUT_SWQ:
-	{
-		struct softnic_swq *swq;
-
-		swq = softnic_swq_find(softnic, params->dev_name);
-		if (swq == NULL)
-			return -1;
-
-		pp.ring.ring = swq->r;
-		pp.ring.tx_burst_sz = params->burst_size;
-
-		pp_nodrop.ring.ring = swq->r;
-		pp_nodrop.ring.tx_burst_sz = params->burst_size;
-		pp_nodrop.ring.n_retries = params->n_retries;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_ring_writer_ops;
-			p.arg_create = &pp.ring;
-		} else {
-			p.ops = &rte_port_ring_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.ring;
-		}
-		break;
-	}
-
-	case PORT_OUT_SINK:
-	{
-		pp.sink.file_name = params->sink.file_name;
-		pp.sink.max_n_pkts = params->sink.max_n_pkts;
-
-		p.ops = &rte_port_sink_ops;
-		p.arg_create = &pp.sink;
-		break;
-	}
-
-	default:
-		return -1;
-	}
-
-	p.f_action = NULL;
-	p.arg_ah = NULL;
+	if (!name || !name[0] || softnic_pipeline_find(softnic, name))
+		goto error;
 
 	/* Resource create */
-	status = rte_pipeline_port_out_create(pipeline->p,
-		&p,
-		&port_id);
+	snprintf(global_name, sizeof(global_name), "/tmp/%s_%s.io", softnic->params.name, name);
 
+	status = iospec_translate(softnic, iospec_file_name, global_name);
 	if (status)
-		return -1;
-
-	/* Pipeline */
-	port_out = &pipeline->port_out[pipeline->n_ports_out];
-	memcpy(&port_out->params, params, sizeof(*params));
-	pipeline->n_ports_out++;
-
-	return 0;
-}
+		goto error;
 
-static const struct rte_acl_field_def table_acl_field_format_ipv4[] = {
-	/* Protocol */
-	[0] = {
-		.type = RTE_ACL_FIELD_TYPE_BITMASK,
-		.size = sizeof(uint8_t),
-		.field_index = 0,
-		.input_index = 0,
-		.offset = offsetof(struct rte_ipv4_hdr, next_proto_id),
-	},
-
-	/* Source IP address (IPv4) */
-	[1] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 1,
-		.input_index = 1,
-		.offset = offsetof(struct rte_ipv4_hdr, src_addr),
-	},
-
-	/* Destination IP address (IPv4) */
-	[2] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 2,
-		.input_index = 2,
-		.offset = offsetof(struct rte_ipv4_hdr, dst_addr),
-	},
-
-	/* Source Port */
-	[3] = {
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = 3,
-		.input_index = 3,
-		.offset = sizeof(struct rte_ipv4_hdr) +
-			offsetof(struct rte_tcp_hdr, src_port),
-	},
-
-	/* Destination Port */
-	[4] = {
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = 4,
-		.input_index = 3,
-		.offset = sizeof(struct rte_ipv4_hdr) +
-			offsetof(struct rte_tcp_hdr, dst_port),
-	},
-};
-
-static const struct rte_acl_field_def table_acl_field_format_ipv6[] = {
-	/* Protocol */
-	[0] = {
-		.type = RTE_ACL_FIELD_TYPE_BITMASK,
-		.size = sizeof(uint8_t),
-		.field_index = 0,
-		.input_index = 0,
-		.offset = offsetof(struct rte_ipv6_hdr, proto),
-	},
-
-	/* Source IP address (IPv6) */
-	[1] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 1,
-		.input_index = 1,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[0]),
-	},
-
-	[2] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 2,
-		.input_index = 2,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[4]),
-	},
-
-	[3] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 3,
-		.input_index = 3,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[8]),
-	},
-
-	[4] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 4,
-		.input_index = 4,
-		.offset = offsetof(struct rte_ipv6_hdr, src_addr[12]),
-	},
-
-	/* Destination IP address (IPv6) */
-	[5] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 5,
-		.input_index = 5,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[0]),
-	},
-
-	[6] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 6,
-		.input_index = 6,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[4]),
-	},
-
-	[7] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 7,
-		.input_index = 7,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[8]),
-	},
-
-	[8] = {
-		.type = RTE_ACL_FIELD_TYPE_MASK,
-		.size = sizeof(uint32_t),
-		.field_index = 8,
-		.input_index = 8,
-		.offset = offsetof(struct rte_ipv6_hdr, dst_addr[12]),
-	},
-
-	/* Source Port */
-	[9] = {
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = 9,
-		.input_index = 9,
-		.offset = sizeof(struct rte_ipv6_hdr) +
-			offsetof(struct rte_tcp_hdr, src_port),
-	},
-
-	/* Destination Port */
-	[10] = {
-		.type = RTE_ACL_FIELD_TYPE_RANGE,
-		.size = sizeof(uint16_t),
-		.field_index = 10,
-		.input_index = 9,
-		.offset = sizeof(struct rte_ipv6_hdr) +
-			offsetof(struct rte_tcp_hdr, dst_port),
-	},
-};
-
-int
-softnic_pipeline_table_create(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	struct softnic_table_params *params)
-{
-	char name[NAME_MAX];
-	struct rte_pipeline_table_params p;
-
-	union {
-		struct rte_table_acl_params acl;
-		struct rte_table_array_params array;
-		struct rte_table_hash_params hash;
-		struct rte_table_lpm_params lpm;
-		struct rte_table_lpm_ipv6_params lpm_ipv6;
-	} pp;
-
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_table_action_profile *ap;
-	struct rte_table_action *action;
-	uint32_t table_id;
-	int status;
+	iospec_file = fopen(global_name, "r");
+	if (!iospec_file)
+		goto error;
 
-	memset(&p, 0, sizeof(p));
-	memset(&pp, 0, sizeof(pp));
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		params == NULL)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL ||
-		pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX)
-		return -1;
-
-	ap = NULL;
-	if (strlen(params->action_profile_name)) {
-		ap = softnic_table_action_profile_find(softnic,
-			params->action_profile_name);
-		if (ap == NULL)
-			return -1;
-	}
-
-	snprintf(name, NAME_MAX, "%s_%s_table%u",
-		softnic->params.name, pipeline_name, pipeline->n_tables);
-
-	switch (params->match_type) {
-	case TABLE_ACL:
-	{
-		uint32_t ip_header_offset = params->match.acl.ip_header_offset -
-			(sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM);
-		uint32_t i;
-
-		if (params->match.acl.n_rules == 0)
-			return -1;
-
-		pp.acl.name = name;
-		pp.acl.n_rules = params->match.acl.n_rules;
-		if (params->match.acl.ip_version) {
-			memcpy(&pp.acl.field_format,
-				&table_acl_field_format_ipv4,
-				sizeof(table_acl_field_format_ipv4));
-			pp.acl.n_rule_fields =
-				RTE_DIM(table_acl_field_format_ipv4);
-		} else {
-			memcpy(&pp.acl.field_format,
-				&table_acl_field_format_ipv6,
-				sizeof(table_acl_field_format_ipv6));
-			pp.acl.n_rule_fields =
-				RTE_DIM(table_acl_field_format_ipv6);
-		}
-
-		for (i = 0; i < pp.acl.n_rule_fields; i++)
-			pp.acl.field_format[i].offset += ip_header_offset;
-
-		p.ops = &rte_table_acl_ops;
-		p.arg_create = &pp.acl;
-		break;
-	}
-
-	case TABLE_ARRAY:
-	{
-		if (params->match.array.n_keys == 0)
-			return -1;
-
-		pp.array.n_entries = params->match.array.n_keys;
-		pp.array.offset = params->match.array.key_offset;
-
-		p.ops = &rte_table_array_ops;
-		p.arg_create = &pp.array;
-		break;
-	}
-
-	case TABLE_HASH:
-	{
-		struct rte_table_ops *ops;
-		rte_table_hash_op_hash f_hash;
-
-		if (params->match.hash.n_keys == 0)
-			return -1;
-
-		switch (params->match.hash.key_size) {
-		case  8:
-			f_hash = rte_table_hash_crc_key8;
-			break;
-		case 16:
-			f_hash = rte_table_hash_crc_key16;
-			break;
-		case 24:
-			f_hash = rte_table_hash_crc_key24;
-			break;
-		case 32:
-			f_hash = rte_table_hash_crc_key32;
-			break;
-		case 40:
-			f_hash = rte_table_hash_crc_key40;
-			break;
-		case 48:
-			f_hash = rte_table_hash_crc_key48;
-			break;
-		case 56:
-			f_hash = rte_table_hash_crc_key56;
-			break;
-		case 64:
-			f_hash = rte_table_hash_crc_key64;
-			break;
-		default:
-			return -1;
-		}
+	snprintf(global_name, sizeof(global_name), "%s_%s", softnic->params.name, name);
 
-		pp.hash.name = name;
-		pp.hash.key_size = params->match.hash.key_size;
-		pp.hash.key_offset = params->match.hash.key_offset;
-		pp.hash.key_mask = params->match.hash.key_mask;
-		pp.hash.n_keys = params->match.hash.n_keys;
-		pp.hash.n_buckets = params->match.hash.n_buckets;
-		pp.hash.f_hash = f_hash;
-		pp.hash.seed = 0;
-
-		if (params->match.hash.extendable_bucket)
-			switch (params->match.hash.key_size) {
-			case  8:
-				ops = &rte_table_hash_key8_ext_ops;
-				break;
-			case 16:
-				ops = &rte_table_hash_key16_ext_ops;
-				break;
-			default:
-				ops = &rte_table_hash_ext_ops;
-			}
-		else
-			switch (params->match.hash.key_size) {
-			case  8:
-				ops = &rte_table_hash_key8_lru_ops;
-				break;
-			case 16:
-				ops = &rte_table_hash_key16_lru_ops;
-				break;
-			default:
-				ops = &rte_table_hash_lru_ops;
-			}
-
-		p.ops = ops;
-		p.arg_create = &pp.hash;
-		break;
-	}
-
-	case TABLE_LPM:
-	{
-		if (params->match.lpm.n_rules == 0)
-			return -1;
-
-		switch (params->match.lpm.key_size) {
-		case 4:
-		{
-			pp.lpm.name = name;
-			pp.lpm.n_rules = params->match.lpm.n_rules;
-			pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
-			pp.lpm.flags = 0;
-			pp.lpm.entry_unique_size = p.action_data_size +
-				sizeof(struct rte_pipeline_table_entry);
-			pp.lpm.offset = params->match.lpm.key_offset;
-
-			p.ops = &rte_table_lpm_ops;
-			p.arg_create = &pp.lpm;
-			break;
-		}
-
-		case 16:
-		{
-			pp.lpm_ipv6.name = name;
-			pp.lpm_ipv6.n_rules = params->match.lpm.n_rules;
-			pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8;
-			pp.lpm_ipv6.entry_unique_size = p.action_data_size +
-				sizeof(struct rte_pipeline_table_entry);
-			pp.lpm_ipv6.offset = params->match.lpm.key_offset;
-
-			p.ops = &rte_table_lpm_ipv6_ops;
-			p.arg_create = &pp.lpm_ipv6;
-			break;
-		}
-
-		default:
-			return -1;
-		}
-
-		break;
-	}
-
-	case TABLE_STUB:
-	{
-		p.ops = &rte_table_stub_ops;
-		p.arg_create = NULL;
-		break;
-	}
-
-	default:
-		return -1;
-	}
-
-	/* Resource create */
-	action = NULL;
-	p.f_action_hit = NULL;
-	p.f_action_miss = NULL;
-	p.arg_ah = NULL;
-
-	if (ap) {
-		action = rte_table_action_create(ap->ap,
-			softnic->params.cpu_id);
-		if (action == NULL)
-			return -1;
-
-		status = rte_table_action_table_params_get(action,
-			&p);
-		if (status ||
-			((p.action_data_size +
-			sizeof(struct rte_pipeline_table_entry)) >
-			TABLE_RULE_ACTION_SIZE_MAX)) {
-			rte_table_action_free(action);
-			return -1;
-		}
-	}
-
-	if (params->match_type == TABLE_LPM) {
-		if (params->match.lpm.key_size == 4)
-			pp.lpm.entry_unique_size = p.action_data_size +
-				sizeof(struct rte_pipeline_table_entry);
-
-		if (params->match.lpm.key_size == 16)
-			pp.lpm_ipv6.entry_unique_size = p.action_data_size +
-				sizeof(struct rte_pipeline_table_entry);
-	}
-
-	status = rte_pipeline_table_create(pipeline->p,
-		&p,
-		&table_id);
-	if (status) {
-		rte_table_action_free(action);
-		return -1;
-	}
+	status = rte_swx_pipeline_build_from_lib(&p,
+						 global_name,
+						 lib_file_name,
+						 iospec_file,
+						 numa_node);
+	if (status)
+		goto error;
 
-	/* Pipeline */
-	table = &pipeline->table[pipeline->n_tables];
-	memcpy(&table->params, params, sizeof(*params));
-	table->ap = ap;
-	table->a = action;
-	TAILQ_INIT(&table->meter_profiles);
-	memset(&table->dscp_table, 0, sizeof(table->dscp_table));
-	pipeline->n_tables++;
+	fclose(iospec_file);
+	iospec_file = NULL;
 
-	return 0;
-}
+	ctl = rte_swx_ctl_pipeline_create(p);
+	if (!ctl)
+		goto error;
 
-int
-softnic_pipeline_port_out_find(struct pmd_internals *softnic,
-		const char *pipeline_name,
-		const char *name,
-		uint32_t *port_id)
-{
-	struct pipeline *pipeline;
-	uint32_t i;
-
-	if (softnic == NULL ||
-			pipeline_name == NULL ||
-			name == NULL ||
-			port_id == NULL)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return -1;
-
-	for (i = 0; i < pipeline->n_ports_out; i++)
-		if (strcmp(pipeline->port_out[i].params.dev_name, name) == 0) {
-			*port_id = i;
-			return 0;
-		}
+	/* Node allocation */
+	pipeline = calloc(1, sizeof(struct pipeline));
+	if (!pipeline)
+		goto error;
 
-	return -1;
-}
+	/* Node fill in */
+	strlcpy(pipeline->name, name, sizeof(pipeline->name));
+	pipeline->p = p;
+	pipeline->ctl = ctl;
 
-struct softnic_table_meter_profile *
-softnic_pipeline_table_meter_profile_find(struct softnic_table *table,
-	uint32_t meter_profile_id)
-{
-	struct softnic_table_meter_profile *mp;
+	/* Node add to list */
+	TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node);
 
-	TAILQ_FOREACH(mp, &table->meter_profiles, node)
-		if (mp->meter_profile_id == meter_profile_id)
-			return mp;
+	return pipeline;
 
+error:
+	free(pipeline);
+	rte_swx_ctl_pipeline_free(ctl);
+	rte_swx_pipeline_free(p);
+	if (iospec_file)
+		fclose(iospec_file);
 	return NULL;
 }
diff --git a/drivers/net/softnic/rte_eth_softnic_thread.c b/drivers/net/softnic/rte_eth_softnic_thread.c
index ec8bef4694..888af6caf4 100644
--- a/drivers/net/softnic/rte_eth_softnic_thread.c
+++ b/drivers/net/softnic/rte_eth_softnic_thread.c
@@ -10,11 +10,6 @@
 #include <rte_service_component.h>
 #include <rte_ring.h>
 
-#include <rte_table_acl.h>
-#include <rte_table_array.h>
-#include <rte_table_hash.h>
-#include <rte_table_lpm.h>
-#include <rte_table_lpm_ipv6.h>
 #include "rte_eth_softnic_internals.h"
 
 /**
@@ -88,7 +83,6 @@ softnic_thread_init(struct pmd_internals *softnic)
 		t_data->timer_period =
 			(rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000;
 		t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period;
-		t_data->time_next_min = t_data->time_next;
 	}
 
 	return 0;
@@ -97,6 +91,9 @@ softnic_thread_init(struct pmd_internals *softnic)
 static inline int
 thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
 {
+	if (thread_id >= RTE_MAX_LCORE)
+		return 0; /* FALSE */
+
 	if (thread_id == rte_get_main_lcore())
 		return 0; /* FALSE */
 
@@ -190,18 +187,22 @@ thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
 	t->service_id = UINT32_MAX;
 }
 
-/**
- * Pipeline is running when:
- *    (A) Pipeline is mapped to a data plane thread AND
- *    (B) Its data plane thread is in RUNNING state.
- */
-static inline int
-pipeline_is_running(struct pipeline *p)
+void
+softnic_thread_pipeline_disable_all(struct pmd_internals *softnic)
 {
-	if (p->enabled == 0)
-		return 0;
+	uint32_t thread_id;
 
-	return thread_is_running(p->thread_id);
+	for (thread_id = 0; thread_id < RTE_MAX_LCORE; thread_id++) {
+		struct softnic_thread_data *td = &softnic->thread_data[thread_id];
+
+		if (!thread_is_valid(softnic, thread_id))
+			continue;
+
+		if (softnic->params.sc && td->n_pipelines)
+			thread_sc_service_down(softnic, thread_id);
+
+		td->n_pipelines = 0;
+	}
 }
 
 /**
@@ -218,18 +219,11 @@ struct thread_msg_req {
 
 	union {
 		struct {
-			struct rte_pipeline *p;
-			struct {
-				struct rte_table_action *a;
-			} table[RTE_PIPELINE_TABLE_MAX];
-			struct rte_ring *msgq_req;
-			struct rte_ring *msgq_rsp;
-			uint32_t timer_period_ms;
-			uint32_t n_tables;
+			struct rte_swx_pipeline *p;
 		} pipeline_enable;
 
 		struct {
-			struct rte_pipeline *p;
+			struct rte_swx_pipeline *p;
 		} pipeline_disable;
 	};
 };
@@ -283,20 +277,16 @@ thread_msg_send_recv(struct pmd_internals *softnic,
 int
 softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 	uint32_t thread_id,
-	const char *pipeline_name)
+	struct pipeline *p)
 {
-	struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
 	struct thread_msg_req *req;
 	struct thread_msg_rsp *rsp;
-	uint32_t n_pipelines, i;
+	uint32_t n_pipelines;
 	int status;
 
 	/* Check input params */
 	if (!thread_is_valid(softnic, thread_id) ||
 		(p == NULL) ||
-		(p->n_ports_in == 0) ||
-		(p->n_ports_out == 0) ||
-		(p->n_tables == 0) ||
 		p->enabled)
 		return -1;
 
@@ -312,22 +302,9 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 
 	if (!thread_is_running(thread_id)) {
 		struct softnic_thread_data *td = &softnic->thread_data[thread_id];
-		struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines];
 
 		/* Data plane thread */
 		td->p[td->n_pipelines] = p->p;
-
-		tdp->p = p->p;
-		for (i = 0; i < p->n_tables; i++)
-			tdp->table_data[i].a =
-				p->table[i].a;
-		tdp->n_tables = p->n_tables;
-
-		tdp->msgq_req = p->msgq_req;
-		tdp->msgq_rsp = p->msgq_rsp;
-		tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000;
-		tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period;
-
 		td->n_pipelines++;
 
 		/* Pipeline */
@@ -345,13 +322,6 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 	/* Write request */
 	req->type = THREAD_REQ_PIPELINE_ENABLE;
 	req->pipeline_enable.p = p->p;
-	for (i = 0; i < p->n_tables; i++)
-		req->pipeline_enable.table[i].a =
-			p->table[i].a;
-	req->pipeline_enable.msgq_req = p->msgq_req;
-	req->pipeline_enable.msgq_rsp = p->msgq_rsp;
-	req->pipeline_enable.timer_period_ms = p->timer_period_ms;
-	req->pipeline_enable.n_tables = p->n_tables;
 
 	/* Send request and wait for response */
 	rsp = thread_msg_send_recv(softnic, thread_id, req);
@@ -375,9 +345,8 @@ softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 int
 softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	uint32_t thread_id,
-	const char *pipeline_name)
+	struct pipeline *p)
 {
-	struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
 	struct thread_msg_req *req;
 	struct thread_msg_rsp *rsp;
 	uint32_t n_pipelines;
@@ -397,21 +366,12 @@ softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 		uint32_t i;
 
 		for (i = 0; i < td->n_pipelines; i++) {
-			struct pipeline_data *tdp = &td->pipeline_data[i];
-
-			if (tdp->p != p->p)
+			if (td->p[i] != p->p)
 				continue;
 
 			/* Data plane thread */
-			if (i < td->n_pipelines - 1) {
-				struct rte_pipeline *pipeline_last =
-					td->p[td->n_pipelines - 1];
-				struct pipeline_data *tdp_last =
-					&td->pipeline_data[td->n_pipelines - 1];
-
-				td->p[i] = pipeline_last;
-				memcpy(tdp, tdp_last, sizeof(*tdp));
-			}
+			if (i < td->n_pipelines - 1)
+				td->p[i] = td->p[td->n_pipelines - 1];
 
 			td->n_pipelines--;
 
@@ -490,25 +450,9 @@ thread_msg_handle_pipeline_enable(struct softnic_thread_data *t,
 	struct thread_msg_req *req)
 {
 	struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
-	struct pipeline_data *p = &t->pipeline_data[t->n_pipelines];
-	uint32_t i;
 
 	/* Request */
 	t->p[t->n_pipelines] = req->pipeline_enable.p;
-
-	p->p = req->pipeline_enable.p;
-	for (i = 0; i < req->pipeline_enable.n_tables; i++)
-		p->table_data[i].a =
-			req->pipeline_enable.table[i].a;
-
-	p->n_tables = req->pipeline_enable.n_tables;
-
-	p->msgq_req = req->pipeline_enable.msgq_req;
-	p->msgq_rsp = req->pipeline_enable.msgq_rsp;
-	p->timer_period =
-		(rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000;
-	p->time_next = rte_get_tsc_cycles() + p->timer_period;
-
 	t->n_pipelines++;
 
 	/* Response */
@@ -522,25 +466,16 @@ thread_msg_handle_pipeline_disable(struct softnic_thread_data *t,
 {
 	struct thread_msg_rsp *rsp = (struct thread_msg_rsp *)req;
 	uint32_t n_pipelines = t->n_pipelines;
-	struct rte_pipeline *pipeline = req->pipeline_disable.p;
+	struct rte_swx_pipeline *pipeline = req->pipeline_disable.p;
 	uint32_t i;
 
 	/* find pipeline */
 	for (i = 0; i < n_pipelines; i++) {
-		struct pipeline_data *p = &t->pipeline_data[i];
-
-		if (p->p != pipeline)
+		if (t->p[i] != pipeline)
 			continue;
 
-		if (i < n_pipelines - 1) {
-			struct rte_pipeline *pipeline_last =
-				t->p[n_pipelines - 1];
-			struct pipeline_data *p_last =
-				&t->pipeline_data[n_pipelines - 1];
-
-			t->p[i] = pipeline_last;
-			memcpy(p, p_last, sizeof(*p));
-		}
+		if (i < n_pipelines - 1)
+			t->p[i] = t->p[n_pipelines - 1];
 
 		t->n_pipelines--;
 
@@ -583,2464 +518,37 @@ thread_msg_handle(struct softnic_thread_data *t)
 }
 
 /**
- * Main thread & data plane threads: message passing
- */
-enum pipeline_req_type {
-	/* Port IN */
-	PIPELINE_REQ_PORT_IN_STATS_READ,
-	PIPELINE_REQ_PORT_IN_ENABLE,
-	PIPELINE_REQ_PORT_IN_DISABLE,
-
-	/* Port OUT */
-	PIPELINE_REQ_PORT_OUT_STATS_READ,
-
-	/* Table */
-	PIPELINE_REQ_TABLE_STATS_READ,
-	PIPELINE_REQ_TABLE_RULE_ADD,
-	PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
-	PIPELINE_REQ_TABLE_RULE_ADD_BULK,
-	PIPELINE_REQ_TABLE_RULE_DELETE,
-	PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT,
-	PIPELINE_REQ_TABLE_RULE_STATS_READ,
-	PIPELINE_REQ_TABLE_MTR_PROFILE_ADD,
-	PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE,
-	PIPELINE_REQ_TABLE_RULE_MTR_READ,
-	PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE,
-	PIPELINE_REQ_TABLE_RULE_TTL_READ,
-	PIPELINE_REQ_MAX
-};
-
-struct pipeline_msg_req_port_in_stats_read {
-	int clear;
-};
-
-struct pipeline_msg_req_port_out_stats_read {
-	int clear;
-};
-
-struct pipeline_msg_req_table_stats_read {
-	int clear;
-};
-
-struct pipeline_msg_req_table_rule_add {
-	struct softnic_table_rule_match match;
-	struct softnic_table_rule_action action;
-};
-
-struct pipeline_msg_req_table_rule_add_default {
-	struct softnic_table_rule_action action;
-};
-
-struct pipeline_msg_req_table_rule_add_bulk {
-	struct softnic_table_rule_match *match;
-	struct softnic_table_rule_action *action;
-	void **data;
-	uint32_t n_rules;
-	int bulk;
-};
-
-struct pipeline_msg_req_table_rule_delete {
-	struct softnic_table_rule_match match;
-};
-
-struct pipeline_msg_req_table_rule_stats_read {
-	void *data;
-	int clear;
-};
-
-struct pipeline_msg_req_table_mtr_profile_add {
-	uint32_t meter_profile_id;
-	struct rte_table_action_meter_profile profile;
-};
-
-struct pipeline_msg_req_table_mtr_profile_delete {
-	uint32_t meter_profile_id;
-};
-
-struct pipeline_msg_req_table_rule_mtr_read {
-	void *data;
-	uint32_t tc_mask;
-	int clear;
-};
-
-struct pipeline_msg_req_table_dscp_table_update {
-	uint64_t dscp_mask;
-	struct rte_table_action_dscp_table dscp_table;
-};
-
-struct pipeline_msg_req_table_rule_ttl_read {
-	void *data;
-	int clear;
-};
-
-struct pipeline_msg_req {
-	enum pipeline_req_type type;
-	uint32_t id; /* Port IN, port OUT or table ID */
-
-	RTE_STD_C11
-	union {
-		struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
-		struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
-		struct pipeline_msg_req_table_stats_read table_stats_read;
-		struct pipeline_msg_req_table_rule_add table_rule_add;
-		struct pipeline_msg_req_table_rule_add_default table_rule_add_default;
-		struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk;
-		struct pipeline_msg_req_table_rule_delete table_rule_delete;
-		struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read;
-		struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add;
-		struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete;
-		struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read;
-		struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update;
-		struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read;
-	};
-};
-
-struct pipeline_msg_rsp_port_in_stats_read {
-	struct rte_pipeline_port_in_stats stats;
-};
-
-struct pipeline_msg_rsp_port_out_stats_read {
-	struct rte_pipeline_port_out_stats stats;
-};
-
-struct pipeline_msg_rsp_table_stats_read {
-	struct rte_pipeline_table_stats stats;
-};
-
-struct pipeline_msg_rsp_table_rule_add {
-	void *data;
-};
-
-struct pipeline_msg_rsp_table_rule_add_default {
-	void *data;
-};
-
-struct pipeline_msg_rsp_table_rule_add_bulk {
-	uint32_t n_rules;
-};
-
-struct pipeline_msg_rsp_table_rule_stats_read {
-	struct rte_table_action_stats_counters stats;
-};
-
-struct pipeline_msg_rsp_table_rule_mtr_read {
-	struct rte_table_action_mtr_counters stats;
-};
-
-struct pipeline_msg_rsp_table_rule_ttl_read {
-	struct rte_table_action_ttl_counters stats;
-};
-
-struct pipeline_msg_rsp {
-	int status;
-
-	RTE_STD_C11
-	union {
-		struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
-		struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
-		struct pipeline_msg_rsp_table_stats_read table_stats_read;
-		struct pipeline_msg_rsp_table_rule_add table_rule_add;
-		struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default;
-		struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk;
-		struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read;
-		struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read;
-		struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read;
-	};
-};
-
-/**
- * Main thread
+ * Data plane threads: main
  */
-static struct pipeline_msg_req *
-pipeline_msg_alloc(void)
-{
-	size_t size = RTE_MAX(sizeof(struct pipeline_msg_req),
-		sizeof(struct pipeline_msg_rsp));
-
-	return calloc(1, size);
-}
-
-static void
-pipeline_msg_free(struct pipeline_msg_rsp *rsp)
-{
-	free(rsp);
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_send_recv(struct pipeline *p,
-	struct pipeline_msg_req *req)
-{
-	struct rte_ring *msgq_req = p->msgq_req;
-	struct rte_ring *msgq_rsp = p->msgq_rsp;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* send */
-	do {
-		status = rte_ring_sp_enqueue(msgq_req, req);
-	} while (status == -ENOBUFS);
-
-	/* recv */
-	do {
-		status = rte_ring_sc_dequeue(msgq_rsp, (void **)&rsp);
-	} while (status != 0);
-
-	return rsp;
-}
-
-int
-softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t port_id,
-	struct rte_pipeline_port_in_stats *stats,
-	int clear)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		stats == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		port_id >= p->n_ports_in)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_port_in_stats_read(p->p,
-			port_id,
-			stats,
-			clear);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
-	req->id = port_id;
-	req->port_in_stats_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t port_id)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		port_id >= p->n_ports_in)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_port_in_enable(p->p, port_id);
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_PORT_IN_ENABLE;
-	req->id = port_id;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t port_id)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		port_id >= p->n_ports_in)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_port_in_disable(p->p, port_id);
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_PORT_IN_DISABLE;
-	req->id = port_id;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t port_id,
-	struct rte_pipeline_port_out_stats *stats,
-	int clear)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		stats == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		port_id >= p->n_ports_out)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_port_out_stats_read(p->p,
-			port_id,
-			stats,
-			clear);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
-	req->id = port_id;
-	req->port_out_stats_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct rte_pipeline_table_stats *stats,
-	int clear)
+static int32_t
+rte_pmd_softnic_run_internal(void *arg)
 {
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		stats == NULL)
-		return -1;
+	struct rte_eth_dev *dev = arg;
+	struct pmd_internals *softnic;
+	struct softnic_thread_data *t;
+	uint32_t thread_id, j;
 
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
+	softnic = dev->data->dev_private;
+	thread_id = rte_lcore_id();
+	t = &softnic->thread_data[thread_id];
+	t->iter++;
 
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_table_stats_read(p->p,
-			table_id,
-			stats,
-			clear);
+	/* Data Plane */
+	for (j = 0; j < t->n_pipelines; j++)
+		rte_swx_pipeline_run(t->p[j], PIPELINE_INSTR_QUANTA);
 
-		return status;
-	}
+	/* Control Plane */
+	if ((t->iter & 0xFLLU) == 0) {
+		uint64_t time = rte_get_tsc_cycles();
+		uint64_t time_next = t->time_next;
 
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_STATS_READ;
-	req->id = table_id;
-	req->table_stats_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-static int
-match_check(struct softnic_table_rule_match *match,
-	struct pipeline *p,
-	uint32_t table_id)
-{
-	struct softnic_table *table;
-
-	if (match == NULL ||
-		p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	table = &p->table[table_id];
-	if (match->match_type != table->params.match_type)
-		return -1;
-
-	switch (match->match_type) {
-	case TABLE_ACL:
-	{
-		struct softnic_table_acl_params *t = &table->params.match.acl;
-		struct softnic_table_rule_match_acl *r = &match->match.acl;
-
-		if ((r->ip_version && (t->ip_version == 0)) ||
-			((r->ip_version == 0) && t->ip_version))
-			return -1;
-
-		if (r->ip_version) {
-			if (r->sa_depth > 32 ||
-				r->da_depth > 32)
-				return -1;
-		} else {
-			if (r->sa_depth > 128 ||
-				r->da_depth > 128)
-				return -1;
-		}
-		return 0;
-	}
-
-	case TABLE_ARRAY:
-		return 0;
-
-	case TABLE_HASH:
-		return 0;
-
-	case TABLE_LPM:
-	{
-		struct softnic_table_lpm_params *t = &table->params.match.lpm;
-		struct softnic_table_rule_match_lpm *r = &match->match.lpm;
-
-		if ((r->ip_version && (t->key_size != 4)) ||
-			((r->ip_version == 0) && (t->key_size != 16)))
-			return -1;
-
-		if (r->ip_version) {
-			if (r->depth > 32)
-				return -1;
-		} else {
-			if (r->depth > 128)
-				return -1;
-		}
-		return 0;
-	}
-
-	case TABLE_STUB:
-		return -1;
-
-	default:
-		return -1;
-	}
-}
-
-static int
-action_check(struct softnic_table_rule_action *action,
-	struct pipeline *p,
-	uint32_t table_id)
-{
-	struct softnic_table_action_profile *ap;
-
-	if (action == NULL ||
-		p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	ap = p->table[table_id].ap;
-	if (action->action_mask != ap->params.action_mask)
-		return -1;
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
-		if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
-			action->fwd.id >= p->n_ports_out)
-			return -1;
-
-		if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
-			action->fwd.id >= p->n_tables)
-			return -1;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
-		uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1;
-		uint32_t tc_mask1 = action->mtr.tc_mask;
-
-		if (tc_mask1 != tc_mask0)
-			return -1;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
-		uint32_t n_subports_per_port =
-			ap->params.tm.n_subports_per_port;
-		uint32_t n_pipes_per_subport =
-			ap->params.tm.n_pipes_per_subport;
-		uint32_t subport_id = action->tm.subport_id;
-		uint32_t pipe_id = action->tm.pipe_id;
-
-		if (subport_id >= n_subports_per_port ||
-			pipe_id >= n_pipes_per_subport)
-			return -1;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
-		uint64_t encap_mask = ap->params.encap.encap_mask;
-		enum rte_table_action_encap_type type = action->encap.type;
-
-		if ((encap_mask & (1LLU << type)) == 0)
-			return -1;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
-		int ip_version0 = ap->params.common.ip_version;
-		int ip_version1 = action->nat.ip_version;
-
-		if ((ip_version1 && (ip_version0 == 0)) ||
-			((ip_version1 == 0) && ip_version0))
-			return -1;
-	}
-
-	return 0;
-}
-
-static int
-action_default_check(struct softnic_table_rule_action *action,
-	struct pipeline *p,
-	uint32_t table_id)
-{
-	if (action == NULL ||
-		action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD) ||
-		p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
-		if (action->fwd.action == RTE_PIPELINE_ACTION_PORT &&
-			action->fwd.id >= p->n_ports_out)
-			return -1;
-
-		if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE &&
-			action->fwd.id >= p->n_tables)
-			return -1;
-	}
-
-	return 0;
-}
-
-union table_rule_match_low_level {
-	struct rte_table_acl_rule_add_params acl_add;
-	struct rte_table_acl_rule_delete_params acl_delete;
-	struct rte_table_array_key array;
-	uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX];
-	struct rte_table_lpm_key lpm_ipv4;
-	struct rte_table_lpm_ipv6_key lpm_ipv6;
-};
-
-static int
-match_convert(struct softnic_table_rule_match *mh,
-	union table_rule_match_low_level *ml,
-	int add);
-
-static int
-action_convert(struct rte_table_action *a,
-	struct softnic_table_rule_action *action,
-	struct rte_pipeline_table_entry *data);
-
-int
-softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match,
-	struct softnic_table_rule_action *action,
-	void **data)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		match == NULL ||
-		action == NULL ||
-		data == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables ||
-		match_check(match, p, table_id) ||
-		action_check(action, p, table_id))
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-		union table_rule_match_low_level match_ll;
-		struct rte_pipeline_table_entry *data_in, *data_out;
-		int key_found;
-		uint8_t *buffer;
-
-		buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
-		if (buffer == NULL)
-			return -1;
-
-		/* Table match-action rule conversion */
-		data_in = (struct rte_pipeline_table_entry *)buffer;
-
-		status = match_convert(match, &match_ll, 1);
-		if (status) {
-			free(buffer);
-			return -1;
-		}
-
-		status = action_convert(a, action, data_in);
-		if (status) {
-			free(buffer);
-			return -1;
-		}
-
-		/* Add rule (match, action) to table */
-		status = rte_pipeline_table_entry_add(p->p,
-				table_id,
-				&match_ll,
-				data_in,
-				&key_found,
-				&data_out);
-		if (status) {
-			free(buffer);
-			return -1;
-		}
-
-		/* Write Response */
-		*data = data_out;
-
-		free(buffer);
-		return 0;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_ADD;
-	req->id = table_id;
-	memcpy(&req->table_rule_add.match, match, sizeof(*match));
-	memcpy(&req->table_rule_add.action, action, sizeof(*action));
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status == 0)
-		*data = rsp->table_rule_add.data;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_action *action,
-	void **data)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		action == NULL ||
-		data == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables ||
-		action_default_check(action, p, table_id))
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_pipeline_table_entry *data_in, *data_out;
-		uint8_t *buffer;
-
-		buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t));
-		if (buffer == NULL)
-			return -1;
-
-		/* Apply actions */
-		data_in = (struct rte_pipeline_table_entry *)buffer;
-
-		data_in->action = action->fwd.action;
-		if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
-			data_in->port_id = action->fwd.id;
-		if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
-			data_in->table_id = action->fwd.id;
-
-		/* Add default rule to table */
-		status = rte_pipeline_table_default_entry_add(p->p,
-				table_id,
-				data_in,
-				&data_out);
-		if (status) {
-			free(buffer);
-			return -1;
-		}
-
-		/* Write Response */
-		*data = data_out;
-
-		free(buffer);
-		return 0;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT;
-	req->id = table_id;
-	memcpy(&req->table_rule_add_default.action, action, sizeof(*action));
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status == 0)
-		*data = rsp->table_rule_add_default.data;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match,
-	struct softnic_table_rule_action *action,
-	void **data,
-	uint32_t *n_rules)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	uint32_t i;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		match == NULL ||
-		action == NULL ||
-		data == NULL ||
-		n_rules == NULL ||
-		(*n_rules == 0))
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	for (i = 0; i < *n_rules; i++)
-		if (match_check(match, p, table_id) ||
-			action_check(action, p, table_id))
-			return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-		union table_rule_match_low_level *match_ll;
-		uint8_t *action_ll;
-		void **match_ll_ptr;
-		struct rte_pipeline_table_entry **action_ll_ptr;
-		struct rte_pipeline_table_entry **entries_ptr =
-			(struct rte_pipeline_table_entry **)data;
-		uint32_t bulk =
-			(p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
-		int *found;
-
-		/* Memory allocation */
-		match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
-		action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
-		match_ll_ptr = calloc(*n_rules, sizeof(void *));
-		action_ll_ptr =
-			calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
-		found = calloc(*n_rules, sizeof(int));
-
-		if (match_ll == NULL ||
-			action_ll == NULL ||
-			match_ll_ptr == NULL ||
-			action_ll_ptr == NULL ||
-			found == NULL)
-			goto fail;
-
-		for (i = 0; i < *n_rules; i++) {
-			match_ll_ptr[i] = (void *)&match_ll[i];
-			action_ll_ptr[i] =
-				(struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
-		}
-
-		/* Rule match conversion */
-		for (i = 0; i < *n_rules; i++) {
-			status = match_convert(&match[i], match_ll_ptr[i], 1);
-			if (status)
-				goto fail;
-		}
-
-		/* Rule action conversion */
-		for (i = 0; i < *n_rules; i++) {
-			status = action_convert(a, &action[i], action_ll_ptr[i]);
-			if (status)
-				goto fail;
-		}
-
-		/* Add rule (match, action) to table */
-		if (bulk) {
-			status = rte_pipeline_table_entry_add_bulk(p->p,
-				table_id,
-				match_ll_ptr,
-				action_ll_ptr,
-				*n_rules,
-				found,
-				entries_ptr);
-			if (status)
-				*n_rules = 0;
-		} else {
-			for (i = 0; i < *n_rules; i++) {
-				status = rte_pipeline_table_entry_add(p->p,
-					table_id,
-					match_ll_ptr[i],
-					action_ll_ptr[i],
-					&found[i],
-					&entries_ptr[i]);
-				if (status) {
-					*n_rules = i;
-					break;
-				}
-			}
-		}
-
-		/* Free */
-		free(found);
-		free(action_ll_ptr);
-		free(match_ll_ptr);
-		free(action_ll);
-		free(match_ll);
-
-		return status;
-
-fail:
-		free(found);
-		free(action_ll_ptr);
-		free(match_ll_ptr);
-		free(action_ll);
-		free(match_ll);
-
-		*n_rules = 0;
-		return -1;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
-	req->id = table_id;
-	req->table_rule_add_bulk.match = match;
-	req->table_rule_add_bulk.action = action;
-	req->table_rule_add_bulk.data = data;
-	req->table_rule_add_bulk.n_rules = *n_rules;
-	req->table_rule_add_bulk.bulk =
-		(p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status == 0)
-		*n_rules = rsp->table_rule_add_bulk.n_rules;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	struct softnic_table_rule_match *match)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		match == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables ||
-		match_check(match, p, table_id))
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		union table_rule_match_low_level match_ll;
-		int key_found;
-
-		status = match_convert(match, &match_ll, 0);
-		if (status)
-			return -1;
-
-		status = rte_pipeline_table_entry_delete(p->p,
-				table_id,
-				&match_ll,
-				&key_found,
-				NULL);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_DELETE;
-	req->id = table_id;
-	memcpy(&req->table_rule_delete.match, match, sizeof(*match));
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		status = rte_pipeline_table_default_entry_delete(p->p,
-			table_id,
-			NULL);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT;
-	req->id = table_id;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	struct rte_table_action_stats_counters *stats,
-	int clear)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		data == NULL ||
-		stats == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-
-		status = rte_table_action_stats_read(a,
-			data,
-			stats,
-			clear);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ;
-	req->id = table_id;
-	req->table_rule_stats_read.data = data;
-	req->table_rule_stats_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint32_t meter_profile_id,
-	struct rte_table_action_meter_profile *profile)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	struct softnic_table *table;
-	struct softnic_table_meter_profile *mp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		profile == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	table = &p->table[table_id];
-	mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
-	if (mp)
-		return -1;
-
-	/* Resource Allocation */
-	mp = calloc(1, sizeof(struct softnic_table_meter_profile));
-	if (mp == NULL)
-		return -1;
-
-	mp->meter_profile_id = meter_profile_id;
-	memcpy(&mp->profile, profile, sizeof(mp->profile));
-
-	if (!pipeline_is_running(p)) {
-		status = rte_table_action_meter_profile_add(table->a,
-			meter_profile_id,
-			profile);
-		if (status) {
-			free(mp);
-			return status;
-		}
-
-		/* Add profile to the table. */
-		TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL) {
-		free(mp);
-		return -1;
-	}
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD;
-	req->id = table_id;
-	req->table_mtr_profile_add.meter_profile_id = meter_profile_id;
-	memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile));
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status == 0)
-		TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
-	else
-		free(mp);
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint32_t meter_profile_id)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-
-		status = rte_table_action_meter_profile_delete(a,
-				meter_profile_id);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE;
-	req->id = table_id;
-	req->table_mtr_profile_delete.meter_profile_id = meter_profile_id;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	uint32_t tc_mask,
-	struct rte_table_action_mtr_counters *stats,
-	int clear)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		data == NULL ||
-		stats == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-
-		status = rte_table_action_meter_read(a,
-				data,
-				tc_mask,
-				stats,
-				clear);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ;
-	req->id = table_id;
-	req->table_rule_mtr_read.data = data;
-	req->table_rule_mtr_read.tc_mask = tc_mask;
-	req->table_rule_mtr_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	uint64_t dscp_mask,
-	struct rte_table_action_dscp_table *dscp_table)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		dscp_table == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-
-		status = rte_table_action_dscp_table_update(a,
-				dscp_mask,
-				dscp_table);
-
-		/* Update table dscp table */
-		if (!status)
-			memcpy(&p->table[table_id].dscp_table, dscp_table,
-				sizeof(p->table[table_id].dscp_table));
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE;
-	req->id = table_id;
-	req->table_dscp_table_update.dscp_mask = dscp_mask;
-	memcpy(&req->table_dscp_table_update.dscp_table,
-		dscp_table, sizeof(*dscp_table));
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-
-	/* Update table dscp table */
-	if (!status)
-		memcpy(&p->table[table_id].dscp_table, dscp_table,
-			sizeof(p->table[table_id].dscp_table));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-int
-softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
-	const char *pipeline_name,
-	uint32_t table_id,
-	void *data,
-	struct rte_table_action_ttl_counters *stats,
-	int clear)
-{
-	struct pipeline *p;
-	struct pipeline_msg_req *req;
-	struct pipeline_msg_rsp *rsp;
-	int status;
-
-	/* Check input params */
-	if (pipeline_name == NULL ||
-		data == NULL ||
-		stats == NULL)
-		return -1;
-
-	p = softnic_pipeline_find(softnic, pipeline_name);
-	if (p == NULL ||
-		table_id >= p->n_tables)
-		return -1;
-
-	if (!pipeline_is_running(p)) {
-		struct rte_table_action *a = p->table[table_id].a;
-
-		status = rte_table_action_ttl_read(a,
-				data,
-				stats,
-				clear);
-
-		return status;
-	}
-
-	/* Allocate request */
-	req = pipeline_msg_alloc();
-	if (req == NULL)
-		return -1;
-
-	/* Write request */
-	req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ;
-	req->id = table_id;
-	req->table_rule_ttl_read.data = data;
-	req->table_rule_ttl_read.clear = clear;
-
-	/* Send request and wait for response */
-	rsp = pipeline_msg_send_recv(p, req);
-
-	/* Read response */
-	status = rsp->status;
-	if (status)
-		memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
-
-	/* Free response */
-	pipeline_msg_free(rsp);
-
-	return status;
-}
-
-/**
- * Data plane threads: message handling
- */
-static inline struct pipeline_msg_req *
-pipeline_msg_recv(struct rte_ring *msgq_req)
-{
-	struct pipeline_msg_req *req;
-
-	int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
-
-	if (status != 0)
-		return NULL;
-
-	return req;
-}
-
-static inline void
-pipeline_msg_send(struct rte_ring *msgq_rsp,
-	struct pipeline_msg_rsp *rsp)
-{
-	int status;
-
-	do {
-		status = rte_ring_sp_enqueue(msgq_rsp, rsp);
-	} while (status == -ENOBUFS);
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t port_id = req->id;
-	int clear = req->port_in_stats_read.clear;
-
-	rsp->status = rte_pipeline_port_in_stats_read(p->p,
-		port_id,
-		&rsp->port_in_stats_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t port_id = req->id;
-
-	rsp->status = rte_pipeline_port_in_enable(p->p,
-		port_id);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_port_in_disable(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t port_id = req->id;
-
-	rsp->status = rte_pipeline_port_in_disable(p->p,
-		port_id);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t port_id = req->id;
-	int clear = req->port_out_stats_read.clear;
-
-	rsp->status = rte_pipeline_port_out_stats_read(p->p,
-		port_id,
-		&rsp->port_out_stats_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t port_id = req->id;
-	int clear = req->table_stats_read.clear;
-
-	rsp->status = rte_pipeline_table_stats_read(p->p,
-		port_id,
-		&rsp->table_stats_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static int
-match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
-{
-	if (depth > 128)
-		return -1;
-
-	switch (depth / 32) {
-	case 0:
-		depth32[0] = depth;
-		depth32[1] = 0;
-		depth32[2] = 0;
-		depth32[3] = 0;
-		return 0;
-
-	case 1:
-		depth32[0] = 32;
-		depth32[1] = depth - 32;
-		depth32[2] = 0;
-		depth32[3] = 0;
-		return 0;
-
-	case 2:
-		depth32[0] = 32;
-		depth32[1] = 32;
-		depth32[2] = depth - 64;
-		depth32[3] = 0;
-		return 0;
-
-	case 3:
-		depth32[0] = 32;
-		depth32[1] = 32;
-		depth32[2] = 32;
-		depth32[3] = depth - 96;
-		return 0;
-
-	case 4:
-		depth32[0] = 32;
-		depth32[1] = 32;
-		depth32[2] = 32;
-		depth32[3] = 32;
-		return 0;
-
-	default:
-		return -1;
-	}
-}
-
-static int
-match_convert(struct softnic_table_rule_match *mh,
-	union table_rule_match_low_level *ml,
-	int add)
-{
-	memset(ml, 0, sizeof(*ml));
-
-	switch (mh->match_type) {
-	case TABLE_ACL:
-		if (mh->match.acl.ip_version)
-			if (add) {
-				ml->acl_add.field_value[0].value.u8 =
-					mh->match.acl.proto;
-				ml->acl_add.field_value[0].mask_range.u8 =
-					mh->match.acl.proto_mask;
-
-				ml->acl_add.field_value[1].value.u32 =
-					mh->match.acl.ipv4.sa;
-				ml->acl_add.field_value[1].mask_range.u32 =
-					mh->match.acl.sa_depth;
-
-				ml->acl_add.field_value[2].value.u32 =
-					mh->match.acl.ipv4.da;
-				ml->acl_add.field_value[2].mask_range.u32 =
-					mh->match.acl.da_depth;
-
-				ml->acl_add.field_value[3].value.u16 =
-					mh->match.acl.sp0;
-				ml->acl_add.field_value[3].mask_range.u16 =
-					mh->match.acl.sp1;
-
-				ml->acl_add.field_value[4].value.u16 =
-					mh->match.acl.dp0;
-				ml->acl_add.field_value[4].mask_range.u16 =
-					mh->match.acl.dp1;
-
-				ml->acl_add.priority =
-					(int32_t)mh->match.acl.priority;
-			} else {
-				ml->acl_delete.field_value[0].value.u8 =
-					mh->match.acl.proto;
-				ml->acl_delete.field_value[0].mask_range.u8 =
-					mh->match.acl.proto_mask;
-
-				ml->acl_delete.field_value[1].value.u32 =
-					mh->match.acl.ipv4.sa;
-				ml->acl_delete.field_value[1].mask_range.u32 =
-					mh->match.acl.sa_depth;
-
-				ml->acl_delete.field_value[2].value.u32 =
-					mh->match.acl.ipv4.da;
-				ml->acl_delete.field_value[2].mask_range.u32 =
-					mh->match.acl.da_depth;
-
-				ml->acl_delete.field_value[3].value.u16 =
-					mh->match.acl.sp0;
-				ml->acl_delete.field_value[3].mask_range.u16 =
-					mh->match.acl.sp1;
-
-				ml->acl_delete.field_value[4].value.u16 =
-					mh->match.acl.dp0;
-				ml->acl_delete.field_value[4].mask_range.u16 =
-					mh->match.acl.dp1;
-			}
-		else
-			if (add) {
-				uint32_t *sa32 =
-					(uint32_t *)mh->match.acl.ipv6.sa;
-				uint32_t *da32 =
-					(uint32_t *)mh->match.acl.ipv6.da;
-				uint32_t sa32_depth[4], da32_depth[4];
-				int status;
-
-				status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
-					sa32_depth);
-				if (status)
-					return status;
-
-				status = match_convert_ipv6_depth(
-					mh->match.acl.da_depth,
-					da32_depth);
-				if (status)
-					return status;
-
-				ml->acl_add.field_value[0].value.u8 =
-					mh->match.acl.proto;
-				ml->acl_add.field_value[0].mask_range.u8 =
-					mh->match.acl.proto_mask;
-
-				ml->acl_add.field_value[1].value.u32 =
-					rte_be_to_cpu_32(sa32[0]);
-				ml->acl_add.field_value[1].mask_range.u32 =
-					sa32_depth[0];
-				ml->acl_add.field_value[2].value.u32 =
-					rte_be_to_cpu_32(sa32[1]);
-				ml->acl_add.field_value[2].mask_range.u32 =
-					sa32_depth[1];
-				ml->acl_add.field_value[3].value.u32 =
-					rte_be_to_cpu_32(sa32[2]);
-				ml->acl_add.field_value[3].mask_range.u32 =
-					sa32_depth[2];
-				ml->acl_add.field_value[4].value.u32 =
-					rte_be_to_cpu_32(sa32[3]);
-				ml->acl_add.field_value[4].mask_range.u32 =
-					sa32_depth[3];
-
-				ml->acl_add.field_value[5].value.u32 =
-					rte_be_to_cpu_32(da32[0]);
-				ml->acl_add.field_value[5].mask_range.u32 =
-					da32_depth[0];
-				ml->acl_add.field_value[6].value.u32 =
-					rte_be_to_cpu_32(da32[1]);
-				ml->acl_add.field_value[6].mask_range.u32 =
-					da32_depth[1];
-				ml->acl_add.field_value[7].value.u32 =
-					rte_be_to_cpu_32(da32[2]);
-				ml->acl_add.field_value[7].mask_range.u32 =
-					da32_depth[2];
-				ml->acl_add.field_value[8].value.u32 =
-					rte_be_to_cpu_32(da32[3]);
-				ml->acl_add.field_value[8].mask_range.u32 =
-					da32_depth[3];
-
-				ml->acl_add.field_value[9].value.u16 =
-					mh->match.acl.sp0;
-				ml->acl_add.field_value[9].mask_range.u16 =
-					mh->match.acl.sp1;
-
-				ml->acl_add.field_value[10].value.u16 =
-					mh->match.acl.dp0;
-				ml->acl_add.field_value[10].mask_range.u16 =
-					mh->match.acl.dp1;
-
-				ml->acl_add.priority =
-					(int32_t)mh->match.acl.priority;
-			} else {
-				uint32_t *sa32 =
-					(uint32_t *)mh->match.acl.ipv6.sa;
-				uint32_t *da32 =
-					(uint32_t *)mh->match.acl.ipv6.da;
-				uint32_t sa32_depth[4], da32_depth[4];
-				int status;
-
-				status = match_convert_ipv6_depth(mh->match.acl.sa_depth,
-					sa32_depth);
-				if (status)
-					return status;
-
-				status = match_convert_ipv6_depth(mh->match.acl.da_depth,
-					da32_depth);
-				if (status)
-					return status;
-
-				ml->acl_delete.field_value[0].value.u8 =
-					mh->match.acl.proto;
-				ml->acl_delete.field_value[0].mask_range.u8 =
-					mh->match.acl.proto_mask;
-
-				ml->acl_delete.field_value[1].value.u32 =
-					rte_be_to_cpu_32(sa32[0]);
-				ml->acl_delete.field_value[1].mask_range.u32 =
-					sa32_depth[0];
-				ml->acl_delete.field_value[2].value.u32 =
-					rte_be_to_cpu_32(sa32[1]);
-				ml->acl_delete.field_value[2].mask_range.u32 =
-					sa32_depth[1];
-				ml->acl_delete.field_value[3].value.u32 =
-					rte_be_to_cpu_32(sa32[2]);
-				ml->acl_delete.field_value[3].mask_range.u32 =
-					sa32_depth[2];
-				ml->acl_delete.field_value[4].value.u32 =
-					rte_be_to_cpu_32(sa32[3]);
-				ml->acl_delete.field_value[4].mask_range.u32 =
-					sa32_depth[3];
-
-				ml->acl_delete.field_value[5].value.u32 =
-					rte_be_to_cpu_32(da32[0]);
-				ml->acl_delete.field_value[5].mask_range.u32 =
-					da32_depth[0];
-				ml->acl_delete.field_value[6].value.u32 =
-					rte_be_to_cpu_32(da32[1]);
-				ml->acl_delete.field_value[6].mask_range.u32 =
-					da32_depth[1];
-				ml->acl_delete.field_value[7].value.u32 =
-					rte_be_to_cpu_32(da32[2]);
-				ml->acl_delete.field_value[7].mask_range.u32 =
-					da32_depth[2];
-				ml->acl_delete.field_value[8].value.u32 =
-					rte_be_to_cpu_32(da32[3]);
-				ml->acl_delete.field_value[8].mask_range.u32 =
-					da32_depth[3];
-
-				ml->acl_delete.field_value[9].value.u16 =
-					mh->match.acl.sp0;
-				ml->acl_delete.field_value[9].mask_range.u16 =
-					mh->match.acl.sp1;
-
-				ml->acl_delete.field_value[10].value.u16 =
-					mh->match.acl.dp0;
-				ml->acl_delete.field_value[10].mask_range.u16 =
-					mh->match.acl.dp1;
-			}
-		return 0;
-
-	case TABLE_ARRAY:
-		ml->array.pos = mh->match.array.pos;
-		return 0;
-
-	case TABLE_HASH:
-		memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash));
-		return 0;
-
-	case TABLE_LPM:
-		if (mh->match.lpm.ip_version) {
-			ml->lpm_ipv4.ip = mh->match.lpm.ipv4;
-			ml->lpm_ipv4.depth = mh->match.lpm.depth;
-		} else {
-			memcpy(ml->lpm_ipv6.ip,
-				mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip));
-			ml->lpm_ipv6.depth = mh->match.lpm.depth;
-		}
-
-		return 0;
-
-	default:
-		return -1;
-	}
-}
-
-static int
-action_convert(struct rte_table_action *a,
-	struct softnic_table_rule_action *action,
-	struct rte_pipeline_table_entry *data)
-{
-	int status;
-
-	/* Apply actions */
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_FWD,
-			&action->fwd);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_LB,
-			&action->lb);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_MTR,
-			&action->mtr);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_TM,
-			&action->tm);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_ENCAP,
-			&action->encap);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_NAT,
-			&action->nat);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_TTL,
-			&action->ttl);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_STATS,
-			&action->stats);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_TIME,
-			&action->time);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_TAG,
-			&action->tag);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_DECAP,
-			&action->decap);
-
-		if (status)
-			return status;
-	}
-
-	if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) {
-		status = rte_table_action_apply(a,
-			data,
-			RTE_TABLE_ACTION_SYM_CRYPTO,
-			&action->sym_crypto);
-
-		if (status)
-			return status;
-	}
-
-	return 0;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_add(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	union table_rule_match_low_level match_ll;
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	struct softnic_table_rule_match *match = &req->table_rule_add.match;
-	struct softnic_table_rule_action *action = &req->table_rule_add.action;
-	struct rte_pipeline_table_entry *data_in, *data_out;
-	uint32_t table_id = req->id;
-	int key_found, status;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	/* Apply actions */
-	memset(p->buffer, 0, sizeof(p->buffer));
-	data_in = (struct rte_pipeline_table_entry *)p->buffer;
-
-	status = match_convert(match, &match_ll, 1);
-	if (status) {
-		rsp->status = -1;
-		return rsp;
-	}
-
-	status = action_convert(a, action, data_in);
-	if (status) {
-		rsp->status = -1;
-		return rsp;
-	}
-
-	status = rte_pipeline_table_entry_add(p->p,
-		table_id,
-		&match_ll,
-		data_in,
-		&key_found,
-		&data_out);
-	if (status) {
-		rsp->status = -1;
-		return rsp;
-	}
-
-	/* Write response */
-	rsp->status = 0;
-	rsp->table_rule_add.data = data_out;
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	struct softnic_table_rule_action *action = &req->table_rule_add_default.action;
-	struct rte_pipeline_table_entry *data_in, *data_out;
-	uint32_t table_id = req->id;
-	int status;
-
-	/* Apply actions */
-	memset(p->buffer, 0, sizeof(p->buffer));
-	data_in = (struct rte_pipeline_table_entry *)p->buffer;
-
-	data_in->action = action->fwd.action;
-	if (action->fwd.action == RTE_PIPELINE_ACTION_PORT)
-		data_in->port_id = action->fwd.id;
-	if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE)
-		data_in->table_id = action->fwd.id;
-
-	/* Add default rule to table */
-	status = rte_pipeline_table_default_entry_add(p->p,
-		table_id,
-		data_in,
-		&data_out);
-	if (status) {
-		rsp->status = -1;
-		return rsp;
-	}
-
-	/* Write response */
-	rsp->status = 0;
-	rsp->table_rule_add_default.data = data_out;
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-
-	uint32_t table_id = req->id;
-	struct softnic_table_rule_match *match = req->table_rule_add_bulk.match;
-	struct softnic_table_rule_action *action = req->table_rule_add_bulk.action;
-	struct rte_pipeline_table_entry **data =
-		(struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
-	uint32_t n_rules = req->table_rule_add_bulk.n_rules;
-	uint32_t bulk = req->table_rule_add_bulk.bulk;
-
-	struct rte_table_action *a = p->table_data[table_id].a;
-	union table_rule_match_low_level *match_ll;
-	uint8_t *action_ll;
-	void **match_ll_ptr;
-	struct rte_pipeline_table_entry **action_ll_ptr;
-	int *found, status;
-	uint32_t i;
-
-	/* Memory allocation */
-	match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
-	action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
-	match_ll_ptr = calloc(n_rules, sizeof(void *));
-	action_ll_ptr =
-		calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
-	found = calloc(n_rules, sizeof(int));
-
-	if (match_ll == NULL ||
-		action_ll == NULL ||
-		match_ll_ptr == NULL ||
-		action_ll_ptr == NULL ||
-		found == NULL)
-		goto fail;
-
-	for (i = 0; i < n_rules; i++) {
-		match_ll_ptr[i] = (void *)&match_ll[i];
-		action_ll_ptr[i] =
-			(struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
-	}
-
-	/* Rule match conversion */
-	for (i = 0; i < n_rules; i++) {
-		status = match_convert(&match[i], match_ll_ptr[i], 1);
-		if (status)
-			goto fail;
-	}
-
-	/* Rule action conversion */
-	for (i = 0; i < n_rules; i++) {
-		status = action_convert(a, &action[i], action_ll_ptr[i]);
-		if (status)
-			goto fail;
-	}
-
-	/* Add rule (match, action) to table */
-	if (bulk) {
-		status = rte_pipeline_table_entry_add_bulk(p->p,
-			table_id,
-			match_ll_ptr,
-			action_ll_ptr,
-			n_rules,
-			found,
-			data);
-		if (status)
-			n_rules = 0;
-	} else {
-		for (i = 0; i < n_rules; i++) {
-			status = rte_pipeline_table_entry_add(p->p,
-				table_id,
-				match_ll_ptr[i],
-				action_ll_ptr[i],
-				&found[i],
-				&data[i]);
-			if (status) {
-				n_rules = i;
-				break;
-			}
-		}
-	}
-
-	/* Write response */
-	rsp->status = 0;
-	rsp->table_rule_add_bulk.n_rules = n_rules;
-
-	/* Free */
-	free(found);
-	free(action_ll_ptr);
-	free(match_ll_ptr);
-	free(action_ll);
-	free(match_ll);
-
-	return rsp;
-
-fail:
-	free(found);
-	free(action_ll_ptr);
-	free(match_ll_ptr);
-	free(action_ll);
-	free(match_ll);
-
-	rsp->status = -1;
-	rsp->table_rule_add_bulk.n_rules = 0;
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_delete(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	union table_rule_match_low_level match_ll;
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	struct softnic_table_rule_match *match = &req->table_rule_delete.match;
-	uint32_t table_id = req->id;
-	int key_found, status;
-
-	status = match_convert(match, &match_ll, 0);
-	if (status) {
-		rsp->status = -1;
-		return rsp;
-	}
-
-	rsp->status = rte_pipeline_table_entry_delete(p->p,
-		table_id,
-		&match_ll,
-		&key_found,
-		NULL);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-
-	rsp->status = rte_pipeline_table_default_entry_delete(p->p,
-		table_id,
-		NULL);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	void *data = req->table_rule_stats_read.data;
-	int clear = req->table_rule_stats_read.clear;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_stats_read(a,
-		data,
-		&rsp->table_rule_stats_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id;
-	struct rte_table_action_meter_profile *profile =
-		&req->table_mtr_profile_add.profile;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_meter_profile_add(a,
-		meter_profile_id,
-		profile);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	uint32_t meter_profile_id =
-		req->table_mtr_profile_delete.meter_profile_id;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_meter_profile_delete(a,
-		meter_profile_id);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	void *data = req->table_rule_mtr_read.data;
-	uint32_t tc_mask = req->table_rule_mtr_read.tc_mask;
-	int clear = req->table_rule_mtr_read.clear;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_meter_read(a,
-		data,
-		tc_mask,
-		&rsp->table_rule_mtr_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask;
-	struct rte_table_action_dscp_table *dscp_table =
-		&req->table_dscp_table_update.dscp_table;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_dscp_table_update(a,
-		dscp_mask,
-		dscp_table);
-
-	return rsp;
-}
-
-static struct pipeline_msg_rsp *
-pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p,
-	struct pipeline_msg_req *req)
-{
-	struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
-	uint32_t table_id = req->id;
-	void *data = req->table_rule_ttl_read.data;
-	int clear = req->table_rule_ttl_read.clear;
-	struct rte_table_action *a = p->table_data[table_id].a;
-
-	rsp->status = rte_table_action_ttl_read(a,
-		data,
-		&rsp->table_rule_ttl_read.stats,
-		clear);
-
-	return rsp;
-}
-
-static void
-pipeline_msg_handle(struct pipeline_data *p)
-{
-	for ( ; ; ) {
-		struct pipeline_msg_req *req;
-		struct pipeline_msg_rsp *rsp;
-
-		req = pipeline_msg_recv(p->msgq_req);
-		if (req == NULL)
-			break;
-
-		switch (req->type) {
-		case PIPELINE_REQ_PORT_IN_STATS_READ:
-			rsp = pipeline_msg_handle_port_in_stats_read(p, req);
-			break;
-
-		case PIPELINE_REQ_PORT_IN_ENABLE:
-			rsp = pipeline_msg_handle_port_in_enable(p, req);
-			break;
-
-		case PIPELINE_REQ_PORT_IN_DISABLE:
-			rsp = pipeline_msg_handle_port_in_disable(p, req);
-			break;
-
-		case PIPELINE_REQ_PORT_OUT_STATS_READ:
-			rsp = pipeline_msg_handle_port_out_stats_read(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_STATS_READ:
-			rsp = pipeline_msg_handle_table_stats_read(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_ADD:
-			rsp = pipeline_msg_handle_table_rule_add(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT:
-			rsp = pipeline_msg_handle_table_rule_add_default(p,	req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_ADD_BULK:
-			rsp = pipeline_msg_handle_table_rule_add_bulk(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_DELETE:
-			rsp = pipeline_msg_handle_table_rule_delete(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT:
-			rsp = pipeline_msg_handle_table_rule_delete_default(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_STATS_READ:
-			rsp = pipeline_msg_handle_table_rule_stats_read(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD:
-			rsp = pipeline_msg_handle_table_mtr_profile_add(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE:
-			rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_MTR_READ:
-			rsp = pipeline_msg_handle_table_rule_mtr_read(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE:
-			rsp = pipeline_msg_handle_table_dscp_table_update(p, req);
-			break;
-
-		case PIPELINE_REQ_TABLE_RULE_TTL_READ:
-			rsp = pipeline_msg_handle_table_rule_ttl_read(p, req);
-			break;
-
-		default:
-			rsp = (struct pipeline_msg_rsp *)req;
-			rsp->status = -1;
-		}
-
-		pipeline_msg_send(p->msgq_rsp, rsp);
-	}
-}
-
-/**
- * Data plane threads: main
- */
-static int32_t
-rte_pmd_softnic_run_internal(void *arg)
-{
-	struct rte_eth_dev *dev = arg;
-	struct pmd_internals *softnic;
-	struct softnic_thread_data *t;
-	uint32_t thread_id, j;
-
-	softnic = dev->data->dev_private;
-	thread_id = rte_lcore_id();
-	t = &softnic->thread_data[thread_id];
-	t->iter++;
-
-	/* Data Plane */
-	for (j = 0; j < t->n_pipelines; j++)
-		rte_pipeline_run(t->p[j]);
-
-	/* Control Plane */
-	if ((t->iter & 0xFLLU) == 0) {
-		uint64_t time = rte_get_tsc_cycles();
-		uint64_t time_next_min = UINT64_MAX;
-
-		if (time < t->time_next_min)
-			return 0;
-
-		/* Pipeline message queues */
-		for (j = 0; j < t->n_pipelines; j++) {
-			struct pipeline_data *p =
-				&t->pipeline_data[j];
-			uint64_t time_next = p->time_next;
-
-			if (time_next <= time) {
-				pipeline_msg_handle(p);
-				rte_pipeline_flush(p->p);
-				time_next = time + p->timer_period;
-				p->time_next = time_next;
-			}
-
-			if (time_next < time_next_min)
-				time_next_min = time_next;
-		}
+		if (time < time_next)
+			return 0;
 
 		/* Thread message queues */
-		{
-			uint64_t time_next = t->time_next;
-
-			if (time_next <= time) {
-				thread_msg_handle(t);
-				time_next = time + t->timer_period;
-				t->time_next = time_next;
-			}
-
-			if (time_next < time_next_min)
-				time_next_min = time_next;
-		}
+		thread_msg_handle(t);
 
-		t->time_next_min = time_next_min;
+		t->time_next = time_next + t->timer_period;
 	}
 
 	return 0;
-- 
2.34.1


  parent reply	other threads:[~2022-08-04 17:00 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 02/21] net/softnic: remove flow support Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 03/21] net/softnic: remove the meter support Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 05/21] net/softnic: remove tap support Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
2022-08-04 16:58 ` Cristian Dumitrescu [this message]
2022-08-04 16:58 ` [PATCH 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 12/21] net/softnic: add pipeline " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
2022-08-04 16:58 ` [PATCH 21/21] net/softnic: update the default device program Cristian Dumitrescu
2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 02/21] net/softnic: remove flow support Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 03/21] net/softnic: remove the meter support Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 05/21] net/softnic: remove tap support Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 12/21] net/softnic: add pipeline " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
2022-08-26 13:17   ` [PATCH V2 21/21] net/softnic: update the default device program Cristian Dumitrescu
2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 02/21] net/softnic: remove flow support Cristian Dumitrescu
2022-11-30 11:18     ` Ferruh Yigit
2022-12-01 11:27       ` Dumitrescu, Cristian
2022-09-01 14:20   ` [PATCH V3 03/21] net/softnic: remove the meter support Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 05/21] net/softnic: remove tap support Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 12/21] net/softnic: add pipeline " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
2022-09-01 14:20   ` [PATCH V3 21/21] net/softnic: update the default device program Cristian Dumitrescu
2022-09-21 11:48   ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Thomas Monjalon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220804165839.1074817-8-cristian.dumitrescu@intel.com \
    --to=cristian.dumitrescu@intel.com \
    --cc=dev@dpdk.org \
    --cc=jasvinder.singh@intel.com \
    --cc=yogesh.jangra@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.