All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline
@ 2022-08-04 16:58 Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
                   ` (22 more replies)
  0 siblings, 23 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

The legacy pipeline API is soon going to be marked for deprecation,
hence the Soft NIC driver is updated to support the new SWX pipeline
type.

The SWX pipeline has better encapsulation than the legacy pipeline,
mainly due to P4 language alignment, which results in most of the
functionality being supported directly in the pipeline library, hence
the big number of lines of code deleted from this driver.

Depends-on: series-24117 ("pipeline: pipeline configuration and build improvements")

Cristian Dumitrescu (21):
  net/softnic: remove the traffic manager support
  net/softnic: remove flow support
  net/softnic: remove the meter support
  net/softnic: remove cryptodev support
  net/softnic: remove tap support
  net/softnic: remove the legacy pipeline CLI commands
  net/softnic: replace the legacy pipeline with the SWX pipeline
  net/softnic: remove the list of Ethernet devices
  net/softnic: remove unused text parsing functions
  net/softnic: add pipeline code generation CLI command
  net/softnic: add pipeline library build CLI command
  net/softnic: add pipeline build CLI command
  net/softnic: add pipeline table CLI commands
  net/softnic: add pipeline selector table CLI commands
  net/softnic: add pipeline learner table CLI commands
  net/softnic: add pipeline commit and abort CLI commands
  net/softnic: add the pipeline register read/write CLI commands
  net/softnic: add the pipeline meter CLI commands
  net/softnic: add pipeline statistics CLI command
  net/softnic: add pipeline mirroring CLI command
  net/softnic: update the default device program

 drivers/net/softnic/firmware.cli              |   51 +-
 drivers/net/softnic/firmware.spec             |   19 +
 drivers/net/softnic/firmware_rx.io            |   30 +
 drivers/net/softnic/firmware_tx.io            |   30 +
 drivers/net/softnic/meson.build               |   10 +-
 drivers/net/softnic/parser.c                  |  523 --
 drivers/net/softnic/parser.h                  |   68 -
 drivers/net/softnic/rte_eth_softnic.c         |  208 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_action.c  |  423 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 7053 ++++-------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   |  168 -
 drivers/net/softnic/rte_eth_softnic_flow.c    | 2293 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  922 +--
 drivers/net/softnic/rte_eth_softnic_link.c    |  101 -
 drivers/net/softnic/rte_eth_softnic_meter.c   |  945 ---
 .../net/softnic/rte_eth_softnic_pipeline.c    | 1129 +--
 drivers/net/softnic/rte_eth_softnic_tap.c     |  118 -
 drivers/net/softnic/rte_eth_softnic_thread.c  | 2594 +-----
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3657 ---------
 20 files changed, 1845 insertions(+), 18507 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_action.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH 01/21] net/softnic: remove the traffic manager support
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 02/21] net/softnic: remove flow support Cristian Dumitrescu
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the Ethernet device traffic manager API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |    3 +-
 drivers/net/softnic/rte_eth_softnic.c         |  170 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 1328 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  176 -
 .../net/softnic/rte_eth_softnic_pipeline.c    |   31 -
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3657 -----------------
 7 files changed, 1 insertion(+), 5374 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index aff5fb3bf2..e2dbd6166e 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -21,6 +21,5 @@ sources = files(
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
-        'rte_eth_softnic_tm.c',
 )
-deps += ['pipeline', 'port', 'table', 'sched', 'cryptodev']
+deps += ['pipeline', 'port', 'table', 'cryptodev']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8c098cad5b..ae3e8b3bcd 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_tm_driver.h>
 #include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
@@ -23,20 +22,6 @@
 #define PMD_PARAM_CONN_PORT                                "conn_port"
 #define PMD_PARAM_CPU_ID                                   "cpu_id"
 #define PMD_PARAM_SC                                       "sc"
-#define PMD_PARAM_TM_N_QUEUES                              "tm_n_queues"
-#define PMD_PARAM_TM_QSIZE0                                "tm_qsize0"
-#define PMD_PARAM_TM_QSIZE1                                "tm_qsize1"
-#define PMD_PARAM_TM_QSIZE2                                "tm_qsize2"
-#define PMD_PARAM_TM_QSIZE3                                "tm_qsize3"
-#define PMD_PARAM_TM_QSIZE4                                "tm_qsize4"
-#define PMD_PARAM_TM_QSIZE5                                "tm_qsize5"
-#define PMD_PARAM_TM_QSIZE6                                "tm_qsize6"
-#define PMD_PARAM_TM_QSIZE7                                "tm_qsize7"
-#define PMD_PARAM_TM_QSIZE8                                "tm_qsize8"
-#define PMD_PARAM_TM_QSIZE9                                "tm_qsize9"
-#define PMD_PARAM_TM_QSIZE10                               "tm_qsize10"
-#define PMD_PARAM_TM_QSIZE11                               "tm_qsize11"
-#define PMD_PARAM_TM_QSIZE12                               "tm_qsize12"
 
 
 static const char * const pmd_valid_args[] = {
@@ -44,20 +29,6 @@ static const char * const pmd_valid_args[] = {
 	PMD_PARAM_CONN_PORT,
 	PMD_PARAM_CPU_ID,
 	PMD_PARAM_SC,
-	PMD_PARAM_TM_N_QUEUES,
-	PMD_PARAM_TM_QSIZE0,
-	PMD_PARAM_TM_QSIZE1,
-	PMD_PARAM_TM_QSIZE2,
-	PMD_PARAM_TM_QSIZE3,
-	PMD_PARAM_TM_QSIZE4,
-	PMD_PARAM_TM_QSIZE5,
-	PMD_PARAM_TM_QSIZE6,
-	PMD_PARAM_TM_QSIZE7,
-	PMD_PARAM_TM_QSIZE8,
-	PMD_PARAM_TM_QSIZE9,
-	PMD_PARAM_TM_QSIZE10,
-	PMD_PARAM_TM_QSIZE11,
-	PMD_PARAM_TM_QSIZE12,
 	NULL
 };
 
@@ -193,12 +164,10 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	return 0;
@@ -218,12 +187,10 @@ pmd_free(struct pmd_internals *p)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	rte_free(p);
@@ -256,14 +223,6 @@ pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_tm_ops **)arg = &pmd_tm_ops;
-
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -282,7 +241,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
 	.flow_ops_get = pmd_flow_ops_get,
-	.tm_ops_get = pmd_tm_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
@@ -325,13 +283,11 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	tm_hierarchy_init(p);
 	softnic_mtr_init(p);
 
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tmgr_init(p);
 	softnic_tap_init(p);
 	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
@@ -459,20 +415,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 	}
 	p->cpu_id = SOFTNIC_CPU_ID;
 	p->sc = SOFTNIC_SC;
-	p->tm.n_queues = SOFTNIC_TM_N_QUEUES;
-	p->tm.qsize[0] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[1] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[2] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[3] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[4] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[5] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[6] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[7] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[8] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[9] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[10] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[11] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[12] = SOFTNIC_TM_QUEUE_SIZE;
 
 	/* Firmware script (optional) */
 	if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) {
@@ -517,104 +459,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 			goto out_free;
 	}
 
-	/* TM number of queues (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_N_QUEUES) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_N_QUEUES,
-			&get_uint32, &p->tm.n_queues);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	/* TM queue size 0 .. 3 (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE0) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE0,
-			&get_uint32, &p->tm.qsize[0]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE1) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE1,
-			&get_uint32, &p->tm.qsize[1]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE2) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE2,
-			&get_uint32, &p->tm.qsize[2]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE3) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE3,
-			&get_uint32, &p->tm.qsize[3]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE4) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE4,
-			&get_uint32, &p->tm.qsize[4]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE5) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE5,
-			&get_uint32, &p->tm.qsize[5]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE6) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE6,
-			&get_uint32, &p->tm.qsize[6]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE7) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE7,
-			&get_uint32, &p->tm.qsize[7]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE8) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE8,
-			&get_uint32, &p->tm.qsize[8]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE9) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE9,
-			&get_uint32, &p->tm.qsize[9]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE10) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE10,
-			&get_uint32, &p->tm.qsize[10]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE11) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE11,
-			&get_uint32, &p->tm.qsize[11]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE12) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE12,
-			&get_uint32, &p->tm.qsize[12]);
-		if (ret < 0)
-			goto out_free;
-	}
-
 out_free:
 	rte_kvargs_free(kvlist);
 	return ret;
@@ -696,20 +540,6 @@ RTE_PMD_REGISTER_PARAM_STRING(net_softnic,
 	PMD_PARAM_FIRMWARE "=<string> "
 	PMD_PARAM_CONN_PORT "=<uint16> "
 	PMD_PARAM_CPU_ID "=<uint32> "
-	PMD_PARAM_TM_N_QUEUES "=<uint32> "
-	PMD_PARAM_TM_QSIZE0 "=<uint32> "
-	PMD_PARAM_TM_QSIZE1 "=<uint32> "
-	PMD_PARAM_TM_QSIZE2 "=<uint32> "
-	PMD_PARAM_TM_QSIZE3 "=<uint32>"
-	PMD_PARAM_TM_QSIZE4 "=<uint32> "
-	PMD_PARAM_TM_QSIZE5 "=<uint32> "
-	PMD_PARAM_TM_QSIZE6 "=<uint32> "
-	PMD_PARAM_TM_QSIZE7 "=<uint32> "
-	PMD_PARAM_TM_QSIZE8 "=<uint32> "
-	PMD_PARAM_TM_QSIZE9 "=<uint32> "
-	PMD_PARAM_TM_QSIZE10 "=<uint32> "
-	PMD_PARAM_TM_QSIZE11 "=<uint32>"
-	PMD_PARAM_TM_QSIZE12 "=<uint32>"
 );
 
 int
diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h
index 6c11d89ab6..3fd80fa571 100644
--- a/drivers/net/softnic/rte_eth_softnic.h
+++ b/drivers/net/softnic/rte_eth_softnic.h
@@ -46,16 +46,6 @@ extern "C" {
 #define SOFTNIC_SC                                         1
 #endif
 
-/** Traffic Manager: Number of scheduler queues. */
-#ifndef SOFTNIC_TM_N_QUEUES
-#define SOFTNIC_TM_N_QUEUES                                (64 * 1024)
-#endif
-
-/** Traffic Manager: Scheduler queue size (per traffic class). */
-#ifndef SOFTNIC_TM_QUEUE_SIZE
-#define SOFTNIC_TM_QUEUE_SIZE                              64
-#endif
-
 /**
  * Soft NIC run.
  *
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7acbeecae7..7556e50831 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,1270 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tmgr shaper profile
- *  id <profile_id>
- *  rate <tb_rate> size <tb_size>
- *  adj <packet_length_adjust>
- */
-static void
-cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_shaper_params sp;
-	struct rte_tm_error error;
-	uint32_t shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
-
-	if (n_tokens != 11) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "rate") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
-		return;
-	}
-
-	if (strcmp(tokens[7], "size") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
-		return;
-	}
-
-	if (strcmp(tokens[9], "adj") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj");
-		return;
-	}
-
-	if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr shared shaper
- *  id <shared_shaper_id>
- *  profile <shaper_profile_id>
- */
-static void
-cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint32_t shared_shaper_id, shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[2], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shared_shaper_add_update(port_id,
-		shared_shaper_id,
-		shaper_profile_id,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr node
- *   id <node_id>
- *   parent <parent_node_id | none>
- *   priority <priority>
- *   weight <weight>
- *   [shaper profile <shaper_profile_id>]
- *   [shared shaper <shared_shaper_id>]
- *   [nonleaf sp <n_sp_priorities>]
- */
-static void
-cmd_tmgr_node(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	struct rte_tm_node_params np;
-	uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&np, 0, sizeof(struct rte_tm_node_params));
-	np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-	np.nonleaf.n_sp_priorities = 1;
-
-	if (n_tokens < 10) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "node") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
-		return;
-	}
-
-	if (strcmp(tokens[2], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "parent") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
-		return;
-	}
-
-	if (strcmp(tokens[5], "none") == 0)
-		parent_node_id = RTE_TM_NODE_ID_NULL;
-	else {
-		if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id");
-			return;
-		}
-	}
-
-	if (strcmp(tokens[6], "priority") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-		return;
-	}
-
-	if (strcmp(tokens[8], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "weight");
-		return;
-	}
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shaper") == 0) &&
-		(strcmp(tokens[1], "profile") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (strcmp(tokens[2], "none") == 0) {
-			np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-		} else {
-			if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-				return;
-			}
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shaper profile */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shared") == 0) &&
-		(strcmp(tokens[1], "shaper") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-			return;
-		}
-
-		np.shared_shaper_id = &shared_shaper_id;
-		np.n_shared_shapers = 1;
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shared shaper */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "nonleaf") == 0) &&
-		(strcmp(tokens[1], "sp") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
-			return;
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* nonleaf sp <n_sp_priorities> */
-
-	if (n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_node_add(port_id,
-		node_id,
-		parent_node_id,
-		priority,
-		weight,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&np,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-static uint32_t
-root_node_id(uint32_t n_spp,
-	uint32_t n_pps)
-{
-	uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_pipes = n_spp * n_pps;
-
-	return n_queues + n_tc + n_pipes + n_spp;
-}
-
-static uint32_t
-subport_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues + n_tc + n_pipes + subport_id;
-}
-
-static uint32_t
-pipe_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		n_tc +
-		pipe_id +
-		subport_id * n_pps;
-}
-
-static uint32_t
-tc_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-}
-
-static uint32_t
-queue_node_id(uint32_t n_spp __rte_unused,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id,
-	uint32_t queue_id)
-{
-	return queue_id + tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_QUEUES_PER_PIPE;
-}
-
-struct tmgr_hierarchy_default_params {
-	uint32_t n_spp; /**< Number of subports per port. */
-	uint32_t n_pps; /**< Number of pipes per subport. */
-
-	struct {
-		uint32_t port;
-		uint32_t subport;
-		uint32_t pipe;
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shaper_profile_id;
-
-	struct {
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t tc_valid[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shared_shaper_id;
-
-	struct {
-		uint32_t queue[RTE_SCHED_QUEUES_PER_PIPE];
-	} weight;
-};
-
-static int
-tmgr_hierarchy_default(struct pmd_internals *softnic,
-	struct tmgr_hierarchy_default_params *params)
-{
-	struct rte_tm_node_params root_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.port,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params subport_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.subport,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params pipe_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.pipe,
-		.nonleaf = {
-			.n_sp_priorities = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-		},
-	};
-
-	uint32_t *shared_shaper_id =
-		(uint32_t *)calloc(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			sizeof(uint32_t));
-
-	if (shared_shaper_id == NULL)
-		return -1;
-
-	memcpy(shared_shaper_id, params->shared_shaper_id.tc,
-		sizeof(params->shared_shaper_id.tc));
-
-	struct rte_tm_node_params tc_node_params[] = {
-		[0] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[0],
-			.shared_shaper_id = &shared_shaper_id[0],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[0]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[1] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[1],
-			.shared_shaper_id = &shared_shaper_id[1],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[1]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[2] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[2],
-			.shared_shaper_id = &shared_shaper_id[2],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[2]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[3] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[3],
-			.shared_shaper_id = &shared_shaper_id[3],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[3]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[4] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[4],
-			.shared_shaper_id = &shared_shaper_id[4],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[4]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[5] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[5],
-			.shared_shaper_id = &shared_shaper_id[5],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[5]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[6] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[6],
-			.shared_shaper_id = &shared_shaper_id[6],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[6]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[7] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[7],
-			.shared_shaper_id = &shared_shaper_id[7],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[7]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[8] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[8],
-			.shared_shaper_id = &shared_shaper_id[8],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[8]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[9] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[9],
-			.shared_shaper_id = &shared_shaper_id[9],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[9]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[10] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[10],
-			.shared_shaper_id = &shared_shaper_id[10],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[10]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[11] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[11],
-			.shared_shaper_id = &shared_shaper_id[11],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[11]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[12] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[12],
-			.shared_shaper_id = &shared_shaper_id[12],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[12]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-	};
-
-	struct rte_tm_node_params queue_node_params = {
-		.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE,
-	};
-
-	struct rte_tm_error error;
-	uint32_t n_spp = params->n_spp, n_pps = params->n_pps, s;
-	int status;
-	uint16_t port_id;
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 0: Root node */
-	status = rte_tm_node_add(port_id,
-		root_node_id(n_spp, n_pps),
-		RTE_TM_NODE_ID_NULL,
-		0,
-		1,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&root_node_params,
-		&error);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 1: Subport nodes */
-	for (s = 0; s < params->n_spp; s++) {
-		uint32_t p;
-
-		status = rte_tm_node_add(port_id,
-			subport_node_id(n_spp, n_pps, s),
-			root_node_id(n_spp, n_pps),
-			0,
-			1,
-			RTE_TM_NODE_LEVEL_ID_ANY,
-			&subport_node_params,
-			&error);
-		if (status)
-			return -1;
-
-		/* Hierarchy level 2: Pipe nodes */
-		for (p = 0; p < params->n_pps; p++) {
-			uint32_t t;
-
-			status = rte_tm_node_add(port_id,
-				pipe_node_id(n_spp, n_pps, s, p),
-				subport_node_id(n_spp, n_pps, s),
-				0,
-				1,
-				RTE_TM_NODE_LEVEL_ID_ANY,
-				&pipe_node_params,
-				&error);
-			if (status)
-				return -1;
-
-			/* Hierarchy level 3: Traffic class nodes */
-			for (t = 0; t < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; t++) {
-				uint32_t q;
-
-				status = rte_tm_node_add(port_id,
-					tc_node_id(n_spp, n_pps, s, p, t),
-					pipe_node_id(n_spp, n_pps, s, p),
-					t,
-					1,
-					RTE_TM_NODE_LEVEL_ID_ANY,
-					&tc_node_params[t],
-					&error);
-				if (status)
-					return -1;
-
-				/* Hierarchy level 4: Queue nodes */
-				if (t < RTE_SCHED_TRAFFIC_CLASS_BE) {
-					/* Strict-priority traffic class queues */
-					q = 0;
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-
-					continue;
-				}
-				/* Best-effort traffic class queues */
-				for (q = 0; q < RTE_SCHED_BE_QUEUES_PER_PIPE; q++) {
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-				}
-			} /* TC */
-		} /* Pipe */
-	} /* Subport */
-
-	return 0;
-}
-
-
-/**
- * tmgr hierarchy-default
- *  spp <n_subports_per_port>
- *  pps <n_pipes_per_subport>
- *  shaper profile
- *   port <profile_id>
- *   subport <profile_id>
- *   pipe <profile_id>
- *   tc0 <profile_id>
- *   tc1 <profile_id>
- *   tc2 <profile_id>
- *   tc3 <profile_id>
- *   tc4 <profile_id>
- *   tc5 <profile_id>
- *   tc6 <profile_id>
- *   tc7 <profile_id>
- *   tc8 <profile_id>
- *   tc9 <profile_id>
- *   tc10 <profile_id>
- *   tc11 <profile_id>
- *   tc12 <profile_id>
- *  shared shaper
- *   tc0 <id | none>
- *   tc1 <id | none>
- *   tc2 <id | none>
- *   tc3 <id | none>
- *   tc4 <id | none>
- *   tc5 <id | none>
- *   tc6 <id | none>
- *   tc7 <id | none>
- *   tc8 <id | none>
- *   tc9 <id | none>
- *   tc10 <id | none>
- *   tc11 <id | none>
- *   tc12 <id | none>
- *  weight
- *   queue  <q12> ... <q15>
- */
-static void
-cmd_tmgr_hierarchy_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct tmgr_hierarchy_default_params p;
-	int i, j, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 74) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy-default") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
-		return;
-	}
-
-	if (strcmp(tokens[2], "spp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
-		return;
-	}
-
-	if (strcmp(tokens[4], "pps") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
-		return;
-	}
-
-	/* Shaper profile */
-
-	if (strcmp(tokens[6], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[7], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[8], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port profile id");
-		return;
-	}
-
-	if (strcmp(tokens[10], "subport") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id");
-		return;
-	}
-
-	if (strcmp(tokens[12], "pipe") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[14], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[16], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[18], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[20], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[22], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[4], tokens[23]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc4 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[24], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[5], tokens[25]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc5 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[26], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[6], tokens[27]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc6 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[28], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[7], tokens[29]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc7 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[30], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[8], tokens[31]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc8 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[32], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[9], tokens[33]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc9 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[34], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[10], tokens[35]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc10 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[36], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[11], tokens[37]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc11 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[38], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[12], tokens[39]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc12 profile id");
-		return;
-	}
-
-	/* Shared shaper */
-
-	if (strcmp(tokens[40], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[41], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[42], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (strcmp(tokens[43], "none") == 0)
-		p.shared_shaper_id.tc_valid[0] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0],
-			tokens[43]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[0] = 1;
-	}
-
-	if (strcmp(tokens[44], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (strcmp(tokens[45], "none") == 0)
-		p.shared_shaper_id.tc_valid[1] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1],
-			tokens[45]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[1] = 1;
-	}
-
-	if (strcmp(tokens[46], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (strcmp(tokens[47], "none") == 0)
-		p.shared_shaper_id.tc_valid[2] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2],
-			tokens[47]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[2] = 1;
-	}
-
-	if (strcmp(tokens[48], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (strcmp(tokens[49], "none") == 0)
-		p.shared_shaper_id.tc_valid[3] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3],
-			tokens[49]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[3] = 1;
-	}
-
-	if (strcmp(tokens[50], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (strcmp(tokens[51], "none") == 0) {
-		p.shared_shaper_id.tc_valid[4] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[4],
-			tokens[51]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc4");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[4] = 1;
-	}
-
-	if (strcmp(tokens[52], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (strcmp(tokens[53], "none") == 0) {
-		p.shared_shaper_id.tc_valid[5] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[5],
-			tokens[53]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc5");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[5] = 1;
-	}
-
-	if (strcmp(tokens[54], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (strcmp(tokens[55], "none") == 0) {
-		p.shared_shaper_id.tc_valid[6] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[6],
-			tokens[55]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc6");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[6] = 1;
-	}
-
-	if (strcmp(tokens[56], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (strcmp(tokens[57], "none") == 0) {
-		p.shared_shaper_id.tc_valid[7] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[7],
-			tokens[57]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc7");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[7] = 1;
-	}
-
-	if (strcmp(tokens[58], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (strcmp(tokens[59], "none") == 0) {
-		p.shared_shaper_id.tc_valid[8] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[8],
-			tokens[59]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc8");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[8] = 1;
-	}
-
-	if (strcmp(tokens[60], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (strcmp(tokens[61], "none") == 0) {
-		p.shared_shaper_id.tc_valid[9] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[9],
-			tokens[61]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc9");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[9] = 1;
-	}
-
-	if (strcmp(tokens[62], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (strcmp(tokens[63], "none") == 0) {
-		p.shared_shaper_id.tc_valid[10] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[10],
-			tokens[63]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc10");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[10] = 1;
-	}
-
-	if (strcmp(tokens[64], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (strcmp(tokens[65], "none") == 0) {
-		p.shared_shaper_id.tc_valid[11] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[11],
-			tokens[65]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc11");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[11] = 1;
-	}
-
-	if (strcmp(tokens[66], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (strcmp(tokens[67], "none") == 0) {
-		p.shared_shaper_id.tc_valid[12] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[12],
-			tokens[67]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc12");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[12] = 1;
-	}
-
-	/* Weight */
-
-	if (strcmp(tokens[68], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (strcmp(tokens[69], "queue") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
-		return;
-	}
-
-	for (i = 0, j = 0; i < 16; i++) {
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			p.weight.queue[i] = 1;
-		} else {
-			if (softnic_parser_read_uint32(&p.weight.queue[i],
-				tokens[70 + j]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "weight queue");
-				return;
-			}
-			j++;
-		}
-	}
-
-	status = tmgr_hierarchy_default(softnic, &p);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr hierarchy commit
- */
-static void
-cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 3) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
-		return;
-	}
-
-	if (strcmp(tokens[2], "commit") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_hierarchy_commit(port_id, 1, &error);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr <tmgr_name>
- */
-static void
-cmd_tmgr(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tmgr_port = softnic_tmgr_port_create(softnic, name);
-	if (tmgr_port == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * tap <tap_name>
  */
@@ -2247,7 +983,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  | cryptodev <cryptodev_name> rxq <queue_id>
@@ -2331,18 +1066,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "tmgr") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tmgr");
-			return;
-		}
-
-		p.type = PORT_IN_TMGR;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tap") == 0) {
 		if (n_tokens < t0 + 6) {
@@ -2482,7 +1205,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
@@ -2557,16 +1279,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tmgr") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tmgr");
-			return;
-		}
-
-		p.type = PORT_OUT_TMGR;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "tap") == 0) {
 		if (n_tokens != 8) {
@@ -6129,46 +4841,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tmgr") == 0) {
-		if (n_tokens == 2) {
-			cmd_tmgr(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shaper") == 0) &&
-			(strcmp(tokens[2], "profile") == 0)) {
-			cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shared") == 0) &&
-			(strcmp(tokens[2], "shaper") == 0)) {
-			cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "node") == 0)) {
-			cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "hierarchy-default") == 0)) {
-			cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "hierarchy") == 0) &&
-			(strcmp(tokens[2], "commit") == 0)) {
-			cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "tap") == 0) {
 		cmd_tap(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 07285ca315..4cc98b7aad 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -13,14 +13,12 @@
 #include <rte_mbuf.h>
 #include <rte_ring.h>
 #include <rte_ethdev.h>
-#include <rte_sched.h>
 #include <rte_port_in_action.h>
 #include <rte_table_action.h>
 #include <rte_pipeline.h>
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_tm_driver.h>
 #include <rte_flow_driver.h>
 #include <rte_mtr_driver.h>
 
@@ -40,12 +38,6 @@ struct pmd_params {
 	uint16_t conn_port;
 	uint32_t cpu_id;
 	int sc; /**< Service cores. */
-
-	/** Traffic Management (TM) */
-	struct {
-		uint32_t n_queues; /**< Number of queues */
-		uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} tm;
 };
 
 /**
@@ -161,134 +153,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TMGR
- */
-
-#ifndef TM_MAX_SUBPORTS
-#define TM_MAX_SUBPORTS					8
-#endif
-
-#ifndef TM_MAX_PIPES_PER_SUBPORT
-#define TM_MAX_PIPES_PER_SUBPORT			4096
-#endif
-
-#ifndef TM_MAX_PIPE_PROFILE
-#define TM_MAX_PIPE_PROFILE				256
-#endif
-
-#ifndef TM_MAX_SUBPORT_PROFILE
-#define TM_MAX_SUBPORT_PROFILE				256
-#endif
-
-struct tm_params {
-	struct rte_sched_port_params port_params;
-	struct rte_sched_subport_params subport_params[TM_MAX_SUBPORTS];
-	struct rte_sched_subport_profile_params
-		subport_profile[TM_MAX_SUBPORT_PROFILE];
-	uint32_t n_subport_profiles;
-	uint32_t subport_to_profile[TM_MAX_SUBPORT_PROFILE];
-	struct rte_sched_pipe_params pipe_profiles[TM_MAX_PIPE_PROFILE];
-	uint32_t n_pipe_profiles;
-	uint32_t pipe_to_profile[TM_MAX_SUBPORTS * TM_MAX_PIPES_PER_SUBPORT];
-};
-
-/* TM Levels */
-enum tm_node_level {
-	TM_NODE_LEVEL_PORT = 0,
-	TM_NODE_LEVEL_SUBPORT,
-	TM_NODE_LEVEL_PIPE,
-	TM_NODE_LEVEL_TC,
-	TM_NODE_LEVEL_QUEUE,
-	TM_NODE_LEVEL_MAX,
-};
-
-/* TM Shaper Profile */
-struct tm_shaper_profile {
-	TAILQ_ENTRY(tm_shaper_profile) node;
-	uint32_t shaper_profile_id;
-	uint32_t n_users;
-	struct rte_tm_shaper_params params;
-};
-
-TAILQ_HEAD(tm_shaper_profile_list, tm_shaper_profile);
-
-/* TM Shared Shaper */
-struct tm_shared_shaper {
-	TAILQ_ENTRY(tm_shared_shaper) node;
-	uint32_t shared_shaper_id;
-	uint32_t n_users;
-	uint32_t shaper_profile_id;
-};
-
-TAILQ_HEAD(tm_shared_shaper_list, tm_shared_shaper);
-
-/* TM WRED Profile */
-struct tm_wred_profile {
-	TAILQ_ENTRY(tm_wred_profile) node;
-	uint32_t wred_profile_id;
-	uint32_t n_users;
-	struct rte_tm_wred_params params;
-};
-
-TAILQ_HEAD(tm_wred_profile_list, tm_wred_profile);
-
-/* TM Node */
-struct tm_node {
-	TAILQ_ENTRY(tm_node) node;
-	uint32_t node_id;
-	uint32_t parent_node_id;
-	uint32_t priority;
-	uint32_t weight;
-	uint32_t level;
-	struct tm_node *parent_node;
-	struct tm_shaper_profile *shaper_profile;
-	struct tm_wred_profile *wred_profile;
-	struct rte_tm_node_params params;
-	struct rte_tm_node_stats stats;
-	uint32_t n_children;
-};
-
-TAILQ_HEAD(tm_node_list, tm_node);
-
-/* TM Hierarchy Specification */
-struct tm_hierarchy {
-	struct tm_shaper_profile_list shaper_profiles;
-	struct tm_shared_shaper_list shared_shapers;
-	struct tm_wred_profile_list wred_profiles;
-	struct tm_node_list nodes;
-
-	uint32_t n_shaper_profiles;
-	uint32_t n_shared_shapers;
-	uint32_t n_wred_profiles;
-	uint32_t n_nodes;
-
-	uint32_t n_tm_nodes[TM_NODE_LEVEL_MAX];
-};
-
-struct tm_internals {
-	/** Hierarchy specification
-	 *
-	 *     -Hierarchy is unfrozen at init and when port is stopped.
-	 *     -Hierarchy is frozen on successful hierarchy commit.
-	 *     -Run-time hierarchy changes are not allowed, therefore it makes
-	 *      sense to keep the hierarchy frozen after the port is started.
-	 */
-	struct tm_hierarchy h;
-	int hierarchy_frozen;
-
-	/** Blueprints */
-	struct tm_params params;
-};
-
-struct softnic_tmgr_port {
-	TAILQ_ENTRY(softnic_tmgr_port) node;
-	char name[NAME_SIZE];
-	struct rte_sched_port *s;
-};
-
-TAILQ_HEAD(softnic_tmgr_port_list, softnic_tmgr_port);
-
 /**
  * TAP
  */
@@ -385,7 +249,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TMGR,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 	PORT_IN_CRYPTODEV,
@@ -426,7 +289,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TMGR,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 	PORT_OUT_CRYPTODEV,
@@ -619,10 +481,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct {
-		struct tm_internals tm; /**< Traffic Management */
-	} soft;
-
 	struct flow_internals flow;
 	struct mtr_internals mtr;
 
@@ -630,7 +488,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tmgr_port_list tmgr_port_list;
 	struct softnic_tap_list tap_list;
 	struct softnic_cryptodev_list cryptodev_list;
 	struct softnic_port_in_action_profile_list port_in_action_profile_list;
@@ -753,39 +610,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TMGR
- */
-int
-softnic_tmgr_init(struct pmd_internals *p);
-
-void
-softnic_tmgr_free(struct pmd_internals *p);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name);
-
-void
-tm_hierarchy_init(struct pmd_internals *p);
-
-void
-tm_hierarchy_free(struct pmd_internals *p);
-
-static inline int
-tm_used(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	return p->soft.tm.h.n_tm_nodes[TM_NODE_LEVEL_PORT];
-}
-
-extern const struct rte_tm_ops pmd_tm_ops;
-
 /**
  * TAP
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 337aa32e57..c7d2a7de19 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -305,21 +305,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-
-		p.ops = &rte_port_sched_reader_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_IN_TAP:
 	{
 		struct softnic_tap *tap;
@@ -545,22 +530,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-		pp.sched.tx_burst_sz = params->burst_size;
-
-		p.ops = &rte_port_sched_writer_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_OUT_TAP:
 	{
 		struct softnic_tap *tap;
diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c
deleted file mode 100644
index 6a7766ba1c..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tm.c
+++ /dev/null
@@ -1,3657 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define SUBPORT_TC_PERIOD	10
-#define PIPE_TC_PERIOD		40
-
-int
-softnic_tmgr_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tmgr_port_list);
-
-	return 0;
-}
-
-void
-softnic_tmgr_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = TAILQ_FIRST(&p->tmgr_port_list);
-		if (tmgr_port == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tmgr_port_list, tmgr_port, node);
-		rte_sched_port_free(tmgr_port->s);
-		free(tmgr_port);
-	}
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tmgr_port, &p->tmgr_port_list, node)
-		if (strcmp(tmgr_port->name, name) == 0)
-			return tmgr_port;
-
-	return NULL;
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-	struct tm_params *t = &p->soft.tm.params;
-	struct rte_sched_port *sched;
-	uint32_t n_subports, subport_id;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tmgr_port_find(p, name))
-		return NULL;
-
-	/*
-	 * Resource
-	 */
-
-	/* Is hierarchy frozen? */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return NULL;
-
-	/* Port */
-	sched = rte_sched_port_config(&t->port_params);
-	if (sched == NULL)
-		return NULL;
-
-	/* Subport */
-	n_subports = t->port_params.n_subports_per_port;
-	for (subport_id = 0; subport_id < n_subports; subport_id++) {
-		uint32_t n_pipes_per_subport =
-		t->subport_params[subport_id].n_pipes_per_subport_enabled;
-		uint32_t pipe_id;
-		int status;
-
-		status = rte_sched_subport_config(sched,
-			subport_id,
-			&t->subport_params[subport_id],
-			t->subport_to_profile[subport_id]);
-		if (status) {
-			rte_sched_port_free(sched);
-			return NULL;
-		}
-
-		/* Pipe */
-		for (pipe_id = 0; pipe_id < n_pipes_per_subport; pipe_id++) {
-			int pos = subport_id * TM_MAX_PIPES_PER_SUBPORT + pipe_id;
-			int profile_id = t->pipe_to_profile[pos];
-
-			if (profile_id < 0)
-				continue;
-
-			status = rte_sched_pipe_config(sched,
-				subport_id,
-				pipe_id,
-				profile_id);
-			if (status) {
-				rte_sched_port_free(sched);
-				return NULL;
-			}
-		}
-	}
-
-	/* Node allocation */
-	tmgr_port = calloc(1, sizeof(struct softnic_tmgr_port));
-	if (tmgr_port == NULL) {
-		rte_sched_port_free(sched);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name));
-	tmgr_port->s = sched;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tmgr_port_list, tmgr_port, node);
-
-	return tmgr_port;
-}
-
-static struct rte_sched_port *
-SCHED(struct pmd_internals *p)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	tmgr_port = softnic_tmgr_port_find(p, "TMGR");
-	if (tmgr_port == NULL)
-		return NULL;
-
-	return tmgr_port->s;
-}
-
-void
-tm_hierarchy_init(struct pmd_internals *p)
-{
-	memset(&p->soft.tm, 0, sizeof(p->soft.tm));
-
-	/* Initialize shaper profile list */
-	TAILQ_INIT(&p->soft.tm.h.shaper_profiles);
-
-	/* Initialize shared shaper list */
-	TAILQ_INIT(&p->soft.tm.h.shared_shapers);
-
-	/* Initialize wred profile list */
-	TAILQ_INIT(&p->soft.tm.h.wred_profiles);
-
-	/* Initialize TM node list */
-	TAILQ_INIT(&p->soft.tm.h.nodes);
-}
-
-void
-tm_hierarchy_free(struct pmd_internals *p)
-{
-	/* Remove all nodes*/
-	for ( ; ; ) {
-		struct tm_node *tm_node;
-
-		tm_node = TAILQ_FIRST(&p->soft.tm.h.nodes);
-		if (tm_node == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.nodes, tm_node, node);
-		free(tm_node);
-	}
-
-	/* Remove all WRED profiles */
-	for ( ; ; ) {
-		struct tm_wred_profile *wred_profile;
-
-		wred_profile = TAILQ_FIRST(&p->soft.tm.h.wred_profiles);
-		if (wred_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wred_profile, node);
-		free(wred_profile);
-	}
-
-	/* Remove all shared shapers */
-	for ( ; ; ) {
-		struct tm_shared_shaper *shared_shaper;
-
-		shared_shaper = TAILQ_FIRST(&p->soft.tm.h.shared_shapers);
-		if (shared_shaper == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, shared_shaper, node);
-		free(shared_shaper);
-	}
-
-	/* Remove all shaper profiles */
-	for ( ; ; ) {
-		struct tm_shaper_profile *shaper_profile;
-
-		shaper_profile = TAILQ_FIRST(&p->soft.tm.h.shaper_profiles);
-		if (shaper_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles,
-			shaper_profile, node);
-		free(shaper_profile);
-	}
-
-	tm_hierarchy_init(p);
-}
-
-static struct tm_shaper_profile *
-tm_shaper_profile_search(struct rte_eth_dev *dev, uint32_t shaper_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-
-	TAILQ_FOREACH(sp, spl, node)
-		if (shaper_profile_id == sp->shaper_profile_id)
-			return sp;
-
-	return NULL;
-}
-
-static struct tm_shared_shaper *
-tm_shared_shaper_search(struct rte_eth_dev *dev, uint32_t shared_shaper_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper_list *ssl = &p->soft.tm.h.shared_shapers;
-	struct tm_shared_shaper *ss;
-
-	TAILQ_FOREACH(ss, ssl, node)
-		if (shared_shaper_id == ss->shared_shaper_id)
-			return ss;
-
-	return NULL;
-}
-
-static struct tm_wred_profile *
-tm_wred_profile_search(struct rte_eth_dev *dev, uint32_t wred_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-
-	TAILQ_FOREACH(wp, wpl, node)
-		if (wred_profile_id == wp->wred_profile_id)
-			return wp;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_node_search(struct rte_eth_dev *dev, uint32_t node_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->node_id == node_id)
-			return n;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_root_node_present(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->parent_node_id == RTE_TM_NODE_ID_NULL)
-			return n;
-
-	return NULL;
-}
-
-static uint32_t
-tm_node_subport_id(struct rte_eth_dev *dev, struct tm_node *subport_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->node_id == subport_node->node_id)
-			return subport_id;
-
-		subport_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_pipe_id(struct rte_eth_dev *dev, struct tm_node *pipe_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *np;
-	uint32_t pipe_id;
-
-	pipe_id = 0;
-	TAILQ_FOREACH(np, nl, node) {
-		if (np->level != TM_NODE_LEVEL_PIPE ||
-			np->parent_node_id != pipe_node->parent_node_id)
-			continue;
-
-		if (np->node_id == pipe_node->node_id)
-			return pipe_id;
-
-		pipe_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_tc_id(struct rte_eth_dev *dev __rte_unused, struct tm_node *tc_node)
-{
-	return tc_node->priority;
-}
-
-static uint32_t
-tm_node_queue_id(struct rte_eth_dev *dev, struct tm_node *queue_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *nq;
-	uint32_t queue_id;
-
-	queue_id = 0;
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node_id != queue_node->parent_node_id)
-			continue;
-
-		if (nq->node_id == queue_node->node_id)
-			return queue_id;
-
-		queue_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_level_get_max_nodes(struct rte_eth_dev *dev, enum tm_node_level level)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t n_queues_max = p->params.tm.n_queues;
-	uint32_t n_tc_max =
-		(n_queues_max * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		/ RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_pipes_max = n_tc_max / RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_subports_max = n_pipes_max;
-	uint32_t n_root_max = 1;
-
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		return n_root_max;
-	case TM_NODE_LEVEL_SUBPORT:
-		return n_subports_max;
-	case TM_NODE_LEVEL_PIPE:
-		return n_pipes_max;
-	case TM_NODE_LEVEL_TC:
-		return n_tc_max;
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		return n_queues_max;
-	}
-}
-
-/* Traffic manager node type get */
-static int
-pmd_tm_node_type_get(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	int *is_leaf,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	if (is_leaf == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_UNSPECIFIED,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (node_id == RTE_TM_NODE_ID_NULL ||
-		(tm_node_search(dev, node_id) == NULL))
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	*is_leaf = node_id < p->params.tm.n_queues;
-
-	return 0;
-}
-
-#ifdef RTE_SCHED_CMAN
-#define WRED_SUPPORTED						1
-#else
-#define WRED_SUPPORTED						0
-#endif
-
-#define STATS_MASK_DEFAULT					\
-	(RTE_TM_STATS_N_PKTS |					\
-	RTE_TM_STATS_N_BYTES |					\
-	RTE_TM_STATS_N_PKTS_GREEN_DROPPED |			\
-	RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
-
-#define STATS_MASK_QUEUE						\
-	(STATS_MASK_DEFAULT |					\
-	RTE_TM_STATS_N_PKTS_QUEUED)
-
-static const struct rte_tm_capabilities tm_cap = {
-	.n_nodes_max = UINT32_MAX,
-	.n_levels_max = TM_NODE_LEVEL_MAX,
-
-	.non_leaf_nodes_identical = 0,
-	.leaf_nodes_identical = 1,
-
-	.shaper_n_max = UINT32_MAX,
-	.shaper_private_n_max = UINT32_MAX,
-	.shaper_private_dual_rate_n_max = 0,
-	.shaper_private_rate_min = 1,
-	.shaper_private_rate_max = UINT32_MAX,
-	.shaper_private_packet_mode_supported = 0,
-	.shaper_private_byte_mode_supported = 1,
-
-	.shaper_shared_n_max = UINT32_MAX,
-	.shaper_shared_n_nodes_per_shaper_max = UINT32_MAX,
-	.shaper_shared_n_shapers_per_node_max = 1,
-	.shaper_shared_dual_rate_n_max = 0,
-	.shaper_shared_rate_min = 1,
-	.shaper_shared_rate_max = UINT32_MAX,
-	.shaper_shared_packet_mode_supported = 0,
-	.shaper_shared_byte_mode_supported = 1,
-
-	.shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-	.shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-
-	.sched_n_children_max = UINT32_MAX,
-	.sched_sp_n_priorities_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-	.sched_wfq_n_children_per_group_max = UINT32_MAX,
-	.sched_wfq_n_groups_max = 1,
-	.sched_wfq_weight_max = UINT32_MAX,
-	.sched_wfq_packet_mode_supported = 0,
-	.sched_wfq_byte_mode_supported = 1,
-
-	.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-	.cman_wred_byte_mode_supported = 0,
-	.cman_head_drop_supported = 0,
-	.cman_wred_context_n_max = 0,
-	.cman_wred_context_private_n_max = 0,
-	.cman_wred_context_shared_n_max = 0,
-	.cman_wred_context_shared_n_nodes_per_context_max = 0,
-	.cman_wred_context_shared_n_contexts_per_node_max = 0,
-
-	.mark_vlan_dei_supported = {0, 0, 0},
-	.mark_ip_ecn_tcp_supported = {0, 0, 0},
-	.mark_ip_ecn_sctp_supported = {0, 0, 0},
-	.mark_ip_dscp_supported = {0, 0, 0},
-
-	.dynamic_update_mask = 0,
-
-	.stats_mask = STATS_MASK_QUEUE,
-};
-
-/* Traffic manager capabilities get */
-static int
-pmd_tm_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	struct rte_tm_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_cap, sizeof(*cap));
-
-	cap->n_nodes_max = tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->shaper_private_n_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC);
-
-	cap->shaper_shared_n_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE *
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT);
-
-	cap->shaper_n_max = cap->shaper_private_n_max +
-		cap->shaper_shared_n_max;
-
-	cap->shaper_shared_n_nodes_per_shaper_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE);
-
-	cap->sched_n_children_max = RTE_MAX(
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE),
-		(uint32_t)RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE);
-
-	cap->sched_wfq_n_children_per_group_max = cap->sched_n_children_max;
-
-	if (WRED_SUPPORTED)
-		cap->cman_wred_context_private_n_max =
-			tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->cman_wred_context_n_max = cap->cman_wred_context_private_n_max +
-		cap->cman_wred_context_shared_n_max;
-
-	return 0;
-}
-
-static const struct rte_tm_level_capabilities tm_level_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.n_nodes_max = 1,
-		.n_nodes_nonleaf_max = 1,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 1,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 1,
-
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = 0,
-		.n_nodes_leaf_max = UINT32_MAX,
-		.non_leaf_nodes_identical = 0,
-		.leaf_nodes_identical = 1,
-
-		{.leaf = {
-			.shaper_private_supported = 0,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 0,
-			.shaper_private_rate_max = 0,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 0,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-
-			.stats_mask = STATS_MASK_QUEUE,
-		} },
-	},
-};
-
-/* Traffic manager level capabilities get */
-static int
-pmd_tm_level_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t level_id,
-	struct rte_tm_level_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (level_id >= TM_NODE_LEVEL_MAX)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_LEVEL_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_level_cap[level_id], sizeof(*cap));
-
-	switch (level_id) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_SUBPORT);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_PIPE);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_TC);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_QUEUE);
-		cap->n_nodes_leaf_max = cap->n_nodes_max;
-		break;
-	}
-
-	return 0;
-}
-
-static const struct rte_tm_node_capabilities tm_node_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 1,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 1,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.shaper_private_supported = 0,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 0,
-		.shaper_private_rate_max = 0,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 0,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-
-		{.leaf = {
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-		} },
-
-		.stats_mask = STATS_MASK_QUEUE,
-	},
-};
-
-/* Traffic manager node capabilities get */
-static int
-pmd_tm_node_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t node_id,
-	struct rte_tm_node_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	struct tm_node *tm_node;
-
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	tm_node = tm_node_search(dev, node_id);
-	if (tm_node == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_node_cap[tm_node->level], sizeof(*cap));
-
-	switch (tm_node->level) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-	case TM_NODE_LEVEL_TC:
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int
-shaper_profile_check(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_shaper_profile *sp;
-
-	/* Shaper profile ID must not be NONE. */
-	if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must not exist. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak rate: non-zero, 32-bit */
-	if (profile->peak.rate == 0 ||
-		profile->peak.rate >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak size: non-zero, 32-bit */
-	if (profile->peak.size == 0 ||
-		profile->peak.size >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Dual-rate profiles are not supported. */
-	if (profile->committed.rate != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet length adjust: 24 bytes */
-	if (profile->pkt_length_adjust != RTE_TM_ETH_FRAMING_OVERHEAD_FCS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet mode is not supported. */
-	if (profile->packet_mode != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PACKET_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-	return 0;
-}
-
-/* Traffic manager shaper profile add */
-static int
-pmd_tm_shaper_profile_add(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-	int status;
-
-	/* Check input params */
-	status = shaper_profile_check(dev, shaper_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	sp = calloc(1, sizeof(struct tm_shaper_profile));
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	sp->shaper_profile_id = shaper_profile_id;
-	memcpy(&sp->params, profile, sizeof(sp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(spl, sp, node);
-	p->soft.tm.h.n_shaper_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager shaper profile delete */
-static int
-pmd_tm_shaper_profile_delete(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp;
-
-	/* Check existing */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (sp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles, sp, node);
-	p->soft.tm.h.n_shaper_profiles--;
-	free(sp);
-
-	return 0;
-}
-
-static struct tm_node *
-tm_shared_shaper_get_tc(struct rte_eth_dev *dev,
-	struct tm_shared_shaper *ss)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	/* Subport: each TC uses shared shaper  */
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->params.n_shared_shapers == 0 ||
-			n->params.shared_shaper_id[0] != ss->shared_shaper_id)
-			continue;
-
-		return n;
-	}
-
-	return NULL;
-}
-
-static int
-subport_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_subport_profiles; i++)
-		if (memcmp(&t->subport_profile[i], sp, sizeof(*sp)) == 0) {
-			if (subport_profile_id)
-				*subport_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static int
-update_subport_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shared_shaper *ss,
-	struct tm_shaper_profile *sp_new)
-{
-	struct rte_sched_subport_profile_params subport_profile;
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-	struct tm_node *np = nt->parent_node;
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_profile_id;
-	struct tm_shaper_profile *sp_old = tm_shaper_profile_search(dev,
-		ss->shaper_profile_id);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return -1;
-
-	subport_profile_id = t->subport_to_profile[subport_id];
-
-	/* Derive new subport configuration. */
-	memcpy(&subport_profile,
-		&p->soft.tm.params.subport_profile[subport_profile_id],
-		sizeof(subport_profile));
-	subport_profile.tc_rate[tc_id] = sp_new->params.peak.rate;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p),
-		subport_id, NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	sp_old->n_users--;
-
-	ss->shaper_profile_id = sp_new->shaper_profile_id;
-	sp_new->n_users++;
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&subport_profile,
-		sizeof(subport_profile));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper add/update */
-static int
-pmd_tm_shared_shaper_add_update(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-	struct tm_shaper_profile *sp;
-	struct tm_node *nt;
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * Add new shared shaper
-	 */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL) {
-		struct tm_shared_shaper_list *ssl =
-			&p->soft.tm.h.shared_shapers;
-
-		/* Hierarchy must not be frozen */
-		if (p->soft.tm.hierarchy_frozen)
-			return -rte_tm_error_set(error,
-				EBUSY,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EBUSY));
-
-		/* Memory allocation */
-		ss = calloc(1, sizeof(struct tm_shared_shaper));
-		if (ss == NULL)
-			return -rte_tm_error_set(error,
-				ENOMEM,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(ENOMEM));
-
-		/* Fill in */
-		ss->shared_shaper_id = shared_shaper_id;
-		ss->shaper_profile_id = shaper_profile_id;
-
-		/* Add to list */
-		TAILQ_INSERT_TAIL(ssl, ss, node);
-		p->soft.tm.h.n_shared_shapers++;
-
-		return 0;
-	}
-
-	/**
-	 * Update existing shared shaper
-	 */
-	/* Hierarchy must be frozen (run-time update) */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-
-	/* Propagate change. */
-	nt = tm_shared_shaper_get_tc(dev, ss);
-	if (update_subport_tc_rate(dev, nt, ss, sp))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper delete */
-static int
-pmd_tm_shared_shaper_delete(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-
-	/* Check existing */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (ss->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, ss, node);
-	p->soft.tm.h.n_shared_shapers--;
-	free(ss);
-
-	return 0;
-}
-
-static int
-wred_profile_check(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_wred_profile *wp;
-	enum rte_color color;
-
-	/* WRED profile ID must not be NONE. */
-	if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WRED profile must not exist. */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-        /* WRED profile should be in packet mode */
-        if (profile->packet_mode == 0)
-                return -rte_tm_error_set(error,
-                        ENOTSUP,
-                        RTE_TM_ERROR_TYPE_WRED_PROFILE,
-                        NULL,
-                        rte_strerror(ENOTSUP));
-
-	/* min_th <= max_th, max_th > 0  */
-	for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-		uint32_t min_th = profile->red_params[color].min_th;
-		uint32_t max_th = profile->red_params[color].max_th;
-
-		if (min_th > max_th ||
-			max_th == 0 ||
-			min_th > UINT16_MAX ||
-			max_th > UINT16_MAX)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_WRED_PROFILE,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager WRED profile add */
-static int
-pmd_tm_wred_profile_add(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-	int status;
-
-	/* Check input params */
-	status = wred_profile_check(dev, wred_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	wp = calloc(1, sizeof(struct tm_wred_profile));
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	wp->wred_profile_id = wred_profile_id;
-	memcpy(&wp->params, profile, sizeof(wp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(wpl, wp, node);
-	p->soft.tm.h.n_wred_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager WRED profile delete */
-static int
-pmd_tm_wred_profile_delete(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile *wp;
-
-	/* Check existing */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (wp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wp, node);
-	p->soft.tm.h.n_wred_profiles--;
-	free(wp);
-
-	return 0;
-}
-
-static int
-node_add_check_port(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp = tm_shaper_profile_search(dev,
-		params->shaper_profile_id);
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_subport(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_pipe(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 4 */
-	if (params->nonleaf.n_sp_priorities !=
-		RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WFQ mode must be byte mode */
-	if (params->nonleaf.wfq_weight_mode != NULL &&
-		params->nonleaf.wfq_weight_mode[0] != 0 &&
-		params->nonleaf.wfq_weight_mode[1] != 0 &&
-		params->nonleaf.wfq_weight_mode[2] != 0 &&
-		params->nonleaf.wfq_weight_mode[3] != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_tc(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority __rte_unused,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Single valid shared shaper */
-	if (params->n_shared_shapers > 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (params->n_shared_shapers == 1 &&
-		(params->shared_shaper_id == NULL ||
-		(!tm_shared_shaper_search(dev, params->shared_shaper_id[0]))))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_queue(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: leaf */
-	if (node_id >= p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shaper */
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management must not be head drop */
-	if (params->leaf.cman == RTE_TM_CMAN_HEAD_DROP)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management set to WRED */
-	if (params->leaf.cman == RTE_TM_CMAN_WRED) {
-		uint32_t wred_profile_id = params->leaf.wred.wred_profile_id;
-		struct tm_wred_profile *wp = tm_wred_profile_search(dev,
-			wred_profile_id);
-
-		/* WRED profile (for private WRED context) must be valid */
-		if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE ||
-			wp == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-
-		/* No shared WRED contexts */
-		if (params->leaf.wred.n_shared_wred_contexts != 0)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_QUEUE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct tm_node *pn;
-	uint32_t level;
-	int status;
-
-	/* node_id, parent_node_id:
-	 *    -node_id must not be RTE_TM_NODE_ID_NULL
-	 *    -node_id must not be in use
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -root node must not exist
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -parent_node_id must be valid
-	 */
-	if (node_id == RTE_TM_NODE_ID_NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (tm_node_search(dev, node_id))
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
-		pn = NULL;
-		if (tm_root_node_present(dev))
-			return -rte_tm_error_set(error,
-				EEXIST,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EEXIST));
-	} else {
-		pn = tm_node_search(dev, parent_node_id);
-		if (pn == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* priority: must be 0 .. 3 */
-	if (priority >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* level_id: if valid, then
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be zero
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be parent level ID plus one
-	 */
-	level = (pn == NULL) ? 0 : pn->level + 1;
-	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY && level_id != level)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: must not be NULL */
-	if (params == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: per level checks */
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		status = node_add_check_port(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		status = node_add_check_subport(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		status = node_add_check_pipe(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		status = node_add_check_tc(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-		status = node_add_check_queue(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager node add */
-static int
-pmd_tm_node_add(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-	uint32_t i;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = node_add_check(dev, node_id, parent_node_id, priority, weight,
-		level_id, params, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	n = calloc(1, sizeof(struct tm_node));
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	n->node_id = node_id;
-	n->parent_node_id = parent_node_id;
-	n->priority = priority;
-	n->weight = weight;
-
-	if (parent_node_id != RTE_TM_NODE_ID_NULL) {
-		n->parent_node = tm_node_search(dev, parent_node_id);
-		n->level = n->parent_node->level + 1;
-	}
-
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		n->shaper_profile = tm_shaper_profile_search(dev,
-			params->shaper_profile_id);
-
-	if (n->level == TM_NODE_LEVEL_QUEUE &&
-		params->leaf.cman == RTE_TM_CMAN_WRED)
-		n->wred_profile = tm_wred_profile_search(dev,
-			params->leaf.wred.wred_profile_id);
-
-	memcpy(&n->params, params, sizeof(n->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(nl, n, node);
-	p->soft.tm.h.n_nodes++;
-
-	/* Update dependencies */
-	if (n->parent_node)
-		n->parent_node->n_children++;
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users++;
-
-	for (i = 0; i < params->n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev, params->shared_shaper_id[i]);
-		ss->n_users++;
-	}
-
-	if (n->wred_profile)
-		n->wred_profile->n_users++;
-
-	p->soft.tm.h.n_tm_nodes[n->level]++;
-
-	return 0;
-}
-
-/* Traffic manager node delete */
-static int
-pmd_tm_node_delete(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node *n;
-	uint32_t i;
-
-	/* Check hierarchy changes are currently allowed */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Check existing */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (n->n_children)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Update dependencies */
-	p->soft.tm.h.n_tm_nodes[n->level]--;
-
-	if (n->wred_profile)
-		n->wred_profile->n_users--;
-
-	for (i = 0; i < n->params.n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev,
-				n->params.shared_shaper_id[i]);
-		ss->n_users--;
-	}
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users--;
-
-	if (n->parent_node)
-		n->parent_node->n_children--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.nodes, n, node);
-	p->soft.tm.h.n_nodes--;
-	free(n);
-
-	return 0;
-}
-
-
-static void
-pipe_profile_build(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_sched_pipe_params *pp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nt, *nq;
-
-	memset(pp, 0, sizeof(*pp));
-
-	/* Pipe */
-	pp->tb_rate = np->shaper_profile->params.peak.rate;
-	pp->tb_size = np->shaper_profile->params.peak.size;
-
-	/* Traffic Class (TC) */
-	pp->tc_period = PIPE_TC_PERIOD;
-
-	pp->tc_ov_weight = np->weight;
-
-	TAILQ_FOREACH(nt, nl, node) {
-		uint32_t queue_id = 0;
-
-		if (nt->level != TM_NODE_LEVEL_TC ||
-			nt->parent_node_id != np->node_id)
-			continue;
-
-		pp->tc_rate[nt->priority] =
-			nt->shaper_profile->params.peak.rate;
-
-		/* Queue */
-		TAILQ_FOREACH(nq, nl, node) {
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE ||
-				nq->parent_node_id != nt->node_id)
-				continue;
-
-			if (nt->priority == RTE_SCHED_TRAFFIC_CLASS_BE)
-				pp->wrr_weights[queue_id] = nq->weight;
-
-			queue_id++;
-		}
-	}
-}
-
-static int
-pipe_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_pipe_profiles < TM_MAX_PIPE_PROFILE) {
-		*pipe_profile_id = t->n_pipe_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static int
-pipe_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_pipe_profiles; i++)
-		if (memcmp(&t->pipe_profiles[i], pp, sizeof(*pp)) == 0) {
-			if (pipe_profile_id)
-				*pipe_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static void
-pipe_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->pipe_profiles[pipe_profile_id], pp, sizeof(*pp));
-	t->n_pipe_profiles++;
-}
-
-static void
-pipe_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport, pos;
-
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	pos = subport_id * n_pipes_per_subport + pipe_id;
-
-	t->pipe_to_profile[pos] = pipe_profile_id;
-}
-
-static struct rte_sched_pipe_params *
-pipe_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	uint32_t pos = subport_id * n_pipes_per_subport + pipe_id;
-	uint32_t pipe_profile_id = t->pipe_to_profile[pos];
-
-	return &t->pipe_profiles[pipe_profile_id];
-}
-
-static int
-pipe_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns, *np;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - pipe_profiles
-	 *    - n_pipe_profiles
-	 *    - pipe_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		uint32_t pipe_id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		pipe_id = 0;
-		TAILQ_FOREACH(np, nl, node) {
-			struct rte_sched_pipe_params pp;
-			uint32_t pos;
-
-			memset(&pp, 0, sizeof(pp));
-
-			if (np->level != TM_NODE_LEVEL_PIPE ||
-				np->parent_node_id != ns->node_id)
-				continue;
-
-			pipe_profile_build(dev, np, &pp);
-
-			if (!pipe_profile_exists(dev, &pp, &pos)) {
-				if (!pipe_profile_free_exists(dev, &pos))
-					return -1;
-
-				pipe_profile_install(dev, &pp, pos);
-			}
-
-			pipe_profile_mark(dev, subport_id, pipe_id, pos);
-
-			pipe_id++;
-		}
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-static struct tm_wred_profile *
-tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nq;
-
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node->priority != tc_id)
-			continue;
-
-		return nq->wred_profile;
-	}
-
-	return NULL;
-}
-
-#ifdef RTE_SCHED_CMAN
-
-static void
-wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_subport_params *pp =
-		&p->soft.tm.params.subport_params[subport_id];
-
-	uint32_t tc_id;
-	enum rte_color color;
-
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++)
-		for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-			struct rte_red_params *dst =
-				&pp->cman_params->red_params[tc_id][color];
-			struct tm_wred_profile *src_wp =
-				tm_tc_wred_profile_get(dev, tc_id);
-			struct rte_tm_red_params *src =
-				&src_wp->params.red_params[color];
-
-			memcpy(dst, src, sizeof(*dst));
-		}
-}
-
-#else
-
-#define wred_profiles_set(dev, subport_id)
-
-#endif
-
-static struct tm_shared_shaper *
-tm_tc_shared_shaper_get(struct rte_eth_dev *dev, struct tm_node *tc_node)
-{
-	return (tc_node->params.n_shared_shapers) ?
-		tm_shared_shaper_search(dev,
-			tc_node->params.shared_shaper_id[0]) :
-		NULL;
-}
-
-static struct tm_shared_shaper *
-tm_subport_tc_shared_shaper_get(struct rte_eth_dev *dev,
-	struct tm_node *subport_node,
-	uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->parent_node->parent_node_id !=
-				subport_node->node_id ||
-			n->priority != tc_id)
-			continue;
-
-		return tm_tc_shared_shaper_get(dev, n);
-	}
-
-	return NULL;
-}
-
-static struct rte_sched_subport_profile_params *
-subport_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return NULL;
-
-	return &t->subport_profile[subport_id];
-}
-
-static void
-subport_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	t->subport_to_profile[subport_id] = subport_profile_id;
-}
-
-static void
-subport_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->subport_profile[subport_profile_id],
-		sp, sizeof(*sp));
-	t->n_subport_profiles++;
-}
-
-static int
-subport_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_subport_profiles < TM_MAX_SUBPORT_PROFILE) {
-		*subport_profile_id = t->n_subport_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static void
-subport_profile_build(struct rte_eth_dev *dev, struct tm_node *np,
-	struct rte_sched_subport_profile_params *sp)
-{
-	uint32_t i;
-	memset(sp, 0, sizeof(*sp));
-
-	sp->tb_rate = np->shaper_profile->params.peak.rate;
-	sp->tb_size = np->shaper_profile->params.peak.size;
-
-	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
-		struct tm_shared_shaper *ss;
-		struct tm_shaper_profile *ssp;
-
-		ss = tm_subport_tc_shared_shaper_get(dev, np, i);
-		ssp = (ss) ? tm_shaper_profile_search(dev,
-			ss->shaper_profile_id) :
-			np->shaper_profile;
-		sp->tc_rate[i] = ssp->params.peak.rate;
-	}
-
-	/* Traffic Class (TC) */
-	sp->tc_period = SUBPORT_TC_PERIOD;
-}
-
-static int
-subport_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - subport_profiles
-	 *    - n_subport_profiles
-	 *    - subport_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		struct rte_sched_subport_profile_params sp;
-		uint32_t pos;
-
-		memset(&sp, 0, sizeof(sp));
-
-		subport_profile_build(dev, ns, &sp);
-
-		if (!subport_profile_exists(dev, &sp, &pos)) {
-			if (!subport_profile_free_exists(dev, &pos))
-				return -1;
-
-			subport_profile_install(dev, &sp, pos);
-		}
-
-		subport_profile_mark(dev, subport_id, pos);
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-
-static int
-hierarchy_commit_check(struct rte_eth_dev *dev, struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_shared_shaper_list *ssl = &h->shared_shapers;
-	struct tm_wred_profile_list *wpl = &h->wred_profiles;
-	struct tm_node *nr = tm_root_node_present(dev), *ns, *np, *nt, *nq;
-	struct tm_shared_shaper *ss;
-
-	uint32_t n_pipes_per_subport;
-
-	/* Root node exists. */
-	if (nr == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one subport, max is not exceeded. */
-	if (nr->n_children == 0 || nr->n_children > TM_MAX_SUBPORTS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one pipe. */
-	if (h->n_tm_nodes[TM_NODE_LEVEL_PIPE] == 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of pipes is the same for all subports. Maximum number of pipes
-	 * per subport is not exceeded.
-	 */
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	if (n_pipes_per_subport > TM_MAX_PIPES_PER_SUBPORT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->n_children != n_pipes_per_subport)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Each pipe has exactly 13 TCs, with exactly one TC for each priority */
-	TAILQ_FOREACH(np, nl, node) {
-		uint32_t mask = 0, mask_expected =
-			RTE_LEN2MASK(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-				uint32_t);
-
-		if (np->level != TM_NODE_LEVEL_PIPE)
-			continue;
-
-		if (np->n_children != RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-
-		TAILQ_FOREACH(nt, nl, node) {
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node_id != np->node_id)
-				continue;
-
-			mask |= 1 << nt->priority;
-		}
-
-		if (mask != mask_expected)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/** Each Strict priority TC has exactly 1 packet queues while
-	 *	lowest priority TC (Best-effort) has 4 queues.
-	 */
-	TAILQ_FOREACH(nt, nl, node) {
-		if (nt->level != TM_NODE_LEVEL_TC)
-			continue;
-
-		if (nt->n_children != 1 && nt->n_children != RTE_SCHED_BE_QUEUES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/**
-	 * Shared shapers:
-	 *    -For each TC #i, all pipes in the same subport use the same
-	 *     shared shaper (or no shared shaper) for their TC#i.
-	 *    -Each shared shaper needs to have at least one user. All its
-	 *     users have to be TC nodes with the same priority and the same
-	 *     subport.
-	 */
-	TAILQ_FOREACH(ns, nl, node) {
-		struct tm_shared_shaper *s[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++)
-			s[id] = tm_subport_tc_shared_shaper_get(dev, ns, id);
-
-		TAILQ_FOREACH(nt, nl, node) {
-			struct tm_shared_shaper *subport_ss, *tc_ss;
-
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node->parent_node_id !=
-					ns->node_id)
-				continue;
-
-			subport_ss = s[nt->priority];
-			tc_ss = tm_tc_shared_shaper_get(dev, nt);
-
-			if (subport_ss == NULL && tc_ss == NULL)
-				continue;
-
-			if ((subport_ss == NULL && tc_ss != NULL) ||
-				(subport_ss != NULL && tc_ss == NULL) ||
-				subport_ss->shared_shaper_id !=
-					tc_ss->shared_shaper_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	TAILQ_FOREACH(ss, ssl, node) {
-		struct tm_node *nt_any = tm_shared_shaper_get_tc(dev, ss);
-		uint32_t n_users = 0;
-
-		if (nt_any != NULL)
-			TAILQ_FOREACH(nt, nl, node) {
-				if (nt->level != TM_NODE_LEVEL_TC ||
-					nt->priority != nt_any->priority ||
-					nt->parent_node->parent_node_id !=
-					nt_any->parent_node->parent_node_id)
-					continue;
-
-				n_users++;
-			}
-
-		if (ss->n_users == 0 || ss->n_users != n_users)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Not too many subport profiles. */
-	if (subport_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-
-	/* Not too many pipe profiles. */
-	if (pipe_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * WRED (when used, i.e. at least one WRED profile defined):
-	 *    -Each WRED profile must have at least one user.
-	 *    -All leaf nodes must have their private WRED context enabled.
-	 *    -For each TC #i, all leaf nodes must use the same WRED profile
-	 *     for their private WRED context.
-	 */
-	if (h->n_wred_profiles) {
-		struct tm_wred_profile *wp;
-		struct tm_wred_profile *w[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		TAILQ_FOREACH(wp, wpl, node)
-			if (wp->n_users == 0)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			w[id] = tm_tc_wred_profile_get(dev, id);
-
-			if (w[id] == NULL)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-
-		TAILQ_FOREACH(nq, nl, node) {
-			uint32_t id;
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE)
-				continue;
-
-			id = nq->parent_node->priority;
-
-			if (nq->wred_profile == NULL ||
-				nq->wred_profile->wred_profile_id !=
-					w[id]->wred_profile_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	return 0;
-}
-
-static void
-hierarchy_blueprints_create(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *root = tm_root_node_present(dev), *n;
-
-	uint32_t subport_id;
-
-	t->port_params = (struct rte_sched_port_params) {
-		.name = dev->data->name,
-		.socket = dev->data->numa_node,
-		.rate = root->shaper_profile->params.peak.rate,
-		.mtu = dev->data->mtu,
-		.frame_overhead =
-			root->shaper_profile->params.pkt_length_adjust,
-		.n_subports_per_port = root->n_children,
-		.n_subport_profiles = t->n_subport_profiles,
-		.subport_profiles = t->subport_profile,
-		.n_max_subport_profiles = TM_MAX_SUBPORT_PROFILE,
-		.n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT,
-	};
-
-	subport_id = 0;
-	TAILQ_FOREACH(n, nl, node) {
-
-		if (n->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		t->subport_params[subport_id] =
-			(struct rte_sched_subport_params) {
-				.n_pipes_per_subport_enabled =
-					h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-					h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT],
-				.qsize = {p->params.tm.qsize[0],
-					p->params.tm.qsize[1],
-					p->params.tm.qsize[2],
-					p->params.tm.qsize[3],
-					p->params.tm.qsize[4],
-					p->params.tm.qsize[5],
-					p->params.tm.qsize[6],
-					p->params.tm.qsize[7],
-					p->params.tm.qsize[8],
-					p->params.tm.qsize[9],
-					p->params.tm.qsize[10],
-					p->params.tm.qsize[11],
-					p->params.tm.qsize[12],
-				},
-				.pipe_profiles = t->pipe_profiles,
-				.n_pipe_profiles = t->n_pipe_profiles,
-				.n_max_pipe_profiles = TM_MAX_PIPE_PROFILE,
-		};
-		wred_profiles_set(dev, subport_id);
-		subport_id++;
-	}
-}
-
-/* Traffic manager hierarchy commit */
-static int
-pmd_tm_hierarchy_commit(struct rte_eth_dev *dev,
-	int clear_on_fail,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = hierarchy_commit_check(dev, error);
-	if (status) {
-		if (clear_on_fail)
-			tm_hierarchy_free(p);
-
-		return status;
-	}
-
-	/* Create blueprints */
-	hierarchy_blueprints_create(dev);
-
-	/* Freeze hierarchy */
-	p->soft.tm.hierarchy_frozen = 1;
-
-	return 0;
-}
-
-static int
-update_pipe_weight(struct rte_eth_dev *dev, struct tm_node *np, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_ov_weight = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->weight = weight;
-
-	return 0;
-}
-
-static int
-update_queue_weight(struct rte_eth_dev *dev,
-	struct tm_node *nq, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	uint32_t pipe_be_queue_id =
-		queue_id - RTE_SCHED_TRAFFIC_CLASS_BE;
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.wrr_weights[pipe_be_queue_id] = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set
-	 * of pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nq->weight = weight;
-
-	return 0;
-}
-
-/* Traffic manager node parent update */
-static int
-pmd_tm_node_parent_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Parent node must be the same */
-	if (n->parent_node_id != parent_node_id)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be the same */
-	if (n->priority != priority)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		if (update_queue_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-static int
-update_subport_rate(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_subport_profile_params *profile0 =
-					subport_profile_get(dev, ns);
-	struct rte_sched_subport_profile_params profile1;
-	uint32_t subport_profile_id;
-
-	if (profile0 == NULL)
-		return -1;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more subport profiles
-	 * after port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (subport_profile_exists(dev, &profile1, &subport_profile_id) == 0)
-		return -1;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p), subport_id,
-		NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	ns->shaper_profile->n_users--;
-
-	ns->shaper_profile = sp;
-	ns->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	subport_profile_mark(dev, subport_id, subport_profile_id);
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&profile1,
-		sizeof(profile1));
-
-	return 0;
-}
-
-static int
-update_pipe_rate(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->shaper_profile->n_users--;
-	np->shaper_profile = sp;
-	np->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-static int
-update_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_rate[tc_id] = sp->params.peak.rate;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nt->shaper_profile->n_users--;
-	nt->shaper_profile = sp;
-	nt->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-/* Traffic manager node shaper update */
-static int
-pmd_tm_node_shaper_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-	struct tm_shaper_profile *sp;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		if (update_subport_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		if (update_tc_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-}
-
-static inline uint32_t
-tm_port_queue_id(struct rte_eth_dev *dev,
-	uint32_t port_subport_id,
-	uint32_t subport_pipe_id,
-	uint32_t pipe_tc_id,
-	uint32_t tc_queue_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-			h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t port_pipe_id =
-		port_subport_id * n_pipes_per_subport + subport_pipe_id;
-
-	uint32_t port_queue_id =
-		port_pipe_id * RTE_SCHED_QUEUES_PER_PIPE + pipe_tc_id + tc_queue_id;
-
-	return port_queue_id;
-}
-
-static int
-read_port_stats(struct rte_eth_dev *dev,
-	struct tm_node *nr,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_subports_per_port = h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	uint32_t subport_id;
-
-	for (subport_id = 0; subport_id < n_subports_per_port; subport_id++) {
-		struct rte_sched_subport_stats s;
-		uint32_t tc_ov, id;
-
-		/* Stats read */
-		int status = rte_sched_subport_read_stats(SCHED(p),
-			subport_id,
-			&s,
-			&tc_ov);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			nr->stats.n_pkts +=
-				s.n_pkts_tc[id] - s.n_pkts_tc_dropped[id];
-			nr->stats.n_bytes +=
-				s.n_bytes_tc[id] - s.n_bytes_tc_dropped[id];
-			nr->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_tc_dropped[id];
-			nr->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_tc_dropped[id];
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nr->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nr->stats, 0, sizeof(nr->stats));
-
-	return 0;
-}
-
-static int
-read_subport_stats(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_subport_stats s;
-	uint32_t tc_ov, tc_id;
-
-	/* Stats read */
-	int status = rte_sched_subport_read_stats(SCHED(p),
-		subport_id,
-		&s,
-		&tc_ov);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++) {
-		ns->stats.n_pkts +=
-			s.n_pkts_tc[tc_id] - s.n_pkts_tc_dropped[tc_id];
-		ns->stats.n_bytes +=
-			s.n_bytes_tc[tc_id] - s.n_bytes_tc_dropped[tc_id];
-		ns->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-			s.n_pkts_tc_dropped[tc_id];
-		ns->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_tc_dropped[tc_id];
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &ns->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&ns->stats, 0, sizeof(ns->stats));
-
-	return 0;
-}
-
-static int
-read_pipe_stats(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	uint32_t tc_id, queue_id;
-	uint32_t i;
-
-	/* Stats read */
-	for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) {
-		struct rte_sched_queue_stats s;
-		uint16_t qlen;
-
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			tc_id = i;
-			queue_id = i;
-		} else {
-			tc_id = RTE_SCHED_TRAFFIC_CLASS_BE;
-			queue_id = i - tc_id;
-		}
-
-		uint32_t qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			queue_id);
-
-		int status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		np->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		np->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		np->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_queued = qlen;
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &np->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&np->stats, 0, sizeof(np->stats));
-
-	return 0;
-}
-
-static int
-read_tc_stats(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_queue_stats s;
-	uint32_t qid, i;
-	uint16_t qlen;
-	int status;
-
-	/* Stats read */
-	if (tc_id < RTE_SCHED_TRAFFIC_CLASS_BE) {
-		qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			0);
-
-		status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_queued = qlen;
-	} else {
-		for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) {
-			qid = tm_port_queue_id(dev,
-				subport_id,
-				pipe_id,
-				tc_id,
-				i);
-
-			status = rte_sched_queue_read_stats(SCHED(p),
-				qid,
-				&s,
-				&qlen);
-			if (status)
-				return status;
-
-			/* Stats accumulate */
-			nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-			nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_dropped;
-			nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_queued = qlen;
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nt->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nt->stats, 0, sizeof(nt->stats));
-
-	return 0;
-}
-
-static int
-read_queue_stats(struct rte_eth_dev *dev,
-	struct tm_node *nq,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_queue_stats s;
-	uint16_t qlen;
-
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	/* Stats read */
-	uint32_t qid = tm_port_queue_id(dev,
-		subport_id,
-		pipe_id,
-		tc_id,
-		queue_id);
-
-	int status = rte_sched_queue_read_stats(SCHED(p),
-		qid,
-		&s,
-		&qlen);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	nq->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-	nq->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-	nq->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-		s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_queued = qlen;
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nq->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_QUEUE;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nq->stats, 0, sizeof(nq->stats));
-
-	return 0;
-}
-
-/* Traffic manager read stats counters for specific node */
-static int
-pmd_tm_node_stats_read(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		if (read_port_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		if (read_subport_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_PIPE:
-		if (read_pipe_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_TC:
-		if (read_tc_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		if (read_queue_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-const struct rte_tm_ops pmd_tm_ops = {
-	.node_type_get = pmd_tm_node_type_get,
-	.capabilities_get = pmd_tm_capabilities_get,
-	.level_capabilities_get = pmd_tm_level_capabilities_get,
-	.node_capabilities_get = pmd_tm_node_capabilities_get,
-
-	.wred_profile_add = pmd_tm_wred_profile_add,
-	.wred_profile_delete = pmd_tm_wred_profile_delete,
-	.shared_wred_context_add_update = NULL,
-	.shared_wred_context_delete = NULL,
-
-	.shaper_profile_add = pmd_tm_shaper_profile_add,
-	.shaper_profile_delete = pmd_tm_shaper_profile_delete,
-	.shared_shaper_add_update = pmd_tm_shared_shaper_add_update,
-	.shared_shaper_delete = pmd_tm_shared_shaper_delete,
-
-	.node_add = pmd_tm_node_add,
-	.node_delete = pmd_tm_node_delete,
-	.node_suspend = NULL,
-	.node_resume = NULL,
-	.hierarchy_commit = pmd_tm_hierarchy_commit,
-
-	.node_parent_update = pmd_tm_node_parent_update,
-	.node_shaper_update = pmd_tm_node_shaper_update,
-	.node_shared_shaper_update = NULL,
-	.node_stats_update = NULL,
-	.node_wfq_weight_mode_update = NULL,
-	.node_cman_update = NULL,
-	.node_wred_context_update = NULL,
-	.node_shared_wred_context_update = NULL,
-
-	.node_stats_read = pmd_tm_node_stats_read,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 02/21] net/softnic: remove flow support
  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 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 03/21] net/softnic: remove the meter support Cristian Dumitrescu
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the Ethernet device flow API support.

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      |    9 -
 drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -
 drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------
 4 files changed, 2384 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index e2dbd6166e..4ebe60921c 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -13,7 +13,6 @@ sources = files(
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_cryptodev.c',
-        'rte_eth_softnic_flow.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_meter.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index ae3e8b3bcd..8e361adbad 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -215,14 +215,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
-		 const struct rte_flow_ops **ops)
-{
-	*ops = &pmd_flow_ops;
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -240,7 +232,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.flow_ops_get = pmd_flow_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7556e50831..671f96cf77 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4731,81 +4731,6 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * flowapi map
- *  group <group_id>
- *  ingress | egress
- *  pipeline <pipeline_name>
- *  table <table_id>
- */
-static void
-cmd_softnic_flowapi_map(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t group_id, table_id;
-	int ingress, status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "map") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "map");
-		return;
-	}
-
-	if (strcmp(tokens[2], "group") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "ingress") == 0) {
-		ingress = 1;
-	} else if (strcmp(tokens[4], "egress") == 0) {
-		ingress = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ingress | egress");
-		return;
-	}
-
-	if (strcmp(tokens[5], "pipeline") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
-		return;
-	}
-
-	pipeline_name = tokens[6];
-
-	if (strcmp(tokens[7], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = flow_attr_map_set(softnic,
-			group_id,
-			ingress,
-			pipeline_name,
-			table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 void
 softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 {
@@ -5063,12 +4988,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		}
 	}
 
-	if (strcmp(tokens[0], "flowapi") == 0) {
-		cmd_softnic_flowapi_map(softnic, tokens, n_tokens, out,
-					out_size);
-		return;
-	}
-
 	snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
 }
 
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
deleted file mode 100644
index ad96288e7e..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ /dev/null
@@ -1,2293 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-#include <rte_flow.h>
-#include <rte_flow_driver.h>
-#include <rte_tailq.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define rte_htons rte_cpu_to_be_16
-#define rte_htonl rte_cpu_to_be_32
-
-#define rte_ntohs rte_be_to_cpu_16
-#define rte_ntohl rte_be_to_cpu_32
-
-static struct rte_flow *
-softnic_flow_find(struct softnic_table *table,
-	struct softnic_table_rule_match *rule_match)
-{
-	struct rte_flow *flow;
-
-	TAILQ_FOREACH(flow, &table->flows, node)
-		if (memcmp(&flow->match, rule_match, sizeof(*rule_match)) == 0)
-			return flow;
-
-	return NULL;
-}
-
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id)
-{
-	struct pipeline *pipeline;
-	struct flow_attr_map *map;
-
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||
-			pipeline_name == NULL)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL ||
-			table_id >= pipeline->n_tables)
-		return -1;
-
-	map = (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-	strlcpy(map->pipeline_name, pipeline_name, sizeof(map->pipeline_name));
-	map->table_id = table_id;
-	map->valid = 1;
-
-	return 0;
-}
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress)
-{
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS)
-		return NULL;
-
-	return (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-}
-
-static int
-flow_pipeline_table_get(struct pmd_internals *softnic,
-		const struct rte_flow_attr *attr,
-		const char **pipeline_name,
-		uint32_t *table_id,
-		struct rte_flow_error *error)
-{
-	struct flow_attr_map *map;
-
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL,
-				"Null attr");
-
-	if (!attr->ingress && !attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Ingress/egress not specified");
-
-	if (attr->ingress && attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Setting both ingress and egress is not allowed");
-
-	map = flow_attr_map_get(softnic,
-			attr->group,
-			attr->ingress);
-	if (map == NULL ||
-			map->valid == 0)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
-				attr,
-				"Invalid group ID");
-
-	if (pipeline_name)
-		*pipeline_name = map->pipeline_name;
-
-	if (table_id)
-		*table_id = map->table_id;
-
-	return 0;
-}
-
-union flow_item {
-	uint8_t raw[TABLE_RULE_MATCH_SIZE_MAX];
-	struct rte_flow_item_eth eth;
-	struct rte_flow_item_vlan vlan;
-	struct rte_flow_item_ipv4 ipv4;
-	struct rte_flow_item_ipv6 ipv6;
-	struct rte_flow_item_icmp icmp;
-	struct rte_flow_item_udp udp;
-	struct rte_flow_item_tcp tcp;
-	struct rte_flow_item_sctp sctp;
-	struct rte_flow_item_vxlan vxlan;
-	struct rte_flow_item_e_tag e_tag;
-	struct rte_flow_item_nvgre nvgre;
-	struct rte_flow_item_mpls mpls;
-	struct rte_flow_item_gre gre;
-	struct rte_flow_item_gtp gtp;
-	struct rte_flow_item_esp esp;
-	struct rte_flow_item_geneve geneve;
-	struct rte_flow_item_vxlan_gpe vxlan_gpe;
-	struct rte_flow_item_arp_eth_ipv4 arp_eth_ipv4;
-	struct rte_flow_item_ipv6_ext ipv6_ext;
-	struct rte_flow_item_icmp6 icmp6;
-	struct rte_flow_item_icmp6_nd_ns icmp6_nd_ns;
-	struct rte_flow_item_icmp6_nd_na icmp6_nd_na;
-	struct rte_flow_item_icmp6_nd_opt icmp6_nd_opt;
-	struct rte_flow_item_icmp6_nd_opt_sla_eth icmp6_nd_opt_sla_eth;
-	struct rte_flow_item_icmp6_nd_opt_tla_eth icmp6_nd_opt_tla_eth;
-};
-
-static const union flow_item flow_item_raw_mask;
-
-static int
-flow_item_is_proto(enum rte_flow_item_type type,
-	const void **mask,
-	size_t *size)
-{
-	switch (type) {
-	case RTE_FLOW_ITEM_TYPE_RAW:
-		*mask = &flow_item_raw_mask;
-		*size = sizeof(flow_item_raw_mask);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_ETH:
-		*mask = &rte_flow_item_eth_mask;
-		*size = sizeof(struct rte_ether_hdr);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_VLAN:
-		*mask = &rte_flow_item_vlan_mask;
-		*size = sizeof(struct rte_vlan_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-		*mask = &rte_flow_item_ipv4_mask;
-		*size = sizeof(struct rte_ipv4_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-		*mask = &rte_flow_item_ipv6_mask;
-		*size = sizeof(struct rte_ipv6_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP:
-		*mask = &rte_flow_item_icmp_mask;
-		*size = sizeof(struct rte_flow_item_icmp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-		*mask = &rte_flow_item_udp_mask;
-		*size = sizeof(struct rte_flow_item_udp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_TCP:
-		*mask = &rte_flow_item_tcp_mask;
-		*size = sizeof(struct rte_flow_item_tcp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-		*mask = &rte_flow_item_sctp_mask;
-		*size = sizeof(struct rte_flow_item_sctp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN:
-		*mask = &rte_flow_item_vxlan_mask;
-		*size = sizeof(struct rte_flow_item_vxlan);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_E_TAG:
-		*mask = &rte_flow_item_e_tag_mask;
-		*size = sizeof(struct rte_flow_item_e_tag);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_NVGRE:
-		*mask = &rte_flow_item_nvgre_mask;
-		*size = sizeof(struct rte_flow_item_nvgre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_MPLS:
-		*mask = &rte_flow_item_mpls_mask;
-		*size = sizeof(struct rte_flow_item_mpls);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GRE:
-		*mask = &rte_flow_item_gre_mask;
-		*size = sizeof(struct rte_flow_item_gre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GTP:
-	case RTE_FLOW_ITEM_TYPE_GTPC:
-	case RTE_FLOW_ITEM_TYPE_GTPU:
-		*mask = &rte_flow_item_gtp_mask;
-		*size = sizeof(struct rte_flow_item_gtp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ESP:
-		*mask = &rte_flow_item_esp_mask;
-		*size = sizeof(struct rte_flow_item_esp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GENEVE:
-		*mask = &rte_flow_item_geneve_mask;
-		*size = sizeof(struct rte_flow_item_geneve);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
-		*mask = &rte_flow_item_vxlan_gpe_mask;
-		*size = sizeof(struct rte_flow_item_vxlan_gpe);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4:
-		*mask = &rte_flow_item_arp_eth_ipv4_mask;
-		*size = sizeof(struct rte_flow_item_arp_eth_ipv4);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
-		*mask = &rte_flow_item_ipv6_ext_mask;
-		*size = sizeof(struct rte_flow_item_ipv6_ext);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6:
-		*mask = &rte_flow_item_icmp6_mask;
-		*size = sizeof(struct rte_flow_item_icmp6);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS:
-		*mask = &rte_flow_item_icmp6_nd_ns_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_ns);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA:
-		*mask = &rte_flow_item_icmp6_nd_na_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_na);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT:
-		*mask = &rte_flow_item_icmp6_nd_opt_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_sla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_tla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth);
-		return 1;
-
-	default: return 0; /* FALSE */
-	}
-}
-
-static int
-flow_item_raw_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const struct rte_flow_item_raw *item_raw_spec = item->spec;
-	const struct rte_flow_item_raw *item_raw_mask = item->mask;
-	const uint8_t *pattern;
-	const uint8_t *pattern_mask;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t pattern_length, pattern_offset, i;
-	int disabled;
-
-	if (!item->spec)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Null specification");
-
-	if (item->last)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Range not allowed (last must be NULL)");
-
-	if (item_raw_spec->relative == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Absolute offset not supported");
-
-	if (item_raw_spec->search)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Search not supported");
-
-	if (item_raw_spec->offset < 0)
-		return rte_flow_error_set(error,
-			ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Negative offset not supported");
-
-	if (item_raw_spec->length == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Zero pattern length");
-
-	if (item_raw_spec->offset + item_raw_spec->length >
-		TABLE_RULE_MATCH_SIZE_MAX)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Item too big");
-
-	if (!item_raw_spec->pattern && item_raw_mask && item_raw_mask->pattern)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Non-NULL pattern mask not allowed with NULL pattern");
-
-	pattern = item_raw_spec->pattern;
-	pattern_mask = (item_raw_mask) ? item_raw_mask->pattern : NULL;
-	pattern_length = (size_t)item_raw_spec->length;
-	pattern_offset = (size_t)item_raw_spec->offset;
-
-	disabled = 0;
-	if (pattern_mask == NULL)
-		disabled = 1;
-	else
-		for (i = 0; i < pattern_length; i++)
-			if ((pattern)[i])
-				disabled = 1;
-
-	memset(spec, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern)
-		memcpy(&spec[pattern_offset], pattern, pattern_length);
-
-	memset(mask, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern_mask)
-		memcpy(&mask[pattern_offset], pattern_mask, pattern_length);
-
-	*item_size = pattern_offset + pattern_length;
-	*item_disabled = disabled;
-
-	return 0;
-}
-
-static int
-flow_item_proto_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const void *mask_default;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t size, i;
-
-	if (!flow_item_is_proto(item->type, &mask_default, &size))
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"Item type not supported");
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_RAW)
-		return flow_item_raw_preprocess(item,
-			item_spec,
-			item_mask,
-			item_size,
-			item_disabled,
-			error);
-
-	/* spec */
-	if (!item->spec) {
-		/* If spec is NULL, then last and mask also have to be NULL. */
-		if (item->last || item->mask)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"Invalid item (NULL spec with non-NULL last or mask)");
-
-		memset(item_spec, 0, size);
-		memset(item_mask, 0, size);
-		*item_size = size;
-		*item_disabled = 1; /* TRUE */
-		return 0;
-	}
-
-	memcpy(spec, item->spec, size);
-	*item_size = size;
-
-	/* mask */
-	if (item->mask)
-		memcpy(mask, item->mask, size);
-	else
-		memcpy(mask, mask_default, size);
-
-	/* disabled */
-	for (i = 0; i < size; i++)
-		if (mask[i])
-			break;
-	*item_disabled = (i == size) ? 1 : 0;
-
-	/* Apply mask over spec. */
-	for (i = 0; i < size; i++)
-		spec[i] &= mask[i];
-
-	/* last */
-	if (item->last) {
-		uint8_t last[size];
-
-		/* init last */
-		memcpy(last, item->last, size);
-		for (i = 0; i < size; i++)
-			last[i] &= mask[i];
-
-		/* check for range */
-		for (i = 0; i < size; i++)
-			if (last[i] != spec[i])
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"Range not supported");
-	}
-
-	return 0;
-}
-
-/***
- * Skip disabled protocol items and VOID items
- * until any of the mutually exclusive conditions
- * from the list below takes place:
- *    (A) A protocol present in the proto_mask
- *        is met (either ENABLED or DISABLED);
- *    (B) A protocol NOT present in the proto_mask is met in ENABLED state;
- *    (C) The END item is met.
- */
-static int
-flow_item_skip_disabled_protos(const struct rte_flow_item **item,
-	uint64_t proto_mask,
-	size_t *length,
-	struct rte_flow_error *error)
-{
-	size_t len = 0;
-
-	for ( ; (*item)->type != RTE_FLOW_ITEM_TYPE_END; (*item)++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled = 0, status;
-
-		if ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(*item,
-				&spec,
-				&mask,
-				&size,
-				&disabled,
-				error);
-		if (status)
-			return status;
-
-		if ((proto_mask & (1LLU << (*item)->type)) ||
-				!disabled)
-			break;
-
-		len += size;
-	}
-
-	if (length)
-		*length = len;
-
-	return 0;
-}
-
-#define FLOW_ITEM_PROTO_IP \
-	((1LLU << RTE_FLOW_ITEM_TYPE_IPV4) | \
-	 (1LLU << RTE_FLOW_ITEM_TYPE_IPV6))
-
-static void
-flow_item_skip_void(const struct rte_flow_item **item)
-{
-	for ( ; ; (*item)++)
-		if ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID)
-			return;
-}
-
-#define IP_PROTOCOL_TCP 0x06
-#define IP_PROTOCOL_UDP 0x11
-#define IP_PROTOCOL_SCTP 0x84
-
-static int
-mask_to_depth(uint64_t mask,
-		uint32_t *depth)
-{
-	uint64_t n;
-
-	if (mask == UINT64_MAX) {
-		if (depth)
-			*depth = 64;
-
-		return 0;
-	}
-
-	mask = ~mask;
-
-	if (mask & (mask + 1))
-		return -1;
-
-	n = __builtin_popcountll(mask);
-	if (depth)
-		*depth = (uint32_t)(64 - n);
-
-	return 0;
-}
-
-static int
-ipv4_mask_to_depth(uint32_t mask,
-		uint32_t *depth)
-{
-	uint32_t d;
-	int status;
-
-	status = mask_to_depth(mask | (UINT64_MAX << 32), &d);
-	if (status)
-		return status;
-
-	d -= 32;
-	if (depth)
-		*depth = d;
-
-	return 0;
-}
-
-static int
-ipv6_mask_to_depth(uint8_t *mask,
-	uint32_t *depth)
-{
-	uint64_t *m = (uint64_t *)mask;
-	uint64_t m0 = rte_be_to_cpu_64(m[0]);
-	uint64_t m1 = rte_be_to_cpu_64(m[1]);
-	uint32_t d0, d1;
-	int status;
-
-	status = mask_to_depth(m0, &d0);
-	if (status)
-		return status;
-
-	status = mask_to_depth(m1, &d1);
-	if (status)
-		return status;
-
-	if (d0 < 64 && d1)
-		return -1;
-
-	if (depth)
-		*depth = d0 + d1;
-
-	return 0;
-}
-
-static int
-port_mask_to_range(uint16_t port,
-	uint16_t port_mask,
-	uint16_t *port0,
-	uint16_t *port1)
-{
-	int status;
-	uint16_t p0, p1;
-
-	status = mask_to_depth(port_mask | (UINT64_MAX << 16), NULL);
-	if (status)
-		return -1;
-
-	p0 = port & port_mask;
-	p1 = p0 | ~port_mask;
-
-	if (port0)
-		*port0 = p0;
-
-	if (port1)
-		*port1 = p1;
-
-	return 0;
-}
-
-static int
-flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
-		struct pipeline *pipeline __rte_unused,
-		struct softnic_table *table __rte_unused,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	union flow_item spec, mask;
-	size_t size, length = 0;
-	int disabled = 0, status;
-	uint8_t ip_proto, ip_proto_mask;
-
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_ACL;
-	rule_match->match.acl.priority = attr->priority;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item,
-			FLOW_ITEM_PROTO_IP, &length, error);
-	if (status)
-		return status;
-
-	/* IP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.src_addr),
-				&sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header source address mask");
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.dst_addr),
-				&da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header destination address mask");
-
-		ip_proto = spec.ipv4.hdr.next_proto_id;
-		ip_proto_mask = mask.ipv4.hdr.next_proto_id;
-
-		rule_match->match.acl.ip_version = 1;
-		rule_match->match.acl.ipv4.sa =
-			rte_ntohl(spec.ipv4.hdr.src_addr);
-		rule_match->match.acl.ipv4.da =
-			rte_ntohl(spec.ipv4.hdr.dst_addr);
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV4 */
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.src_addr, &sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header source address mask");
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.dst_addr, &da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header destination address mask");
-
-		ip_proto = spec.ipv6.hdr.proto;
-		ip_proto_mask = mask.ipv6.hdr.proto;
-
-		rule_match->match.acl.ip_version = 0;
-		memcpy(rule_match->match.acl.ipv6.sa,
-			spec.ipv6.hdr.src_addr,
-			sizeof(spec.ipv6.hdr.src_addr));
-		memcpy(rule_match->match.acl.ipv6.da,
-			spec.ipv6.hdr.dst_addr,
-			sizeof(spec.ipv6.hdr.dst_addr));
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV6 */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: IP protocol required");
-	} /* switch */
-
-	if (ip_proto_mask != UINT8_MAX)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Illegal IP protocol mask");
-
-	item++;
-
-	/* VOID only, if any. */
-	flow_item_skip_void(&item);
-
-	/* TCP/UDP/SCTP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_TCP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_TCP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is TCP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.src_port),
-				rte_ntohs(mask.tcp.hdr.src_port),
-				&sp0,
-				&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.dst_port),
-				rte_ntohs(mask.tcp.hdr.dst_port),
-				&dp0,
-				&dp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_TCP */
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_UDP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is UDP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.src_port),
-			rte_ntohs(mask.udp.hdr.src_port),
-			&sp0,
-			&sp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.dst_port),
-			rte_ntohs(mask.udp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_UDP */
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_SCTP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is SCTP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.src_port),
-			rte_ntohs(mask.sctp.hdr.src_port),
-			&sp0,
-			&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.dst_port),
-			rte_ntohs(mask.sctp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_SCTP */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: TCP/UDP/SCTP required");
-	} /* switch */
-
-	item++;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-	if (status)
-		return status;
-
-	/* END only. */
-	if (item->type != RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Expecting END item");
-
-	return 0;
-}
-
-/***
- * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize*
- * respectively.
- * They are located within a larger buffer at offsets *toffset* and *foffset*
- * respectively. Both *tmask* and *fmask* represent bitmasks for the larger
- * buffer.
- * Question: are the two masks equivalent?
- *
- * Notes:
- * 1. Offset basically indicates that the first offset bytes in the buffer
- *    are "don't care", so offset is equivalent to pre-pending an "all-zeros"
- *    array of *offset* bytes to the *mask*.
- * 2. Each *mask* might contain a number of zero bytes at the beginning or
- *    at the end.
- * 3. Bytes in the larger buffer after the end of the *mask* are also considered
- *    "don't care", so they are equivalent to appending an "all-zeros" array of
- *    bytes to the *mask*.
- *
- * Example:
- * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes
- * tmask = [00 22 00 33 00], toffset = 2, tsize = 5
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * fmask = [22 00 33], foffset = 3, fsize = 3 =>
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * Therefore, the tmask and fmask from this example are equivalent.
- */
-static int
-hash_key_mask_is_same(uint8_t *tmask,
-	size_t toffset,
-	size_t tsize,
-	uint8_t *fmask,
-	size_t foffset,
-	size_t fsize,
-	size_t *toffset_plus,
-	size_t *foffset_plus)
-{
-	size_t tpos; /* Position of first non-zero byte in the tmask buffer. */
-	size_t fpos; /* Position of first non-zero byte in the fmask buffer. */
-
-	/* Compute tpos and fpos. */
-	for (tpos = 0; tmask[tpos] == 0; tpos++)
-		;
-	for (fpos = 0; fmask[fpos] == 0; fpos++)
-		;
-
-	if (toffset + tpos != foffset + fpos)
-		return 0; /* FALSE */
-
-	tsize -= tpos;
-	fsize -= fpos;
-
-	if (tsize < fsize) {
-		size_t i;
-
-		for (i = 0; i < tsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < fsize; i++)
-			if (fmask[fpos + i])
-				return 0; /* FALSE */
-	} else {
-		size_t i;
-
-		for (i = 0; i < fsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < tsize; i++)
-			if (tmask[tpos + i])
-				return 0; /* FALSE */
-	}
-
-	if (toffset_plus)
-		*toffset_plus = tpos;
-
-	if (foffset_plus)
-		*foffset_plus = fpos;
-
-	return 1; /* TRUE */
-}
-
-static int
-flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused,
-	struct pipeline *pipeline __rte_unused,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr __rte_unused,
-	const struct rte_flow_item *item,
-	struct softnic_table_rule_match *rule_match,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match_hash key, key_mask;
-	struct softnic_table_hash_params *params = &table->params.match.hash;
-	size_t offset = 0, length = 0, tpos, fpos;
-	int status;
-
-	memset(&key, 0, sizeof(key));
-	memset(&key_mask, 0, sizeof(key_mask));
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, &offset, error);
-	if (status)
-		return status;
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"HASH: END detected too early");
-
-	/* VOID or any protocols (enabled or disabled). */
-	for ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled, status;
-
-		if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(item,
-			&spec,
-			&mask,
-			&size,
-			&disabled,
-			error);
-		if (status)
-			return status;
-
-		if (length + size > sizeof(key)) {
-			if (disabled)
-				break;
-
-			return rte_flow_error_set(error,
-				ENOTSUP,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Item too big");
-		}
-
-		memcpy(&key.key[length], &spec, size);
-		memcpy(&key_mask.key[length], &mask, size);
-		length += size;
-	}
-
-	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
-		/* VOID or disabled protos only, if any. */
-		status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-		if (status)
-			return status;
-
-		/* END only. */
-		if (item->type != RTE_FLOW_ITEM_TYPE_END)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Expecting END item");
-	}
-
-	/* Compare flow key mask against table key mask. */
-	offset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
-
-	if (!hash_key_mask_is_same(params->key_mask,
-		params->key_offset,
-		params->key_size,
-		key_mask.key,
-		offset,
-		length,
-		&tpos,
-		&fpos))
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"HASH: Item list is not observing the match format");
-
-	/* Rule match. */
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_HASH;
-	memcpy(&rule_match->match.hash.key[tpos],
-		&key.key[fpos],
-		RTE_MIN(sizeof(rule_match->match.hash.key) - tpos,
-			length - fpos));
-
-	return 0;
-}
-
-static int
-flow_rule_match_get(struct pmd_internals *softnic,
-		struct pipeline *pipeline,
-		struct softnic_table *table,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	switch (table->params.match_type) {
-	case TABLE_ACL:
-		return flow_rule_match_acl_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	case TABLE_HASH:
-		return flow_rule_match_hash_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Unsupported pipeline table match type");
-	}
-}
-
-static int
-flow_rule_action_get(struct pmd_internals *softnic,
-	struct pipeline *pipeline,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_action *action,
-	struct softnic_table_rule_action *rule_action,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_action_profile *profile;
-	struct softnic_table_action_profile_params *params;
-	struct softnic_mtr_meter_policy *policy;
-	int n_jump_queue_rss_drop = 0;
-	int n_count = 0;
-	int n_mark = 0;
-	int n_vxlan_decap = 0;
-
-	profile = softnic_table_action_profile_find(softnic,
-		table->params.action_profile_name);
-	if (profile == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			action,
-			"JUMP: Table action profile");
-
-	params = &profile->params;
-
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
-			continue;
-
-		switch (action->type) {
-		case RTE_FLOW_ACTION_TYPE_JUMP:
-		{
-			const struct rte_flow_action_jump *conf = action->conf;
-			struct flow_attr_map *map;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"JUMP: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is"
-					" allowed per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			map = flow_attr_map_get(softnic,
-				conf->group,
-				attr->ingress);
-			if (map == NULL || map->valid == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Invalid group mapping");
-
-			if (strcmp(pipeline->name, map->pipeline_name) != 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Jump to table in different pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-			rule_action->fwd.id = map->table_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_JUMP */
-
-		case RTE_FLOW_ACTION_TYPE_QUEUE:
-		{
-			char name[NAME_SIZE];
-			struct rte_eth_dev *dev;
-			const struct rte_flow_action_queue *conf = action->conf;
-			uint32_t port_id;
-			int status;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed"
-					" per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"QUEUE action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			dev = ETHDEV(softnic);
-			if (dev == NULL ||
-				conf->index >= dev->data->nb_rx_queues)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Invalid RX queue ID");
-
-			snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->index);
-
-			status = softnic_pipeline_port_out_find(softnic,
-				pipeline->name,
-				name,
-				&port_id);
-			if (status)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: RX queue not accessible from this pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT;
-			rule_action->fwd.id = port_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /*RTE_FLOW_ACTION_TYPE_QUEUE */
-
-		case RTE_FLOW_ACTION_TYPE_RSS:
-		{
-			const struct rte_flow_action_rss *conf = action->conf;
-			uint32_t i;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"RSS: Null configuration");
-
-			if (!rte_is_power_of_2(conf->queue_num))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues must be a power of 2");
-
-			if (conf->queue_num > RTE_DIM(rule_action->lb.out))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues too big");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-
-			if (((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0) ||
-				((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_LB)) == 0))
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this table");
-
-			if (params->lb.out_offset !=
-				pipeline->params.offset_port_id)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this pipeline");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_LB */
-			for (i = 0; i < conf->queue_num; i++) {
-				char name[NAME_SIZE];
-				struct rte_eth_dev *dev;
-				uint32_t port_id;
-				int status;
-
-				dev = ETHDEV(softnic);
-				if (dev == NULL ||
-					conf->queue[i] >=
-						dev->data->nb_rx_queues)
-					return rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: Invalid RX queue ID");
-
-				snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->queue[i]);
-
-				status = softnic_pipeline_port_out_find(softnic,
-					pipeline->name,
-					name,
-					&port_id);
-				if (status)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: RX queue not accessible from this pipeline");
-
-				rule_action->lb.out[i] = port_id;
-			}
-
-			for ( ; i < RTE_DIM(rule_action->lb.out); i++)
-				rule_action->lb.out[i] =
-				rule_action->lb.out[i % conf->queue_num];
-
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_RSS */
-
-		case RTE_FLOW_ACTION_TYPE_DROP:
-		{
-			const void *conf = action->conf;
-
-			if (conf != NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"DROP: No configuration required");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"DROP action not supported by this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_DROP;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_DROP */
-
-		case RTE_FLOW_ACTION_TYPE_COUNT:
-		{
-			const struct rte_flow_action_count *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"COUNT: Null configuration");
-
-			if (n_count)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one COUNT action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_STATS)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"COUNT action not supported by this table");
-
-			n_count = 1;
-
-			/* RTE_TABLE_ACTION_STATS */
-			rule_action->stats.n_packets = 0;
-			rule_action->stats.n_bytes = 0;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_COUNT */
-
-		case RTE_FLOW_ACTION_TYPE_MARK:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"MARK: Null configuration");
-
-			if (n_mark)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one MARK action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_TAG)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"MARK action not supported by this table");
-
-			n_mark = 1;
-
-			/* RTE_TABLE_ACTION_TAG */
-			rule_action->tag.tag = conf->id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_MARK */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN DECAP: Non-null configuration");
-
-			if (n_vxlan_decap)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one VXLAN DECAP action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_DECAP)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN DECAP action not supported by this table");
-
-			n_vxlan_decap = 1;
-
-			/* RTE_TABLE_ACTION_DECAP */
-			rule_action->decap.n = 50; /* Ether/IPv4/UDP/VXLAN */
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_DECAP */
-
-		case RTE_FLOW_ACTION_TYPE_METER:
-		{
-			const struct rte_flow_action_meter *conf = action->conf;
-			struct softnic_mtr_meter_profile *mp;
-			struct softnic_mtr *m;
-			uint32_t table_id = table - pipeline->table;
-			uint32_t meter_profile_id;
-			int status;
-
-			if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Table action not supported");
-
-			if (params->mtr.n_tc != 1)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Multiple TCs not supported");
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"METER: Null configuration");
-
-			m = softnic_mtr_find(softnic, conf->mtr_id);
-
-			if (m == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Invalid meter ID");
-
-			if (m->flow)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Meter already attached to a flow");
-
-			meter_profile_id = m->params.meter_profile_id;
-			mp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);
-
-			/* Add meter profile to pipeline table */
-			if (!softnic_pipeline_table_meter_profile_find(table,
-					meter_profile_id)) {
-				struct rte_table_action_meter_profile profile;
-
-				memset(&profile, 0, sizeof(profile));
-				profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-				profile.trtcm.cir = mp->params.trtcm_rfc2698.cir;
-				profile.trtcm.pir = mp->params.trtcm_rfc2698.pir;
-				profile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;
-				profile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;
-
-				status = softnic_pipeline_table_mtr_profile_add(softnic,
-						pipeline->name,
-						table_id,
-						meter_profile_id,
-						&profile);
-				if (status) {
-					rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: Table meter profile add failed");
-					return -1;
-				}
-			}
-			/* Meter policy must exist */
-			policy = softnic_mtr_meter_policy_find(softnic,
-					m->params.meter_policy_id);
-			if (policy == NULL) {
-				rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: fail to find meter policy");
-				return -1;
-			}
-			/* RTE_TABLE_ACTION_METER */
-			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
-				policy->policer[RTE_COLOR_GREEN];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
-				policy->policer[RTE_COLOR_YELLOW];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
-				policy->policer[RTE_COLOR_RED];
-			rule_action->mtr.tc_mask = 1;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_METER */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
-		{
-			const struct rte_flow_action_vxlan_encap *conf =
-				action->conf;
-			const struct rte_flow_item *item;
-			union flow_item spec, mask;
-			int disabled = 0, status;
-			size_t size;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration");
-
-			item = conf->definition;
-			if (item == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration definition");
-
-			if (!(params->action_mask &
-					(1LLU << RTE_TABLE_ACTION_ENCAP)))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN ENCAP: Encap action not enabled for this table");
-
-			/* Check for Ether. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-				&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: first encap item should be ether");
-			}
-			rte_ether_addr_copy(&spec.eth.dst,
-					&rule_action->encap.vxlan.ether.da);
-			rte_ether_addr_copy(&spec.eth.src,
-					&rule_action->encap.vxlan.ether.sa);
-
-			item++;
-
-			/* Check for VLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
-				if (!params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: vlan encap not supported by table");
-
-				uint16_t tci = rte_ntohs(spec.vlan.tci);
-				rule_action->encap.vxlan.vlan.pcp =
-					tci >> 13;
-				rule_action->encap.vxlan.vlan.dei =
-					(tci >> 12) & 0x1;
-				rule_action->encap.vxlan.vlan.vid =
-					tci & 0xfff;
-
-				item++;
-
-				flow_item_skip_void(&item);
-				status = flow_item_proto_preprocess(item, &spec,
-						&mask, &size, &disabled, error);
-				if (status)
-					return status;
-			} else {
-				if (params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: expecting vlan encap item");
-			}
-
-			/* Check for IPV4/IPV6. */
-			switch (item->type) {
-			case RTE_FLOW_ITEM_TYPE_IPV4:
-			{
-				rule_action->encap.vxlan.ipv4.sa =
-					rte_ntohl(spec.ipv4.hdr.src_addr);
-				rule_action->encap.vxlan.ipv4.da =
-					rte_ntohl(spec.ipv4.hdr.dst_addr);
-				rule_action->encap.vxlan.ipv4.dscp =
-					spec.ipv4.hdr.type_of_service >> 2;
-				rule_action->encap.vxlan.ipv4.ttl =
-					spec.ipv4.hdr.time_to_live;
-				break;
-			}
-			case RTE_FLOW_ITEM_TYPE_IPV6:
-			{
-				uint32_t vtc_flow;
-
-				memcpy(&rule_action->encap.vxlan.ipv6.sa,
-						&spec.ipv6.hdr.src_addr,
-						sizeof(spec.ipv6.hdr.src_addr));
-				memcpy(&rule_action->encap.vxlan.ipv6.da,
-						&spec.ipv6.hdr.dst_addr,
-						sizeof(spec.ipv6.hdr.dst_addr));
-				vtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);
-				rule_action->encap.vxlan.ipv6.flow_label =
-						vtc_flow & 0xfffff;
-				rule_action->encap.vxlan.ipv6.dscp =
-						(vtc_flow >> 22) & 0x3f;
-				rule_action->encap.vxlan.ipv6.hop_limit =
-					spec.ipv6.hdr.hop_limits;
-				break;
-			}
-			default:
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ether should be ipv4/ipv6");
-			}
-
-			item++;
-
-			/* Check for UDP. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_UDP) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp");
-			}
-			rule_action->encap.vxlan.udp.sp =
-				rte_ntohs(spec.udp.hdr.src_port);
-			rule_action->encap.vxlan.udp.dp =
-				rte_ntohs(spec.udp.hdr.dst_port);
-
-			item++;
-
-			/* Check for VXLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after udp should be vxlan");
-			}
-			rule_action->encap.vxlan.vxlan.vni =
-				(spec.vxlan.vni[0] << 16U |
-					spec.vxlan.vni[1] << 8U
-					| spec.vxlan.vni[2]);
-
-			item++;
-
-			/* Check for END. */
-			flow_item_skip_void(&item);
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_END)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: expecting END item");
-
-			rule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */
-
-		default:
-			return -ENOTSUP;
-		}
-	}
-
-	if (n_jump_queue_rss_drop == 0)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			action,
-			"Flow does not have any terminating action");
-
-	return 0;
-}
-
-static int
-pmd_flow_validate(struct rte_eth_dev *dev,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item item[],
-		const struct rte_flow_action action[],
-		struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int status;
-
-	/* Check input parameters. */
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL, "Null attr");
-
-	if (item == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				NULL,
-				"Null item");
-
-	if (action == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION,
-				NULL,
-				"Null action");
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return status;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline name");
-
-	if (table_id >= pipeline->n_tables)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline table ID");
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			&rule_match,
-			error);
-	if (status)
-		return status;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return status;
-
-	return 0;
-}
-
-static struct softnic_mtr *
-flow_action_meter_get(struct pmd_internals *softnic,
-	const struct rte_flow_action *action)
-{
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++)
-		if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
-			const struct rte_flow_action_meter *conf = action->conf;
-
-			if (conf == NULL)
-				return NULL;
-
-			return softnic_mtr_find(softnic, conf->mtr_id);
-		}
-
-	return NULL;
-}
-
-static void
-flow_meter_owner_reset(struct pmd_internals *softnic,
-	struct rte_flow *flow)
-{
-	struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->flow == flow) {
-			m->flow = NULL;
-			break;
-		}
-}
-
-static void
-flow_meter_owner_set(struct pmd_internals *softnic,
-	struct rte_flow *flow,
-	struct softnic_mtr *mtr)
-{
-	/* Reset current flow meter  */
-	flow_meter_owner_reset(softnic, flow);
-
-	/* Set new flow meter */
-	mtr->flow = flow;
-}
-
-static int
-is_meter_action_enable(struct pmd_internals *softnic,
-	struct softnic_table *table)
-{
-	struct softnic_table_action_profile *profile =
-		softnic_table_action_profile_find(softnic,
-			table->params.action_profile_name);
-	struct softnic_table_action_profile_params *params = &profile->params;
-
-	return (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) ? 1 : 0;
-}
-
-static struct rte_flow *
-pmd_flow_create(struct rte_eth_dev *dev,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_item item[],
-	const struct rte_flow_action action[],
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-	void *rule_data;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct rte_flow *flow;
-	struct softnic_mtr *mtr;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int new_flow, status;
-
-	/* Check input parameters. */
-	if (attr == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ATTR,
-			NULL,
-			"Null attr");
-		return NULL;
-	}
-
-	if (item == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			NULL,
-			"Null item");
-		return NULL;
-	}
-
-	if (action == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			NULL,
-			"Null action");
-		return NULL;
-	}
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return NULL;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline name");
-		return NULL;
-	}
-
-	if (table_id >= pipeline->n_tables) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline table ID");
-		return NULL;
-	}
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-		pipeline,
-		table,
-		attr,
-		item,
-		&rule_match,
-		error);
-	if (status)
-		return NULL;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return NULL;
-
-	/* Flow find/allocate. */
-	new_flow = 0;
-	flow = softnic_flow_find(table, &rule_match);
-	if (flow == NULL) {
-		new_flow = 1;
-		flow = calloc(1, sizeof(struct rte_flow));
-		if (flow == NULL) {
-			rte_flow_error_set(error,
-				ENOMEM,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Not enough memory for new flow");
-			return NULL;
-		}
-	}
-
-	/* Rule add. */
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&rule_match,
-		&rule_action,
-		&rule_data);
-	if (status) {
-		if (new_flow)
-			free(flow);
-
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule add failed");
-		return NULL;
-	}
-
-	/* Flow fill in. */
-	memcpy(&flow->match, &rule_match, sizeof(rule_match));
-	memcpy(&flow->action, &rule_action, sizeof(rule_action));
-	flow->data = rule_data;
-	flow->pipeline = pipeline;
-	flow->table_id = table_id;
-
-	mtr = flow_action_meter_get(softnic, action);
-	if (mtr)
-		flow_meter_owner_set(softnic, flow, mtr);
-
-	/* Flow add to list. */
-	if (new_flow)
-		TAILQ_INSERT_TAIL(&table->flows, flow, node);
-
-	return flow;
-}
-
-static int
-pmd_flow_destroy(struct rte_eth_dev *dev,
-	struct rte_flow *flow,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct softnic_table *table;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule delete. */
-	status = softnic_pipeline_table_rule_delete(softnic,
-		flow->pipeline->name,
-		flow->table_id,
-		&flow->match);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule delete failed");
-
-	/* Update dependencies */
-	if (is_meter_action_enable(softnic, table))
-		flow_meter_owner_reset(softnic, flow);
-
-	/* Flow delete. */
-	TAILQ_REMOVE(&table->flows, flow, node);
-	free(flow);
-
-	return 0;
-}
-
-static int
-pmd_flow_flush(struct rte_eth_dev *dev,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	int fail_to_del_rule = 0;
-	uint32_t i;
-
-	TAILQ_FOREACH(pipeline, &softnic->pipeline_list, node) {
-		/* Remove all the flows added to the tables. */
-		for (i = 0; i < pipeline->n_tables; i++) {
-			struct softnic_table *table = &pipeline->table[i];
-			struct rte_flow *flow;
-			void *temp;
-			int status;
-
-			RTE_TAILQ_FOREACH_SAFE(flow, &table->flows, node,
-				temp) {
-				/* Rule delete. */
-				status = softnic_pipeline_table_rule_delete
-						(softnic,
-						pipeline->name,
-						i,
-						&flow->match);
-				if (status)
-					fail_to_del_rule = 1;
-				/* Update dependencies */
-				if (is_meter_action_enable(softnic, table))
-					flow_meter_owner_reset(softnic, flow);
-
-				/* Flow delete. */
-				TAILQ_REMOVE(&table->flows, flow, node);
-				free(flow);
-			}
-		}
-	}
-
-	if (fail_to_del_rule)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Some of the rules could not be deleted");
-
-	return 0;
-}
-
-static int
-pmd_flow_query(struct rte_eth_dev *dev __rte_unused,
-	struct rte_flow *flow,
-	const struct rte_flow_action *action __rte_unused,
-	void *data,
-	struct rte_flow_error *error)
-{
-	struct rte_table_action_stats_counters stats;
-	struct softnic_table *table;
-	struct rte_flow_query_count *flow_stats = data;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	if (data == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Null data");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule stats read. */
-	status = rte_table_action_stats_read(table->a,
-		flow->data,
-		&stats,
-		flow_stats->reset);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule stats read failed");
-
-	/* Fill in flow stats. */
-	flow_stats->hits_set =
-		(table->ap->params.stats.n_packets_enabled) ? 1 : 0;
-	flow_stats->bytes_set =
-		(table->ap->params.stats.n_bytes_enabled) ? 1 : 0;
-	flow_stats->hits = stats.n_packets;
-	flow_stats->bytes = stats.n_bytes;
-
-	return 0;
-}
-
-const struct rte_flow_ops pmd_flow_ops = {
-	.validate = pmd_flow_validate,
-	.create = pmd_flow_create,
-	.destroy = pmd_flow_destroy,
-	.flush = pmd_flow_flush,
-	.query = pmd_flow_query,
-	.isolate = NULL,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 03/21] net/softnic: remove the meter support
  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 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the Ethernet device meter API support.

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         |  16 -
 .../net/softnic/rte_eth_softnic_internals.h   | 117 ---
 drivers/net/softnic/rte_eth_softnic_meter.c   | 945 ------------------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  12 -
 5 files changed, 1091 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 4ebe60921c..d466dc7700 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -15,7 +15,6 @@ sources = files(
         'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
-        'rte_eth_softnic_meter.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8e361adbad..a7136bb0c0 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "rte_eth_softnic_internals.h"
@@ -168,8 +167,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	return 0;
 }
 
@@ -191,8 +188,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	rte_free(p);
 }
 
@@ -215,14 +210,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_mtr_ops **)arg = &pmd_mtr_ops;
-
-	return 0;
-}
-
 static const struct eth_dev_ops pmd_ops = {
 	.dev_configure = pmd_dev_configure,
 	.dev_start = pmd_dev_start,
@@ -232,7 +219,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
 static uint16_t
@@ -274,8 +260,6 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	softnic_mtr_init(p);
-
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 4cc98b7aad..d578cb1f25 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -19,8 +19,6 @@
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_flow_driver.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "conn.h"
@@ -40,68 +38,6 @@ struct pmd_params {
 	int sc; /**< Service cores. */
 };
 
-/**
- * Ethdev Flow API
- */
-struct rte_flow;
-
-TAILQ_HEAD(flow_list, rte_flow);
-
-struct flow_attr_map {
-	char pipeline_name[NAME_SIZE];
-	uint32_t table_id;
-	int valid;
-};
-
-#ifndef SOFTNIC_FLOW_MAX_GROUPS
-#define SOFTNIC_FLOW_MAX_GROUPS                            64
-#endif
-
-struct flow_internals {
-	struct flow_attr_map ingress_map[SOFTNIC_FLOW_MAX_GROUPS];
-	struct flow_attr_map egress_map[SOFTNIC_FLOW_MAX_GROUPS];
-};
-
-/**
- * Meter
- */
-
-/* MTR meter profile */
-struct softnic_mtr_meter_profile {
-	TAILQ_ENTRY(softnic_mtr_meter_profile) node;
-	uint32_t meter_profile_id;
-	struct rte_mtr_meter_profile params;
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
-
-/* MTR meter policy */
-struct softnic_mtr_meter_policy {
-	TAILQ_ENTRY(softnic_mtr_meter_policy) node;
-	uint32_t meter_policy_id;
-	enum rte_table_action_policer policer[RTE_COLORS];
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
-
-/* MTR meter object */
-struct softnic_mtr {
-	TAILQ_ENTRY(softnic_mtr) node;
-	uint32_t mtr_id;
-	struct rte_mtr_params params;
-	struct rte_flow *flow;
-};
-
-TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
-
-struct mtr_internals {
-	struct softnic_mtr_meter_profile_list meter_profiles;
-	struct softnic_mtr_meter_policy_list meter_policies;
-	struct softnic_mtr_list mtrs;
-};
-
 /**
  * MEMPOOL
  */
@@ -383,7 +319,6 @@ struct softnic_table {
 	struct softnic_table_params params;
 	struct softnic_table_action_profile *ap;
 	struct rte_table_action *a;
-	struct flow_list flows;
 	struct rte_table_action_dscp_table dscp_table;
 	struct softnic_table_meter_profile_list meter_profiles;
 };
@@ -481,9 +416,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct flow_internals flow;
-	struct mtr_internals mtr;
-
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
@@ -513,46 +445,6 @@ ETHDEV(struct pmd_internals *softnic)
 	return &rte_eth_devices[port_id];
 }
 
-/**
- * Ethdev Flow API
- */
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id);
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress);
-
-extern const struct rte_flow_ops pmd_flow_ops;
-
-/**
- * Meter
- */
-int
-softnic_mtr_init(struct pmd_internals *p);
-
-void
-softnic_mtr_free(struct pmd_internals *p);
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p,
-	uint32_t mtr_id);
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id);
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id);
-
-extern const struct rte_mtr_ops pmd_mtr_ops;
-
 /**
  * MEMPOOL
  */
@@ -814,15 +706,6 @@ struct softnic_table_rule_action {
 	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
 };
 
-struct rte_flow {
-	TAILQ_ENTRY(rte_flow) node;
-	struct softnic_table_rule_match match;
-	struct softnic_table_rule_action action;
-	void *data;
-	struct pipeline *pipeline;
-	uint32_t table_id;
-};
-
 int
 softnic_pipeline_port_in_stats_read(struct pmd_internals *p,
 	const char *pipeline_name,
diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c
deleted file mode 100644
index 6b02f43e31..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_meter.c
+++ /dev/null
@@ -1,945 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_mtr.h>
-#include <rte_mtr_driver.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_mtr_init(struct pmd_internals *p)
-{
-	/* Initialize meter profiles list */
-	TAILQ_INIT(&p->mtr.meter_profiles);
-
-	/* Initialize meter policies list */
-	TAILQ_INIT(&p->mtr.meter_policies);
-
-	/* Initialize MTR objects list */
-	TAILQ_INIT(&p->mtr.mtrs);
-
-	return 0;
-}
-
-void
-softnic_mtr_free(struct pmd_internals *p)
-{
-	/* Remove MTR objects */
-	for ( ; ; ) {
-		struct softnic_mtr *m;
-
-		m = TAILQ_FIRST(&p->mtr.mtrs);
-		if (m == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.mtrs, m, node);
-		free(m);
-	}
-
-	/* Remove meter profiles */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_profile *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_profiles);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-		free(mp);
-	}
-
-	/* Remove meter policies */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_policy *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_policies);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-		free(mp);
-	}
-}
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id)
-{
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_profile_id == mp->meter_profile_id)
-			return mp;
-
-	return NULL;
-}
-
-static int
-meter_profile_check(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile ID must be valid. */
-	if (meter_profile_id == UINT32_MAX)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter profile must not exist. */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter prfile already exists");
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"profile null");
-
-	/* Traffic metering algorithm : TRTCM_RFC2698 */
-	if (profile->alg != RTE_MTR_TRTCM_RFC2698)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"Metering alg not supported");
-
-	/* Not support packet mode, just support byte mode. */
-	if (profile->packet_mode)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
-			NULL,
-			"Meter packet mode not supported");
-
-	return 0;
-}
-
-/* MTR meter profile add */
-static int
-pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-	int status;
-
-	/* Check input params */
-	status = meter_profile_check(dev, meter_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_profile_id = meter_profile_id;
-	memcpy(&mp->params, profile, sizeof(mp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter profile delete */
-static int
-pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id)
-{
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_policy_id == mp->meter_policy_id)
-			return mp;
-
-	return NULL;
-}
-
-/* MTR meter policy add */
-static int
-pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_meter_policy_params *policy,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-	const struct rte_flow_action *act;
-	const struct rte_flow_action_meter_color *recolor;
-	uint32_t i;
-	bool valid_act_found;
-
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY,
-			NULL,
-			"Null meter policy invalid");
-
-	/* Meter policy must not exist. */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy already exists");
-
-	for (i = 0; i < RTE_COLORS; i++) {
-		if (policy->actions[i] == NULL)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"Null action list");
-		for (act = policy->actions[i], valid_act_found = false;
-		     act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
-			if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
-				continue;
-			/*
-			 * Support one (and one only) of
-			 * METER_COLOR or DROP action.
-			 */
-			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
-				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
-				valid_act_found)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_METER_POLICY,
-					NULL,
-					"Action invalid");
-			valid_act_found = true;
-		}
-		if (!valid_act_found)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"No valid action found");
-	}
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_policy_id = meter_policy_id;
-	for (i = 0; i < RTE_COLORS; i++) {
-		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
-		act = policy->actions[i];
-		if (!act)
-			continue;
-		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
-			recolor = act->conf;
-			switch (recolor->color) {
-			case RTE_COLOR_GREEN:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-				break;
-			case RTE_COLOR_YELLOW:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-				break;
-			case RTE_COLOR_RED:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_RED;
-				break;
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter policy delete */
-static int
-pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy *mp;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
-{
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->mtr_id == mtr_id)
-			return m;
-
-	return NULL;
-}
-
-
-static int
-mtr_check(struct pmd_internals *p,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	/* MTR id valid  */
-	if (softnic_mtr_find(p, mtr_id))
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object already exists");
-
-	/* MTR params must not be NULL */
-	if (params == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"MTR object params null");
-
-	/* Previous meter color not supported */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"Previous meter color not supported");
-
-	/* Shared MTR object not supported */
-	if (shared)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_SHARED,
-			NULL,
-			"Shared MTR object not supported");
-
-	return 0;
-}
-
-/* MTR object create */
-static int
-pmd_mtr_create(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr_meter_policy *policy;
-	struct softnic_mtr *m;
-	int status;
-
-	/* Check parameters */
-	status = mtr_check(p, mtr_id, params, shared, error);
-	if (status)
-		return status;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
-	if (policy == NULL) {
-		return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-				NULL,
-				"Meter policy id invalid");
-	}
-
-	/* Memory allocation */
-	m = calloc(1, sizeof(struct softnic_mtr));
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	m->mtr_id = mtr_id;
-	memcpy(&m->params, params, sizeof(m->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(ml, m, node);
-
-	/* Update dependencies */
-	mp->n_users++;
-	policy->n_users++;
-
-	return 0;
-}
-
-/* MTR object destroy */
-static int
-pmd_mtr_destroy(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr *m;
-	struct softnic_mtr_meter_policy *policy;
-
-	/* MTR object must exist */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object must not have any owner */
-	if (m->flow != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"MTR object is being used");
-
-	/* Get meter profile */
-	mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"MTR object meter profile invalid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"MTR object meter policy invalid");
-
-	/* Update dependencies */
-	mp->n_users--;
-	policy->n_users--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(ml, m, node);
-	free(m);
-
-	return 0;
-}
-
-/* MTR object meter profile update */
-static int
-pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp_new, *mp_old;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* Meter profile id must be valid */
-	mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile not valid");
-
-	/* MTR object already set to meter profile id */
-	if (m->params.meter_profile_id == meter_profile_id)
-		return 0;
-
-	/*  MTR object owner table update */
-	if (m->flow) {
-		uint32_t table_id = m->flow->table_id;
-		struct softnic_table *table = &m->flow->pipeline->table[table_id];
-		struct softnic_table_rule_action action;
-
-		if (!softnic_pipeline_table_meter_profile_find(table,
-			meter_profile_id)) {
-			struct rte_table_action_meter_profile profile;
-
-			memset(&profile, 0, sizeof(profile));
-
-			profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-			profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
-			profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
-			profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
-			profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
-
-			/* Add meter profile to pipeline table */
-			status = softnic_pipeline_table_mtr_profile_add(p,
-					m->flow->pipeline->name,
-					table_id,
-					meter_profile_id,
-					&profile);
-			if (status)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"Table meter profile add failed");
-		}
-
-		/* Set meter action */
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		action.mtr.mtr[0].meter_profile_id = meter_profile_id;
-
-		/* Re-add rule */
-		status = softnic_pipeline_table_rule_add(p,
-			m->flow->pipeline->name,
-			table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule add failed");
-
-		/* Flow: update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-	}
-
-	mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-
-	/* Meter: Set meter profile */
-	m->params.meter_profile_id = meter_profile_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-/* MTR object meter DSCP table update */
-static int
-pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	enum rte_color *dscp_table,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_dscp_table dt;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	uint32_t table_id, i;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object owner valid? */
-	if (m->flow == NULL)
-		return 0;
-
-	pipeline = m->flow->pipeline;
-	table_id = m->flow->table_id;
-	table = &pipeline->table[table_id];
-
-	memcpy(&dt, &table->dscp_table, sizeof(dt));
-	for (i = 0; i < RTE_DIM(dt.entry); i++)
-		dt.entry[i].color = (enum rte_color)dscp_table[i];
-
-	/* Update table */
-	status = softnic_pipeline_table_dscp_table_update(p,
-			pipeline->name,
-			table_id,
-			UINT64_MAX,
-			&dt);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Table action dscp table update failed");
-
-	return 0;
-}
-
-/* MTR object policy update */
-static int
-pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr *m;
-	uint32_t i;
-	int status;
-	struct softnic_mtr_meter_policy *mp_new, *mp_old;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	if (m->params.meter_policy_id == meter_policy_id)
-		return 0;
-
-	/* Meter policy must exist */
-	mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* MTR object owner valid? */
-	if (m->flow) {
-		struct pipeline *pipeline = m->flow->pipeline;
-		struct softnic_table *table = &pipeline->table[m->flow->table_id];
-		struct softnic_table_rule_action action;
-
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		/* Set action */
-		for (i = 0; i < RTE_COLORS; i++)
-			action.mtr.mtr[0].policer[i] = mp_new->policer[i];
-
-		/* Re-add the rule */
-		status = softnic_pipeline_table_rule_add(p,
-			pipeline->name,
-			m->flow->table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule re-add failed");
-
-		/* Flow: Update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-
-		/* Reset the meter stats */
-		rte_table_action_meter_read(table->a, m->flow->data,
-			1, NULL, 1);
-	}
-
-	mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp_old == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Old meter policy id invalid");
-
-	/* Meter: Set meter profile */
-	m->params.meter_policy_id = meter_policy_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-#define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
-				RTE_MTR_STATS_N_PKTS_YELLOW | \
-				RTE_MTR_STATS_N_PKTS_RED | \
-				RTE_MTR_STATS_N_PKTS_DROPPED)
-
-#define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
-				RTE_MTR_STATS_N_BYTES_YELLOW | \
-				RTE_MTR_STATS_N_BYTES_RED | \
-				RTE_MTR_STATS_N_BYTES_DROPPED)
-
-/* MTR object stats read */
-static void
-mtr_stats_convert(struct pmd_internals *p,
-	struct softnic_mtr *m,
-	struct rte_table_action_mtr_counters_tc *in,
-	struct rte_mtr_stats *out,
-	uint64_t *out_mask)
-{
-	struct softnic_mtr_meter_policy *mp;
-
-	memset(&out, 0, sizeof(out));
-	*out_mask = 0;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp == NULL)
-		return;
-
-	if (in->n_packets_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_pkts_dropped += in->n_packets[i];
-		}
-
-		*out_mask |= MTR_STATS_PKTS_DEFAULT;
-	}
-
-	if (in->n_bytes_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_bytes_dropped += in->n_bytes[i];
-		}
-
-		*out_mask |= MTR_STATS_BYTES_DEFAULT;
-	}
-}
-
-/* MTR object stats read */
-static int
-pmd_mtr_stats_read(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_mtr_counters counters;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR meter object owner valid? */
-	if (m->flow == NULL) {
-		if (stats != NULL)
-			memset(stats, 0, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = MTR_STATS_PKTS_DEFAULT |
-				MTR_STATS_BYTES_DEFAULT;
-
-		return 0;
-	}
-
-	pipeline = m->flow->pipeline;
-	table = &pipeline->table[m->flow->table_id];
-
-	/* Meter stats read. */
-	status = rte_table_action_meter_read(table->a,
-		m->flow->data,
-		1,
-		&counters,
-		clear);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Meter stats read failed");
-
-	/* Stats format conversion. */
-	if (stats || stats_mask) {
-		struct rte_mtr_stats s;
-		uint64_t s_mask = 0;
-
-		mtr_stats_convert(p,
-			m,
-			&counters.stats[0],
-			&s,
-			&s_mask);
-
-		if (stats)
-			memcpy(stats, &s, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = s_mask;
-	}
-
-	return 0;
-}
-
-const struct rte_mtr_ops pmd_mtr_ops = {
-	.capabilities_get = NULL,
-
-	.meter_profile_add = pmd_mtr_meter_profile_add,
-	.meter_profile_delete = pmd_mtr_meter_profile_delete,
-
-	.meter_policy_add = pmd_mtr_meter_policy_add,
-	.meter_policy_delete = pmd_mtr_meter_policy_delete,
-
-	.create = pmd_mtr_create,
-	.destroy = pmd_mtr_destroy,
-	.meter_enable = NULL,
-	.meter_disable = NULL,
-
-	.meter_profile_update = pmd_mtr_meter_profile_update,
-	.meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
-	.meter_policy_update = pmd_mtr_meter_policy_update,
-	.stats_update = NULL,
-
-	.stats_read = pmd_mtr_stats_read,
-};
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index c7d2a7de19..2cf7fa52d1 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -46,17 +46,6 @@ softnic_pipeline_init(struct pmd_internals *p)
 static void
 softnic_pipeline_table_free(struct softnic_table *table)
 {
-	for ( ; ; ) {
-		struct rte_flow *flow;
-
-		flow = TAILQ_FIRST(&table->flows);
-		if (flow == NULL)
-			break;
-
-		TAILQ_REMOVE(&table->flows, flow, node);
-		free(flow);
-	}
-
 	for ( ; ; ) {
 		struct softnic_table_meter_profile *mp;
 
@@ -1035,7 +1024,6 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 	memcpy(&table->params, params, sizeof(*params));
 	table->ap = ap;
 	table->a = action;
-	TAILQ_INIT(&table->flows);
 	TAILQ_INIT(&table->meter_profiles);
 	memset(&table->dscp_table, 0, sizeof(table->dscp_table));
 	pipeline->n_tables++;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 04/21] net/softnic: remove cryptodev support
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (2 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 03/21] net/softnic: remove the meter support Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 05/21] net/softnic: remove tap support Cristian Dumitrescu
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the cryptographic device API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |   3 +-
 drivers/net/softnic/rte_eth_softnic.c         |   1 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 171 ------------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   | 168 -----------------
 .../net/softnic/rte_eth_softnic_internals.h   |  54 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  54 ------
 6 files changed, 1 insertion(+), 450 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index d466dc7700..b3d235841d 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -12,7 +12,6 @@ sources = files(
         'rte_eth_softnic.c',
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
@@ -20,4 +19,4 @@ sources = files(
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
-deps += ['pipeline', 'port', 'table', 'cryptodev']
+deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a7136bb0c0..1ea5989223 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -264,7 +264,6 @@ pmd_init(struct pmd_params *params)
 	softnic_swq_init(p);
 	softnic_link_init(p);
 	softnic_tap_init(p);
-	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 671f96cf77..bca0b176d6 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -213,80 +213,6 @@ cmd_tap(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * cryptodev <tap_name> dev <device_name> | dev_id <device_id>
- * queue <n_queues> <queue_size> max_sessions <n_sessions>
- **/
-
-static void
-cmd_cryptodev(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	struct softnic_cryptodev_params params;
-	char *name;
-
-	memset(&params, 0, sizeof(params));
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0)
-		params.dev_name = tokens[3];
-	else if (strcmp(tokens[2], "dev_id") == 0) {
-		if (softnic_parser_read_uint32(&params.dev_id, tokens[3]) < 0) {
-			snprintf(out, out_size,	MSG_ARG_INVALID,
-				"dev_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"cryptodev");
-		return;
-	}
-
-	if (strcmp(tokens[4], "queue")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.n_queues, tokens[5]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.queue_size, tokens[6]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"queue_size");
-		return;
-	}
-
-	if (strcmp(tokens[7], "max_sessions")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.session_pool_size, tokens[8])
-			< 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_cryptodev_create(softnic, name, &params) == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -879,41 +805,6 @@ cmd_table_action_profile(struct pmd_internals *softnic,
 		t0 += 1;
 	} /* decap */
 
-	if (t0 < n_tokens && (strcmp(tokens[t0], "sym_crypto") == 0)) {
-		struct softnic_cryptodev *cryptodev;
-
-		if (n_tokens < t0 + 5 ||
-				strcmp(tokens[t0 + 1], "dev") ||
-				strcmp(tokens[t0 + 3], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		cryptodev = softnic_cryptodev_find(softnic, tokens[t0 + 2]);
-		if (cryptodev == NULL) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.cryptodev_id = cryptodev->dev_id;
-
-		if (softnic_parser_read_uint32(&p.sym_crypto.op_offset,
-				tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-					"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.mp_create = cryptodev->mp_create;
-		p.sym_crypto.mp_init = cryptodev->mp_init;
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-		t0 += 5;
-	} /* sym_crypto */
-
 	if (t0 < n_tokens) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
@@ -985,7 +876,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  | cryptodev <cryptodev_name> rxq <queue_id>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
  */
@@ -1138,27 +1028,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		}
 
 		t0 += 7;
-	} else if (strcmp(tokens[t0], "cryptodev") == 0) {
-		if (n_tokens < t0 + 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in cryptodev");
-			return;
-		}
-
-		p.type = PORT_IN_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-				tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"rxq");
-			return;
-		}
-
-		p.cryptodev.arg_callback = NULL;
-		p.cryptodev.f_callback = NULL;
-
-		t0 += 4;
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -1207,7 +1076,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
- *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
  */
 static void
 cmd_pipeline_port_out(struct pmd_internals *softnic,
@@ -1322,40 +1190,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 				return;
 			}
 		}
-	} else if (strcmp(tokens[6], "cryptodev") == 0) {
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		p.type = PORT_OUT_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.cryptodev.queue_id, tokens[9])
-				!= 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-
-		if (strcmp(tokens[10], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.cryptodev.op_offset,
-				tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -4771,11 +4605,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "cryptodev") == 0) {
-		cmd_cryptodev(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_cryptodev.c b/drivers/net/softnic/rte_eth_softnic_cryptodev.c
deleted file mode 100644
index e4754055e9..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_cryptodev.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <rte_cryptodev.h>
-#include <cryptodev_pmd.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define SOFTNIC_CRYPTO_SESSION_CACHE_SIZE 128
-
-int
-softnic_cryptodev_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->cryptodev_list);
-
-	return 0;
-}
-
-void
-softnic_cryptodev_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = TAILQ_FIRST(&p->cryptodev_list);
-		if (cryptodev == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->cryptodev_list, cryptodev, node);
-		free(cryptodev);
-	}
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_cryptodev *cryptodev;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(cryptodev, &p->cryptodev_list, node)
-		if (strcmp(cryptodev->name, name) == 0)
-			return cryptodev;
-
-	return NULL;
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params)
-{
-	struct rte_cryptodev_info dev_info;
-	struct rte_cryptodev_config dev_conf;
-	struct rte_cryptodev_qp_conf queue_conf;
-	struct softnic_cryptodev *cryptodev;
-	uint32_t dev_id, i;
-	uint32_t socket_id;
-	uint32_t cache_size;
-	char mp_name[NAME_SIZE];
-	int status;
-
-	/* Check input params */
-	if ((name == NULL) ||
-		softnic_cryptodev_find(p, name) ||
-		(params->n_queues == 0) ||
-		(params->queue_size == 0) ||
-		(params->session_pool_size == 0))
-		return NULL;
-
-	if (params->dev_name) {
-		status = rte_cryptodev_get_dev_id(params->dev_name);
-		if (status == -1)
-			return NULL;
-
-		dev_id = (uint32_t)status;
-	} else {
-		if (rte_cryptodev_is_valid_dev(params->dev_id) == 0)
-			return NULL;
-
-		dev_id = params->dev_id;
-	}
-
-	cache_size = (params->session_pool_size / 2 <
-			SOFTNIC_CRYPTO_SESSION_CACHE_SIZE) ?
-					(params->session_pool_size / 2) :
-					SOFTNIC_CRYPTO_SESSION_CACHE_SIZE;
-
-	socket_id = rte_cryptodev_socket_id(dev_id);
-	rte_cryptodev_info_get(dev_id, &dev_info);
-
-	if (dev_info.max_nb_queue_pairs < params->n_queues)
-		return NULL;
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED)
-		return NULL;
-
-	dev_conf.socket_id = socket_id;
-	dev_conf.nb_queue_pairs = params->n_queues;
-
-	status = rte_cryptodev_configure(dev_id, &dev_conf);
-	if (status < 0)
-		return NULL;
-
-	queue_conf.nb_descriptors = params->queue_size;
-	for (i = 0; i < params->n_queues; i++) {
-		status = rte_cryptodev_queue_pair_setup(dev_id, i,
-				&queue_conf, socket_id);
-		if (status < 0)
-			return NULL;
-	}
-
-	if (rte_cryptodev_start(dev_id) < 0)
-		return NULL;
-
-	cryptodev = calloc(1, sizeof(struct softnic_cryptodev));
-	if (cryptodev == NULL) {
-		rte_cryptodev_stop(dev_id);
-		return NULL;
-	}
-
-	strlcpy(cryptodev->name, name, sizeof(cryptodev->name));
-	cryptodev->dev_id = dev_id;
-	cryptodev->n_queues = params->n_queues;
-
-	snprintf(mp_name, NAME_SIZE, "%s_mp%u", name, dev_id);
-	cryptodev->mp_create = rte_cryptodev_sym_session_pool_create(mp_name,
-			params->session_pool_size,
-			0,
-			cache_size,
-			0,
-			socket_id);
-	if (!cryptodev->mp_create)
-		goto error_exit;
-
-	snprintf(mp_name, NAME_SIZE, "%s_priv_mp%u", name, dev_id);
-	cryptodev->mp_init = rte_mempool_create(mp_name,
-			params->session_pool_size,
-			rte_cryptodev_sym_get_private_session_size(dev_id),
-			cache_size,
-			0,
-			NULL,
-			NULL,
-			NULL,
-			NULL,
-			socket_id,
-			0);
-	if (!cryptodev->mp_init)
-		goto error_exit;
-
-	TAILQ_INSERT_TAIL(&p->cryptodev_list, cryptodev, node);
-
-	return cryptodev;
-
-error_exit:
-	rte_mempool_free(cryptodev->mp_create);
-	rte_mempool_free(cryptodev->mp_init);
-
-	free(cryptodev);
-
-	return NULL;
-}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d578cb1f25..ddcde99b98 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -100,28 +100,6 @@ struct softnic_tap {
 
 TAILQ_HEAD(softnic_tap_list, softnic_tap);
 
-/**
- * Cryptodev
- */
-struct softnic_cryptodev_params {
-	const char *dev_name;
-	uint32_t dev_id; /**< Valid only when *dev_name* is NULL. */
-	uint32_t n_queues;
-	uint32_t queue_size;
-	uint32_t session_pool_size;
-};
-
-struct softnic_cryptodev {
-	TAILQ_ENTRY(softnic_cryptodev) node;
-	char name[NAME_SIZE];
-	uint16_t dev_id;
-	uint32_t n_queues;
-	struct rte_mempool *mp_create;
-	struct rte_mempool *mp_init;
-};
-
-TAILQ_HEAD(softnic_cryptodev_list, softnic_cryptodev);
-
 /**
  * Input port action
  */
@@ -187,7 +165,6 @@ enum softnic_port_in_type {
 	PORT_IN_SWQ,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
-	PORT_IN_CRYPTODEV,
 };
 
 struct softnic_port_in_params {
@@ -209,12 +186,6 @@ struct softnic_port_in_params {
 			const char *file_name;
 			uint32_t n_bytes_per_pkt;
 		} source;
-
-		struct {
-			uint16_t queue_id;
-			void *f_callback;
-			void *arg_callback;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 
@@ -227,7 +198,6 @@ enum softnic_port_out_type {
 	PORT_OUT_SWQ,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
-	PORT_OUT_CRYPTODEV,
 };
 
 struct softnic_port_out_params {
@@ -242,11 +212,6 @@ struct softnic_port_out_params {
 			const char *file_name;
 			uint32_t max_n_pkts;
 		} sink;
-
-		struct {
-			uint16_t queue_id;
-			uint32_t op_offset;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 	int retry;
@@ -421,7 +386,6 @@ struct pmd_internals {
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
 	struct softnic_tap_list tap_list;
-	struct softnic_cryptodev_list cryptodev_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;
@@ -519,24 +483,6 @@ struct softnic_tap *
 softnic_tap_create(struct pmd_internals *p,
 	const char *name);
 
-/**
- * Sym Crypto
- */
-int
-softnic_cryptodev_init(struct pmd_internals *p);
-
-void
-softnic_cryptodev_free(struct pmd_internals *p);
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 2cf7fa52d1..51a1ea73c0 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -227,7 +227,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		struct rte_port_sched_reader_params sched;
 		struct rte_port_fd_reader_params fd;
 		struct rte_port_source_params source;
-		struct rte_port_sym_crypto_reader_params cryptodev;
 	} pp;
 
 	struct pipeline *pipeline;
@@ -330,23 +329,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.f_callback = params->cryptodev.f_callback;
-		pp.cryptodev.arg_callback = params->cryptodev.arg_callback;
-		p.ops = &rte_port_sym_crypto_reader_ops;
-		p.arg_create = &pp.cryptodev;
-		break;
-	}
-
 	default:
 		return -1;
 	}
@@ -433,14 +415,12 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		struct rte_port_sched_writer_params sched;
 		struct rte_port_fd_writer_params fd;
 		struct rte_port_sink_params sink;
-		struct rte_port_sym_crypto_writer_params cryptodev;
 	} 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;
-		struct rte_port_sym_crypto_writer_nodrop_params cryptodev;
 	} pp_nodrop;
 
 	struct pipeline *pipeline;
@@ -554,40 +534,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		if (params->cryptodev.queue_id >= cryptodev->n_queues)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.tx_burst_sz = params->burst_size;
-		pp.cryptodev.crypto_op_offset = params->cryptodev.op_offset;
-
-		pp_nodrop.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp_nodrop.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp_nodrop.cryptodev.tx_burst_sz = params->burst_size;
-		pp_nodrop.cryptodev.n_retries = params->retry;
-		pp_nodrop.cryptodev.crypto_op_offset =
-				params->cryptodev.op_offset;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_sym_crypto_writer_ops;
-			p.arg_create = &pp.cryptodev;
-		} else {
-			p.ops = &rte_port_sym_crypto_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.cryptodev;
-		}
-
-		break;
-	}
-
 	default:
 		return -1;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 05/21] net/softnic: remove tap support
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (3 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the TUN/TAP device support. The TUN/TAP devices are still
supported as virtual Ethernet devices through the TAP Poll Mode
Driver.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  76 -----------
 .../net/softnic/rte_eth_softnic_internals.h   |  36 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  44 -------
 drivers/net/softnic/rte_eth_softnic_tap.c     | 118 ------------------
 6 files changed, 278 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index b3d235841d..91f1f3220f 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -16,7 +16,6 @@ sources = files(
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
-        'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
 deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 1ea5989223..eb97ae7185 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -162,7 +162,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
@@ -183,7 +182,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
@@ -263,7 +261,6 @@ pmd_init(struct pmd_params *params)
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tap_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index bca0b176d6..501ef08c4c 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,33 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tap <tap_name>
- */
-static void
-cmd_tap(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tap *tap;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tap = softnic_tap_create(softnic, name);
-	if (tap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -874,7 +847,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
@@ -957,38 +929,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
 		t0 += 2;
-	} else if (strcmp(tokens[t0], "tap") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tap");
-			return;
-		}
-
-		p.type = PORT_IN_TAP;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.tap.mempool_name = tokens[t0 + 3];
-
-		if (strcmp(tokens[t0 + 4], "mtu") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mtu");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tap.mtu,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
-			return;
-		}
-
-		t0 += 6;
 	} else if (strcmp(tokens[t0], "source") == 0) {
 		if (n_tokens < t0 + 6) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1074,7 +1014,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  */
 static void
@@ -1147,16 +1086,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tap") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tap");
-			return;
-		}
-
-		p.type = PORT_OUT_TAP;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "sink") == 0) {
 		if ((n_tokens != 7) && (n_tokens != 11)) {
@@ -4600,11 +4529,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tap") == 0) {
-		cmd_tap(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index ddcde99b98..df74c1fbdc 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -89,17 +89,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TAP
- */
-struct softnic_tap {
-	TAILQ_ENTRY(softnic_tap) node;
-	char name[NAME_SIZE];
-	int fd;
-};
-
-TAILQ_HEAD(softnic_tap_list, softnic_tap);
-
 /**
  * Input port action
  */
@@ -163,7 +152,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 };
 
@@ -176,11 +164,6 @@ struct softnic_port_in_params {
 			uint16_t queue_id;
 		} rxq;
 
-		struct {
-			const char *mempool_name;
-			uint32_t mtu;
-		} tap;
-
 		struct {
 			const char *mempool_name;
 			const char *file_name;
@@ -196,7 +179,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 };
 
@@ -385,7 +367,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tap_list tap_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;
@@ -466,23 +447,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TAP
- */
-int
-softnic_tap_init(struct pmd_internals *p);
-
-void
-softnic_tap_free(struct pmd_internals *p);
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 51a1ea73c0..7a2828b785 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -293,25 +293,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TAP:
-	{
-		struct softnic_tap *tap;
-		struct softnic_mempool *mempool;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		mempool = softnic_mempool_find(softnic, params->tap.mempool_name);
-		if (tap == NULL || mempool == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.mempool = mempool->m;
-		pp.fd.mtu = params->tap.mtu;
-
-		p.ops = &rte_port_fd_reader_ops;
-		p.arg_create = &pp.fd;
-		break;
-	}
-
 	case PORT_IN_SOURCE:
 	{
 		struct softnic_mempool *mempool;
@@ -499,31 +480,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TAP:
-	{
-		struct softnic_tap *tap;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		if (tap == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.tx_burst_sz = params->burst_size;
-
-		pp_nodrop.fd.fd = tap->fd;
-		pp_nodrop.fd.tx_burst_sz = params->burst_size;
-		pp_nodrop.fd.n_retries = params->n_retries;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_fd_writer_ops;
-			p.arg_create = &pp.fd;
-		} else {
-			p.ops = &rte_port_fd_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.fd;
-		}
-		break;
-	}
-
 	case PORT_OUT_SINK:
 	{
 		pp.sink.file_name = params->sink.file_name;
diff --git a/drivers/net/softnic/rte_eth_softnic_tap.c b/drivers/net/softnic/rte_eth_softnic_tap.c
deleted file mode 100644
index 36fe9f0287..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tap.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <netinet/in.h>
-#ifdef RTE_EXEC_ENV_LINUX
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#endif
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define TAP_DEV                                            "/dev/net/tun"
-
-int
-softnic_tap_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tap_list);
-
-	return 0;
-}
-
-void
-softnic_tap_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tap *tap;
-
-		tap = TAILQ_FIRST(&p->tap_list);
-		if (tap == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tap_list, tap, node);
-		free(tap);
-	}
-}
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tap, &p->tap_list, node)
-		if (strcmp(tap->name, name) == 0)
-			return tap;
-
-	return NULL;
-}
-
-#ifndef RTE_EXEC_ENV_LINUX
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p __rte_unused,
-	const char *name __rte_unused)
-{
-	return NULL;
-}
-
-#else
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-	struct ifreq ifr;
-	int fd, status;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tap_find(p, name))
-		return NULL;
-
-	/* Resource create */
-	fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
-	if (fd < 0)
-		return NULL;
-
-	memset(&ifr, 0, sizeof(ifr));
-	ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
-	strlcpy(ifr.ifr_name, name, IFNAMSIZ);
-
-	status = ioctl(fd, TUNSETIFF, (void *)&ifr);
-	if (status < 0) {
-		close(fd);
-		return NULL;
-	}
-
-	/* Node allocation */
-	tap = calloc(1, sizeof(struct softnic_tap));
-	if (tap == NULL) {
-		close(fd);
-		return NULL;
-	}
-	/* Node fill in */
-	strlcpy(tap->name, name, sizeof(tap->name));
-	tap->fd = fd;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tap_list, tap, node);
-
-	return tap;
-}
-
-#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 06/21] net/softnic: remove the legacy pipeline CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (4 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 05/21] net/softnic: remove tap support Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the legacy pipeline CLI commands.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 4527 ---------------------
 1 file changed, 4527 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 501ef08c4c..abe275ec83 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -10,7 +10,6 @@
 #include <rte_common.h>
 #include <rte_cycles.h>
 #include <rte_string_fns.h>
-#include <rte_cryptodev.h>
 
 #include "rte_eth_softnic_internals.h"
 #include "parser.h"
@@ -186,4227 +185,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * port in action profile <profile_name>
- *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
- *  [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
- */
-static void
-cmd_port_in_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_action_profile_params p;
-	struct softnic_port_in_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[2], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[3], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[4];
-
-	t0 = 5;
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "filter") == 0)) {
-		uint32_t size;
-
-		if (n_tokens < t0 + 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "match") == 0) {
-			p.fltr.filter_on_match = 1;
-		} else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
-			p.fltr.filter_on_match = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.fltr.key_mask, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 7],
-			p.fltr.key, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.port_id,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
-		t0 += 10;
-	} /* filter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		uint32_t i;
-
-		if (n_tokens < t0 + 22) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"port in action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		for (i = 0; i < 16; i++)
-			if (softnic_parser_read_uint32(&p.lb.port_id[i],
-			tokens[t0 + 6 + i]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-				return;
-			}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
-		t0 += 22;
-	} /* balance */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_port_in_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * table action profile <profile_name>
- *  ipv4 | ipv6
- *  offset <ip_offset>
- *  fwd
- *  [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
- *  [meter srtcm | trtcm
- *      tc <n_tc>
- *      stats none | pkts | bytes | both]
- *  [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
- *  [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe |
- *      vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]
- *  [nat src | dst
- *      proto udp | tcp]
- *  [ttl drop | fwd
- *      stats none | pkts]
- *  [stats pkts | bytes | both]
- *  [time]
- *  [tag]
- *  [decap]
- *
- */
-static void
-cmd_table_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_action_profile_params p;
-	struct softnic_table_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[3];
-
-	if (strcmp(tokens[4], "ipv4") == 0) {
-		p.common.ip_version = 1;
-	} else if (strcmp(tokens[4], "ipv6") == 0) {
-		p.common.ip_version = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
-		return;
-	}
-
-	if (strcmp(tokens[5], "offset") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.common.ip_offset,
-		tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
-		return;
-	}
-
-	if (strcmp(tokens[7], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
-		return;
-	}
-
-	p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
-
-	t0 = 8;
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		if (n_tokens < t0 + 7) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.out_offset,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
-		t0 += 7;
-	} /* balance */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "meter") == 0)) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile meter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
-		} else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"srtcm or trtcm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "tc") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.mtr.n_tc,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "none") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 5], "both") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
-		t0 += 6;
-	} /* meter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tm") == 0)) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile tm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "spp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_subports_per_port");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "pps") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_pipes_per_subport");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
-		t0 += 5;
-	} /* tm */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "encap") == 0)) {
-		uint32_t n_extra_tokens = 0;
-
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"action profile encap");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "ether") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
-		} else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
-		} else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
-		} else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
-		} else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
-		} else if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
-			if (n_tokens < t0 + 2 + 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					"action profile encap vxlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2], "offset") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: offset");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.encap.vxlan.data_offset,
-				tokens[t0 + 2 + 1]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ether_offset");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
-				p.encap.vxlan.ip_version = 1;
-			else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
-				p.encap.vxlan.ip_version = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ipv4 or ipv6");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: vlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
-				p.encap.vxlan.vlan = 1;
-			else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
-				p.encap.vxlan.vlan = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: on or off");
-				return;
-			}
-
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
-			n_extra_tokens = 5;
-
-		} else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) {
-			p.encap.encap_mask =
-				1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
-		t0 += 2 + n_extra_tokens;
-	} /* encap */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "nat") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile nat");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "src") == 0) {
-			p.nat.source_nat = 1;
-		} else if (strcmp(tokens[t0 + 1], "dst") == 0) {
-			p.nat.source_nat = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"src or dst");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "proto") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "tcp") == 0) {
-			p.nat.proto = 0x06;
-		} else if (strcmp(tokens[t0 + 3], "udp") == 0) {
-			p.nat.proto = 0x11;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"tcp or udp");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
-		t0 += 4;
-	} /* nat */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "ttl") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile ttl");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "drop") == 0) {
-			p.ttl.drop = 1;
-		} else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
-			p.ttl.drop = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"drop or fwd");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "none") == 0) {
-			p.ttl.n_packets_enabled = 0;
-		} else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
-			p.ttl.n_packets_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
-		t0 += 4;
-	} /* ttl */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "stats") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "pkts") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
-			p.stats.n_packets_enabled = 0;
-			p.stats.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 1], "both") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-				"pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
-		t0 += 2;
-	} /* stats */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "time") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
-		t0 += 1;
-	} /* time */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tag") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG;
-		t0 += 1;
-	} /* tag */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "decap") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP;
-		t0 += 1;
-	} /* decap */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_table_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name>
- *  period <timer_period_ms>
- *  offset_port_id <offset_port_id>
- */
-static void
-cmd_pipeline(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct pipeline_params p;
-	char *name;
-	struct pipeline *pipeline;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "period") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.timer_period_ms,
-		tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
-		return;
-	}
-
-	if (strcmp(tokens[4], "offset_port_id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.offset_port_id,
-		tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
-		return;
-	}
-
-	pipeline = softnic_pipeline_create(softnic, name, &p);
-	if (pipeline == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in
- *  bsz <burst_size>
- *  link <link_name> rxq <queue_id>
- *  | swq <swq_name>
- *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  [action <port_in_action_profile_name>]
- *  [disabled]
- */
-static void
-cmd_pipeline_port_in(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int enabled, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	t0 = 6;
-
-	if (strcmp(tokens[t0], "link") == 0) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in link");
-			return;
-		}
-
-		p.type = PORT_IN_RXQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"queue_id");
-			return;
-		}
-		t0 += 4;
-	} else if (strcmp(tokens[t0], "swq") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in swq");
-			return;
-		}
-
-		p.type = PORT_IN_SWQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "source") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in source");
-			return;
-		}
-
-		p.type = PORT_IN_SOURCE;
-
-		if (strcmp(tokens[t0 + 1], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.source.mempool_name = tokens[t0 + 2];
-
-		if (strcmp(tokens[t0 + 3], "file") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"file");
-			return;
-		}
-
-		p.source.file_name = tokens[t0 + 4];
-
-		if (strcmp(tokens[t0 + 5], "bpp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"bpp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_bytes_per_pkt");
-			return;
-		}
-
-		t0 += 7;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	enabled = 1;
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "disabled") == 0)) {
-		enabled = 0;
-
-		t0 += 1;
-	}
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_in_create(softnic,
-		pipeline_name,
-		&p,
-		enabled);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out
- *  bsz <burst_size>
- *  link <link_name> txq <txq_id>
- *  | swq <swq_name>
- *  | sink [file <file_name> pkts <max_n_pkts>]
- */
-static void
-cmd_pipeline_port_out(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_out_params p;
-	char *pipeline_name;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	if (strcmp(tokens[6], "link") == 0) {
-		if (n_tokens != 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out link");
-			return;
-		}
-
-		p.type = PORT_OUT_TXQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.txq.queue_id,
-			tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-	} else if (strcmp(tokens[6], "swq") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out swq");
-			return;
-		}
-
-		p.type = PORT_OUT_SWQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "sink") == 0) {
-		if ((n_tokens != 7) && (n_tokens != 11)) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out sink");
-			return;
-		}
-
-		p.type = PORT_OUT_SINK;
-
-		if (n_tokens == 7) {
-			p.sink.file_name = NULL;
-			p.sink.max_n_pkts = 0;
-		} else {
-			if (strcmp(tokens[7], "file") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"file");
-				return;
-			}
-
-			p.sink.file_name = tokens[8];
-
-			if (strcmp(tokens[9], "pkts") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
-				tokens[10]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
-				return;
-			}
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table
- *      match
- *      acl
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | array
- *          offset <key_offset>
- *          size <n_keys>
- *      | hash
- *          ext | lru
- *          key <key_size>
- *          mask <key_mask>
- *          offset <key_offset>
- *          buckets <n_buckets>
- *          size <n_keys>
- *      | lpm
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | stub
- *  [action <table_action_profile_name>]
- */
-static void
-cmd_pipeline_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (strcmp(tokens[3], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return;
-	}
-
-	t0 = 4;
-	if (strcmp(tokens[t0], "acl") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table acl");
-			return;
-		}
-
-		p.match_type = TABLE_ACL;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.acl.ip_version = 1;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.acl.ip_version = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"ip_header_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "array") == 0) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table array");
-			return;
-		}
-
-		p.match_type = TABLE_ARRAY;
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.n_keys,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 5;
-	} else if (strcmp(tokens[t0], "hash") == 0) {
-		uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-		if (n_tokens < t0 + 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table hash");
-			return;
-		}
-
-		p.match_type = TABLE_HASH;
-
-		if (strcmp(tokens[t0 + 1], "ext") == 0) {
-			p.match.hash.extendable_bucket = 1;
-		} else if (strcmp(tokens[t0 + 1], "lru") == 0) {
-			p.match.hash.extendable_bucket = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ext or lru");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		if ((softnic_parser_read_uint32(&p.match.hash.key_size,
-			tokens[t0 + 3]) != 0) ||
-			p.match.hash.key_size == 0 ||
-			p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.match.hash.key_mask, &key_mask_size) != 0) ||
-			key_mask_size != p.match.hash.key_size) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.key_offset,
-			tokens[t0 + 7]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "buckets") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 10], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_keys,
-			tokens[t0 + 11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 12;
-	} else if (strcmp(tokens[t0], "lpm") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table lpm");
-			return;
-		}
-
-		p.match_type = TABLE_LPM;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.lpm.key_size = 4;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.lpm.key_size = 16;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "stub") == 0) {
-		p.match_type = TABLE_STUB;
-
-		t0 += 1;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	if (n_tokens > t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> table <table_id>
- */
-static void
-cmd_pipeline_port_in_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id, table_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_connect_to_table(softnic,
-		pipeline_name,
-		port_id,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> stats read [clear]
- */
-
-#define MSG_PIPELINE_PORT_IN_STATS                         \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_in_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_in_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_in_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> enable
- */
-static void
-cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "enable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> disable
- */
-static void
-cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "disable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out <port_id> stats read [clear]
- */
-#define MSG_PIPELINE_PORT_OUT_STATS                        \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_out_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_out_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_out_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> stats read [clear]
- */
-#define MSG_PIPELINE_TABLE_STATS                                     \
-	"Pkts in: %" PRIu64 "\n"                                     \
-	"Pkts in with lookup miss: %" PRIu64 "\n"                    \
-	"Pkts in with lookup hit dropped by AH: %" PRIu64 "\n"       \
-	"Pkts in with lookup hit dropped by others: %" PRIu64 "\n"   \
-	"Pkts in with lookup miss dropped by AH: %" PRIu64 "\n"      \
-	"Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_table_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_table_stats stats;
-	char *pipeline_name;
-	uint32_t table_id;
-	int clear, status;
-
-	if (n_tokens != 6 &&
-		n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[5], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 7) {
-		if (strcmp(tokens[6], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_table_stats_read(softnic,
-		pipeline_name,
-		table_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
-		stats.stats.n_pkts_in,
-		stats.stats.n_pkts_lookup_miss,
-		stats.n_pkts_dropped_by_lkp_hit_ah,
-		stats.n_pkts_dropped_lkp_hit,
-		stats.n_pkts_dropped_by_lkp_miss_ah,
-		stats.n_pkts_dropped_lkp_miss);
-}
-
-/**
- * <match> ::=
- *
- * match
- *    acl
- *       priority <priority>
- *       ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
- *       <sp0> <sp1> <dp0> <dp1> <proto>
- *    | array <pos>
- *    | hash
- *       raw <key>
- *       | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv4_addr <addr>
- *       | ipv6_addr <addr>
- *       | qinq <svlan> <cvlan>
- *    | lpm
- *       ipv4 | ipv6 <addr> <depth>
- */
-struct pkt_key_qinq {
-	uint16_t ethertype_svlan;
-	uint16_t svlan;
-	uint16_t ethertype_cvlan;
-	uint16_t cvlan;
-} __rte_packed;
-
-struct pkt_key_ipv4_5tuple {
-	uint8_t time_to_live;
-	uint8_t proto;
-	uint16_t hdr_checksum;
-	uint32_t sa;
-	uint32_t da;
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv6_5tuple {
-	uint16_t payload_length;
-	uint8_t proto;
-	uint8_t hop_limit;
-	uint8_t sa[16];
-	uint8_t da[16];
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv4_addr {
-	uint32_t addr;
-} __rte_packed;
-
-struct pkt_key_ipv6_addr {
-	uint8_t addr[16];
-} __rte_packed;
-
-static uint32_t
-parse_match(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_match *m)
-{
-	memset(m, 0, sizeof(*m));
-
-	if (n_tokens < 2)
-		return 0;
-
-	if (strcmp(tokens[0], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return 0;
-	}
-
-	if (strcmp(tokens[1], "acl") == 0) {
-		if (n_tokens < 14) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ACL;
-
-		if (strcmp(tokens[2], "priority") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.priority,
-			tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-			return 0;
-		}
-
-		if (strcmp(tokens[4], "ipv4") == 0) {
-			struct in_addr saddr, daddr;
-
-			m->match.acl.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
-
-			if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
-		} else if (strcmp(tokens[4], "ipv6") == 0) {
-			struct in6_addr saddr, daddr;
-
-			m->match.acl.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
-
-			if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.sa_depth,
-			tokens[6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.da_depth,
-			tokens[8]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "proto");
-			return 0;
-		}
-
-		m->match.acl.proto_mask = 0xff;
-
-		return 14;
-	} /* acl */
-
-	if (strcmp(tokens[1], "array") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ARRAY;
-
-		if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pos");
-			return 0;
-		}
-
-		return 3;
-	} /* array */
-
-	if (strcmp(tokens[1], "hash") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_HASH;
-
-		if (strcmp(tokens[2], "raw") == 0) {
-			uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_hex_string(tokens[3],
-				m->match.hash.key, &key_size) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "key");
-				return 0;
-			}
-
-			return 4;
-		} /* hash raw */
-
-		if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
-			struct pkt_key_ipv4_5tuple *ipv4 =
-				(struct pkt_key_ipv4_5tuple *)m->match.hash.key;
-			struct in_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			ipv4->sa = saddr.s_addr;
-			ipv4->da = daddr.s_addr;
-			ipv4->sp = rte_cpu_to_be_16(sp);
-			ipv4->dp = rte_cpu_to_be_16(dp);
-			ipv4->proto = proto;
-
-			return 8;
-		} /* hash ipv4_5tuple */
-
-		if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
-			struct pkt_key_ipv6_5tuple *ipv6 =
-				(struct pkt_key_ipv6_5tuple *)m->match.hash.key;
-			struct in6_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			memcpy(ipv6->sa, saddr.s6_addr, 16);
-			memcpy(ipv6->da, daddr.s6_addr, 16);
-			ipv6->sp = rte_cpu_to_be_16(sp);
-			ipv6->dp = rte_cpu_to_be_16(dp);
-			ipv6->proto = proto;
-
-			return 8;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "ipv4_addr") == 0) {
-			struct pkt_key_ipv4_addr *ipv4_addr =
-				(struct pkt_key_ipv4_addr *)m->match.hash.key;
-			struct in_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			ipv4_addr->addr = addr.s_addr;
-
-			return 4;
-		} /* hash ipv4_addr */
-
-		if (strcmp(tokens[2], "ipv6_addr") == 0) {
-			struct pkt_key_ipv6_addr *ipv6_addr =
-				(struct pkt_key_ipv6_addr *)m->match.hash.key;
-			struct in6_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(ipv6_addr->addr, addr.s6_addr, 16);
-
-			return 4;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "qinq") == 0) {
-			struct pkt_key_qinq *qinq =
-				(struct pkt_key_qinq *)m->match.hash.key;
-			uint16_t svlan, cvlan;
-
-			if (n_tokens < 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) ||
-				svlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"svlan");
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) ||
-				cvlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"cvlan");
-				return 0;
-			}
-
-			qinq->svlan = rte_cpu_to_be_16(svlan);
-			qinq->cvlan = rte_cpu_to_be_16(cvlan);
-
-			return 5;
-		} /* hash qinq */
-
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return 0;
-	} /* hash */
-
-	if (strcmp(tokens[1], "lpm") == 0) {
-		if (n_tokens < 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_LPM;
-
-		if (strcmp(tokens[2], "ipv4") == 0) {
-			struct in_addr addr;
-
-			m->match.lpm.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		} else if (strcmp(tokens[2], "ipv6") == 0) {
-			struct in6_addr addr;
-
-			m->match.lpm.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "depth");
-			return 0;
-		}
-
-		return 5;
-	} /* lpm */
-
-	snprintf(out, out_size, MSG_ARG_MISMATCH,
-		"acl or array or hash or lpm");
-	return 0;
-}
-
-/**
- * table_action ::=
- *
- * action
- *    fwd
- *       drop
- *       | port <port_id>
- *       | meta
- *       | table <table_id>
- *    [balance <out0> ... <out7>]
- *    [meter
- *       tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
- *    [tm subport <subport_id> pipe <pipe_id>]
- *    [encap
- *       ether <da> <sa>
- *       | vlan <da> <sa> <pcp> <dei> <vid>
- *       | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
- *       | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id>
- *       | mpls unicast | multicast
- *          <da> <sa>
- *          label0 <label> <tc> <ttl>
- *          [label1 <label> <tc> <ttl>
- *          [label2 <label> <tc> <ttl>
- *          [label3 <label> <tc> <ttl>]]]
- *       | pppoe <da> <sa> <session_id>]
- *       | vxlan ether <da> <sa>
- *          [vlan <pcp> <dei> <vid>]
- *          ipv4 <sa> <da> <dscp> <ttl>
- *          | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit>
- *          udp <sp> <dp>
- *          vxlan <vni>]
- *    [nat ipv4 | ipv6 <addr> <port>]
- *    [ttl dec | keep]
- *    [stats]
- *    [time]
- *    [tag <tag>]
- *    [decap <n>]
- *    [sym_crypto
- *       encrypt | decrypt
- *       type
- *       | cipher
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *       | cipher_auth
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *          auth_algo <algo> auth_key <key> digest_size <size>
- *       | aead
- *          aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad>
- *          digest_size <size>
- *       data_offset <data_offset>]
- *
- * where:
- *    <pa> ::= g | y | r | drop
- */
-static uint32_t
-parse_table_action_fwd(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "fwd") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_DROP;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_balance(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t i;
-
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "balance") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
-		return 0;
-
-	for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
-		if (softnic_parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
-			return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-	return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
-}
-
-static int
-parse_policer_action(char *token, enum rte_table_action_policer *a)
-{
-	if (strcmp(token, "g") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-		return 0;
-	}
-
-	if (strcmp(token, "y") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-		return 0;
-	}
-
-	if (strcmp(token, "r") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
-		return 0;
-	}
-
-	if (strcmp(token, "drop") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_DROP;
-		return 0;
-	}
-
-	return -1;
-}
-
-static uint32_t
-parse_table_action_meter_tc(char **tokens,
-	uint32_t n_tokens,
-	struct rte_table_action_mtr_tc_params *mtr)
-{
-	if (n_tokens < 9 ||
-		strcmp(tokens[0], "meter") ||
-		softnic_parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
-		strcmp(tokens[2], "policer") ||
-		strcmp(tokens[3], "g") ||
-		parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) ||
-		strcmp(tokens[5], "y") ||
-		parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) ||
-		strcmp(tokens[7], "r") ||
-		parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED]))
-		return 0;
-
-	return 9;
-}
-
-static uint32_t
-parse_table_action_meter(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "meter"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < 10 ||
-		strcmp(tokens[0], "tc0") ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1,
-			&a->mtr.mtr[0]) == 0))
-		return 0;
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "tc1")) {
-		a->mtr.tc_mask = 1;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-		return 1 + 10;
-	}
-
-	if (n_tokens < 30 ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
-		strcmp(tokens[10], "tc2") ||
-		(parse_table_action_meter_tc(tokens + 11,
-			n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
-		strcmp(tokens[20], "tc3") ||
-		(parse_table_action_meter_tc(tokens + 21,
-			n_tokens - 21, &a->mtr.mtr[3]) == 0))
-		return 0;
-
-	a->mtr.tc_mask = 0xF;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-	return 1 + 10 + 3 * 10;
-}
-
-static uint32_t
-parse_table_action_tm(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t subport_id, pipe_id;
-
-	if (n_tokens < 5 ||
-		strcmp(tokens[0], "tm") ||
-		strcmp(tokens[1], "subport") ||
-		softnic_parser_read_uint32(&subport_id, tokens[2]) ||
-		strcmp(tokens[3], "pipe") ||
-		softnic_parser_read_uint32(&pipe_id, tokens[4]))
-		return 0;
-
-	a->tm.subport_id = subport_id;
-	a->tm.pipe_id = pipe_id;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
-	return 5;
-}
-
-static uint32_t
-parse_table_action_encap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "encap"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	/* ether */
-	if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
-		if (n_tokens < 3 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 3;
-	}
-
-	/* vlan */
-	if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
-		uint32_t pcp, dei, vid;
-
-		if (n_tokens < 6 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
-			softnic_parser_read_uint32(&pcp, tokens[3]) ||
-			pcp > 0x7 ||
-			softnic_parser_read_uint32(&dei, tokens[4]) ||
-			dei > 0x1 ||
-			softnic_parser_read_uint32(&vid, tokens[5]) ||
-			vid > 0xFFF)
-			return 0;
-
-		a->encap.vlan.vlan.pcp = pcp & 0x7;
-		a->encap.vlan.vlan.dei = dei & 0x1;
-		a->encap.vlan.vlan.vid = vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 6;
-	}
-
-	/* qinq */
-	if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 9 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF)
-			return 0;
-
-		a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 9;
-	}
-
-	/* qinq_pppoe */
-	if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 10 ||
-			softnic_parse_mac_addr(tokens[1],
-				&a->encap.qinq_pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2],
-				&a->encap.qinq_pppoe.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF ||
-			softnic_parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id,
-				tokens[9]))
-			return 0;
-
-		a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 10;
-	}
-
-	/* mpls */
-	if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
-		uint32_t label, tc, ttl;
-
-		if (n_tokens < 8)
-			return 0;
-
-		if (strcmp(tokens[1], "unicast") == 0)
-			a->encap.mpls.unicast = 1;
-		else if (strcmp(tokens[1], "multicast") == 0)
-			a->encap.mpls.unicast = 0;
-		else
-			return 0;
-
-		if (softnic_parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
-			softnic_parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
-			strcmp(tokens[4], "label0") ||
-			softnic_parser_read_uint32(&label, tokens[5]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[6]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[7]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[0].label = label;
-		a->encap.mpls.mpls[0].tc = tc;
-		a->encap.mpls.mpls[0].ttl = ttl;
-
-		tokens += 8;
-		n_tokens -= 8;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label1")) {
-			a->encap.mpls.mpls_count = 1;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[1].label = label;
-		a->encap.mpls.mpls[1].tc = tc;
-		a->encap.mpls.mpls[1].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label2")) {
-			a->encap.mpls.mpls_count = 2;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[2].label = label;
-		a->encap.mpls.mpls[2].tc = tc;
-		a->encap.mpls.mpls[2].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label3")) {
-			a->encap.mpls.mpls_count = 3;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[3].label = label;
-		a->encap.mpls.mpls[3].tc = tc;
-		a->encap.mpls.mpls[3].ttl = ttl;
-
-		a->encap.mpls.mpls_count = 4;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 8 + 4 + 4 + 4;
-	}
-
-	/* pppoe */
-	if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
-		if (n_tokens < 4 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
-			softnic_parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
-				tokens[3]))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 4;
-	}
-
-	/* vxlan */
-	if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) {
-		uint32_t n = 0;
-
-		n_tokens--;
-		tokens++;
-		n++;
-
-		/* ether <da> <sa> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "ether") ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* [vlan <pcp> <dei> <vid>] */
-		if (strcmp(tokens[0], "vlan") == 0) {
-			uint32_t pcp, dei, vid;
-
-			if ((n_tokens < 4) ||
-				softnic_parser_read_uint32(&pcp, tokens[1]) ||
-				(pcp > 7) ||
-				softnic_parser_read_uint32(&dei, tokens[2]) ||
-				(dei > 1) ||
-				softnic_parser_read_uint32(&vid, tokens[3]) ||
-				(vid > 0xFFF))
-				return 0;
-
-			a->encap.vxlan.vlan.pcp = pcp;
-			a->encap.vxlan.vlan.dei = dei;
-			a->encap.vxlan.vlan.vid = vid;
-
-			n_tokens -= 4;
-			tokens += 4;
-			n += 4;
-		}
-
-		/* ipv4 <sa> <da> <dscp> <ttl>
-		   | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */
-		if (strcmp(tokens[0], "ipv4") == 0) {
-			struct in_addr sa, da;
-			uint8_t dscp, ttl;
-
-			if ((n_tokens < 5) ||
-				softnic_parse_ipv4_addr(tokens[1], &sa) ||
-				softnic_parse_ipv4_addr(tokens[2], &da) ||
-				softnic_parser_read_uint8(&dscp, tokens[3]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&ttl, tokens[4]))
-				return 0;
-
-			a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr);
-			a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr);
-			a->encap.vxlan.ipv4.dscp = dscp;
-			a->encap.vxlan.ipv4.ttl = ttl;
-
-			n_tokens -= 5;
-			tokens += 5;
-			n += 5;
-		} else if (strcmp(tokens[0], "ipv6") == 0) {
-			struct in6_addr sa, da;
-			uint32_t flow_label;
-			uint8_t dscp, hop_limit;
-
-			if ((n_tokens < 6) ||
-				softnic_parse_ipv6_addr(tokens[1], &sa) ||
-				softnic_parse_ipv6_addr(tokens[2], &da) ||
-				softnic_parser_read_uint32(&flow_label, tokens[3]) ||
-				softnic_parser_read_uint8(&dscp, tokens[4]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&hop_limit, tokens[5]))
-				return 0;
-
-			memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
-			memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
-			a->encap.vxlan.ipv6.flow_label = flow_label;
-			a->encap.vxlan.ipv6.dscp = dscp;
-			a->encap.vxlan.ipv6.hop_limit = hop_limit;
-
-			n_tokens -= 6;
-			tokens += 6;
-			n += 6;
-		} else
-			return 0;
-
-		/* udp <sp> <dp> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "udp") ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2]))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* vxlan <vni> */
-		if ((n_tokens < 2) ||
-			strcmp(tokens[0], "vxlan") ||
-			softnic_parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) ||
-			(a->encap.vxlan.vxlan.vni > 0xFFFFFF))
-			return 0;
-
-		n_tokens -= 2;
-		tokens += 2;
-		n += 2;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + n;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_nat(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 4 ||
-		strcmp(tokens[0], "nat"))
-		return 0;
-
-	if (strcmp(tokens[1], "ipv4") == 0) {
-		struct in_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv4_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 1;
-		a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	if (strcmp(tokens[1], "ipv6") == 0) {
-		struct in6_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv6_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 0;
-		memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_ttl(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "ttl"))
-		return 0;
-
-	if (strcmp(tokens[1], "dec") == 0)
-		a->ttl.decrement = 1;
-	else if (strcmp(tokens[1], "keep") == 0)
-		a->ttl.decrement = 0;
-	else
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_stats(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "stats"))
-		return 0;
-
-	a->stats.n_packets = 0;
-	a->stats.n_bytes = 0;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-	return 1;
-}
-
-static uint32_t
-parse_table_action_time(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "time"))
-		return 0;
-
-	a->time.time = rte_rdtsc();
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
-	return 1;
-}
-
-static void
-parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
-{
-	struct rte_crypto_sym_xform *xform[2] = {NULL};
-	uint32_t i;
-
-	xform[0] = p->xform;
-	if (xform[0])
-		xform[1] = xform[0]->next;
-
-	for (i = 0; i < 2; i++) {
-		if (xform[i] == NULL)
-			continue;
-
-		switch (xform[i]->type) {
-		case RTE_CRYPTO_SYM_XFORM_CIPHER:
-			free(p->cipher_auth.cipher_iv.val);
-			free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AUTH:
-			if (p->cipher_auth.auth_iv.val)
-				free(p->cipher_auth.cipher_iv.val);
-			if (p->cipher_auth.auth_iv_update.val)
-				free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AEAD:
-			free(p->aead.iv.val);
-			free(p->aead.aad.val);
-			break;
-		default:
-			continue;
-		}
-	}
-
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	int status;
-	size_t len;
-
-	if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") ||
-			strcmp(tokens[3], "cipher_key") ||
-			strcmp(tokens[5], "cipher_iv"))
-		return NULL;
-
-	xform_cipher = calloc(1, sizeof(*xform_cipher));
-	if (xform_cipher == NULL)
-		return NULL;
-
-	xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
-	xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT :
-			RTE_CRYPTO_CIPHER_OP_DECRYPT;
-
-	/* cipher_algo */
-	status = rte_cryptodev_get_cipher_algo_enum(
-			&xform_cipher->cipher.algo, tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* cipher_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.key.data = key;
-	xform_cipher->cipher.key.length = (uint16_t)len;
-
-	/* cipher_iv */
-	len = strlen(tokens[6]);
-
-	p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1);
-	if (p->cipher_auth.cipher_iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6],
-			p->cipher_auth.cipher_iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.iv.length = (uint16_t)len;
-	xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->cipher_auth.cipher_iv.length = (uint32_t)len;
-	*used_n_tokens = 7;
-
-	return xform_cipher;
-
-error_exit:
-	if (p->cipher_auth.cipher_iv.val) {
-		free(p->cipher_auth.cipher_iv.val);
-		p->cipher_auth.cipher_iv.val = NULL;
-	}
-
-	free(xform_cipher);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	struct rte_crypto_sym_xform *xform_auth;
-	int status;
-	size_t len;
-
-	if (n_tokens < 13 ||
-			strcmp(tokens[7], "auth_algo") ||
-			strcmp(tokens[9], "auth_key") ||
-			strcmp(tokens[11], "digest_size"))
-		return NULL;
-
-	xform_auth = calloc(1, sizeof(*xform_auth));
-	if (xform_auth == NULL)
-		return NULL;
-
-	xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH;
-	xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE :
-			RTE_CRYPTO_AUTH_OP_VERIFY;
-
-	/* auth_algo */
-	status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo,
-			tokens[8]);
-	if (status < 0)
-		goto error_exit;
-
-	/* auth_key */
-	len = strlen(tokens[10]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_auth->auth.key.data = key;
-	xform_auth->auth.key.length = (uint16_t)len;
-
-	key += xform_auth->auth.key.length;
-	max_key_len -= xform_auth->auth.key.length;
-
-	if (strcmp(tokens[11], "digest_size"))
-		goto error_exit;
-
-	status = softnic_parser_read_uint16(&xform_auth->auth.digest_length,
-			tokens[12]);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7,
-			encrypt, used_n_tokens);
-	if (xform_cipher == NULL)
-		goto error_exit;
-
-	*used_n_tokens += 6;
-
-	if (encrypt) {
-		xform_cipher->next = xform_auth;
-		return xform_cipher;
-	} else {
-		xform_auth->next = xform_cipher;
-		return xform_auth;
-	}
-
-error_exit:
-	if (p->cipher_auth.auth_iv.val) {
-		free(p->cipher_auth.auth_iv.val);
-		p->cipher_auth.auth_iv.val = 0;
-	}
-
-	free(xform_auth);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_aead;
-	int status;
-	size_t len;
-
-	if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") ||
-			strcmp(tokens[3], "aead_key") ||
-			strcmp(tokens[5], "aead_iv") ||
-			strcmp(tokens[7], "aead_aad") ||
-			strcmp(tokens[9], "digest_size"))
-		return NULL;
-
-	xform_aead = calloc(1, sizeof(*xform_aead));
-	if (xform_aead == NULL)
-		return NULL;
-
-	xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD;
-	xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT :
-			RTE_CRYPTO_AEAD_OP_DECRYPT;
-
-	/* aead_algo */
-	status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo,
-			tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* aead_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.key.data = key;
-	xform_aead->aead.key.length = (uint16_t)len;
-
-	/* aead_iv */
-	len = strlen(tokens[6]);
-	p->aead.iv.val = calloc(1, len / 2 + 1);
-	if (p->aead.iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6], p->aead.iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.iv.length = (uint16_t)len;
-	xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->aead.iv.length = (uint32_t)len;
-
-	/* aead_aad */
-	len = strlen(tokens[8]);
-	p->aead.aad.val = calloc(1, len / 2 + 1);
-	if (p->aead.aad.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.aad_length = (uint16_t)len;
-	p->aead.aad.length = (uint32_t)len;
-
-	/* digest_size */
-	status = softnic_parser_read_uint16(&xform_aead->aead.digest_length,
-			tokens[10]);
-	if (status < 0)
-		goto error_exit;
-
-	*used_n_tokens = 11;
-
-	return xform_aead;
-
-error_exit:
-	if (p->aead.iv.val) {
-		free(p->aead.iv.val);
-		p->aead.iv.val = NULL;
-	}
-	if (p->aead.aad.val) {
-		free(p->aead.aad.val);
-		p->aead.aad.val = NULL;
-	}
-
-	free(xform_aead);
-
-	return NULL;
-}
-
-
-static uint32_t
-parse_table_action_sym_crypto(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
-	struct rte_crypto_sym_xform *xform = NULL;
-	uint8_t *key = a->sym_crypto_key;
-	uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
-	uint32_t used_n_tokens;
-	uint32_t encrypt;
-	int status;
-
-	if ((n_tokens < 12) ||
-		strcmp(tokens[0], "sym_crypto") ||
-		strcmp(tokens[2], "type"))
-		return 0;
-
-	memset(p, 0, sizeof(*p));
-
-	if (strcmp(tokens[1], "encrypt") == 0)
-		encrypt = 1;
-	else
-		encrypt = 0;
-
-	status = softnic_parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]);
-	if (status < 0)
-		return 0;
-
-	if (strcmp(tokens[3], "cipher") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "cipher_auth") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher_auth(p, key, max_key_len,
-				tokens, n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "aead") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_aead(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	}
-
-	if (xform == NULL)
-		return 0;
-
-	p->xform = xform;
-
-	if (strcmp(tokens[used_n_tokens], "data_offset")) {
-		parse_free_sym_crypto_param_data(p);
-		return 0;
-	}
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-	return used_n_tokens + 5;
-}
-
-static uint32_t
-parse_table_action_tag(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "tag"))
-		return 0;
-
-	if (softnic_parser_read_uint32(&a->tag.tag, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_decap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "decap"))
-		return 0;
-
-	if (softnic_parser_read_uint16(&a->decap.n, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-	return 2;
-}
-
-static uint32_t
-parse_table_action(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t n_tokens0 = n_tokens;
-
-	memset(a, 0, sizeof(*a));
-
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "action"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_fwd(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action fwd");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_balance(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action balance");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_meter(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action meter");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tm(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tm");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_encap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action encap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_nat(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action nat");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_ttl(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action ttl");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_stats(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action stats");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_time(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action time");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tag") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tag(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tag");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "decap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_decap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action decap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_sym_crypto(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action sym_crypto");
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens0 - n_tokens == 1) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return 0;
-	}
-
-	return n_tokens0 - n_tokens;
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match <match>
- *    action <table_action>
- */
-static void
-cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	struct softnic_table_rule_action a;
-	char *pipeline_name;
-	void *data;
-	uint32_t table_id, t0, n_tokens_parsed;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	/* action */
-	n_tokens_parsed = parse_table_action(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&a);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (t0 != n_tokens) {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&m,
-		&a,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match
- *       default
- *    action
- *       fwd
- *          drop
- *          | port <port_id>
- *          | meta
- *          | table <table_id>
- */
-static void
-cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_action action;
-	void *data;
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 11 &&
-		n_tokens != 12) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	if (strcmp(tokens[8], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return;
-	}
-
-	if (strcmp(tokens[9], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
-		return;
-	}
-
-	action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
-
-	if (strcmp(tokens[10], "drop") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_DROP;
-	} else if (strcmp(tokens[10], "port") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT;
-		action.fwd.id = id;
-	} else if (strcmp(tokens[10], "meta") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-	} else if (strcmp(tokens[10], "table") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		action.fwd.id = id;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID,
-			"drop or port or meta or table");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add_default(softnic,
-		pipeline_name,
-		table_id,
-		&action,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
- *
- * File <file_name>:
- * - line format: match <match> action <action>
- */
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size);
-
-static void
-cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match *match;
-	struct softnic_table_rule_action *action;
-	void **data;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, n_rules, n_rules_parsed, line_number;
-	int status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "bulk") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
-		return;
-	}
-
-	file_name = tokens[7];
-
-	if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
-		n_rules == 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-		return;
-	}
-
-	/* Memory allocation. */
-	match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
-	action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
-	data = calloc(n_rules, sizeof(void *));
-	if (match == NULL ||
-		action == NULL ||
-		data == NULL) {
-		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Load rule file */
-	n_rules_parsed = n_rules;
-	status = cli_rule_file_process(file_name,
-		1024,
-		match,
-		action,
-		&n_rules_parsed,
-		&line_number,
-		out,
-		out_size);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-	if (n_rules_parsed != n_rules) {
-		snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Rule bulk add */
-	status = softnic_pipeline_table_rule_add_bulk(softnic,
-		pipeline_name,
-		table_id,
-		match,
-		action,
-		data,
-		&n_rules);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Memory free */
-	free(data);
-	free(action);
-	free(match);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match <match>
- */
-static void
-cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	char *pipeline_name;
-	uint32_t table_id, n_tokens_parsed, t0;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete(softnic,
-		pipeline_name,
-		table_id,
-		&m);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match
- *       default
- */
-static void
-cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete_default(softnic,
-		pipeline_name,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read stats [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>
- *  add srtcm cir <cir> cbs <cbs> ebs <ebs>
- *  | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>
- */
-static void
-cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_meter_profile p;
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens < 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[8], "srtcm") == 0) {
-		if (n_tokens != 15) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_SRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[13], "ebs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
-			return;
-		}
-	} else if (strcmp(tokens[8], "trtcm") == 0) {
-		if (n_tokens != 17) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_TRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "pir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pir");
-			return;
-		}
-		if (strcmp(tokens[13], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[15], "pbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_add(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id,
-		&p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id>
- *  meter profile <meter_profile_id> delete
- */
-static void
-cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_delete(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read meter [clear]
- */
-static void
-cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> dscp <file_name>
- *
- * File <file_name>:
- *  - exactly 64 lines
- *  - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r
- */
-static int
-load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
-	const char *file_name,
-	uint32_t *line_number)
-{
-	FILE *f = NULL;
-	uint32_t dscp, l;
-
-	/* Check input arguments */
-	if (dscp_table == NULL ||
-		file_name == NULL ||
-		line_number == NULL) {
-		if (line_number)
-			*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Open input file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Read file */
-	for (dscp = 0, l = 1; ; l++) {
-		char line[64];
-		char *tokens[3];
-		enum rte_color color;
-		uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
-
-		if (fgets(line, sizeof(line), f) == NULL)
-			break;
-
-		if (is_comment(line))
-			continue;
-
-		if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		if (n_tokens == 0)
-			continue;
-
-		if (dscp >= RTE_DIM(dscp_table->entry) ||
-			n_tokens != RTE_DIM(tokens) ||
-			softnic_parser_read_uint32(&tc_id, tokens[0]) ||
-			tc_id >= RTE_TABLE_ACTION_TC_MAX ||
-			softnic_parser_read_uint32(&tc_queue_id, tokens[1]) ||
-			tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX ||
-			(strlen(tokens[2]) != 1)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		switch (tokens[2][0]) {
-		case 'g':
-		case 'G':
-			color = RTE_COLOR_GREEN;
-			break;
-
-		case 'y':
-		case 'Y':
-			color = RTE_COLOR_YELLOW;
-			break;
-
-		case 'r':
-		case 'R':
-			color = RTE_COLOR_RED;
-			break;
-
-		default:
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		dscp_table->entry[dscp].tc_id = tc_id;
-		dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
-		dscp_table->entry[dscp].color = color;
-		dscp++;
-	}
-
-	/* Close file */
-	fclose(f);
-	return 0;
-}
-
-static void
-cmd_pipeline_table_dscp(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_dscp_table dscp_table;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, line_number;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "dscp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
-		return;
-	}
-
-	file_name = tokens[5];
-
-	status = load_dscp_table(&dscp_table, file_name, &line_number);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		return;
-	}
-
-	status = softnic_pipeline_table_dscp_table_update(softnic,
-		pipeline_name,
-		table_id,
-		UINT64_MAX,
-		&dscp_table);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read ttl [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
 /**
  * thread <thread_id> pipeline <pipeline_name> enable
  */
@@ -4529,202 +307,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "port") == 0) {
-		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "table") == 0) {
-		cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "pipeline") == 0) {
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[2], "period") == 0)) {
-			cmd_pipeline(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 4 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[3], "match") == 0)) {
-			cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "table") == 0)) {
-			cmd_pipeline_port_in_table(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_in_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "enable") == 0)) {
-			cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "disable") == 0)) {
-			cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_out_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "stats") == 0)) {
-			cmd_pipeline_table_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_add_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-			}
-
-			cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "bulk") == 0)) {
-			cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "delete") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-				}
-
-			cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "stats") == 0)) {
-			cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "add") == 0)) {
-			cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "delete") == 0)) {
-			cmd_pipeline_table_meter_profile_delete(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "meter") == 0)) {
-			cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "dscp") == 0)) {
-			cmd_pipeline_table_dscp(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "ttl") == 0)) {
-			cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
@@ -4800,112 +382,3 @@ softnic_cli_script_process(struct pmd_internals *softnic,
 	free(msg_in);
 	return 0;
 }
-
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size)
-{
-	FILE *f = NULL;
-	char *line = NULL;
-	uint32_t rule_id, line_id;
-	int status = 0;
-
-	/* Check input arguments */
-	if (file_name == NULL ||
-		(strlen(file_name) == 0) ||
-		line_len_max == 0) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Memory allocation */
-	line = malloc(line_len_max + 1);
-	if (line == NULL) {
-		*line_number = 0;
-		return -ENOMEM;
-	}
-
-	/* Open file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		free(line);
-		return -EIO;
-	}
-
-	/* Read file */
-	for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
-		char *tokens[CMD_MAX_TOKENS];
-		uint32_t n_tokens, n_tokens_parsed, t0;
-
-		/* Read next line from file. */
-		if (fgets(line, line_len_max + 1, f) == NULL)
-			break;
-
-		/* Comment. */
-		if (is_comment(line))
-			continue;
-
-		/* Parse line. */
-		n_tokens = RTE_DIM(tokens);
-		status = softnic_parse_tokenize_string(line, tokens, &n_tokens);
-		if (status) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Empty line. */
-		if (n_tokens == 0)
-			continue;
-		t0 = 0;
-
-		/* Rule match. */
-		n_tokens_parsed = parse_match(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&m[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Rule action. */
-		n_tokens_parsed = parse_table_action(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&a[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Line completed. */
-		if (t0 < n_tokens) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Increment rule count */
-		rule_id++;
-	}
-
-	/* Close file */
-	fclose(f);
-
-	/* Memory free */
-	free(line);
-
-	*n_rules = rule_id;
-	*line_number = line_id;
-	return status;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (5 preceding siblings ...)
  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
  2022-08-04 16:58 ` [PATCH 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 08/21] net/softnic: remove the list of Ethernet devices
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (6 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

The list of Ethernet devices within this driver is redundant, as the
DPDK global list of Ethernet devices can be used instead.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  49 ---------
 .../net/softnic/rte_eth_softnic_internals.h   |  37 -------
 drivers/net/softnic/rte_eth_softnic_link.c    | 101 ------------------
 5 files changed, 191 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index f0cfc6dc17..0ffe26d671 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -11,7 +11,6 @@ sources = files(
         'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a940952c7a..b1f4edd629 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -160,7 +160,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	/* Firmware */
 	softnic_pipeline_disable_all(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
@@ -178,7 +177,6 @@ pmd_free(struct pmd_internals *p)
 
 	softnic_thread_free(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
@@ -256,7 +254,6 @@ pmd_init(struct pmd_params *params)
 	/* Resources */
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
-	softnic_link_init(p);
 	softnic_pipeline_init(p);
 
 	status = softnic_thread_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 2b00b65c6c..ec9ac133b9 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -102,50 +102,6 @@ cmd_mempool(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * link <link_name>
- *    dev <device_name> | port <port_id>
- */
-static void
-cmd_link(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_link_params p;
-	struct softnic_link *link;
-	char *name;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 4) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0) {
-		p.dev_name = tokens[3];
-	} else if (strcmp(tokens[2], "port") == 0) {
-		p.dev_name = NULL;
-
-		if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
-		return;
-	}
-
-	link = softnic_link_create(softnic, name, &p);
-	if (link == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * swq <swq_name>
  *  size <size>
@@ -309,11 +265,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "link") == 0) {
-		cmd_link(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "swq") == 0) {
 		cmd_swq(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d817883a39..a1c2309589 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -70,24 +70,6 @@ struct softnic_swq {
 
 TAILQ_HEAD(softnic_swq_list, softnic_swq);
 
-/**
- * LINK
- */
-struct softnic_link_params {
-	const char *dev_name;
-	uint16_t port_id; /**< Valid only when *dev_name* is NULL. */
-};
-
-struct softnic_link {
-	TAILQ_ENTRY(softnic_link) node;
-	char name[NAME_SIZE];
-	uint16_t port_id;
-	uint32_t n_rxq;
-	uint32_t n_txq;
-};
-
-TAILQ_HEAD(softnic_link_list, softnic_link);
-
 /**
  * Pipeline
  */
@@ -162,7 +144,6 @@ struct pmd_internals {
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
-	struct softnic_link_list link_list;
 	struct pipeline_list pipeline_list;
 	struct softnic_thread thread[RTE_MAX_LCORE];
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
@@ -223,24 +204,6 @@ softnic_swq_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_swq_params *params);
 
-/**
- * LINK
- */
-int
-softnic_link_init(struct pmd_internals *p);
-
-void
-softnic_link_free(struct pmd_internals *p);
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params);
-
 /**
  * Pipeline
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_link.c b/drivers/net/softnic/rte_eth_softnic_link.c
deleted file mode 100644
index 21a64069f6..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_link.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_ethdev.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_link_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->link_list);
-
-	return 0;
-}
-
-void
-softnic_link_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_link *link;
-
-		link = TAILQ_FIRST(&p->link_list);
-		if (link == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->link_list, link, node);
-		free(link);
-	}
-}
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_link *link;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(link, &p->link_list, node)
-		if (strcmp(link->name, name) == 0)
-			return link;
-
-	return NULL;
-}
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params)
-{
-	struct rte_eth_dev_info port_info;
-	struct softnic_link *link;
-	uint16_t port_id;
-	int ret;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_link_find(p, name) ||
-		params == NULL)
-		return NULL;
-
-	port_id = params->port_id;
-	if (params->dev_name) {
-		int status;
-
-		status = rte_eth_dev_get_port_by_name(params->dev_name,
-			&port_id);
-
-		if (status)
-			return NULL;
-	} else {
-		if (!rte_eth_dev_is_valid_port(port_id))
-			return NULL;
-	}
-
-	ret = rte_eth_dev_info_get(port_id, &port_info);
-	if (ret != 0)
-		return NULL;
-
-	/* Node allocation */
-	link = calloc(1, sizeof(struct softnic_link));
-	if (link == NULL)
-		return NULL;
-
-	/* Node fill in */
-	strlcpy(link->name, name, sizeof(link->name));
-	link->port_id = port_id;
-	link->n_rxq = port_info.nb_rx_queues;
-	link->n_txq = port_info.nb_tx_queues;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->link_list, link, node);
-
-	return link;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 09/21] net/softnic: remove unused text parsing functions
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (7 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Remove the text parsing functions that are not used.

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/parser.c              | 523 ----------------------
 drivers/net/softnic/parser.h              |  68 ---
 drivers/net/softnic/rte_eth_softnic_cli.c |  56 ++-
 4 files changed, 48 insertions(+), 600 deletions(-)
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 0ffe26d671..5dfbd16c77 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -8,7 +8,6 @@ endif
 headers = files('rte_eth_softnic.h')
 sources = files(
         'conn.c',
-        'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_mempool.c',
diff --git a/drivers/net/softnic/parser.c b/drivers/net/softnic/parser.c
deleted file mode 100644
index ebcb10268a..0000000000
--- a/drivers/net/softnic/parser.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 Intel Corporation.
- * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
- * All rights reserved.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-#include <rte_errno.h>
-
-#include "parser.h"
-
-static uint32_t
-get_hex_val(char c)
-{
-	switch (c) {
-	case '0': case '1': case '2': case '3': case '4': case '5':
-	case '6': case '7': case '8': case '9':
-		return c - '0';
-	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-		return c - 'A' + 10;
-	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-		return c - 'a' + 10;
-	default:
-		return 0;
-	}
-}
-
-int
-softnic_parser_read_arg_bool(const char *p)
-{
-	p = skip_white_spaces(p);
-	int result = -EINVAL;
-
-	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
-		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
-		p += 3;
-		result = 1;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'n')) ||
-		((p[0] == 'O') && (p[1] == 'N'))) {
-		p += 2;
-		result = 1;
-	}
-
-	if (((p[0] == 'n') && (p[1] == 'o')) ||
-		((p[0] == 'N') && (p[1] == 'O'))) {
-		p += 2;
-		result = 0;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
-		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
-		p += 3;
-		result = 0;
-	}
-
-	p = skip_white_spaces(p);
-
-	if (p[0] != '\0')
-		return -EINVAL;
-
-	return result;
-}
-
-int
-softnic_parser_read_int32(int32_t *value, const char *p)
-{
-	char *next;
-	int32_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtol(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtoul(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	p = next;
-	switch (*p) {
-	case 'T':
-		val *= 1024ULL;
-		/* fall through */
-	case 'G':
-		val *= 1024ULL;
-		/* fall through */
-	case 'M':
-		val *= 1024ULL;
-		/* fall through */
-	case 'k':
-	case 'K':
-		val *= 1024ULL;
-		p++;
-		break;
-	}
-
-	p = skip_white_spaces(p);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-
-	val = strtoul(p, &next, 16);
-	if (p == next)
-		return -EINVAL;
-
-	p = skip_white_spaces(next);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
-{
-	uint32_t i;
-
-	if (string == NULL ||
-		tokens == NULL ||
-		(*n_tokens < 1))
-		return -EINVAL;
-
-	for (i = 0; i < *n_tokens; i++) {
-		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
-		if (tokens[i] == NULL)
-			break;
-	}
-
-	if (i == *n_tokens &&
-		strtok_r(string, PARSE_DELIMITER, &string) != NULL)
-		return -E2BIG;
-
-	*n_tokens = i;
-	return 0;
-}
-
-int
-softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
-{
-	char *c;
-	uint32_t len, i;
-
-	/* Check input parameters */
-	if (src == NULL ||
-		dst == NULL ||
-		size == NULL ||
-		(*size == 0))
-		return -1;
-
-	len = strlen(src);
-	if (((len & 3) != 0) ||
-		(len > (*size) * 2))
-		return -1;
-	*size = len / 2;
-
-	for (c = src; *c != 0; c++) {
-		if ((((*c) >= '0') && ((*c) <= '9')) ||
-			(((*c) >= 'A') && ((*c) <= 'F')) ||
-			(((*c) >= 'a') && ((*c) <= 'f')))
-			continue;
-
-		return -1;
-	}
-
-	/* Convert chars to bytes */
-	for (i = 0; i < *size; i++)
-		dst[i] = get_hex_val(src[2 * i]) * 16 +
-			get_hex_val(src[2 * i + 1]);
-
-	return 0;
-}
-
-int
-softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
-{
-	uint32_t n_max_labels = *n_labels, count = 0;
-
-	/* Check for void list of labels */
-	if (strcmp(string, "<void>") == 0) {
-		*n_labels = 0;
-		return 0;
-	}
-
-	/* At least one label should be present */
-	for ( ; (*string != '\0'); ) {
-		char *next;
-		int value;
-
-		if (count >= n_max_labels)
-			return -1;
-
-		if (count > 0) {
-			if (string[0] != ':')
-				return -1;
-
-			string++;
-		}
-
-		value = strtol(string, &next, 10);
-		if (next == string)
-			return -1;
-		string = next;
-
-		labels[count++] = (uint32_t)value;
-	}
-
-	*n_labels = count;
-	return 0;
-}
-
-static struct rte_ether_addr *
-my_ether_aton(const char *a)
-{
-	int i;
-	char *end;
-	unsigned long o[RTE_ETHER_ADDR_LEN];
-	static struct rte_ether_addr ether_addr;
-
-	i = 0;
-	do {
-		errno = 0;
-		o[i] = strtoul(a, &end, 16);
-		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
-			return NULL;
-		a = end + 1;
-	} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
-
-	/* Junk at the end of line */
-	if (end[0] != 0)
-		return NULL;
-
-	/* Support the format XX:XX:XX:XX:XX:XX */
-	if (i == RTE_ETHER_ADDR_LEN) {
-		while (i-- != 0) {
-			if (o[i] > UINT8_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i] = (uint8_t)o[i];
-		}
-	/* Support the format XXXX:XXXX:XXXX */
-	} else if (i == RTE_ETHER_ADDR_LEN / 2) {
-		while (i-- != 0) {
-			if (o[i] > UINT16_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
-			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
-		}
-	/* unknown format */
-	} else
-		return NULL;
-
-	return (struct rte_ether_addr *)&ether_addr;
-}
-
-int
-softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
-{
-	if (strlen(token) >= INET_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET, token, ipv4) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
-{
-	if (strlen(token) >= INET6_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET6, token, ipv6) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
-{
-	struct rte_ether_addr *tmp;
-
-	tmp = my_ether_aton(token);
-	if (tmp == NULL)
-		return -1;
-
-	memcpy(addr, tmp, sizeof(struct rte_ether_addr));
-	return 0;
-}
-
-int
-softnic_parse_cpu_core(const char *entry,
-	struct softnic_cpu_core_params *p)
-{
-	size_t num_len;
-	char num[8];
-
-	uint32_t s = 0, c = 0, h = 0, val;
-	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
-	const char *next = skip_white_spaces(entry);
-	char type;
-
-	if (p == NULL)
-		return -EINVAL;
-
-	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
-	while (*next != '\0') {
-		/* If everything parsed nothing should left */
-		if (s_parsed && c_parsed && h_parsed)
-			return -EINVAL;
-
-		type = *next;
-		switch (type) {
-		case 's':
-		case 'S':
-			if (s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-			s_parsed = 1;
-			next++;
-			break;
-		case 'c':
-		case 'C':
-			if (c_parsed || h_parsed)
-				return -EINVAL;
-			c_parsed = 1;
-			next++;
-			break;
-		case 'h':
-		case 'H':
-			if (h_parsed)
-				return -EINVAL;
-			h_parsed = 1;
-			next++;
-			break;
-		default:
-			/* If it start from digit it must be only core id. */
-			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-
-			type = 'C';
-		}
-
-		for (num_len = 0; *next != '\0'; next++, num_len++) {
-			if (num_len == RTE_DIM(num))
-				return -EINVAL;
-
-			if (!isdigit(*next))
-				break;
-
-			num[num_len] = *next;
-		}
-
-		if (num_len == 0 && type != 'h' && type != 'H')
-			return -EINVAL;
-
-		if (num_len != 0 && (type == 'h' || type == 'H'))
-			return -EINVAL;
-
-		num[num_len] = '\0';
-		val = strtol(num, NULL, 10);
-
-		h = 0;
-		switch (type) {
-		case 's':
-		case 'S':
-			s = val;
-			break;
-		case 'c':
-		case 'C':
-			c = val;
-			break;
-		case 'h':
-		case 'H':
-			h = 1;
-			break;
-		}
-	}
-
-	p->socket_id = s;
-	p->core_id = c;
-	p->thread_id = h;
-	return 0;
-}
diff --git a/drivers/net/softnic/parser.h b/drivers/net/softnic/parser.h
deleted file mode 100644
index 6f408b2485..0000000000
--- a/drivers/net/softnic/parser.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
- */
-
-#ifndef __INCLUDE_SOFTNIC_PARSER_H__
-#define __INCLUDE_SOFTNIC_PARSER_H__
-
-#include <stdint.h>
-
-#include <rte_ip.h>
-#include <rte_ether.h>
-
-#define PARSE_DELIMITER				" \f\n\r\t\v"
-
-#define skip_white_spaces(pos)			\
-({						\
-	__typeof__(pos) _p = (pos);		\
-	for ( ; isspace(*_p); _p++)		\
-		;				\
-	_p;					\
-})
-
-static inline size_t
-skip_digits(const char *src)
-{
-	size_t i;
-
-	for (i = 0; isdigit(src[i]); i++)
-		;
-
-	return i;
-}
-
-int softnic_parser_read_arg_bool(const char *p);
-
-int softnic_parser_read_int32(int32_t *value, const char *p);
-
-int softnic_parser_read_uint64(uint64_t *value, const char *p);
-int softnic_parser_read_uint32(uint32_t *value, const char *p);
-int softnic_parser_read_uint16(uint16_t *value, const char *p);
-int softnic_parser_read_uint8(uint8_t *value, const char *p);
-
-int softnic_parser_read_uint64_hex(uint64_t *value, const char *p);
-int softnic_parser_read_uint32_hex(uint32_t *value, const char *p);
-int softnic_parser_read_uint16_hex(uint16_t *value, const char *p);
-int softnic_parser_read_uint8_hex(uint8_t *value, const char *p);
-
-int softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
-
-int softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4);
-int softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6);
-int softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr);
-int softnic_parse_mpls_labels(char *string,
-		uint32_t *labels, uint32_t *n_labels);
-
-struct softnic_cpu_core_params {
-	uint32_t socket_id;
-	uint32_t core_id;
-	uint32_t thread_id;
-};
-
-int softnic_parse_cpu_core(const char *entry,
-		struct softnic_cpu_core_params *p);
-
-int softnic_parse_tokenize_string(char *string,
-		char *tokens[], uint32_t *n_tokens);
-
-#endif
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index ec9ac133b9..c87a481355 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -12,7 +12,6 @@
 #include <rte_string_fns.h>
 
 #include "rte_eth_softnic_internals.h"
-#include "parser.h"
 
 #ifndef CMD_MAX_TOKENS
 #define CMD_MAX_TOKENS     256
@@ -30,6 +29,47 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint32_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoul(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+static int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+	uint32_t i;
+
+	if ((string == NULL) ||
+		(tokens == NULL) ||
+		(*n_tokens < 1))
+		return -EINVAL;
+
+	for (i = 0; i < *n_tokens; i++) {
+		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+		if (tokens[i] == NULL)
+			break;
+	}
+
+	if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string))
+		return -E2BIG;
+
+	*n_tokens = i;
+	return 0;
+}
+
 static int
 is_comment(char *in)
 {
@@ -70,7 +110,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
 		return;
 	}
@@ -80,7 +120,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
+	if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
 		return;
 	}
@@ -90,7 +130,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
+	if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
 		return;
 	}
@@ -129,7 +169,7 @@ cmd_swq(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "size");
 		return;
 	}
@@ -161,7 +201,7 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -210,7 +250,7 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -251,7 +291,7 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 	if (is_comment(in))
 		return;
 
-	status = softnic_parse_tokenize_string(in, tokens, &n_tokens);
+	status = parse_tokenize_string(in, tokens, &n_tokens);
 	if (status) {
 		snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
 		return;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 10/21] net/softnic: add pipeline code generation CLI command
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (8 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for pipeline code generation.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 57 ++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index c87a481355..f42db41996 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -182,7 +182,55 @@ cmd_swq(struct pmd_internals *softnic,
 }
 
 /**
- * thread <thread_id> pipeline <pipeline_name> enable
+ * pipeline codegen <spec_file> <code_file>
+ */
+static void
+cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	FILE *spec_file = NULL;
+	FILE *code_file = NULL;
+	uint32_t err_line;
+	const char *err_msg;
+	int status;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	spec_file = fopen(tokens[2], "r");
+	if (!spec_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+		return;
+	}
+
+	code_file = fopen(tokens[3], "w");
+	if (!code_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+		return;
+	}
+
+	status = rte_swx_pipeline_codegen(spec_file,
+					  code_file,
+					  &err_line,
+					  &err_msg);
+
+	fclose(spec_file);
+	fclose(code_file);
+
+	if (status) {
+		snprintf(out, out_size, "Error %d at line %u: %s\n.",
+			status, err_line, err_msg);
+		return;
+	}
+}
+
+/**
+ * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
 static void
 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
@@ -310,6 +358,13 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
+	if (!strcmp(tokens[0], "pipeline")) {
+		if ((n_tokens >= 2) && !strcmp(tokens[1], "codegen")) {
+			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+	}
+
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 11/21] net/softnic: add pipeline library build CLI command
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (9 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 12/21] net/softnic: add pipeline " Cristian Dumitrescu
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for pipeline shared library build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 143 ++++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index f42db41996..9dc26d9f06 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -6,6 +6,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_cycles.h>
@@ -17,6 +18,10 @@
 #define CMD_MAX_TOKENS     256
 #endif
 
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
 #define MSG_OUT_OF_MEMORY   "Not enough memory.\n"
 #define MSG_CMD_UNKNOWN     "Unknown command \"%s\".\n"
 #define MSG_CMD_UNIMPLEM    "Command \"%s\" not implemented.\n"
@@ -229,6 +234,139 @@ cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
 	}
 }
 
+/**
+ * pipeline libbuild <code_file> <lib_file>
+ */
+static void
+cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+	char *install_dir, *cwd = NULL, *buffer = NULL;
+	size_t length;
+	int status = 0;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		goto free;
+	}
+
+	install_dir = getenv("RTE_INSTALL_DIR");
+	if (!install_dir) {
+		cwd = malloc(MAX_LINE_SIZE);
+		if (!cwd) {
+			snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+			goto free;
+		}
+
+		install_dir = getcwd(cwd, MAX_LINE_SIZE);
+		if (!install_dir) {
+			snprintf(out, out_size, "Error: Path too long.\n");
+			goto free;
+		}
+	}
+
+	snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	code_file = tokens[2];
+	length = strnlen(code_file, MAX_LINE_SIZE);
+	if ((length < 3) ||
+	    (code_file[length - 2] != '.') ||
+	    (code_file[length - 1] != 'c')) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+		goto free;
+	}
+
+	lib_file = tokens[3];
+	length = strnlen(lib_file, MAX_LINE_SIZE);
+	if ((length < 4) ||
+	    (lib_file[length - 3] != '.') ||
+	    (lib_file[length - 2] != 's') ||
+	    (lib_file[length - 1] != 'o')) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+		goto free;
+	}
+
+	obj_file = malloc(length);
+	log_file = malloc(length + 2);
+	if (!obj_file || !log_file) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		goto free;
+	}
+
+	memcpy(obj_file, lib_file, length - 2);
+	obj_file[length - 2] = 'o';
+	obj_file[length - 1] = 0;
+
+	memcpy(log_file, lib_file, length - 2);
+	log_file[length - 2] = 'l';
+	log_file[length - 1] = 'o';
+	log_file[length] = 'g';
+	log_file[length + 1] = 0;
+
+	buffer = malloc(MAX_LINE_SIZE);
+	if (!buffer) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		return;
+	}
+
+	snprintf(buffer,
+		 MAX_LINE_SIZE,
+		 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+		 "-I %s/lib/pipeline "
+		 "-I %s/lib/eal/include "
+		 "-I %s/lib/eal/x86/include "
+		 "-I %s/lib/eal/include/generic "
+		 "-I %s/lib/meter "
+		 "-I %s/lib/port "
+		 "-I %s/lib/table "
+		 "-I %s/lib/pipeline "
+		 "-I %s/config "
+		 "-I %s/build "
+		 "-I %s/lib/eal/linux/include "
+		 ">%s 2>&1 "
+		 "&& "
+		 "gcc -shared %s -o %s "
+		 ">>%s 2>&1",
+		 obj_file,
+		 code_file,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 log_file,
+		 obj_file,
+		 lib_file,
+		 log_file);
+
+	status = system(buffer);
+	if (status) {
+		snprintf(out,
+			 out_size,
+			 "Library build failed, see file \"%s\" for details.\n",
+			 log_file);
+		goto free;
+	}
+
+free:
+	free(cwd);
+	free(obj_file);
+	free(log_file);
+	free(buffer);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -363,6 +501,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[1], "libbuild")) {
+			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 12/21] net/softnic: add pipeline build CLI command
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (10 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for pipeline build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 66 +++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 9dc26d9f06..a814257229 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -367,6 +367,67 @@ cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
 	free(buffer);
 }
 
+/**
+ * pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>
+ */
+static void
+cmd_softnic_pipeline_build(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p = NULL;
+	char *pipeline_name, *lib_file_name, *iospec_file_name;
+	uint32_t numa_node = 0;
+
+	/* Parsing. */
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+
+	if (strcmp(tokens[2], "build")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
+		return;
+	}
+
+	if (strcmp(tokens[3], "lib")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
+		return;
+	}
+
+	lib_file_name = tokens[4];
+
+	if (strcmp(tokens[5], "io")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
+		return;
+	}
+
+	iospec_file_name = tokens[6];
+
+	if (strcmp(tokens[7], "numa")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
+		return;
+	}
+
+	if (parser_read_uint32(&numa_node, tokens[8])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+		return;
+	}
+
+	/* Pipeline create. */
+	p = softnic_pipeline_create(softnic,
+				    pipeline_name,
+				    lib_file_name,
+				    iospec_file_name,
+				    (int)numa_node);
+	if (!p)
+		snprintf(out, out_size, "Pipeline creation failed.\n");
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -506,6 +567,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "build")) {
+			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 13/21] net/softnic: add pipeline table CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (11 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 12/21] net/softnic: add pipeline " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI commands for pipeline table entry management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 376 ++++++++++++++++++++++
 1 file changed, 376 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index a814257229..dd219e229d 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -428,6 +428,354 @@ cmd_softnic_pipeline_build(struct pmd_internals *softnic,
 		snprintf(out, out_size, "Pipeline creation failed.\n");
 }
 
+static void
+table_entry_free(struct rte_swx_table_entry *entry)
+{
+	if (!entry)
+		return;
+
+	free(entry->key);
+	free(entry->key_mask);
+	free(entry->action_data);
+	free(entry);
+}
+
+static int
+pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
+			   const char *table_name,
+			   FILE *file,
+			   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_add(p,
+							      table_name,
+							      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> add <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_add(p->ctl,
+					    table_name,
+					    file,
+					    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p,
+			      const char *table_name,
+			      FILE *file,
+			      uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_delete(p,
+								 table_name,
+								 entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_delete(p->ctl,
+					       table_name,
+					       file,
+					       &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				 const char *table_name,
+				 FILE *file,
+				 uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_default_entry_add(p,
+								      table_name,
+								      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_default_entry_add(p->ctl,
+						  table_name,
+						  file,
+						  &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -572,6 +920,34 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 5) &&
+			!strcmp(tokens[2], "table") &&
+			!strcmp(tokens[4], "add")) {
+			cmd_softnic_pipeline_table_add(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 5) &&
+			!strcmp(tokens[2], "table") &&
+			!strcmp(tokens[4], "delete")) {
+			cmd_softnic_pipeline_table_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 5) &&
+			!strcmp(tokens[2], "table") &&
+			!strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_table_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 5) && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 14/21] net/softnic: add pipeline selector table CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (12 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI commands for selector tables group and member management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 517 ++++++++++++++++++++++
 1 file changed, 517 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index dd219e229d..dd094bfb65 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -776,6 +776,477 @@ cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
 		fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> selector <selector_name> group add
+ */
+static void
+cmd_softnic_pipeline_selector_group_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
+		selector_name,
+		&group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+	else
+		snprintf(out, out_size, "Group ID: %u\n", group_id);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group delete <group_id>
+ */
+static void
+cmd_softnic_pipeline_selector_group_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 7) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete");
+		return;
+	}
+
+	if (parser_read_uint32(&group_id, tokens[6]) != 0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
+		selector_name,
+		group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+}
+
+#define GROUP_MEMBER_INFO_TOKENS_MAX 6
+
+static int
+token_is_comment(const char *token)
+{
+	if ((token[0] == '#') ||
+	    (token[0] == ';') ||
+	    ((token[0] == '/') && (token[1] == '/')))
+		return 1; /* TRUE. */
+
+	return 0; /* FALSE. */
+}
+
+static int
+pipeline_selector_group_member_read(const char *string,
+				    uint32_t *group_id,
+				    uint32_t *member_id,
+				    uint32_t *weight,
+				    int *is_blank_or_comment)
+{
+	char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens;
+	char *s0 = NULL, *s;
+	uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0;
+	int blank_or_comment = 0;
+
+	/* Check input arguments. */
+	if (!string || !string[0])
+		goto error;
+
+	/* Memory allocation. */
+	s0 = strdup(string);
+	if (!s0)
+		goto error;
+
+	/* Parse the string into tokens. */
+	for (s = s0; ; ) {
+		char *token;
+
+		token = strtok_r(s, " \f\n\r\t\v", &s);
+		if (!token || token_is_comment(token))
+			break;
+
+		if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX)
+			goto error;
+
+		token_array[n_tokens] = token;
+		n_tokens++;
+	}
+
+	if (!n_tokens) {
+		blank_or_comment = 1;
+		goto error;
+	}
+
+	tokens = token_array;
+
+	if (n_tokens < 4 ||
+		strcmp(tokens[0], "group") ||
+		strcmp(tokens[2], "member"))
+		goto error;
+
+	/*
+	 * Group ID.
+	 */
+	if (parser_read_uint32(&group_id_val, tokens[1]) != 0)
+		goto error;
+	*group_id = group_id_val;
+
+	/*
+	 * Member ID.
+	 */
+	if (parser_read_uint32(&member_id_val, tokens[3]) != 0)
+		goto error;
+	*member_id = member_id_val;
+
+	tokens += 4;
+	n_tokens -= 4;
+
+	/*
+	 * Weight.
+	 */
+	if (n_tokens && !strcmp(tokens[0], "weight")) {
+		if (n_tokens < 2)
+			goto error;
+
+		if (parser_read_uint32(&weight_val, tokens[1]) != 0)
+			goto error;
+		*weight = weight_val;
+
+		tokens += 2;
+		n_tokens -= 2;
+	}
+
+	if (n_tokens)
+		goto error;
+
+	free(s0);
+	return 0;
+
+error:
+	free(s0);
+	if (is_blank_or_comment)
+		*is_blank_or_comment = blank_or_comment;
+	return -EINVAL;
+}
+
+static int
+pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p,
+				    const char *selector_name,
+				    FILE *file,
+				    uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_add(p,
+			selector_name,
+			group_id,
+			member_id,
+			weight);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member add <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_add(p->ctl,
+		selector_name,
+		file,
+		&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p,
+				       const char *selector_name,
+				       FILE *file,
+				       uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_delete(p,
+			selector_name,
+			group_id,
+			member_id);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_delete(p->ctl,
+							selector_name,
+							file,
+							&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -948,6 +1419,52 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 6) &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_selector_group_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 6) &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_selector_group_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 7) &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "add")) {
+			cmd_softnic_pipeline_selector_group_member_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 7) &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "delete")) {
+			cmd_softnic_pipeline_selector_group_member_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 5) &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_selector_show(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 15/21] net/softnic: add pipeline learner table CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (13 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for managing the learner table default entry.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 106 ++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index dd094bfb65..5710ea6a73 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1247,6 +1247,104 @@ cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
 		fclose(file);
 }
 
+static int
+pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				   const char *learner_name,
+				   FILE *file,
+				   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_learner_default_entry_read(p,
+									learner_name,
+									line,
+									&is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_default_entry_add(p,
+									learner_name,
+									entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> learner <learner_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *learner_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	learner_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_learner_default_entry_add(p->ctl,
+						    learner_name,
+						    file,
+						    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1465,6 +1563,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 5) &&
+			!strcmp(tokens[2], "learner") &&
+			!strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_learner_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 16/21] net/softnic: add pipeline commit and abort CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (14 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI commands for pipeline table update commit and abort.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 70 +++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 5710ea6a73..064a1906d9 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1345,6 +1345,66 @@ cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
 	fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> commit
+ */
+static void
+cmd_softnic_pipeline_commit(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
+	if (status)
+		snprintf(out, out_size, "Commit failed. "
+			"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
+}
+
+/**
+ * pipeline <pipeline_name> abort
+ */
+static void
+cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	rte_swx_ctl_pipeline_abort(p->ctl);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1571,6 +1631,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "commit")) {
+			cmd_softnic_pipeline_commit(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "abort")) {
+			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 17/21] net/softnic: add the pipeline register read/write CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (15 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI commands for pipeline registers read and write operations.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 127 ++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 064a1906d9..b419c67cb8 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -34,6 +34,22 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint64(uint64_t *value, char *p)
+{
+	uint64_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoull(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
 static int
 parser_read_uint32(uint32_t *value, char *p)
 {
@@ -1405,6 +1421,107 @@ cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
 	rte_swx_ctl_pipeline_abort(p->ctl);
 }
 
+/**
+ * pipeline <pipeline_name> regrd <register_array_name> <index>
+ */
+static void
+cmd_softnic_pipeline_regrd(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 5) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regrd")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+
+	snprintf(out, out_size, "0x%" PRIx64 "\n", value);
+}
+
+/**
+ * pipeline <pipeline_name> regwr <register_array_name> <index> <value>
+ */
+static void
+cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regwr")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	if (parser_read_uint64(&value, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "value");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1641,6 +1758,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "regrd")) {
+			cmd_softnic_pipeline_regrd(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "regwr")) {
+			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 18/21] net/softnic: add the pipeline meter CLI commands
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (16 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI commands for pipeline meter configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 423 ++++++++++++++++++++++
 1 file changed, 423 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index b419c67cb8..449e750e41 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1522,6 +1522,395 @@ cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> add cir <cir> pir <pir> cbs <cbs> pbs <pbs>
+ */
+static void
+cmd_softnic_pipeline_meter_profile_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_meter_trtcm_params params;
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 14) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+		return;
+	}
+
+	if (strcmp(tokens[6], "cir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cir, tokens[7])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cir");
+		return;
+	}
+
+	if (strcmp(tokens[8], "pir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pir, tokens[9])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pir");
+		return;
+	}
+
+	if (strcmp(tokens[10], "cbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cbs, tokens[11])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
+		return;
+	}
+
+	if (strcmp(tokens[12], "pbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pbs, tokens[13])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_add(p->p, profile_name, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> delete
+ */
+static void
+cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> reset
+ */
+static void
+cmd_softnic_pipeline_meter_reset(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "reset")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
+		return;
+	}
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_reset(p->p, name, idx0);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> set
+ * 	profile <profile_name>
+ */
+static void
+cmd_softnic_pipeline_meter_set(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name, *profile_name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "set")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
+		return;
+	}
+
+	if (strcmp(tokens[9], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[10];
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> stats
+ */
+static void
+cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_meter_stats stats;
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || (idx1 < idx0)) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	/* Table header. */
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
+		 "METER #",
+		 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
+		 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	/* Table rows. */
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
+		if (status) {
+			snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
+			out_size -= strlen(out);
+			out += strlen(out);
+			return;
+		}
+
+		snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
+			 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
+			 idx0,
+			 stats.n_pkts[RTE_COLOR_GREEN],
+			 stats.n_pkts[RTE_COLOR_YELLOW],
+			 stats.n_pkts[RTE_COLOR_RED],
+			 stats.n_bytes[RTE_COLOR_GREEN],
+			 stats.n_bytes[RTE_COLOR_YELLOW],
+			 stats.n_bytes[RTE_COLOR_RED]);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1768,6 +2157,40 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 6) &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_meter_profile_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 6) &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_meter_profile_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 9) && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "reset")) {
+			cmd_softnic_pipeline_meter_reset(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 9) && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "set")) {
+			cmd_softnic_pipeline_meter_set(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if ((n_tokens >= 9) && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "stats")) {
+			cmd_softnic_pipeline_meter_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 19/21] net/softnic: add pipeline statistics CLI command
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (17 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for pipeline statistics counters query.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 204 ++++++++++++++++++++++
 1 file changed, 204 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 449e750e41..a391ce1139 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1911,6 +1911,206 @@ cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> stats
+ */
+static void
+cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_pipeline_info info;
+	struct pipeline *p;
+	uint32_t i;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_info_get(p->p, &info);
+	if (status) {
+		snprintf(out, out_size, "Pipeline info get error.");
+		return;
+	}
+
+	snprintf(out, out_size, "Input ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_in; i++) {
+		struct rte_swx_port_in_stats stats;
+
+		rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
+
+		snprintf(out, out_size, "\tPort %u:"
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" empty %" PRIu64 "\n",
+			i, stats.n_pkts, stats.n_bytes, stats.n_empty);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nOutput ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_out; i++) {
+		struct rte_swx_port_out_stats stats;
+
+		rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
+
+		if (i != info.n_ports_out - 1)
+			snprintf(out, out_size, "\tPort %u:", i);
+		else
+			snprintf(out, out_size, "\tDROP:");
+
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out,
+			out_size,
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" clone %" PRIu64
+			" clonerr %" PRIu64 "\n",
+			stats.n_pkts,
+			stats.n_bytes,
+			stats.n_pkts_clone,
+			stats.n_pkts_clone_err);
+
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nTables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_tables; i++) {
+		struct rte_swx_ctl_table_info table_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_table_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+		if (status) {
+			snprintf(out, out_size, "Table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tTable %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n",
+			table_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+
+	snprintf(out, out_size, "\nLearner tables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_learners; i++) {
+		struct rte_swx_ctl_learner_info learner_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_learner_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
+		if (status) {
+			snprintf(out, out_size, "Learner table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Learner table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tLearner table %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n"
+			"\t\tLearn OK (packets): %" PRIu64 "\n"
+			"\t\tLearn error (packets): %" PRIu64 "\n"
+			"\t\tRearm (packets): %" PRIu64 "\n"
+			"\t\tForget (packets): %" PRIu64 "\n",
+			learner_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss,
+			stats.n_pkts_learn_ok,
+			stats.n_pkts_learn_err,
+			stats.n_pkts_rearm,
+			stats.n_pkts_forget);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2191,6 +2391,10 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			return;
 		}
 
+		if ((n_tokens >= 3) && !strcmp(tokens[2], "stats")) {
+			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 20/21] net/softnic: add pipeline mirroring CLI command
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (18 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-04 16:58 ` [PATCH 21/21] net/softnic: update the default device program Cristian Dumitrescu
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Add CLI command for pipeline mirroring configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 96 +++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index a391ce1139..61221b2f2e 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -2111,6 +2111,94 @@ cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow
+ * 	truncate <truncation_length>
+ */
+static void
+cmd_softnic_pipeline_mirror_session(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_pipeline_mirroring_session_params params;
+	struct pipeline *p;
+	uint32_t session_id = 0;
+	int status;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	if (strcmp(tokens[0], "pipeline")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "mirror")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
+		return;
+	}
+
+	if (strcmp(tokens[3], "session")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session");
+		return;
+	}
+
+	if (parser_read_uint32(&session_id, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "session_id");
+		return;
+	}
+
+	if (strcmp(tokens[5], "port")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+		return;
+	}
+
+	if (parser_read_uint32(&params.port_id, tokens[6])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+		return;
+	}
+
+	if (strcmp(tokens[7], "clone")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone");
+		return;
+	}
+
+	if (!strcmp(tokens[8], "fast"))
+		params.fast_clone = 1;
+	else if (!strcmp(tokens[8], "slow"))
+		params.fast_clone = 0;
+	else {
+		snprintf(out, out_size, MSG_ARG_INVALID, "clone");
+		return;
+	}
+
+	if (strcmp(tokens[9], "truncate")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate");
+		return;
+	}
+
+	if (parser_read_uint32(&params.truncation_length, tokens[10])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed!\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2395,6 +2483,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if ((n_tokens >= 4) &&
+			!strcmp(tokens[2], "mirror") &&
+			!strcmp(tokens[3], "session")) {
+			cmd_softnic_pipeline_mirror_session(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH 21/21] net/softnic: update the default device program
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (19 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
@ 2022-08-04 16:58 ` Cristian Dumitrescu
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
  22 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-04 16:58 UTC (permalink / raw)
  To: dev; +Cc: jasvinder.singh, yogesh.jangra

Update the default device program.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/firmware.cli   | 51 ++++++++++++++++++++----------
 drivers/net/softnic/firmware.spec  | 19 +++++++++++
 drivers/net/softnic/firmware_rx.io | 30 ++++++++++++++++++
 drivers/net/softnic/firmware_tx.io | 30 ++++++++++++++++++
 4 files changed, 114 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io

diff --git a/drivers/net/softnic/firmware.cli b/drivers/net/softnic/firmware.cli
index 300cf6e33f..8f1ff3bbb7 100644
--- a/drivers/net/softnic/firmware.cli
+++ b/drivers/net/softnic/firmware.cli
@@ -1,21 +1,40 @@
 ; SPDX-License-Identifier: BSD-3-Clause
-; Copyright(c) 2018 Intel Corporation
+; Copyright(c) 2022 Intel Corporation
 
-link LINK dev 0000:02:00.0
+# Example command line for the DPDK test-pmd application. Out of the 3 application cores (see the
+# -c <core_mask> argument), core 0 is running the master thread doing configuration and CLI, core 1
+# is running the forwarding thread, and core 2 is setup as service core (see the -s <core_mask>
+# argument) for the purpose of running the Soft NIC device:
+#
+#	./build/app/dpdk-testpmd -c 7 -s 4 --vdev 'net_softnic0,firmware=./drivers/net/softnic/firmware.cli,cpu_id=0,conn_port=8086' -- -i
+#
+# Commands from within the DPDK test-pmd application:
+#
+# 	testpmd> set portlist <softnic_port_id>
+#	testpmd> show config fwd
+#	testpmd> start
+#
+# To setup the CLI prompt to the Soft NIC device, the DPDK test-pmd application needs to be modified
+# to call the rte_pmd_softnic_manage() function. Once the Soft NIC device is started, the command to
+# get the CLI prompt is:
+#
+#	telnet 0.0.0.0 8086
 
-pipeline RX period 10 offset_port_id 0
-pipeline RX port in bsz 32 link LINK rxq 0
-pipeline RX port out bsz 32 swq RXQ0
-pipeline RX table match stub
-pipeline RX port in 0 table 0
-pipeline RX table 0 rule add match default action fwd port 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./drivers/net/softnic/firmware.spec /tmp/firmware.c
+pipeline libbuild /tmp/firmware.c /tmp/firmware.so
 
-pipeline TX period 10 offset_port_id 0
-pipeline TX port in bsz 32 swq TXQ0
-pipeline TX port out bsz 32 link LINK txq 0
-pipeline TX table match stub
-pipeline TX port in 0 table 0
-pipeline TX table 0 rule add match default action fwd port 0
+;
+; List of pipelines.
+;
+pipeline RX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_rx.io numa 0
+pipeline TX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_tx.io numa 0
 
-thread 1 pipeline RX enable
-thread 1 pipeline TX enable
+;
+; Pipelines-to-threads mapping. For the Soft NIC devices, the pipelines can be mapped to any of the
+; application service cores (see the -s <core_mask> argument):
+;
+thread 2 pipeline RX enable
+thread 2 pipeline TX enable
diff --git a/drivers/net/softnic/firmware.spec b/drivers/net/softnic/firmware.spec
new file mode 100644
index 0000000000..106caae735
--- /dev/null
+++ b/drivers/net/softnic/firmware.spec
@@ -0,0 +1,19 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+//
+// Meta-data.
+//
+struct metadata_t {
+	bit<32> port
+}
+
+metadata instanceof metadata_t
+
+//
+// Pipeline.
+//
+apply {
+	rx m.port
+	tx m.port
+}
diff --git a/drivers/net/softnic/firmware_rx.io b/drivers/net/softnic/firmware_rx.io
new file mode 100644
index 0000000000..9baa4612b1
--- /dev/null
+++ b/drivers/net/softnic/firmware_rx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ring RXQ0 bsz 32
diff --git a/drivers/net/softnic/firmware_tx.io b/drivers/net/softnic/firmware_tx.io
new file mode 100644
index 0000000000..4c4608b105
--- /dev/null
+++ b/drivers/net/softnic/firmware_tx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ring TXQ0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ethdev 0000:18:00.0 txq 0 bsz 32
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (20 preceding siblings ...)
  2022-08-04 16:58 ` [PATCH 21/21] net/softnic: update the default device program Cristian Dumitrescu
@ 2022-08-26 13:17 ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
                     ` (20 more replies)
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
  22 siblings, 21 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev

The legacy pipeline API is soon going to be marked for deprecation,
hence the Soft NIC driver is updated to support the new SWX pipeline
type.

The SWX pipeline has better encapsulation than the legacy pipeline,
mainly due to P4 language alignment, which results in most of the
functionality being supported directly in the pipeline library, hence
the big number of lines of code deleted from this driver.

Depends-on: series-24117 ("pipeline: pipeline configuration and build improvements")

Change log:

V2:
-Fixed minor style checks and warnings reported by the CI/CD.

Cristian Dumitrescu (21):
  net/softnic: remove the traffic manager support
  net/softnic: remove flow support
  net/softnic: remove the meter support
  net/softnic: remove cryptodev support
  net/softnic: remove tap support
  net/softnic: remove the legacy pipeline CLI commands
  net/softnic: replace the legacy pipeline with the SWX pipeline
  net/softnic: remove the list of Ethernet devices
  net/softnic: remove unused text parsing functions
  net/softnic: add pipeline code generation CLI command
  net/softnic: add pipeline library build CLI command
  net/softnic: add pipeline build CLI command
  net/softnic: add pipeline table CLI commands
  net/softnic: add pipeline selector table CLI commands
  net/softnic: add pipeline learner table CLI commands
  net/softnic: add pipeline commit and abort CLI commands
  net/softnic: add the pipeline register read/write CLI commands
  net/softnic: add the pipeline meter CLI commands
  net/softnic: add pipeline statistics CLI command
  net/softnic: add pipeline mirroring CLI command
  net/softnic: update the default device program

 drivers/net/softnic/firmware.cli              |   51 +-
 drivers/net/softnic/firmware.spec             |   19 +
 drivers/net/softnic/firmware_rx.io            |   30 +
 drivers/net/softnic/firmware_tx.io            |   30 +
 drivers/net/softnic/meson.build               |   10 +-
 drivers/net/softnic/parser.c                  |  523 --
 drivers/net/softnic/parser.h                  |   68 -
 drivers/net/softnic/rte_eth_softnic.c         |  208 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_action.c  |  423 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 6985 ++++-------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   |  168 -
 drivers/net/softnic/rte_eth_softnic_flow.c    | 2293 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  922 +--
 drivers/net/softnic/rte_eth_softnic_link.c    |  101 -
 drivers/net/softnic/rte_eth_softnic_meter.c   |  945 ---
 .../net/softnic/rte_eth_softnic_pipeline.c    | 1129 +--
 drivers/net/softnic/rte_eth_softnic_tap.c     |  118 -
 drivers/net/softnic/rte_eth_softnic_thread.c  | 2594 +-----
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3657 ---------
 20 files changed, 1807 insertions(+), 18477 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_action.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH V2 01/21] net/softnic: remove the traffic manager support
  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   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 02/21] net/softnic: remove flow support Cristian Dumitrescu
                     ` (19 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device traffic manager API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |    3 +-
 drivers/net/softnic/rte_eth_softnic.c         |  170 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 1328 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  176 -
 .../net/softnic/rte_eth_softnic_pipeline.c    |   31 -
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3657 -----------------
 7 files changed, 1 insertion(+), 5374 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index aff5fb3bf2..e2dbd6166e 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -21,6 +21,5 @@ sources = files(
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
-        'rte_eth_softnic_tm.c',
 )
-deps += ['pipeline', 'port', 'table', 'sched', 'cryptodev']
+deps += ['pipeline', 'port', 'table', 'cryptodev']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8c098cad5b..ae3e8b3bcd 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_tm_driver.h>
 #include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
@@ -23,20 +22,6 @@
 #define PMD_PARAM_CONN_PORT                                "conn_port"
 #define PMD_PARAM_CPU_ID                                   "cpu_id"
 #define PMD_PARAM_SC                                       "sc"
-#define PMD_PARAM_TM_N_QUEUES                              "tm_n_queues"
-#define PMD_PARAM_TM_QSIZE0                                "tm_qsize0"
-#define PMD_PARAM_TM_QSIZE1                                "tm_qsize1"
-#define PMD_PARAM_TM_QSIZE2                                "tm_qsize2"
-#define PMD_PARAM_TM_QSIZE3                                "tm_qsize3"
-#define PMD_PARAM_TM_QSIZE4                                "tm_qsize4"
-#define PMD_PARAM_TM_QSIZE5                                "tm_qsize5"
-#define PMD_PARAM_TM_QSIZE6                                "tm_qsize6"
-#define PMD_PARAM_TM_QSIZE7                                "tm_qsize7"
-#define PMD_PARAM_TM_QSIZE8                                "tm_qsize8"
-#define PMD_PARAM_TM_QSIZE9                                "tm_qsize9"
-#define PMD_PARAM_TM_QSIZE10                               "tm_qsize10"
-#define PMD_PARAM_TM_QSIZE11                               "tm_qsize11"
-#define PMD_PARAM_TM_QSIZE12                               "tm_qsize12"
 
 
 static const char * const pmd_valid_args[] = {
@@ -44,20 +29,6 @@ static const char * const pmd_valid_args[] = {
 	PMD_PARAM_CONN_PORT,
 	PMD_PARAM_CPU_ID,
 	PMD_PARAM_SC,
-	PMD_PARAM_TM_N_QUEUES,
-	PMD_PARAM_TM_QSIZE0,
-	PMD_PARAM_TM_QSIZE1,
-	PMD_PARAM_TM_QSIZE2,
-	PMD_PARAM_TM_QSIZE3,
-	PMD_PARAM_TM_QSIZE4,
-	PMD_PARAM_TM_QSIZE5,
-	PMD_PARAM_TM_QSIZE6,
-	PMD_PARAM_TM_QSIZE7,
-	PMD_PARAM_TM_QSIZE8,
-	PMD_PARAM_TM_QSIZE9,
-	PMD_PARAM_TM_QSIZE10,
-	PMD_PARAM_TM_QSIZE11,
-	PMD_PARAM_TM_QSIZE12,
 	NULL
 };
 
@@ -193,12 +164,10 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	return 0;
@@ -218,12 +187,10 @@ pmd_free(struct pmd_internals *p)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	rte_free(p);
@@ -256,14 +223,6 @@ pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_tm_ops **)arg = &pmd_tm_ops;
-
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -282,7 +241,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
 	.flow_ops_get = pmd_flow_ops_get,
-	.tm_ops_get = pmd_tm_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
@@ -325,13 +283,11 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	tm_hierarchy_init(p);
 	softnic_mtr_init(p);
 
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tmgr_init(p);
 	softnic_tap_init(p);
 	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
@@ -459,20 +415,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 	}
 	p->cpu_id = SOFTNIC_CPU_ID;
 	p->sc = SOFTNIC_SC;
-	p->tm.n_queues = SOFTNIC_TM_N_QUEUES;
-	p->tm.qsize[0] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[1] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[2] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[3] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[4] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[5] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[6] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[7] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[8] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[9] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[10] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[11] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[12] = SOFTNIC_TM_QUEUE_SIZE;
 
 	/* Firmware script (optional) */
 	if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) {
@@ -517,104 +459,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 			goto out_free;
 	}
 
-	/* TM number of queues (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_N_QUEUES) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_N_QUEUES,
-			&get_uint32, &p->tm.n_queues);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	/* TM queue size 0 .. 3 (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE0) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE0,
-			&get_uint32, &p->tm.qsize[0]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE1) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE1,
-			&get_uint32, &p->tm.qsize[1]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE2) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE2,
-			&get_uint32, &p->tm.qsize[2]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE3) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE3,
-			&get_uint32, &p->tm.qsize[3]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE4) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE4,
-			&get_uint32, &p->tm.qsize[4]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE5) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE5,
-			&get_uint32, &p->tm.qsize[5]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE6) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE6,
-			&get_uint32, &p->tm.qsize[6]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE7) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE7,
-			&get_uint32, &p->tm.qsize[7]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE8) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE8,
-			&get_uint32, &p->tm.qsize[8]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE9) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE9,
-			&get_uint32, &p->tm.qsize[9]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE10) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE10,
-			&get_uint32, &p->tm.qsize[10]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE11) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE11,
-			&get_uint32, &p->tm.qsize[11]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE12) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE12,
-			&get_uint32, &p->tm.qsize[12]);
-		if (ret < 0)
-			goto out_free;
-	}
-
 out_free:
 	rte_kvargs_free(kvlist);
 	return ret;
@@ -696,20 +540,6 @@ RTE_PMD_REGISTER_PARAM_STRING(net_softnic,
 	PMD_PARAM_FIRMWARE "=<string> "
 	PMD_PARAM_CONN_PORT "=<uint16> "
 	PMD_PARAM_CPU_ID "=<uint32> "
-	PMD_PARAM_TM_N_QUEUES "=<uint32> "
-	PMD_PARAM_TM_QSIZE0 "=<uint32> "
-	PMD_PARAM_TM_QSIZE1 "=<uint32> "
-	PMD_PARAM_TM_QSIZE2 "=<uint32> "
-	PMD_PARAM_TM_QSIZE3 "=<uint32>"
-	PMD_PARAM_TM_QSIZE4 "=<uint32> "
-	PMD_PARAM_TM_QSIZE5 "=<uint32> "
-	PMD_PARAM_TM_QSIZE6 "=<uint32> "
-	PMD_PARAM_TM_QSIZE7 "=<uint32> "
-	PMD_PARAM_TM_QSIZE8 "=<uint32> "
-	PMD_PARAM_TM_QSIZE9 "=<uint32> "
-	PMD_PARAM_TM_QSIZE10 "=<uint32> "
-	PMD_PARAM_TM_QSIZE11 "=<uint32>"
-	PMD_PARAM_TM_QSIZE12 "=<uint32>"
 );
 
 int
diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h
index 6c11d89ab6..3fd80fa571 100644
--- a/drivers/net/softnic/rte_eth_softnic.h
+++ b/drivers/net/softnic/rte_eth_softnic.h
@@ -46,16 +46,6 @@ extern "C" {
 #define SOFTNIC_SC                                         1
 #endif
 
-/** Traffic Manager: Number of scheduler queues. */
-#ifndef SOFTNIC_TM_N_QUEUES
-#define SOFTNIC_TM_N_QUEUES                                (64 * 1024)
-#endif
-
-/** Traffic Manager: Scheduler queue size (per traffic class). */
-#ifndef SOFTNIC_TM_QUEUE_SIZE
-#define SOFTNIC_TM_QUEUE_SIZE                              64
-#endif
-
 /**
  * Soft NIC run.
  *
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7acbeecae7..7556e50831 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,1270 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tmgr shaper profile
- *  id <profile_id>
- *  rate <tb_rate> size <tb_size>
- *  adj <packet_length_adjust>
- */
-static void
-cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_shaper_params sp;
-	struct rte_tm_error error;
-	uint32_t shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
-
-	if (n_tokens != 11) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "rate") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
-		return;
-	}
-
-	if (strcmp(tokens[7], "size") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
-		return;
-	}
-
-	if (strcmp(tokens[9], "adj") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj");
-		return;
-	}
-
-	if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr shared shaper
- *  id <shared_shaper_id>
- *  profile <shaper_profile_id>
- */
-static void
-cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint32_t shared_shaper_id, shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[2], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shared_shaper_add_update(port_id,
-		shared_shaper_id,
-		shaper_profile_id,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr node
- *   id <node_id>
- *   parent <parent_node_id | none>
- *   priority <priority>
- *   weight <weight>
- *   [shaper profile <shaper_profile_id>]
- *   [shared shaper <shared_shaper_id>]
- *   [nonleaf sp <n_sp_priorities>]
- */
-static void
-cmd_tmgr_node(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	struct rte_tm_node_params np;
-	uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&np, 0, sizeof(struct rte_tm_node_params));
-	np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-	np.nonleaf.n_sp_priorities = 1;
-
-	if (n_tokens < 10) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "node") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
-		return;
-	}
-
-	if (strcmp(tokens[2], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "parent") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
-		return;
-	}
-
-	if (strcmp(tokens[5], "none") == 0)
-		parent_node_id = RTE_TM_NODE_ID_NULL;
-	else {
-		if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id");
-			return;
-		}
-	}
-
-	if (strcmp(tokens[6], "priority") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-		return;
-	}
-
-	if (strcmp(tokens[8], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "weight");
-		return;
-	}
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shaper") == 0) &&
-		(strcmp(tokens[1], "profile") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (strcmp(tokens[2], "none") == 0) {
-			np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-		} else {
-			if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-				return;
-			}
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shaper profile */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shared") == 0) &&
-		(strcmp(tokens[1], "shaper") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-			return;
-		}
-
-		np.shared_shaper_id = &shared_shaper_id;
-		np.n_shared_shapers = 1;
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shared shaper */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "nonleaf") == 0) &&
-		(strcmp(tokens[1], "sp") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
-			return;
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* nonleaf sp <n_sp_priorities> */
-
-	if (n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_node_add(port_id,
-		node_id,
-		parent_node_id,
-		priority,
-		weight,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&np,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-static uint32_t
-root_node_id(uint32_t n_spp,
-	uint32_t n_pps)
-{
-	uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_pipes = n_spp * n_pps;
-
-	return n_queues + n_tc + n_pipes + n_spp;
-}
-
-static uint32_t
-subport_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues + n_tc + n_pipes + subport_id;
-}
-
-static uint32_t
-pipe_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		n_tc +
-		pipe_id +
-		subport_id * n_pps;
-}
-
-static uint32_t
-tc_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-}
-
-static uint32_t
-queue_node_id(uint32_t n_spp __rte_unused,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id,
-	uint32_t queue_id)
-{
-	return queue_id + tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_QUEUES_PER_PIPE;
-}
-
-struct tmgr_hierarchy_default_params {
-	uint32_t n_spp; /**< Number of subports per port. */
-	uint32_t n_pps; /**< Number of pipes per subport. */
-
-	struct {
-		uint32_t port;
-		uint32_t subport;
-		uint32_t pipe;
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shaper_profile_id;
-
-	struct {
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t tc_valid[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shared_shaper_id;
-
-	struct {
-		uint32_t queue[RTE_SCHED_QUEUES_PER_PIPE];
-	} weight;
-};
-
-static int
-tmgr_hierarchy_default(struct pmd_internals *softnic,
-	struct tmgr_hierarchy_default_params *params)
-{
-	struct rte_tm_node_params root_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.port,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params subport_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.subport,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params pipe_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.pipe,
-		.nonleaf = {
-			.n_sp_priorities = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-		},
-	};
-
-	uint32_t *shared_shaper_id =
-		(uint32_t *)calloc(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			sizeof(uint32_t));
-
-	if (shared_shaper_id == NULL)
-		return -1;
-
-	memcpy(shared_shaper_id, params->shared_shaper_id.tc,
-		sizeof(params->shared_shaper_id.tc));
-
-	struct rte_tm_node_params tc_node_params[] = {
-		[0] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[0],
-			.shared_shaper_id = &shared_shaper_id[0],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[0]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[1] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[1],
-			.shared_shaper_id = &shared_shaper_id[1],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[1]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[2] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[2],
-			.shared_shaper_id = &shared_shaper_id[2],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[2]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[3] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[3],
-			.shared_shaper_id = &shared_shaper_id[3],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[3]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[4] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[4],
-			.shared_shaper_id = &shared_shaper_id[4],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[4]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[5] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[5],
-			.shared_shaper_id = &shared_shaper_id[5],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[5]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[6] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[6],
-			.shared_shaper_id = &shared_shaper_id[6],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[6]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[7] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[7],
-			.shared_shaper_id = &shared_shaper_id[7],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[7]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[8] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[8],
-			.shared_shaper_id = &shared_shaper_id[8],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[8]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[9] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[9],
-			.shared_shaper_id = &shared_shaper_id[9],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[9]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[10] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[10],
-			.shared_shaper_id = &shared_shaper_id[10],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[10]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[11] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[11],
-			.shared_shaper_id = &shared_shaper_id[11],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[11]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[12] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[12],
-			.shared_shaper_id = &shared_shaper_id[12],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[12]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-	};
-
-	struct rte_tm_node_params queue_node_params = {
-		.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE,
-	};
-
-	struct rte_tm_error error;
-	uint32_t n_spp = params->n_spp, n_pps = params->n_pps, s;
-	int status;
-	uint16_t port_id;
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 0: Root node */
-	status = rte_tm_node_add(port_id,
-		root_node_id(n_spp, n_pps),
-		RTE_TM_NODE_ID_NULL,
-		0,
-		1,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&root_node_params,
-		&error);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 1: Subport nodes */
-	for (s = 0; s < params->n_spp; s++) {
-		uint32_t p;
-
-		status = rte_tm_node_add(port_id,
-			subport_node_id(n_spp, n_pps, s),
-			root_node_id(n_spp, n_pps),
-			0,
-			1,
-			RTE_TM_NODE_LEVEL_ID_ANY,
-			&subport_node_params,
-			&error);
-		if (status)
-			return -1;
-
-		/* Hierarchy level 2: Pipe nodes */
-		for (p = 0; p < params->n_pps; p++) {
-			uint32_t t;
-
-			status = rte_tm_node_add(port_id,
-				pipe_node_id(n_spp, n_pps, s, p),
-				subport_node_id(n_spp, n_pps, s),
-				0,
-				1,
-				RTE_TM_NODE_LEVEL_ID_ANY,
-				&pipe_node_params,
-				&error);
-			if (status)
-				return -1;
-
-			/* Hierarchy level 3: Traffic class nodes */
-			for (t = 0; t < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; t++) {
-				uint32_t q;
-
-				status = rte_tm_node_add(port_id,
-					tc_node_id(n_spp, n_pps, s, p, t),
-					pipe_node_id(n_spp, n_pps, s, p),
-					t,
-					1,
-					RTE_TM_NODE_LEVEL_ID_ANY,
-					&tc_node_params[t],
-					&error);
-				if (status)
-					return -1;
-
-				/* Hierarchy level 4: Queue nodes */
-				if (t < RTE_SCHED_TRAFFIC_CLASS_BE) {
-					/* Strict-priority traffic class queues */
-					q = 0;
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-
-					continue;
-				}
-				/* Best-effort traffic class queues */
-				for (q = 0; q < RTE_SCHED_BE_QUEUES_PER_PIPE; q++) {
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-				}
-			} /* TC */
-		} /* Pipe */
-	} /* Subport */
-
-	return 0;
-}
-
-
-/**
- * tmgr hierarchy-default
- *  spp <n_subports_per_port>
- *  pps <n_pipes_per_subport>
- *  shaper profile
- *   port <profile_id>
- *   subport <profile_id>
- *   pipe <profile_id>
- *   tc0 <profile_id>
- *   tc1 <profile_id>
- *   tc2 <profile_id>
- *   tc3 <profile_id>
- *   tc4 <profile_id>
- *   tc5 <profile_id>
- *   tc6 <profile_id>
- *   tc7 <profile_id>
- *   tc8 <profile_id>
- *   tc9 <profile_id>
- *   tc10 <profile_id>
- *   tc11 <profile_id>
- *   tc12 <profile_id>
- *  shared shaper
- *   tc0 <id | none>
- *   tc1 <id | none>
- *   tc2 <id | none>
- *   tc3 <id | none>
- *   tc4 <id | none>
- *   tc5 <id | none>
- *   tc6 <id | none>
- *   tc7 <id | none>
- *   tc8 <id | none>
- *   tc9 <id | none>
- *   tc10 <id | none>
- *   tc11 <id | none>
- *   tc12 <id | none>
- *  weight
- *   queue  <q12> ... <q15>
- */
-static void
-cmd_tmgr_hierarchy_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct tmgr_hierarchy_default_params p;
-	int i, j, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 74) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy-default") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
-		return;
-	}
-
-	if (strcmp(tokens[2], "spp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
-		return;
-	}
-
-	if (strcmp(tokens[4], "pps") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
-		return;
-	}
-
-	/* Shaper profile */
-
-	if (strcmp(tokens[6], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[7], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[8], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port profile id");
-		return;
-	}
-
-	if (strcmp(tokens[10], "subport") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id");
-		return;
-	}
-
-	if (strcmp(tokens[12], "pipe") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[14], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[16], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[18], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[20], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[22], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[4], tokens[23]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc4 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[24], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[5], tokens[25]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc5 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[26], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[6], tokens[27]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc6 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[28], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[7], tokens[29]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc7 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[30], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[8], tokens[31]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc8 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[32], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[9], tokens[33]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc9 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[34], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[10], tokens[35]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc10 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[36], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[11], tokens[37]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc11 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[38], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[12], tokens[39]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc12 profile id");
-		return;
-	}
-
-	/* Shared shaper */
-
-	if (strcmp(tokens[40], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[41], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[42], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (strcmp(tokens[43], "none") == 0)
-		p.shared_shaper_id.tc_valid[0] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0],
-			tokens[43]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[0] = 1;
-	}
-
-	if (strcmp(tokens[44], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (strcmp(tokens[45], "none") == 0)
-		p.shared_shaper_id.tc_valid[1] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1],
-			tokens[45]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[1] = 1;
-	}
-
-	if (strcmp(tokens[46], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (strcmp(tokens[47], "none") == 0)
-		p.shared_shaper_id.tc_valid[2] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2],
-			tokens[47]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[2] = 1;
-	}
-
-	if (strcmp(tokens[48], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (strcmp(tokens[49], "none") == 0)
-		p.shared_shaper_id.tc_valid[3] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3],
-			tokens[49]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[3] = 1;
-	}
-
-	if (strcmp(tokens[50], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (strcmp(tokens[51], "none") == 0) {
-		p.shared_shaper_id.tc_valid[4] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[4],
-			tokens[51]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc4");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[4] = 1;
-	}
-
-	if (strcmp(tokens[52], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (strcmp(tokens[53], "none") == 0) {
-		p.shared_shaper_id.tc_valid[5] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[5],
-			tokens[53]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc5");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[5] = 1;
-	}
-
-	if (strcmp(tokens[54], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (strcmp(tokens[55], "none") == 0) {
-		p.shared_shaper_id.tc_valid[6] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[6],
-			tokens[55]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc6");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[6] = 1;
-	}
-
-	if (strcmp(tokens[56], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (strcmp(tokens[57], "none") == 0) {
-		p.shared_shaper_id.tc_valid[7] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[7],
-			tokens[57]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc7");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[7] = 1;
-	}
-
-	if (strcmp(tokens[58], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (strcmp(tokens[59], "none") == 0) {
-		p.shared_shaper_id.tc_valid[8] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[8],
-			tokens[59]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc8");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[8] = 1;
-	}
-
-	if (strcmp(tokens[60], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (strcmp(tokens[61], "none") == 0) {
-		p.shared_shaper_id.tc_valid[9] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[9],
-			tokens[61]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc9");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[9] = 1;
-	}
-
-	if (strcmp(tokens[62], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (strcmp(tokens[63], "none") == 0) {
-		p.shared_shaper_id.tc_valid[10] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[10],
-			tokens[63]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc10");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[10] = 1;
-	}
-
-	if (strcmp(tokens[64], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (strcmp(tokens[65], "none") == 0) {
-		p.shared_shaper_id.tc_valid[11] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[11],
-			tokens[65]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc11");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[11] = 1;
-	}
-
-	if (strcmp(tokens[66], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (strcmp(tokens[67], "none") == 0) {
-		p.shared_shaper_id.tc_valid[12] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[12],
-			tokens[67]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc12");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[12] = 1;
-	}
-
-	/* Weight */
-
-	if (strcmp(tokens[68], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (strcmp(tokens[69], "queue") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
-		return;
-	}
-
-	for (i = 0, j = 0; i < 16; i++) {
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			p.weight.queue[i] = 1;
-		} else {
-			if (softnic_parser_read_uint32(&p.weight.queue[i],
-				tokens[70 + j]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "weight queue");
-				return;
-			}
-			j++;
-		}
-	}
-
-	status = tmgr_hierarchy_default(softnic, &p);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr hierarchy commit
- */
-static void
-cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 3) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
-		return;
-	}
-
-	if (strcmp(tokens[2], "commit") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_hierarchy_commit(port_id, 1, &error);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr <tmgr_name>
- */
-static void
-cmd_tmgr(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tmgr_port = softnic_tmgr_port_create(softnic, name);
-	if (tmgr_port == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * tap <tap_name>
  */
@@ -2247,7 +983,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  | cryptodev <cryptodev_name> rxq <queue_id>
@@ -2331,18 +1066,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "tmgr") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tmgr");
-			return;
-		}
-
-		p.type = PORT_IN_TMGR;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tap") == 0) {
 		if (n_tokens < t0 + 6) {
@@ -2482,7 +1205,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
@@ -2557,16 +1279,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tmgr") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tmgr");
-			return;
-		}
-
-		p.type = PORT_OUT_TMGR;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "tap") == 0) {
 		if (n_tokens != 8) {
@@ -6129,46 +4841,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tmgr") == 0) {
-		if (n_tokens == 2) {
-			cmd_tmgr(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shaper") == 0) &&
-			(strcmp(tokens[2], "profile") == 0)) {
-			cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shared") == 0) &&
-			(strcmp(tokens[2], "shaper") == 0)) {
-			cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "node") == 0)) {
-			cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "hierarchy-default") == 0)) {
-			cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "hierarchy") == 0) &&
-			(strcmp(tokens[2], "commit") == 0)) {
-			cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "tap") == 0) {
 		cmd_tap(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 07285ca315..4cc98b7aad 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -13,14 +13,12 @@
 #include <rte_mbuf.h>
 #include <rte_ring.h>
 #include <rte_ethdev.h>
-#include <rte_sched.h>
 #include <rte_port_in_action.h>
 #include <rte_table_action.h>
 #include <rte_pipeline.h>
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_tm_driver.h>
 #include <rte_flow_driver.h>
 #include <rte_mtr_driver.h>
 
@@ -40,12 +38,6 @@ struct pmd_params {
 	uint16_t conn_port;
 	uint32_t cpu_id;
 	int sc; /**< Service cores. */
-
-	/** Traffic Management (TM) */
-	struct {
-		uint32_t n_queues; /**< Number of queues */
-		uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} tm;
 };
 
 /**
@@ -161,134 +153,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TMGR
- */
-
-#ifndef TM_MAX_SUBPORTS
-#define TM_MAX_SUBPORTS					8
-#endif
-
-#ifndef TM_MAX_PIPES_PER_SUBPORT
-#define TM_MAX_PIPES_PER_SUBPORT			4096
-#endif
-
-#ifndef TM_MAX_PIPE_PROFILE
-#define TM_MAX_PIPE_PROFILE				256
-#endif
-
-#ifndef TM_MAX_SUBPORT_PROFILE
-#define TM_MAX_SUBPORT_PROFILE				256
-#endif
-
-struct tm_params {
-	struct rte_sched_port_params port_params;
-	struct rte_sched_subport_params subport_params[TM_MAX_SUBPORTS];
-	struct rte_sched_subport_profile_params
-		subport_profile[TM_MAX_SUBPORT_PROFILE];
-	uint32_t n_subport_profiles;
-	uint32_t subport_to_profile[TM_MAX_SUBPORT_PROFILE];
-	struct rte_sched_pipe_params pipe_profiles[TM_MAX_PIPE_PROFILE];
-	uint32_t n_pipe_profiles;
-	uint32_t pipe_to_profile[TM_MAX_SUBPORTS * TM_MAX_PIPES_PER_SUBPORT];
-};
-
-/* TM Levels */
-enum tm_node_level {
-	TM_NODE_LEVEL_PORT = 0,
-	TM_NODE_LEVEL_SUBPORT,
-	TM_NODE_LEVEL_PIPE,
-	TM_NODE_LEVEL_TC,
-	TM_NODE_LEVEL_QUEUE,
-	TM_NODE_LEVEL_MAX,
-};
-
-/* TM Shaper Profile */
-struct tm_shaper_profile {
-	TAILQ_ENTRY(tm_shaper_profile) node;
-	uint32_t shaper_profile_id;
-	uint32_t n_users;
-	struct rte_tm_shaper_params params;
-};
-
-TAILQ_HEAD(tm_shaper_profile_list, tm_shaper_profile);
-
-/* TM Shared Shaper */
-struct tm_shared_shaper {
-	TAILQ_ENTRY(tm_shared_shaper) node;
-	uint32_t shared_shaper_id;
-	uint32_t n_users;
-	uint32_t shaper_profile_id;
-};
-
-TAILQ_HEAD(tm_shared_shaper_list, tm_shared_shaper);
-
-/* TM WRED Profile */
-struct tm_wred_profile {
-	TAILQ_ENTRY(tm_wred_profile) node;
-	uint32_t wred_profile_id;
-	uint32_t n_users;
-	struct rte_tm_wred_params params;
-};
-
-TAILQ_HEAD(tm_wred_profile_list, tm_wred_profile);
-
-/* TM Node */
-struct tm_node {
-	TAILQ_ENTRY(tm_node) node;
-	uint32_t node_id;
-	uint32_t parent_node_id;
-	uint32_t priority;
-	uint32_t weight;
-	uint32_t level;
-	struct tm_node *parent_node;
-	struct tm_shaper_profile *shaper_profile;
-	struct tm_wred_profile *wred_profile;
-	struct rte_tm_node_params params;
-	struct rte_tm_node_stats stats;
-	uint32_t n_children;
-};
-
-TAILQ_HEAD(tm_node_list, tm_node);
-
-/* TM Hierarchy Specification */
-struct tm_hierarchy {
-	struct tm_shaper_profile_list shaper_profiles;
-	struct tm_shared_shaper_list shared_shapers;
-	struct tm_wred_profile_list wred_profiles;
-	struct tm_node_list nodes;
-
-	uint32_t n_shaper_profiles;
-	uint32_t n_shared_shapers;
-	uint32_t n_wred_profiles;
-	uint32_t n_nodes;
-
-	uint32_t n_tm_nodes[TM_NODE_LEVEL_MAX];
-};
-
-struct tm_internals {
-	/** Hierarchy specification
-	 *
-	 *     -Hierarchy is unfrozen at init and when port is stopped.
-	 *     -Hierarchy is frozen on successful hierarchy commit.
-	 *     -Run-time hierarchy changes are not allowed, therefore it makes
-	 *      sense to keep the hierarchy frozen after the port is started.
-	 */
-	struct tm_hierarchy h;
-	int hierarchy_frozen;
-
-	/** Blueprints */
-	struct tm_params params;
-};
-
-struct softnic_tmgr_port {
-	TAILQ_ENTRY(softnic_tmgr_port) node;
-	char name[NAME_SIZE];
-	struct rte_sched_port *s;
-};
-
-TAILQ_HEAD(softnic_tmgr_port_list, softnic_tmgr_port);
-
 /**
  * TAP
  */
@@ -385,7 +249,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TMGR,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 	PORT_IN_CRYPTODEV,
@@ -426,7 +289,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TMGR,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 	PORT_OUT_CRYPTODEV,
@@ -619,10 +481,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct {
-		struct tm_internals tm; /**< Traffic Management */
-	} soft;
-
 	struct flow_internals flow;
 	struct mtr_internals mtr;
 
@@ -630,7 +488,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tmgr_port_list tmgr_port_list;
 	struct softnic_tap_list tap_list;
 	struct softnic_cryptodev_list cryptodev_list;
 	struct softnic_port_in_action_profile_list port_in_action_profile_list;
@@ -753,39 +610,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TMGR
- */
-int
-softnic_tmgr_init(struct pmd_internals *p);
-
-void
-softnic_tmgr_free(struct pmd_internals *p);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name);
-
-void
-tm_hierarchy_init(struct pmd_internals *p);
-
-void
-tm_hierarchy_free(struct pmd_internals *p);
-
-static inline int
-tm_used(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	return p->soft.tm.h.n_tm_nodes[TM_NODE_LEVEL_PORT];
-}
-
-extern const struct rte_tm_ops pmd_tm_ops;
-
 /**
  * TAP
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 337aa32e57..c7d2a7de19 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -305,21 +305,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-
-		p.ops = &rte_port_sched_reader_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_IN_TAP:
 	{
 		struct softnic_tap *tap;
@@ -545,22 +530,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-		pp.sched.tx_burst_sz = params->burst_size;
-
-		p.ops = &rte_port_sched_writer_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_OUT_TAP:
 	{
 		struct softnic_tap *tap;
diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c
deleted file mode 100644
index 6a7766ba1c..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tm.c
+++ /dev/null
@@ -1,3657 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define SUBPORT_TC_PERIOD	10
-#define PIPE_TC_PERIOD		40
-
-int
-softnic_tmgr_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tmgr_port_list);
-
-	return 0;
-}
-
-void
-softnic_tmgr_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = TAILQ_FIRST(&p->tmgr_port_list);
-		if (tmgr_port == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tmgr_port_list, tmgr_port, node);
-		rte_sched_port_free(tmgr_port->s);
-		free(tmgr_port);
-	}
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tmgr_port, &p->tmgr_port_list, node)
-		if (strcmp(tmgr_port->name, name) == 0)
-			return tmgr_port;
-
-	return NULL;
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-	struct tm_params *t = &p->soft.tm.params;
-	struct rte_sched_port *sched;
-	uint32_t n_subports, subport_id;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tmgr_port_find(p, name))
-		return NULL;
-
-	/*
-	 * Resource
-	 */
-
-	/* Is hierarchy frozen? */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return NULL;
-
-	/* Port */
-	sched = rte_sched_port_config(&t->port_params);
-	if (sched == NULL)
-		return NULL;
-
-	/* Subport */
-	n_subports = t->port_params.n_subports_per_port;
-	for (subport_id = 0; subport_id < n_subports; subport_id++) {
-		uint32_t n_pipes_per_subport =
-		t->subport_params[subport_id].n_pipes_per_subport_enabled;
-		uint32_t pipe_id;
-		int status;
-
-		status = rte_sched_subport_config(sched,
-			subport_id,
-			&t->subport_params[subport_id],
-			t->subport_to_profile[subport_id]);
-		if (status) {
-			rte_sched_port_free(sched);
-			return NULL;
-		}
-
-		/* Pipe */
-		for (pipe_id = 0; pipe_id < n_pipes_per_subport; pipe_id++) {
-			int pos = subport_id * TM_MAX_PIPES_PER_SUBPORT + pipe_id;
-			int profile_id = t->pipe_to_profile[pos];
-
-			if (profile_id < 0)
-				continue;
-
-			status = rte_sched_pipe_config(sched,
-				subport_id,
-				pipe_id,
-				profile_id);
-			if (status) {
-				rte_sched_port_free(sched);
-				return NULL;
-			}
-		}
-	}
-
-	/* Node allocation */
-	tmgr_port = calloc(1, sizeof(struct softnic_tmgr_port));
-	if (tmgr_port == NULL) {
-		rte_sched_port_free(sched);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name));
-	tmgr_port->s = sched;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tmgr_port_list, tmgr_port, node);
-
-	return tmgr_port;
-}
-
-static struct rte_sched_port *
-SCHED(struct pmd_internals *p)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	tmgr_port = softnic_tmgr_port_find(p, "TMGR");
-	if (tmgr_port == NULL)
-		return NULL;
-
-	return tmgr_port->s;
-}
-
-void
-tm_hierarchy_init(struct pmd_internals *p)
-{
-	memset(&p->soft.tm, 0, sizeof(p->soft.tm));
-
-	/* Initialize shaper profile list */
-	TAILQ_INIT(&p->soft.tm.h.shaper_profiles);
-
-	/* Initialize shared shaper list */
-	TAILQ_INIT(&p->soft.tm.h.shared_shapers);
-
-	/* Initialize wred profile list */
-	TAILQ_INIT(&p->soft.tm.h.wred_profiles);
-
-	/* Initialize TM node list */
-	TAILQ_INIT(&p->soft.tm.h.nodes);
-}
-
-void
-tm_hierarchy_free(struct pmd_internals *p)
-{
-	/* Remove all nodes*/
-	for ( ; ; ) {
-		struct tm_node *tm_node;
-
-		tm_node = TAILQ_FIRST(&p->soft.tm.h.nodes);
-		if (tm_node == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.nodes, tm_node, node);
-		free(tm_node);
-	}
-
-	/* Remove all WRED profiles */
-	for ( ; ; ) {
-		struct tm_wred_profile *wred_profile;
-
-		wred_profile = TAILQ_FIRST(&p->soft.tm.h.wred_profiles);
-		if (wred_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wred_profile, node);
-		free(wred_profile);
-	}
-
-	/* Remove all shared shapers */
-	for ( ; ; ) {
-		struct tm_shared_shaper *shared_shaper;
-
-		shared_shaper = TAILQ_FIRST(&p->soft.tm.h.shared_shapers);
-		if (shared_shaper == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, shared_shaper, node);
-		free(shared_shaper);
-	}
-
-	/* Remove all shaper profiles */
-	for ( ; ; ) {
-		struct tm_shaper_profile *shaper_profile;
-
-		shaper_profile = TAILQ_FIRST(&p->soft.tm.h.shaper_profiles);
-		if (shaper_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles,
-			shaper_profile, node);
-		free(shaper_profile);
-	}
-
-	tm_hierarchy_init(p);
-}
-
-static struct tm_shaper_profile *
-tm_shaper_profile_search(struct rte_eth_dev *dev, uint32_t shaper_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-
-	TAILQ_FOREACH(sp, spl, node)
-		if (shaper_profile_id == sp->shaper_profile_id)
-			return sp;
-
-	return NULL;
-}
-
-static struct tm_shared_shaper *
-tm_shared_shaper_search(struct rte_eth_dev *dev, uint32_t shared_shaper_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper_list *ssl = &p->soft.tm.h.shared_shapers;
-	struct tm_shared_shaper *ss;
-
-	TAILQ_FOREACH(ss, ssl, node)
-		if (shared_shaper_id == ss->shared_shaper_id)
-			return ss;
-
-	return NULL;
-}
-
-static struct tm_wred_profile *
-tm_wred_profile_search(struct rte_eth_dev *dev, uint32_t wred_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-
-	TAILQ_FOREACH(wp, wpl, node)
-		if (wred_profile_id == wp->wred_profile_id)
-			return wp;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_node_search(struct rte_eth_dev *dev, uint32_t node_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->node_id == node_id)
-			return n;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_root_node_present(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->parent_node_id == RTE_TM_NODE_ID_NULL)
-			return n;
-
-	return NULL;
-}
-
-static uint32_t
-tm_node_subport_id(struct rte_eth_dev *dev, struct tm_node *subport_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->node_id == subport_node->node_id)
-			return subport_id;
-
-		subport_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_pipe_id(struct rte_eth_dev *dev, struct tm_node *pipe_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *np;
-	uint32_t pipe_id;
-
-	pipe_id = 0;
-	TAILQ_FOREACH(np, nl, node) {
-		if (np->level != TM_NODE_LEVEL_PIPE ||
-			np->parent_node_id != pipe_node->parent_node_id)
-			continue;
-
-		if (np->node_id == pipe_node->node_id)
-			return pipe_id;
-
-		pipe_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_tc_id(struct rte_eth_dev *dev __rte_unused, struct tm_node *tc_node)
-{
-	return tc_node->priority;
-}
-
-static uint32_t
-tm_node_queue_id(struct rte_eth_dev *dev, struct tm_node *queue_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *nq;
-	uint32_t queue_id;
-
-	queue_id = 0;
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node_id != queue_node->parent_node_id)
-			continue;
-
-		if (nq->node_id == queue_node->node_id)
-			return queue_id;
-
-		queue_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_level_get_max_nodes(struct rte_eth_dev *dev, enum tm_node_level level)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t n_queues_max = p->params.tm.n_queues;
-	uint32_t n_tc_max =
-		(n_queues_max * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		/ RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_pipes_max = n_tc_max / RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_subports_max = n_pipes_max;
-	uint32_t n_root_max = 1;
-
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		return n_root_max;
-	case TM_NODE_LEVEL_SUBPORT:
-		return n_subports_max;
-	case TM_NODE_LEVEL_PIPE:
-		return n_pipes_max;
-	case TM_NODE_LEVEL_TC:
-		return n_tc_max;
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		return n_queues_max;
-	}
-}
-
-/* Traffic manager node type get */
-static int
-pmd_tm_node_type_get(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	int *is_leaf,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	if (is_leaf == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_UNSPECIFIED,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (node_id == RTE_TM_NODE_ID_NULL ||
-		(tm_node_search(dev, node_id) == NULL))
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	*is_leaf = node_id < p->params.tm.n_queues;
-
-	return 0;
-}
-
-#ifdef RTE_SCHED_CMAN
-#define WRED_SUPPORTED						1
-#else
-#define WRED_SUPPORTED						0
-#endif
-
-#define STATS_MASK_DEFAULT					\
-	(RTE_TM_STATS_N_PKTS |					\
-	RTE_TM_STATS_N_BYTES |					\
-	RTE_TM_STATS_N_PKTS_GREEN_DROPPED |			\
-	RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
-
-#define STATS_MASK_QUEUE						\
-	(STATS_MASK_DEFAULT |					\
-	RTE_TM_STATS_N_PKTS_QUEUED)
-
-static const struct rte_tm_capabilities tm_cap = {
-	.n_nodes_max = UINT32_MAX,
-	.n_levels_max = TM_NODE_LEVEL_MAX,
-
-	.non_leaf_nodes_identical = 0,
-	.leaf_nodes_identical = 1,
-
-	.shaper_n_max = UINT32_MAX,
-	.shaper_private_n_max = UINT32_MAX,
-	.shaper_private_dual_rate_n_max = 0,
-	.shaper_private_rate_min = 1,
-	.shaper_private_rate_max = UINT32_MAX,
-	.shaper_private_packet_mode_supported = 0,
-	.shaper_private_byte_mode_supported = 1,
-
-	.shaper_shared_n_max = UINT32_MAX,
-	.shaper_shared_n_nodes_per_shaper_max = UINT32_MAX,
-	.shaper_shared_n_shapers_per_node_max = 1,
-	.shaper_shared_dual_rate_n_max = 0,
-	.shaper_shared_rate_min = 1,
-	.shaper_shared_rate_max = UINT32_MAX,
-	.shaper_shared_packet_mode_supported = 0,
-	.shaper_shared_byte_mode_supported = 1,
-
-	.shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-	.shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-
-	.sched_n_children_max = UINT32_MAX,
-	.sched_sp_n_priorities_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-	.sched_wfq_n_children_per_group_max = UINT32_MAX,
-	.sched_wfq_n_groups_max = 1,
-	.sched_wfq_weight_max = UINT32_MAX,
-	.sched_wfq_packet_mode_supported = 0,
-	.sched_wfq_byte_mode_supported = 1,
-
-	.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-	.cman_wred_byte_mode_supported = 0,
-	.cman_head_drop_supported = 0,
-	.cman_wred_context_n_max = 0,
-	.cman_wred_context_private_n_max = 0,
-	.cman_wred_context_shared_n_max = 0,
-	.cman_wred_context_shared_n_nodes_per_context_max = 0,
-	.cman_wred_context_shared_n_contexts_per_node_max = 0,
-
-	.mark_vlan_dei_supported = {0, 0, 0},
-	.mark_ip_ecn_tcp_supported = {0, 0, 0},
-	.mark_ip_ecn_sctp_supported = {0, 0, 0},
-	.mark_ip_dscp_supported = {0, 0, 0},
-
-	.dynamic_update_mask = 0,
-
-	.stats_mask = STATS_MASK_QUEUE,
-};
-
-/* Traffic manager capabilities get */
-static int
-pmd_tm_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	struct rte_tm_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_cap, sizeof(*cap));
-
-	cap->n_nodes_max = tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->shaper_private_n_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC);
-
-	cap->shaper_shared_n_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE *
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT);
-
-	cap->shaper_n_max = cap->shaper_private_n_max +
-		cap->shaper_shared_n_max;
-
-	cap->shaper_shared_n_nodes_per_shaper_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE);
-
-	cap->sched_n_children_max = RTE_MAX(
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE),
-		(uint32_t)RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE);
-
-	cap->sched_wfq_n_children_per_group_max = cap->sched_n_children_max;
-
-	if (WRED_SUPPORTED)
-		cap->cman_wred_context_private_n_max =
-			tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->cman_wred_context_n_max = cap->cman_wred_context_private_n_max +
-		cap->cman_wred_context_shared_n_max;
-
-	return 0;
-}
-
-static const struct rte_tm_level_capabilities tm_level_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.n_nodes_max = 1,
-		.n_nodes_nonleaf_max = 1,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 1,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 1,
-
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = 0,
-		.n_nodes_leaf_max = UINT32_MAX,
-		.non_leaf_nodes_identical = 0,
-		.leaf_nodes_identical = 1,
-
-		{.leaf = {
-			.shaper_private_supported = 0,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 0,
-			.shaper_private_rate_max = 0,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 0,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-
-			.stats_mask = STATS_MASK_QUEUE,
-		} },
-	},
-};
-
-/* Traffic manager level capabilities get */
-static int
-pmd_tm_level_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t level_id,
-	struct rte_tm_level_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (level_id >= TM_NODE_LEVEL_MAX)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_LEVEL_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_level_cap[level_id], sizeof(*cap));
-
-	switch (level_id) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_SUBPORT);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_PIPE);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_TC);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_QUEUE);
-		cap->n_nodes_leaf_max = cap->n_nodes_max;
-		break;
-	}
-
-	return 0;
-}
-
-static const struct rte_tm_node_capabilities tm_node_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 1,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 1,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.shaper_private_supported = 0,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 0,
-		.shaper_private_rate_max = 0,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 0,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-
-		{.leaf = {
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-		} },
-
-		.stats_mask = STATS_MASK_QUEUE,
-	},
-};
-
-/* Traffic manager node capabilities get */
-static int
-pmd_tm_node_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t node_id,
-	struct rte_tm_node_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	struct tm_node *tm_node;
-
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	tm_node = tm_node_search(dev, node_id);
-	if (tm_node == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_node_cap[tm_node->level], sizeof(*cap));
-
-	switch (tm_node->level) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-	case TM_NODE_LEVEL_TC:
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int
-shaper_profile_check(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_shaper_profile *sp;
-
-	/* Shaper profile ID must not be NONE. */
-	if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must not exist. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak rate: non-zero, 32-bit */
-	if (profile->peak.rate == 0 ||
-		profile->peak.rate >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak size: non-zero, 32-bit */
-	if (profile->peak.size == 0 ||
-		profile->peak.size >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Dual-rate profiles are not supported. */
-	if (profile->committed.rate != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet length adjust: 24 bytes */
-	if (profile->pkt_length_adjust != RTE_TM_ETH_FRAMING_OVERHEAD_FCS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet mode is not supported. */
-	if (profile->packet_mode != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PACKET_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-	return 0;
-}
-
-/* Traffic manager shaper profile add */
-static int
-pmd_tm_shaper_profile_add(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-	int status;
-
-	/* Check input params */
-	status = shaper_profile_check(dev, shaper_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	sp = calloc(1, sizeof(struct tm_shaper_profile));
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	sp->shaper_profile_id = shaper_profile_id;
-	memcpy(&sp->params, profile, sizeof(sp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(spl, sp, node);
-	p->soft.tm.h.n_shaper_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager shaper profile delete */
-static int
-pmd_tm_shaper_profile_delete(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp;
-
-	/* Check existing */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (sp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles, sp, node);
-	p->soft.tm.h.n_shaper_profiles--;
-	free(sp);
-
-	return 0;
-}
-
-static struct tm_node *
-tm_shared_shaper_get_tc(struct rte_eth_dev *dev,
-	struct tm_shared_shaper *ss)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	/* Subport: each TC uses shared shaper  */
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->params.n_shared_shapers == 0 ||
-			n->params.shared_shaper_id[0] != ss->shared_shaper_id)
-			continue;
-
-		return n;
-	}
-
-	return NULL;
-}
-
-static int
-subport_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_subport_profiles; i++)
-		if (memcmp(&t->subport_profile[i], sp, sizeof(*sp)) == 0) {
-			if (subport_profile_id)
-				*subport_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static int
-update_subport_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shared_shaper *ss,
-	struct tm_shaper_profile *sp_new)
-{
-	struct rte_sched_subport_profile_params subport_profile;
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-	struct tm_node *np = nt->parent_node;
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_profile_id;
-	struct tm_shaper_profile *sp_old = tm_shaper_profile_search(dev,
-		ss->shaper_profile_id);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return -1;
-
-	subport_profile_id = t->subport_to_profile[subport_id];
-
-	/* Derive new subport configuration. */
-	memcpy(&subport_profile,
-		&p->soft.tm.params.subport_profile[subport_profile_id],
-		sizeof(subport_profile));
-	subport_profile.tc_rate[tc_id] = sp_new->params.peak.rate;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p),
-		subport_id, NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	sp_old->n_users--;
-
-	ss->shaper_profile_id = sp_new->shaper_profile_id;
-	sp_new->n_users++;
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&subport_profile,
-		sizeof(subport_profile));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper add/update */
-static int
-pmd_tm_shared_shaper_add_update(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-	struct tm_shaper_profile *sp;
-	struct tm_node *nt;
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * Add new shared shaper
-	 */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL) {
-		struct tm_shared_shaper_list *ssl =
-			&p->soft.tm.h.shared_shapers;
-
-		/* Hierarchy must not be frozen */
-		if (p->soft.tm.hierarchy_frozen)
-			return -rte_tm_error_set(error,
-				EBUSY,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EBUSY));
-
-		/* Memory allocation */
-		ss = calloc(1, sizeof(struct tm_shared_shaper));
-		if (ss == NULL)
-			return -rte_tm_error_set(error,
-				ENOMEM,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(ENOMEM));
-
-		/* Fill in */
-		ss->shared_shaper_id = shared_shaper_id;
-		ss->shaper_profile_id = shaper_profile_id;
-
-		/* Add to list */
-		TAILQ_INSERT_TAIL(ssl, ss, node);
-		p->soft.tm.h.n_shared_shapers++;
-
-		return 0;
-	}
-
-	/**
-	 * Update existing shared shaper
-	 */
-	/* Hierarchy must be frozen (run-time update) */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-
-	/* Propagate change. */
-	nt = tm_shared_shaper_get_tc(dev, ss);
-	if (update_subport_tc_rate(dev, nt, ss, sp))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper delete */
-static int
-pmd_tm_shared_shaper_delete(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-
-	/* Check existing */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (ss->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, ss, node);
-	p->soft.tm.h.n_shared_shapers--;
-	free(ss);
-
-	return 0;
-}
-
-static int
-wred_profile_check(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_wred_profile *wp;
-	enum rte_color color;
-
-	/* WRED profile ID must not be NONE. */
-	if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WRED profile must not exist. */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-        /* WRED profile should be in packet mode */
-        if (profile->packet_mode == 0)
-                return -rte_tm_error_set(error,
-                        ENOTSUP,
-                        RTE_TM_ERROR_TYPE_WRED_PROFILE,
-                        NULL,
-                        rte_strerror(ENOTSUP));
-
-	/* min_th <= max_th, max_th > 0  */
-	for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-		uint32_t min_th = profile->red_params[color].min_th;
-		uint32_t max_th = profile->red_params[color].max_th;
-
-		if (min_th > max_th ||
-			max_th == 0 ||
-			min_th > UINT16_MAX ||
-			max_th > UINT16_MAX)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_WRED_PROFILE,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager WRED profile add */
-static int
-pmd_tm_wred_profile_add(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-	int status;
-
-	/* Check input params */
-	status = wred_profile_check(dev, wred_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	wp = calloc(1, sizeof(struct tm_wred_profile));
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	wp->wred_profile_id = wred_profile_id;
-	memcpy(&wp->params, profile, sizeof(wp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(wpl, wp, node);
-	p->soft.tm.h.n_wred_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager WRED profile delete */
-static int
-pmd_tm_wred_profile_delete(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile *wp;
-
-	/* Check existing */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (wp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wp, node);
-	p->soft.tm.h.n_wred_profiles--;
-	free(wp);
-
-	return 0;
-}
-
-static int
-node_add_check_port(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp = tm_shaper_profile_search(dev,
-		params->shaper_profile_id);
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_subport(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_pipe(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 4 */
-	if (params->nonleaf.n_sp_priorities !=
-		RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WFQ mode must be byte mode */
-	if (params->nonleaf.wfq_weight_mode != NULL &&
-		params->nonleaf.wfq_weight_mode[0] != 0 &&
-		params->nonleaf.wfq_weight_mode[1] != 0 &&
-		params->nonleaf.wfq_weight_mode[2] != 0 &&
-		params->nonleaf.wfq_weight_mode[3] != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_tc(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority __rte_unused,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Single valid shared shaper */
-	if (params->n_shared_shapers > 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (params->n_shared_shapers == 1 &&
-		(params->shared_shaper_id == NULL ||
-		(!tm_shared_shaper_search(dev, params->shared_shaper_id[0]))))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_queue(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: leaf */
-	if (node_id >= p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shaper */
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management must not be head drop */
-	if (params->leaf.cman == RTE_TM_CMAN_HEAD_DROP)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management set to WRED */
-	if (params->leaf.cman == RTE_TM_CMAN_WRED) {
-		uint32_t wred_profile_id = params->leaf.wred.wred_profile_id;
-		struct tm_wred_profile *wp = tm_wred_profile_search(dev,
-			wred_profile_id);
-
-		/* WRED profile (for private WRED context) must be valid */
-		if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE ||
-			wp == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-
-		/* No shared WRED contexts */
-		if (params->leaf.wred.n_shared_wred_contexts != 0)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_QUEUE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct tm_node *pn;
-	uint32_t level;
-	int status;
-
-	/* node_id, parent_node_id:
-	 *    -node_id must not be RTE_TM_NODE_ID_NULL
-	 *    -node_id must not be in use
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -root node must not exist
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -parent_node_id must be valid
-	 */
-	if (node_id == RTE_TM_NODE_ID_NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (tm_node_search(dev, node_id))
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
-		pn = NULL;
-		if (tm_root_node_present(dev))
-			return -rte_tm_error_set(error,
-				EEXIST,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EEXIST));
-	} else {
-		pn = tm_node_search(dev, parent_node_id);
-		if (pn == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* priority: must be 0 .. 3 */
-	if (priority >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* level_id: if valid, then
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be zero
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be parent level ID plus one
-	 */
-	level = (pn == NULL) ? 0 : pn->level + 1;
-	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY && level_id != level)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: must not be NULL */
-	if (params == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: per level checks */
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		status = node_add_check_port(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		status = node_add_check_subport(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		status = node_add_check_pipe(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		status = node_add_check_tc(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-		status = node_add_check_queue(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager node add */
-static int
-pmd_tm_node_add(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-	uint32_t i;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = node_add_check(dev, node_id, parent_node_id, priority, weight,
-		level_id, params, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	n = calloc(1, sizeof(struct tm_node));
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	n->node_id = node_id;
-	n->parent_node_id = parent_node_id;
-	n->priority = priority;
-	n->weight = weight;
-
-	if (parent_node_id != RTE_TM_NODE_ID_NULL) {
-		n->parent_node = tm_node_search(dev, parent_node_id);
-		n->level = n->parent_node->level + 1;
-	}
-
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		n->shaper_profile = tm_shaper_profile_search(dev,
-			params->shaper_profile_id);
-
-	if (n->level == TM_NODE_LEVEL_QUEUE &&
-		params->leaf.cman == RTE_TM_CMAN_WRED)
-		n->wred_profile = tm_wred_profile_search(dev,
-			params->leaf.wred.wred_profile_id);
-
-	memcpy(&n->params, params, sizeof(n->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(nl, n, node);
-	p->soft.tm.h.n_nodes++;
-
-	/* Update dependencies */
-	if (n->parent_node)
-		n->parent_node->n_children++;
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users++;
-
-	for (i = 0; i < params->n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev, params->shared_shaper_id[i]);
-		ss->n_users++;
-	}
-
-	if (n->wred_profile)
-		n->wred_profile->n_users++;
-
-	p->soft.tm.h.n_tm_nodes[n->level]++;
-
-	return 0;
-}
-
-/* Traffic manager node delete */
-static int
-pmd_tm_node_delete(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node *n;
-	uint32_t i;
-
-	/* Check hierarchy changes are currently allowed */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Check existing */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (n->n_children)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Update dependencies */
-	p->soft.tm.h.n_tm_nodes[n->level]--;
-
-	if (n->wred_profile)
-		n->wred_profile->n_users--;
-
-	for (i = 0; i < n->params.n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev,
-				n->params.shared_shaper_id[i]);
-		ss->n_users--;
-	}
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users--;
-
-	if (n->parent_node)
-		n->parent_node->n_children--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.nodes, n, node);
-	p->soft.tm.h.n_nodes--;
-	free(n);
-
-	return 0;
-}
-
-
-static void
-pipe_profile_build(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_sched_pipe_params *pp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nt, *nq;
-
-	memset(pp, 0, sizeof(*pp));
-
-	/* Pipe */
-	pp->tb_rate = np->shaper_profile->params.peak.rate;
-	pp->tb_size = np->shaper_profile->params.peak.size;
-
-	/* Traffic Class (TC) */
-	pp->tc_period = PIPE_TC_PERIOD;
-
-	pp->tc_ov_weight = np->weight;
-
-	TAILQ_FOREACH(nt, nl, node) {
-		uint32_t queue_id = 0;
-
-		if (nt->level != TM_NODE_LEVEL_TC ||
-			nt->parent_node_id != np->node_id)
-			continue;
-
-		pp->tc_rate[nt->priority] =
-			nt->shaper_profile->params.peak.rate;
-
-		/* Queue */
-		TAILQ_FOREACH(nq, nl, node) {
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE ||
-				nq->parent_node_id != nt->node_id)
-				continue;
-
-			if (nt->priority == RTE_SCHED_TRAFFIC_CLASS_BE)
-				pp->wrr_weights[queue_id] = nq->weight;
-
-			queue_id++;
-		}
-	}
-}
-
-static int
-pipe_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_pipe_profiles < TM_MAX_PIPE_PROFILE) {
-		*pipe_profile_id = t->n_pipe_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static int
-pipe_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_pipe_profiles; i++)
-		if (memcmp(&t->pipe_profiles[i], pp, sizeof(*pp)) == 0) {
-			if (pipe_profile_id)
-				*pipe_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static void
-pipe_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->pipe_profiles[pipe_profile_id], pp, sizeof(*pp));
-	t->n_pipe_profiles++;
-}
-
-static void
-pipe_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport, pos;
-
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	pos = subport_id * n_pipes_per_subport + pipe_id;
-
-	t->pipe_to_profile[pos] = pipe_profile_id;
-}
-
-static struct rte_sched_pipe_params *
-pipe_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	uint32_t pos = subport_id * n_pipes_per_subport + pipe_id;
-	uint32_t pipe_profile_id = t->pipe_to_profile[pos];
-
-	return &t->pipe_profiles[pipe_profile_id];
-}
-
-static int
-pipe_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns, *np;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - pipe_profiles
-	 *    - n_pipe_profiles
-	 *    - pipe_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		uint32_t pipe_id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		pipe_id = 0;
-		TAILQ_FOREACH(np, nl, node) {
-			struct rte_sched_pipe_params pp;
-			uint32_t pos;
-
-			memset(&pp, 0, sizeof(pp));
-
-			if (np->level != TM_NODE_LEVEL_PIPE ||
-				np->parent_node_id != ns->node_id)
-				continue;
-
-			pipe_profile_build(dev, np, &pp);
-
-			if (!pipe_profile_exists(dev, &pp, &pos)) {
-				if (!pipe_profile_free_exists(dev, &pos))
-					return -1;
-
-				pipe_profile_install(dev, &pp, pos);
-			}
-
-			pipe_profile_mark(dev, subport_id, pipe_id, pos);
-
-			pipe_id++;
-		}
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-static struct tm_wred_profile *
-tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nq;
-
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node->priority != tc_id)
-			continue;
-
-		return nq->wred_profile;
-	}
-
-	return NULL;
-}
-
-#ifdef RTE_SCHED_CMAN
-
-static void
-wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_subport_params *pp =
-		&p->soft.tm.params.subport_params[subport_id];
-
-	uint32_t tc_id;
-	enum rte_color color;
-
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++)
-		for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-			struct rte_red_params *dst =
-				&pp->cman_params->red_params[tc_id][color];
-			struct tm_wred_profile *src_wp =
-				tm_tc_wred_profile_get(dev, tc_id);
-			struct rte_tm_red_params *src =
-				&src_wp->params.red_params[color];
-
-			memcpy(dst, src, sizeof(*dst));
-		}
-}
-
-#else
-
-#define wred_profiles_set(dev, subport_id)
-
-#endif
-
-static struct tm_shared_shaper *
-tm_tc_shared_shaper_get(struct rte_eth_dev *dev, struct tm_node *tc_node)
-{
-	return (tc_node->params.n_shared_shapers) ?
-		tm_shared_shaper_search(dev,
-			tc_node->params.shared_shaper_id[0]) :
-		NULL;
-}
-
-static struct tm_shared_shaper *
-tm_subport_tc_shared_shaper_get(struct rte_eth_dev *dev,
-	struct tm_node *subport_node,
-	uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->parent_node->parent_node_id !=
-				subport_node->node_id ||
-			n->priority != tc_id)
-			continue;
-
-		return tm_tc_shared_shaper_get(dev, n);
-	}
-
-	return NULL;
-}
-
-static struct rte_sched_subport_profile_params *
-subport_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return NULL;
-
-	return &t->subport_profile[subport_id];
-}
-
-static void
-subport_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	t->subport_to_profile[subport_id] = subport_profile_id;
-}
-
-static void
-subport_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->subport_profile[subport_profile_id],
-		sp, sizeof(*sp));
-	t->n_subport_profiles++;
-}
-
-static int
-subport_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_subport_profiles < TM_MAX_SUBPORT_PROFILE) {
-		*subport_profile_id = t->n_subport_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static void
-subport_profile_build(struct rte_eth_dev *dev, struct tm_node *np,
-	struct rte_sched_subport_profile_params *sp)
-{
-	uint32_t i;
-	memset(sp, 0, sizeof(*sp));
-
-	sp->tb_rate = np->shaper_profile->params.peak.rate;
-	sp->tb_size = np->shaper_profile->params.peak.size;
-
-	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
-		struct tm_shared_shaper *ss;
-		struct tm_shaper_profile *ssp;
-
-		ss = tm_subport_tc_shared_shaper_get(dev, np, i);
-		ssp = (ss) ? tm_shaper_profile_search(dev,
-			ss->shaper_profile_id) :
-			np->shaper_profile;
-		sp->tc_rate[i] = ssp->params.peak.rate;
-	}
-
-	/* Traffic Class (TC) */
-	sp->tc_period = SUBPORT_TC_PERIOD;
-}
-
-static int
-subport_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - subport_profiles
-	 *    - n_subport_profiles
-	 *    - subport_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		struct rte_sched_subport_profile_params sp;
-		uint32_t pos;
-
-		memset(&sp, 0, sizeof(sp));
-
-		subport_profile_build(dev, ns, &sp);
-
-		if (!subport_profile_exists(dev, &sp, &pos)) {
-			if (!subport_profile_free_exists(dev, &pos))
-				return -1;
-
-			subport_profile_install(dev, &sp, pos);
-		}
-
-		subport_profile_mark(dev, subport_id, pos);
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-
-static int
-hierarchy_commit_check(struct rte_eth_dev *dev, struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_shared_shaper_list *ssl = &h->shared_shapers;
-	struct tm_wred_profile_list *wpl = &h->wred_profiles;
-	struct tm_node *nr = tm_root_node_present(dev), *ns, *np, *nt, *nq;
-	struct tm_shared_shaper *ss;
-
-	uint32_t n_pipes_per_subport;
-
-	/* Root node exists. */
-	if (nr == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one subport, max is not exceeded. */
-	if (nr->n_children == 0 || nr->n_children > TM_MAX_SUBPORTS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one pipe. */
-	if (h->n_tm_nodes[TM_NODE_LEVEL_PIPE] == 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of pipes is the same for all subports. Maximum number of pipes
-	 * per subport is not exceeded.
-	 */
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	if (n_pipes_per_subport > TM_MAX_PIPES_PER_SUBPORT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->n_children != n_pipes_per_subport)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Each pipe has exactly 13 TCs, with exactly one TC for each priority */
-	TAILQ_FOREACH(np, nl, node) {
-		uint32_t mask = 0, mask_expected =
-			RTE_LEN2MASK(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-				uint32_t);
-
-		if (np->level != TM_NODE_LEVEL_PIPE)
-			continue;
-
-		if (np->n_children != RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-
-		TAILQ_FOREACH(nt, nl, node) {
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node_id != np->node_id)
-				continue;
-
-			mask |= 1 << nt->priority;
-		}
-
-		if (mask != mask_expected)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/** Each Strict priority TC has exactly 1 packet queues while
-	 *	lowest priority TC (Best-effort) has 4 queues.
-	 */
-	TAILQ_FOREACH(nt, nl, node) {
-		if (nt->level != TM_NODE_LEVEL_TC)
-			continue;
-
-		if (nt->n_children != 1 && nt->n_children != RTE_SCHED_BE_QUEUES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/**
-	 * Shared shapers:
-	 *    -For each TC #i, all pipes in the same subport use the same
-	 *     shared shaper (or no shared shaper) for their TC#i.
-	 *    -Each shared shaper needs to have at least one user. All its
-	 *     users have to be TC nodes with the same priority and the same
-	 *     subport.
-	 */
-	TAILQ_FOREACH(ns, nl, node) {
-		struct tm_shared_shaper *s[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++)
-			s[id] = tm_subport_tc_shared_shaper_get(dev, ns, id);
-
-		TAILQ_FOREACH(nt, nl, node) {
-			struct tm_shared_shaper *subport_ss, *tc_ss;
-
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node->parent_node_id !=
-					ns->node_id)
-				continue;
-
-			subport_ss = s[nt->priority];
-			tc_ss = tm_tc_shared_shaper_get(dev, nt);
-
-			if (subport_ss == NULL && tc_ss == NULL)
-				continue;
-
-			if ((subport_ss == NULL && tc_ss != NULL) ||
-				(subport_ss != NULL && tc_ss == NULL) ||
-				subport_ss->shared_shaper_id !=
-					tc_ss->shared_shaper_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	TAILQ_FOREACH(ss, ssl, node) {
-		struct tm_node *nt_any = tm_shared_shaper_get_tc(dev, ss);
-		uint32_t n_users = 0;
-
-		if (nt_any != NULL)
-			TAILQ_FOREACH(nt, nl, node) {
-				if (nt->level != TM_NODE_LEVEL_TC ||
-					nt->priority != nt_any->priority ||
-					nt->parent_node->parent_node_id !=
-					nt_any->parent_node->parent_node_id)
-					continue;
-
-				n_users++;
-			}
-
-		if (ss->n_users == 0 || ss->n_users != n_users)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Not too many subport profiles. */
-	if (subport_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-
-	/* Not too many pipe profiles. */
-	if (pipe_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * WRED (when used, i.e. at least one WRED profile defined):
-	 *    -Each WRED profile must have at least one user.
-	 *    -All leaf nodes must have their private WRED context enabled.
-	 *    -For each TC #i, all leaf nodes must use the same WRED profile
-	 *     for their private WRED context.
-	 */
-	if (h->n_wred_profiles) {
-		struct tm_wred_profile *wp;
-		struct tm_wred_profile *w[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		TAILQ_FOREACH(wp, wpl, node)
-			if (wp->n_users == 0)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			w[id] = tm_tc_wred_profile_get(dev, id);
-
-			if (w[id] == NULL)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-
-		TAILQ_FOREACH(nq, nl, node) {
-			uint32_t id;
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE)
-				continue;
-
-			id = nq->parent_node->priority;
-
-			if (nq->wred_profile == NULL ||
-				nq->wred_profile->wred_profile_id !=
-					w[id]->wred_profile_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	return 0;
-}
-
-static void
-hierarchy_blueprints_create(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *root = tm_root_node_present(dev), *n;
-
-	uint32_t subport_id;
-
-	t->port_params = (struct rte_sched_port_params) {
-		.name = dev->data->name,
-		.socket = dev->data->numa_node,
-		.rate = root->shaper_profile->params.peak.rate,
-		.mtu = dev->data->mtu,
-		.frame_overhead =
-			root->shaper_profile->params.pkt_length_adjust,
-		.n_subports_per_port = root->n_children,
-		.n_subport_profiles = t->n_subport_profiles,
-		.subport_profiles = t->subport_profile,
-		.n_max_subport_profiles = TM_MAX_SUBPORT_PROFILE,
-		.n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT,
-	};
-
-	subport_id = 0;
-	TAILQ_FOREACH(n, nl, node) {
-
-		if (n->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		t->subport_params[subport_id] =
-			(struct rte_sched_subport_params) {
-				.n_pipes_per_subport_enabled =
-					h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-					h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT],
-				.qsize = {p->params.tm.qsize[0],
-					p->params.tm.qsize[1],
-					p->params.tm.qsize[2],
-					p->params.tm.qsize[3],
-					p->params.tm.qsize[4],
-					p->params.tm.qsize[5],
-					p->params.tm.qsize[6],
-					p->params.tm.qsize[7],
-					p->params.tm.qsize[8],
-					p->params.tm.qsize[9],
-					p->params.tm.qsize[10],
-					p->params.tm.qsize[11],
-					p->params.tm.qsize[12],
-				},
-				.pipe_profiles = t->pipe_profiles,
-				.n_pipe_profiles = t->n_pipe_profiles,
-				.n_max_pipe_profiles = TM_MAX_PIPE_PROFILE,
-		};
-		wred_profiles_set(dev, subport_id);
-		subport_id++;
-	}
-}
-
-/* Traffic manager hierarchy commit */
-static int
-pmd_tm_hierarchy_commit(struct rte_eth_dev *dev,
-	int clear_on_fail,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = hierarchy_commit_check(dev, error);
-	if (status) {
-		if (clear_on_fail)
-			tm_hierarchy_free(p);
-
-		return status;
-	}
-
-	/* Create blueprints */
-	hierarchy_blueprints_create(dev);
-
-	/* Freeze hierarchy */
-	p->soft.tm.hierarchy_frozen = 1;
-
-	return 0;
-}
-
-static int
-update_pipe_weight(struct rte_eth_dev *dev, struct tm_node *np, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_ov_weight = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->weight = weight;
-
-	return 0;
-}
-
-static int
-update_queue_weight(struct rte_eth_dev *dev,
-	struct tm_node *nq, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	uint32_t pipe_be_queue_id =
-		queue_id - RTE_SCHED_TRAFFIC_CLASS_BE;
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.wrr_weights[pipe_be_queue_id] = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set
-	 * of pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nq->weight = weight;
-
-	return 0;
-}
-
-/* Traffic manager node parent update */
-static int
-pmd_tm_node_parent_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Parent node must be the same */
-	if (n->parent_node_id != parent_node_id)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be the same */
-	if (n->priority != priority)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		if (update_queue_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-static int
-update_subport_rate(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_subport_profile_params *profile0 =
-					subport_profile_get(dev, ns);
-	struct rte_sched_subport_profile_params profile1;
-	uint32_t subport_profile_id;
-
-	if (profile0 == NULL)
-		return -1;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more subport profiles
-	 * after port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (subport_profile_exists(dev, &profile1, &subport_profile_id) == 0)
-		return -1;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p), subport_id,
-		NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	ns->shaper_profile->n_users--;
-
-	ns->shaper_profile = sp;
-	ns->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	subport_profile_mark(dev, subport_id, subport_profile_id);
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&profile1,
-		sizeof(profile1));
-
-	return 0;
-}
-
-static int
-update_pipe_rate(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->shaper_profile->n_users--;
-	np->shaper_profile = sp;
-	np->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-static int
-update_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_rate[tc_id] = sp->params.peak.rate;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nt->shaper_profile->n_users--;
-	nt->shaper_profile = sp;
-	nt->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-/* Traffic manager node shaper update */
-static int
-pmd_tm_node_shaper_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-	struct tm_shaper_profile *sp;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		if (update_subport_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		if (update_tc_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-}
-
-static inline uint32_t
-tm_port_queue_id(struct rte_eth_dev *dev,
-	uint32_t port_subport_id,
-	uint32_t subport_pipe_id,
-	uint32_t pipe_tc_id,
-	uint32_t tc_queue_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-			h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t port_pipe_id =
-		port_subport_id * n_pipes_per_subport + subport_pipe_id;
-
-	uint32_t port_queue_id =
-		port_pipe_id * RTE_SCHED_QUEUES_PER_PIPE + pipe_tc_id + tc_queue_id;
-
-	return port_queue_id;
-}
-
-static int
-read_port_stats(struct rte_eth_dev *dev,
-	struct tm_node *nr,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_subports_per_port = h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	uint32_t subport_id;
-
-	for (subport_id = 0; subport_id < n_subports_per_port; subport_id++) {
-		struct rte_sched_subport_stats s;
-		uint32_t tc_ov, id;
-
-		/* Stats read */
-		int status = rte_sched_subport_read_stats(SCHED(p),
-			subport_id,
-			&s,
-			&tc_ov);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			nr->stats.n_pkts +=
-				s.n_pkts_tc[id] - s.n_pkts_tc_dropped[id];
-			nr->stats.n_bytes +=
-				s.n_bytes_tc[id] - s.n_bytes_tc_dropped[id];
-			nr->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_tc_dropped[id];
-			nr->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_tc_dropped[id];
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nr->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nr->stats, 0, sizeof(nr->stats));
-
-	return 0;
-}
-
-static int
-read_subport_stats(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_subport_stats s;
-	uint32_t tc_ov, tc_id;
-
-	/* Stats read */
-	int status = rte_sched_subport_read_stats(SCHED(p),
-		subport_id,
-		&s,
-		&tc_ov);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++) {
-		ns->stats.n_pkts +=
-			s.n_pkts_tc[tc_id] - s.n_pkts_tc_dropped[tc_id];
-		ns->stats.n_bytes +=
-			s.n_bytes_tc[tc_id] - s.n_bytes_tc_dropped[tc_id];
-		ns->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-			s.n_pkts_tc_dropped[tc_id];
-		ns->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_tc_dropped[tc_id];
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &ns->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&ns->stats, 0, sizeof(ns->stats));
-
-	return 0;
-}
-
-static int
-read_pipe_stats(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	uint32_t tc_id, queue_id;
-	uint32_t i;
-
-	/* Stats read */
-	for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) {
-		struct rte_sched_queue_stats s;
-		uint16_t qlen;
-
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			tc_id = i;
-			queue_id = i;
-		} else {
-			tc_id = RTE_SCHED_TRAFFIC_CLASS_BE;
-			queue_id = i - tc_id;
-		}
-
-		uint32_t qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			queue_id);
-
-		int status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		np->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		np->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		np->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_queued = qlen;
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &np->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&np->stats, 0, sizeof(np->stats));
-
-	return 0;
-}
-
-static int
-read_tc_stats(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_queue_stats s;
-	uint32_t qid, i;
-	uint16_t qlen;
-	int status;
-
-	/* Stats read */
-	if (tc_id < RTE_SCHED_TRAFFIC_CLASS_BE) {
-		qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			0);
-
-		status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_queued = qlen;
-	} else {
-		for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) {
-			qid = tm_port_queue_id(dev,
-				subport_id,
-				pipe_id,
-				tc_id,
-				i);
-
-			status = rte_sched_queue_read_stats(SCHED(p),
-				qid,
-				&s,
-				&qlen);
-			if (status)
-				return status;
-
-			/* Stats accumulate */
-			nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-			nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_dropped;
-			nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_queued = qlen;
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nt->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nt->stats, 0, sizeof(nt->stats));
-
-	return 0;
-}
-
-static int
-read_queue_stats(struct rte_eth_dev *dev,
-	struct tm_node *nq,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_queue_stats s;
-	uint16_t qlen;
-
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	/* Stats read */
-	uint32_t qid = tm_port_queue_id(dev,
-		subport_id,
-		pipe_id,
-		tc_id,
-		queue_id);
-
-	int status = rte_sched_queue_read_stats(SCHED(p),
-		qid,
-		&s,
-		&qlen);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	nq->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-	nq->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-	nq->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-		s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_queued = qlen;
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nq->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_QUEUE;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nq->stats, 0, sizeof(nq->stats));
-
-	return 0;
-}
-
-/* Traffic manager read stats counters for specific node */
-static int
-pmd_tm_node_stats_read(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		if (read_port_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		if (read_subport_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_PIPE:
-		if (read_pipe_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_TC:
-		if (read_tc_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		if (read_queue_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-const struct rte_tm_ops pmd_tm_ops = {
-	.node_type_get = pmd_tm_node_type_get,
-	.capabilities_get = pmd_tm_capabilities_get,
-	.level_capabilities_get = pmd_tm_level_capabilities_get,
-	.node_capabilities_get = pmd_tm_node_capabilities_get,
-
-	.wred_profile_add = pmd_tm_wred_profile_add,
-	.wred_profile_delete = pmd_tm_wred_profile_delete,
-	.shared_wred_context_add_update = NULL,
-	.shared_wred_context_delete = NULL,
-
-	.shaper_profile_add = pmd_tm_shaper_profile_add,
-	.shaper_profile_delete = pmd_tm_shaper_profile_delete,
-	.shared_shaper_add_update = pmd_tm_shared_shaper_add_update,
-	.shared_shaper_delete = pmd_tm_shared_shaper_delete,
-
-	.node_add = pmd_tm_node_add,
-	.node_delete = pmd_tm_node_delete,
-	.node_suspend = NULL,
-	.node_resume = NULL,
-	.hierarchy_commit = pmd_tm_hierarchy_commit,
-
-	.node_parent_update = pmd_tm_node_parent_update,
-	.node_shaper_update = pmd_tm_node_shaper_update,
-	.node_shared_shaper_update = NULL,
-	.node_stats_update = NULL,
-	.node_wfq_weight_mode_update = NULL,
-	.node_cman_update = NULL,
-	.node_wred_context_update = NULL,
-	.node_shared_wred_context_update = NULL,
-
-	.node_stats_read = pmd_tm_node_stats_read,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 02/21] net/softnic: remove flow support
  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   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 03/21] net/softnic: remove the meter support Cristian Dumitrescu
                     ` (18 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device flow API support.

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      |    9 -
 drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -
 drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------
 4 files changed, 2384 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index e2dbd6166e..4ebe60921c 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -13,7 +13,6 @@ sources = files(
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_cryptodev.c',
-        'rte_eth_softnic_flow.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_meter.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index ae3e8b3bcd..8e361adbad 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -215,14 +215,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
-		 const struct rte_flow_ops **ops)
-{
-	*ops = &pmd_flow_ops;
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -240,7 +232,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.flow_ops_get = pmd_flow_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7556e50831..671f96cf77 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4731,81 +4731,6 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * flowapi map
- *  group <group_id>
- *  ingress | egress
- *  pipeline <pipeline_name>
- *  table <table_id>
- */
-static void
-cmd_softnic_flowapi_map(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t group_id, table_id;
-	int ingress, status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "map") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "map");
-		return;
-	}
-
-	if (strcmp(tokens[2], "group") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "ingress") == 0) {
-		ingress = 1;
-	} else if (strcmp(tokens[4], "egress") == 0) {
-		ingress = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ingress | egress");
-		return;
-	}
-
-	if (strcmp(tokens[5], "pipeline") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
-		return;
-	}
-
-	pipeline_name = tokens[6];
-
-	if (strcmp(tokens[7], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = flow_attr_map_set(softnic,
-			group_id,
-			ingress,
-			pipeline_name,
-			table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 void
 softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 {
@@ -5063,12 +4988,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		}
 	}
 
-	if (strcmp(tokens[0], "flowapi") == 0) {
-		cmd_softnic_flowapi_map(softnic, tokens, n_tokens, out,
-					out_size);
-		return;
-	}
-
 	snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
 }
 
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
deleted file mode 100644
index ad96288e7e..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ /dev/null
@@ -1,2293 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-#include <rte_flow.h>
-#include <rte_flow_driver.h>
-#include <rte_tailq.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define rte_htons rte_cpu_to_be_16
-#define rte_htonl rte_cpu_to_be_32
-
-#define rte_ntohs rte_be_to_cpu_16
-#define rte_ntohl rte_be_to_cpu_32
-
-static struct rte_flow *
-softnic_flow_find(struct softnic_table *table,
-	struct softnic_table_rule_match *rule_match)
-{
-	struct rte_flow *flow;
-
-	TAILQ_FOREACH(flow, &table->flows, node)
-		if (memcmp(&flow->match, rule_match, sizeof(*rule_match)) == 0)
-			return flow;
-
-	return NULL;
-}
-
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id)
-{
-	struct pipeline *pipeline;
-	struct flow_attr_map *map;
-
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||
-			pipeline_name == NULL)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL ||
-			table_id >= pipeline->n_tables)
-		return -1;
-
-	map = (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-	strlcpy(map->pipeline_name, pipeline_name, sizeof(map->pipeline_name));
-	map->table_id = table_id;
-	map->valid = 1;
-
-	return 0;
-}
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress)
-{
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS)
-		return NULL;
-
-	return (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-}
-
-static int
-flow_pipeline_table_get(struct pmd_internals *softnic,
-		const struct rte_flow_attr *attr,
-		const char **pipeline_name,
-		uint32_t *table_id,
-		struct rte_flow_error *error)
-{
-	struct flow_attr_map *map;
-
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL,
-				"Null attr");
-
-	if (!attr->ingress && !attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Ingress/egress not specified");
-
-	if (attr->ingress && attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Setting both ingress and egress is not allowed");
-
-	map = flow_attr_map_get(softnic,
-			attr->group,
-			attr->ingress);
-	if (map == NULL ||
-			map->valid == 0)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
-				attr,
-				"Invalid group ID");
-
-	if (pipeline_name)
-		*pipeline_name = map->pipeline_name;
-
-	if (table_id)
-		*table_id = map->table_id;
-
-	return 0;
-}
-
-union flow_item {
-	uint8_t raw[TABLE_RULE_MATCH_SIZE_MAX];
-	struct rte_flow_item_eth eth;
-	struct rte_flow_item_vlan vlan;
-	struct rte_flow_item_ipv4 ipv4;
-	struct rte_flow_item_ipv6 ipv6;
-	struct rte_flow_item_icmp icmp;
-	struct rte_flow_item_udp udp;
-	struct rte_flow_item_tcp tcp;
-	struct rte_flow_item_sctp sctp;
-	struct rte_flow_item_vxlan vxlan;
-	struct rte_flow_item_e_tag e_tag;
-	struct rte_flow_item_nvgre nvgre;
-	struct rte_flow_item_mpls mpls;
-	struct rte_flow_item_gre gre;
-	struct rte_flow_item_gtp gtp;
-	struct rte_flow_item_esp esp;
-	struct rte_flow_item_geneve geneve;
-	struct rte_flow_item_vxlan_gpe vxlan_gpe;
-	struct rte_flow_item_arp_eth_ipv4 arp_eth_ipv4;
-	struct rte_flow_item_ipv6_ext ipv6_ext;
-	struct rte_flow_item_icmp6 icmp6;
-	struct rte_flow_item_icmp6_nd_ns icmp6_nd_ns;
-	struct rte_flow_item_icmp6_nd_na icmp6_nd_na;
-	struct rte_flow_item_icmp6_nd_opt icmp6_nd_opt;
-	struct rte_flow_item_icmp6_nd_opt_sla_eth icmp6_nd_opt_sla_eth;
-	struct rte_flow_item_icmp6_nd_opt_tla_eth icmp6_nd_opt_tla_eth;
-};
-
-static const union flow_item flow_item_raw_mask;
-
-static int
-flow_item_is_proto(enum rte_flow_item_type type,
-	const void **mask,
-	size_t *size)
-{
-	switch (type) {
-	case RTE_FLOW_ITEM_TYPE_RAW:
-		*mask = &flow_item_raw_mask;
-		*size = sizeof(flow_item_raw_mask);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_ETH:
-		*mask = &rte_flow_item_eth_mask;
-		*size = sizeof(struct rte_ether_hdr);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_VLAN:
-		*mask = &rte_flow_item_vlan_mask;
-		*size = sizeof(struct rte_vlan_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-		*mask = &rte_flow_item_ipv4_mask;
-		*size = sizeof(struct rte_ipv4_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-		*mask = &rte_flow_item_ipv6_mask;
-		*size = sizeof(struct rte_ipv6_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP:
-		*mask = &rte_flow_item_icmp_mask;
-		*size = sizeof(struct rte_flow_item_icmp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-		*mask = &rte_flow_item_udp_mask;
-		*size = sizeof(struct rte_flow_item_udp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_TCP:
-		*mask = &rte_flow_item_tcp_mask;
-		*size = sizeof(struct rte_flow_item_tcp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-		*mask = &rte_flow_item_sctp_mask;
-		*size = sizeof(struct rte_flow_item_sctp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN:
-		*mask = &rte_flow_item_vxlan_mask;
-		*size = sizeof(struct rte_flow_item_vxlan);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_E_TAG:
-		*mask = &rte_flow_item_e_tag_mask;
-		*size = sizeof(struct rte_flow_item_e_tag);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_NVGRE:
-		*mask = &rte_flow_item_nvgre_mask;
-		*size = sizeof(struct rte_flow_item_nvgre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_MPLS:
-		*mask = &rte_flow_item_mpls_mask;
-		*size = sizeof(struct rte_flow_item_mpls);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GRE:
-		*mask = &rte_flow_item_gre_mask;
-		*size = sizeof(struct rte_flow_item_gre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GTP:
-	case RTE_FLOW_ITEM_TYPE_GTPC:
-	case RTE_FLOW_ITEM_TYPE_GTPU:
-		*mask = &rte_flow_item_gtp_mask;
-		*size = sizeof(struct rte_flow_item_gtp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ESP:
-		*mask = &rte_flow_item_esp_mask;
-		*size = sizeof(struct rte_flow_item_esp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GENEVE:
-		*mask = &rte_flow_item_geneve_mask;
-		*size = sizeof(struct rte_flow_item_geneve);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
-		*mask = &rte_flow_item_vxlan_gpe_mask;
-		*size = sizeof(struct rte_flow_item_vxlan_gpe);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4:
-		*mask = &rte_flow_item_arp_eth_ipv4_mask;
-		*size = sizeof(struct rte_flow_item_arp_eth_ipv4);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
-		*mask = &rte_flow_item_ipv6_ext_mask;
-		*size = sizeof(struct rte_flow_item_ipv6_ext);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6:
-		*mask = &rte_flow_item_icmp6_mask;
-		*size = sizeof(struct rte_flow_item_icmp6);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS:
-		*mask = &rte_flow_item_icmp6_nd_ns_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_ns);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA:
-		*mask = &rte_flow_item_icmp6_nd_na_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_na);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT:
-		*mask = &rte_flow_item_icmp6_nd_opt_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_sla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_tla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth);
-		return 1;
-
-	default: return 0; /* FALSE */
-	}
-}
-
-static int
-flow_item_raw_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const struct rte_flow_item_raw *item_raw_spec = item->spec;
-	const struct rte_flow_item_raw *item_raw_mask = item->mask;
-	const uint8_t *pattern;
-	const uint8_t *pattern_mask;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t pattern_length, pattern_offset, i;
-	int disabled;
-
-	if (!item->spec)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Null specification");
-
-	if (item->last)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Range not allowed (last must be NULL)");
-
-	if (item_raw_spec->relative == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Absolute offset not supported");
-
-	if (item_raw_spec->search)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Search not supported");
-
-	if (item_raw_spec->offset < 0)
-		return rte_flow_error_set(error,
-			ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Negative offset not supported");
-
-	if (item_raw_spec->length == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Zero pattern length");
-
-	if (item_raw_spec->offset + item_raw_spec->length >
-		TABLE_RULE_MATCH_SIZE_MAX)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Item too big");
-
-	if (!item_raw_spec->pattern && item_raw_mask && item_raw_mask->pattern)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Non-NULL pattern mask not allowed with NULL pattern");
-
-	pattern = item_raw_spec->pattern;
-	pattern_mask = (item_raw_mask) ? item_raw_mask->pattern : NULL;
-	pattern_length = (size_t)item_raw_spec->length;
-	pattern_offset = (size_t)item_raw_spec->offset;
-
-	disabled = 0;
-	if (pattern_mask == NULL)
-		disabled = 1;
-	else
-		for (i = 0; i < pattern_length; i++)
-			if ((pattern)[i])
-				disabled = 1;
-
-	memset(spec, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern)
-		memcpy(&spec[pattern_offset], pattern, pattern_length);
-
-	memset(mask, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern_mask)
-		memcpy(&mask[pattern_offset], pattern_mask, pattern_length);
-
-	*item_size = pattern_offset + pattern_length;
-	*item_disabled = disabled;
-
-	return 0;
-}
-
-static int
-flow_item_proto_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const void *mask_default;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t size, i;
-
-	if (!flow_item_is_proto(item->type, &mask_default, &size))
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"Item type not supported");
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_RAW)
-		return flow_item_raw_preprocess(item,
-			item_spec,
-			item_mask,
-			item_size,
-			item_disabled,
-			error);
-
-	/* spec */
-	if (!item->spec) {
-		/* If spec is NULL, then last and mask also have to be NULL. */
-		if (item->last || item->mask)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"Invalid item (NULL spec with non-NULL last or mask)");
-
-		memset(item_spec, 0, size);
-		memset(item_mask, 0, size);
-		*item_size = size;
-		*item_disabled = 1; /* TRUE */
-		return 0;
-	}
-
-	memcpy(spec, item->spec, size);
-	*item_size = size;
-
-	/* mask */
-	if (item->mask)
-		memcpy(mask, item->mask, size);
-	else
-		memcpy(mask, mask_default, size);
-
-	/* disabled */
-	for (i = 0; i < size; i++)
-		if (mask[i])
-			break;
-	*item_disabled = (i == size) ? 1 : 0;
-
-	/* Apply mask over spec. */
-	for (i = 0; i < size; i++)
-		spec[i] &= mask[i];
-
-	/* last */
-	if (item->last) {
-		uint8_t last[size];
-
-		/* init last */
-		memcpy(last, item->last, size);
-		for (i = 0; i < size; i++)
-			last[i] &= mask[i];
-
-		/* check for range */
-		for (i = 0; i < size; i++)
-			if (last[i] != spec[i])
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"Range not supported");
-	}
-
-	return 0;
-}
-
-/***
- * Skip disabled protocol items and VOID items
- * until any of the mutually exclusive conditions
- * from the list below takes place:
- *    (A) A protocol present in the proto_mask
- *        is met (either ENABLED or DISABLED);
- *    (B) A protocol NOT present in the proto_mask is met in ENABLED state;
- *    (C) The END item is met.
- */
-static int
-flow_item_skip_disabled_protos(const struct rte_flow_item **item,
-	uint64_t proto_mask,
-	size_t *length,
-	struct rte_flow_error *error)
-{
-	size_t len = 0;
-
-	for ( ; (*item)->type != RTE_FLOW_ITEM_TYPE_END; (*item)++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled = 0, status;
-
-		if ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(*item,
-				&spec,
-				&mask,
-				&size,
-				&disabled,
-				error);
-		if (status)
-			return status;
-
-		if ((proto_mask & (1LLU << (*item)->type)) ||
-				!disabled)
-			break;
-
-		len += size;
-	}
-
-	if (length)
-		*length = len;
-
-	return 0;
-}
-
-#define FLOW_ITEM_PROTO_IP \
-	((1LLU << RTE_FLOW_ITEM_TYPE_IPV4) | \
-	 (1LLU << RTE_FLOW_ITEM_TYPE_IPV6))
-
-static void
-flow_item_skip_void(const struct rte_flow_item **item)
-{
-	for ( ; ; (*item)++)
-		if ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID)
-			return;
-}
-
-#define IP_PROTOCOL_TCP 0x06
-#define IP_PROTOCOL_UDP 0x11
-#define IP_PROTOCOL_SCTP 0x84
-
-static int
-mask_to_depth(uint64_t mask,
-		uint32_t *depth)
-{
-	uint64_t n;
-
-	if (mask == UINT64_MAX) {
-		if (depth)
-			*depth = 64;
-
-		return 0;
-	}
-
-	mask = ~mask;
-
-	if (mask & (mask + 1))
-		return -1;
-
-	n = __builtin_popcountll(mask);
-	if (depth)
-		*depth = (uint32_t)(64 - n);
-
-	return 0;
-}
-
-static int
-ipv4_mask_to_depth(uint32_t mask,
-		uint32_t *depth)
-{
-	uint32_t d;
-	int status;
-
-	status = mask_to_depth(mask | (UINT64_MAX << 32), &d);
-	if (status)
-		return status;
-
-	d -= 32;
-	if (depth)
-		*depth = d;
-
-	return 0;
-}
-
-static int
-ipv6_mask_to_depth(uint8_t *mask,
-	uint32_t *depth)
-{
-	uint64_t *m = (uint64_t *)mask;
-	uint64_t m0 = rte_be_to_cpu_64(m[0]);
-	uint64_t m1 = rte_be_to_cpu_64(m[1]);
-	uint32_t d0, d1;
-	int status;
-
-	status = mask_to_depth(m0, &d0);
-	if (status)
-		return status;
-
-	status = mask_to_depth(m1, &d1);
-	if (status)
-		return status;
-
-	if (d0 < 64 && d1)
-		return -1;
-
-	if (depth)
-		*depth = d0 + d1;
-
-	return 0;
-}
-
-static int
-port_mask_to_range(uint16_t port,
-	uint16_t port_mask,
-	uint16_t *port0,
-	uint16_t *port1)
-{
-	int status;
-	uint16_t p0, p1;
-
-	status = mask_to_depth(port_mask | (UINT64_MAX << 16), NULL);
-	if (status)
-		return -1;
-
-	p0 = port & port_mask;
-	p1 = p0 | ~port_mask;
-
-	if (port0)
-		*port0 = p0;
-
-	if (port1)
-		*port1 = p1;
-
-	return 0;
-}
-
-static int
-flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
-		struct pipeline *pipeline __rte_unused,
-		struct softnic_table *table __rte_unused,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	union flow_item spec, mask;
-	size_t size, length = 0;
-	int disabled = 0, status;
-	uint8_t ip_proto, ip_proto_mask;
-
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_ACL;
-	rule_match->match.acl.priority = attr->priority;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item,
-			FLOW_ITEM_PROTO_IP, &length, error);
-	if (status)
-		return status;
-
-	/* IP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.src_addr),
-				&sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header source address mask");
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.dst_addr),
-				&da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header destination address mask");
-
-		ip_proto = spec.ipv4.hdr.next_proto_id;
-		ip_proto_mask = mask.ipv4.hdr.next_proto_id;
-
-		rule_match->match.acl.ip_version = 1;
-		rule_match->match.acl.ipv4.sa =
-			rte_ntohl(spec.ipv4.hdr.src_addr);
-		rule_match->match.acl.ipv4.da =
-			rte_ntohl(spec.ipv4.hdr.dst_addr);
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV4 */
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.src_addr, &sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header source address mask");
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.dst_addr, &da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header destination address mask");
-
-		ip_proto = spec.ipv6.hdr.proto;
-		ip_proto_mask = mask.ipv6.hdr.proto;
-
-		rule_match->match.acl.ip_version = 0;
-		memcpy(rule_match->match.acl.ipv6.sa,
-			spec.ipv6.hdr.src_addr,
-			sizeof(spec.ipv6.hdr.src_addr));
-		memcpy(rule_match->match.acl.ipv6.da,
-			spec.ipv6.hdr.dst_addr,
-			sizeof(spec.ipv6.hdr.dst_addr));
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV6 */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: IP protocol required");
-	} /* switch */
-
-	if (ip_proto_mask != UINT8_MAX)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Illegal IP protocol mask");
-
-	item++;
-
-	/* VOID only, if any. */
-	flow_item_skip_void(&item);
-
-	/* TCP/UDP/SCTP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_TCP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_TCP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is TCP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.src_port),
-				rte_ntohs(mask.tcp.hdr.src_port),
-				&sp0,
-				&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.dst_port),
-				rte_ntohs(mask.tcp.hdr.dst_port),
-				&dp0,
-				&dp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_TCP */
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_UDP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is UDP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.src_port),
-			rte_ntohs(mask.udp.hdr.src_port),
-			&sp0,
-			&sp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.dst_port),
-			rte_ntohs(mask.udp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_UDP */
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_SCTP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is SCTP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.src_port),
-			rte_ntohs(mask.sctp.hdr.src_port),
-			&sp0,
-			&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.dst_port),
-			rte_ntohs(mask.sctp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_SCTP */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: TCP/UDP/SCTP required");
-	} /* switch */
-
-	item++;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-	if (status)
-		return status;
-
-	/* END only. */
-	if (item->type != RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Expecting END item");
-
-	return 0;
-}
-
-/***
- * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize*
- * respectively.
- * They are located within a larger buffer at offsets *toffset* and *foffset*
- * respectively. Both *tmask* and *fmask* represent bitmasks for the larger
- * buffer.
- * Question: are the two masks equivalent?
- *
- * Notes:
- * 1. Offset basically indicates that the first offset bytes in the buffer
- *    are "don't care", so offset is equivalent to pre-pending an "all-zeros"
- *    array of *offset* bytes to the *mask*.
- * 2. Each *mask* might contain a number of zero bytes at the beginning or
- *    at the end.
- * 3. Bytes in the larger buffer after the end of the *mask* are also considered
- *    "don't care", so they are equivalent to appending an "all-zeros" array of
- *    bytes to the *mask*.
- *
- * Example:
- * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes
- * tmask = [00 22 00 33 00], toffset = 2, tsize = 5
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * fmask = [22 00 33], foffset = 3, fsize = 3 =>
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * Therefore, the tmask and fmask from this example are equivalent.
- */
-static int
-hash_key_mask_is_same(uint8_t *tmask,
-	size_t toffset,
-	size_t tsize,
-	uint8_t *fmask,
-	size_t foffset,
-	size_t fsize,
-	size_t *toffset_plus,
-	size_t *foffset_plus)
-{
-	size_t tpos; /* Position of first non-zero byte in the tmask buffer. */
-	size_t fpos; /* Position of first non-zero byte in the fmask buffer. */
-
-	/* Compute tpos and fpos. */
-	for (tpos = 0; tmask[tpos] == 0; tpos++)
-		;
-	for (fpos = 0; fmask[fpos] == 0; fpos++)
-		;
-
-	if (toffset + tpos != foffset + fpos)
-		return 0; /* FALSE */
-
-	tsize -= tpos;
-	fsize -= fpos;
-
-	if (tsize < fsize) {
-		size_t i;
-
-		for (i = 0; i < tsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < fsize; i++)
-			if (fmask[fpos + i])
-				return 0; /* FALSE */
-	} else {
-		size_t i;
-
-		for (i = 0; i < fsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < tsize; i++)
-			if (tmask[tpos + i])
-				return 0; /* FALSE */
-	}
-
-	if (toffset_plus)
-		*toffset_plus = tpos;
-
-	if (foffset_plus)
-		*foffset_plus = fpos;
-
-	return 1; /* TRUE */
-}
-
-static int
-flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused,
-	struct pipeline *pipeline __rte_unused,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr __rte_unused,
-	const struct rte_flow_item *item,
-	struct softnic_table_rule_match *rule_match,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match_hash key, key_mask;
-	struct softnic_table_hash_params *params = &table->params.match.hash;
-	size_t offset = 0, length = 0, tpos, fpos;
-	int status;
-
-	memset(&key, 0, sizeof(key));
-	memset(&key_mask, 0, sizeof(key_mask));
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, &offset, error);
-	if (status)
-		return status;
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"HASH: END detected too early");
-
-	/* VOID or any protocols (enabled or disabled). */
-	for ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled, status;
-
-		if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(item,
-			&spec,
-			&mask,
-			&size,
-			&disabled,
-			error);
-		if (status)
-			return status;
-
-		if (length + size > sizeof(key)) {
-			if (disabled)
-				break;
-
-			return rte_flow_error_set(error,
-				ENOTSUP,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Item too big");
-		}
-
-		memcpy(&key.key[length], &spec, size);
-		memcpy(&key_mask.key[length], &mask, size);
-		length += size;
-	}
-
-	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
-		/* VOID or disabled protos only, if any. */
-		status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-		if (status)
-			return status;
-
-		/* END only. */
-		if (item->type != RTE_FLOW_ITEM_TYPE_END)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Expecting END item");
-	}
-
-	/* Compare flow key mask against table key mask. */
-	offset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
-
-	if (!hash_key_mask_is_same(params->key_mask,
-		params->key_offset,
-		params->key_size,
-		key_mask.key,
-		offset,
-		length,
-		&tpos,
-		&fpos))
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"HASH: Item list is not observing the match format");
-
-	/* Rule match. */
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_HASH;
-	memcpy(&rule_match->match.hash.key[tpos],
-		&key.key[fpos],
-		RTE_MIN(sizeof(rule_match->match.hash.key) - tpos,
-			length - fpos));
-
-	return 0;
-}
-
-static int
-flow_rule_match_get(struct pmd_internals *softnic,
-		struct pipeline *pipeline,
-		struct softnic_table *table,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	switch (table->params.match_type) {
-	case TABLE_ACL:
-		return flow_rule_match_acl_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	case TABLE_HASH:
-		return flow_rule_match_hash_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Unsupported pipeline table match type");
-	}
-}
-
-static int
-flow_rule_action_get(struct pmd_internals *softnic,
-	struct pipeline *pipeline,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_action *action,
-	struct softnic_table_rule_action *rule_action,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_action_profile *profile;
-	struct softnic_table_action_profile_params *params;
-	struct softnic_mtr_meter_policy *policy;
-	int n_jump_queue_rss_drop = 0;
-	int n_count = 0;
-	int n_mark = 0;
-	int n_vxlan_decap = 0;
-
-	profile = softnic_table_action_profile_find(softnic,
-		table->params.action_profile_name);
-	if (profile == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			action,
-			"JUMP: Table action profile");
-
-	params = &profile->params;
-
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
-			continue;
-
-		switch (action->type) {
-		case RTE_FLOW_ACTION_TYPE_JUMP:
-		{
-			const struct rte_flow_action_jump *conf = action->conf;
-			struct flow_attr_map *map;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"JUMP: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is"
-					" allowed per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			map = flow_attr_map_get(softnic,
-				conf->group,
-				attr->ingress);
-			if (map == NULL || map->valid == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Invalid group mapping");
-
-			if (strcmp(pipeline->name, map->pipeline_name) != 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Jump to table in different pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-			rule_action->fwd.id = map->table_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_JUMP */
-
-		case RTE_FLOW_ACTION_TYPE_QUEUE:
-		{
-			char name[NAME_SIZE];
-			struct rte_eth_dev *dev;
-			const struct rte_flow_action_queue *conf = action->conf;
-			uint32_t port_id;
-			int status;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed"
-					" per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"QUEUE action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			dev = ETHDEV(softnic);
-			if (dev == NULL ||
-				conf->index >= dev->data->nb_rx_queues)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Invalid RX queue ID");
-
-			snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->index);
-
-			status = softnic_pipeline_port_out_find(softnic,
-				pipeline->name,
-				name,
-				&port_id);
-			if (status)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: RX queue not accessible from this pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT;
-			rule_action->fwd.id = port_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /*RTE_FLOW_ACTION_TYPE_QUEUE */
-
-		case RTE_FLOW_ACTION_TYPE_RSS:
-		{
-			const struct rte_flow_action_rss *conf = action->conf;
-			uint32_t i;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"RSS: Null configuration");
-
-			if (!rte_is_power_of_2(conf->queue_num))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues must be a power of 2");
-
-			if (conf->queue_num > RTE_DIM(rule_action->lb.out))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues too big");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-
-			if (((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0) ||
-				((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_LB)) == 0))
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this table");
-
-			if (params->lb.out_offset !=
-				pipeline->params.offset_port_id)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this pipeline");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_LB */
-			for (i = 0; i < conf->queue_num; i++) {
-				char name[NAME_SIZE];
-				struct rte_eth_dev *dev;
-				uint32_t port_id;
-				int status;
-
-				dev = ETHDEV(softnic);
-				if (dev == NULL ||
-					conf->queue[i] >=
-						dev->data->nb_rx_queues)
-					return rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: Invalid RX queue ID");
-
-				snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->queue[i]);
-
-				status = softnic_pipeline_port_out_find(softnic,
-					pipeline->name,
-					name,
-					&port_id);
-				if (status)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: RX queue not accessible from this pipeline");
-
-				rule_action->lb.out[i] = port_id;
-			}
-
-			for ( ; i < RTE_DIM(rule_action->lb.out); i++)
-				rule_action->lb.out[i] =
-				rule_action->lb.out[i % conf->queue_num];
-
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_RSS */
-
-		case RTE_FLOW_ACTION_TYPE_DROP:
-		{
-			const void *conf = action->conf;
-
-			if (conf != NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"DROP: No configuration required");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"DROP action not supported by this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_DROP;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_DROP */
-
-		case RTE_FLOW_ACTION_TYPE_COUNT:
-		{
-			const struct rte_flow_action_count *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"COUNT: Null configuration");
-
-			if (n_count)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one COUNT action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_STATS)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"COUNT action not supported by this table");
-
-			n_count = 1;
-
-			/* RTE_TABLE_ACTION_STATS */
-			rule_action->stats.n_packets = 0;
-			rule_action->stats.n_bytes = 0;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_COUNT */
-
-		case RTE_FLOW_ACTION_TYPE_MARK:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"MARK: Null configuration");
-
-			if (n_mark)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one MARK action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_TAG)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"MARK action not supported by this table");
-
-			n_mark = 1;
-
-			/* RTE_TABLE_ACTION_TAG */
-			rule_action->tag.tag = conf->id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_MARK */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN DECAP: Non-null configuration");
-
-			if (n_vxlan_decap)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one VXLAN DECAP action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_DECAP)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN DECAP action not supported by this table");
-
-			n_vxlan_decap = 1;
-
-			/* RTE_TABLE_ACTION_DECAP */
-			rule_action->decap.n = 50; /* Ether/IPv4/UDP/VXLAN */
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_DECAP */
-
-		case RTE_FLOW_ACTION_TYPE_METER:
-		{
-			const struct rte_flow_action_meter *conf = action->conf;
-			struct softnic_mtr_meter_profile *mp;
-			struct softnic_mtr *m;
-			uint32_t table_id = table - pipeline->table;
-			uint32_t meter_profile_id;
-			int status;
-
-			if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Table action not supported");
-
-			if (params->mtr.n_tc != 1)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Multiple TCs not supported");
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"METER: Null configuration");
-
-			m = softnic_mtr_find(softnic, conf->mtr_id);
-
-			if (m == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Invalid meter ID");
-
-			if (m->flow)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Meter already attached to a flow");
-
-			meter_profile_id = m->params.meter_profile_id;
-			mp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);
-
-			/* Add meter profile to pipeline table */
-			if (!softnic_pipeline_table_meter_profile_find(table,
-					meter_profile_id)) {
-				struct rte_table_action_meter_profile profile;
-
-				memset(&profile, 0, sizeof(profile));
-				profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-				profile.trtcm.cir = mp->params.trtcm_rfc2698.cir;
-				profile.trtcm.pir = mp->params.trtcm_rfc2698.pir;
-				profile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;
-				profile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;
-
-				status = softnic_pipeline_table_mtr_profile_add(softnic,
-						pipeline->name,
-						table_id,
-						meter_profile_id,
-						&profile);
-				if (status) {
-					rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: Table meter profile add failed");
-					return -1;
-				}
-			}
-			/* Meter policy must exist */
-			policy = softnic_mtr_meter_policy_find(softnic,
-					m->params.meter_policy_id);
-			if (policy == NULL) {
-				rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: fail to find meter policy");
-				return -1;
-			}
-			/* RTE_TABLE_ACTION_METER */
-			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
-				policy->policer[RTE_COLOR_GREEN];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
-				policy->policer[RTE_COLOR_YELLOW];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
-				policy->policer[RTE_COLOR_RED];
-			rule_action->mtr.tc_mask = 1;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_METER */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
-		{
-			const struct rte_flow_action_vxlan_encap *conf =
-				action->conf;
-			const struct rte_flow_item *item;
-			union flow_item spec, mask;
-			int disabled = 0, status;
-			size_t size;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration");
-
-			item = conf->definition;
-			if (item == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration definition");
-
-			if (!(params->action_mask &
-					(1LLU << RTE_TABLE_ACTION_ENCAP)))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN ENCAP: Encap action not enabled for this table");
-
-			/* Check for Ether. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-				&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: first encap item should be ether");
-			}
-			rte_ether_addr_copy(&spec.eth.dst,
-					&rule_action->encap.vxlan.ether.da);
-			rte_ether_addr_copy(&spec.eth.src,
-					&rule_action->encap.vxlan.ether.sa);
-
-			item++;
-
-			/* Check for VLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
-				if (!params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: vlan encap not supported by table");
-
-				uint16_t tci = rte_ntohs(spec.vlan.tci);
-				rule_action->encap.vxlan.vlan.pcp =
-					tci >> 13;
-				rule_action->encap.vxlan.vlan.dei =
-					(tci >> 12) & 0x1;
-				rule_action->encap.vxlan.vlan.vid =
-					tci & 0xfff;
-
-				item++;
-
-				flow_item_skip_void(&item);
-				status = flow_item_proto_preprocess(item, &spec,
-						&mask, &size, &disabled, error);
-				if (status)
-					return status;
-			} else {
-				if (params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: expecting vlan encap item");
-			}
-
-			/* Check for IPV4/IPV6. */
-			switch (item->type) {
-			case RTE_FLOW_ITEM_TYPE_IPV4:
-			{
-				rule_action->encap.vxlan.ipv4.sa =
-					rte_ntohl(spec.ipv4.hdr.src_addr);
-				rule_action->encap.vxlan.ipv4.da =
-					rte_ntohl(spec.ipv4.hdr.dst_addr);
-				rule_action->encap.vxlan.ipv4.dscp =
-					spec.ipv4.hdr.type_of_service >> 2;
-				rule_action->encap.vxlan.ipv4.ttl =
-					spec.ipv4.hdr.time_to_live;
-				break;
-			}
-			case RTE_FLOW_ITEM_TYPE_IPV6:
-			{
-				uint32_t vtc_flow;
-
-				memcpy(&rule_action->encap.vxlan.ipv6.sa,
-						&spec.ipv6.hdr.src_addr,
-						sizeof(spec.ipv6.hdr.src_addr));
-				memcpy(&rule_action->encap.vxlan.ipv6.da,
-						&spec.ipv6.hdr.dst_addr,
-						sizeof(spec.ipv6.hdr.dst_addr));
-				vtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);
-				rule_action->encap.vxlan.ipv6.flow_label =
-						vtc_flow & 0xfffff;
-				rule_action->encap.vxlan.ipv6.dscp =
-						(vtc_flow >> 22) & 0x3f;
-				rule_action->encap.vxlan.ipv6.hop_limit =
-					spec.ipv6.hdr.hop_limits;
-				break;
-			}
-			default:
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ether should be ipv4/ipv6");
-			}
-
-			item++;
-
-			/* Check for UDP. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_UDP) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp");
-			}
-			rule_action->encap.vxlan.udp.sp =
-				rte_ntohs(spec.udp.hdr.src_port);
-			rule_action->encap.vxlan.udp.dp =
-				rte_ntohs(spec.udp.hdr.dst_port);
-
-			item++;
-
-			/* Check for VXLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after udp should be vxlan");
-			}
-			rule_action->encap.vxlan.vxlan.vni =
-				(spec.vxlan.vni[0] << 16U |
-					spec.vxlan.vni[1] << 8U
-					| spec.vxlan.vni[2]);
-
-			item++;
-
-			/* Check for END. */
-			flow_item_skip_void(&item);
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_END)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: expecting END item");
-
-			rule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */
-
-		default:
-			return -ENOTSUP;
-		}
-	}
-
-	if (n_jump_queue_rss_drop == 0)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			action,
-			"Flow does not have any terminating action");
-
-	return 0;
-}
-
-static int
-pmd_flow_validate(struct rte_eth_dev *dev,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item item[],
-		const struct rte_flow_action action[],
-		struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int status;
-
-	/* Check input parameters. */
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL, "Null attr");
-
-	if (item == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				NULL,
-				"Null item");
-
-	if (action == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION,
-				NULL,
-				"Null action");
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return status;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline name");
-
-	if (table_id >= pipeline->n_tables)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline table ID");
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			&rule_match,
-			error);
-	if (status)
-		return status;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return status;
-
-	return 0;
-}
-
-static struct softnic_mtr *
-flow_action_meter_get(struct pmd_internals *softnic,
-	const struct rte_flow_action *action)
-{
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++)
-		if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
-			const struct rte_flow_action_meter *conf = action->conf;
-
-			if (conf == NULL)
-				return NULL;
-
-			return softnic_mtr_find(softnic, conf->mtr_id);
-		}
-
-	return NULL;
-}
-
-static void
-flow_meter_owner_reset(struct pmd_internals *softnic,
-	struct rte_flow *flow)
-{
-	struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->flow == flow) {
-			m->flow = NULL;
-			break;
-		}
-}
-
-static void
-flow_meter_owner_set(struct pmd_internals *softnic,
-	struct rte_flow *flow,
-	struct softnic_mtr *mtr)
-{
-	/* Reset current flow meter  */
-	flow_meter_owner_reset(softnic, flow);
-
-	/* Set new flow meter */
-	mtr->flow = flow;
-}
-
-static int
-is_meter_action_enable(struct pmd_internals *softnic,
-	struct softnic_table *table)
-{
-	struct softnic_table_action_profile *profile =
-		softnic_table_action_profile_find(softnic,
-			table->params.action_profile_name);
-	struct softnic_table_action_profile_params *params = &profile->params;
-
-	return (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) ? 1 : 0;
-}
-
-static struct rte_flow *
-pmd_flow_create(struct rte_eth_dev *dev,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_item item[],
-	const struct rte_flow_action action[],
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-	void *rule_data;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct rte_flow *flow;
-	struct softnic_mtr *mtr;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int new_flow, status;
-
-	/* Check input parameters. */
-	if (attr == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ATTR,
-			NULL,
-			"Null attr");
-		return NULL;
-	}
-
-	if (item == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			NULL,
-			"Null item");
-		return NULL;
-	}
-
-	if (action == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			NULL,
-			"Null action");
-		return NULL;
-	}
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return NULL;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline name");
-		return NULL;
-	}
-
-	if (table_id >= pipeline->n_tables) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline table ID");
-		return NULL;
-	}
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-		pipeline,
-		table,
-		attr,
-		item,
-		&rule_match,
-		error);
-	if (status)
-		return NULL;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return NULL;
-
-	/* Flow find/allocate. */
-	new_flow = 0;
-	flow = softnic_flow_find(table, &rule_match);
-	if (flow == NULL) {
-		new_flow = 1;
-		flow = calloc(1, sizeof(struct rte_flow));
-		if (flow == NULL) {
-			rte_flow_error_set(error,
-				ENOMEM,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Not enough memory for new flow");
-			return NULL;
-		}
-	}
-
-	/* Rule add. */
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&rule_match,
-		&rule_action,
-		&rule_data);
-	if (status) {
-		if (new_flow)
-			free(flow);
-
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule add failed");
-		return NULL;
-	}
-
-	/* Flow fill in. */
-	memcpy(&flow->match, &rule_match, sizeof(rule_match));
-	memcpy(&flow->action, &rule_action, sizeof(rule_action));
-	flow->data = rule_data;
-	flow->pipeline = pipeline;
-	flow->table_id = table_id;
-
-	mtr = flow_action_meter_get(softnic, action);
-	if (mtr)
-		flow_meter_owner_set(softnic, flow, mtr);
-
-	/* Flow add to list. */
-	if (new_flow)
-		TAILQ_INSERT_TAIL(&table->flows, flow, node);
-
-	return flow;
-}
-
-static int
-pmd_flow_destroy(struct rte_eth_dev *dev,
-	struct rte_flow *flow,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct softnic_table *table;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule delete. */
-	status = softnic_pipeline_table_rule_delete(softnic,
-		flow->pipeline->name,
-		flow->table_id,
-		&flow->match);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule delete failed");
-
-	/* Update dependencies */
-	if (is_meter_action_enable(softnic, table))
-		flow_meter_owner_reset(softnic, flow);
-
-	/* Flow delete. */
-	TAILQ_REMOVE(&table->flows, flow, node);
-	free(flow);
-
-	return 0;
-}
-
-static int
-pmd_flow_flush(struct rte_eth_dev *dev,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	int fail_to_del_rule = 0;
-	uint32_t i;
-
-	TAILQ_FOREACH(pipeline, &softnic->pipeline_list, node) {
-		/* Remove all the flows added to the tables. */
-		for (i = 0; i < pipeline->n_tables; i++) {
-			struct softnic_table *table = &pipeline->table[i];
-			struct rte_flow *flow;
-			void *temp;
-			int status;
-
-			RTE_TAILQ_FOREACH_SAFE(flow, &table->flows, node,
-				temp) {
-				/* Rule delete. */
-				status = softnic_pipeline_table_rule_delete
-						(softnic,
-						pipeline->name,
-						i,
-						&flow->match);
-				if (status)
-					fail_to_del_rule = 1;
-				/* Update dependencies */
-				if (is_meter_action_enable(softnic, table))
-					flow_meter_owner_reset(softnic, flow);
-
-				/* Flow delete. */
-				TAILQ_REMOVE(&table->flows, flow, node);
-				free(flow);
-			}
-		}
-	}
-
-	if (fail_to_del_rule)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Some of the rules could not be deleted");
-
-	return 0;
-}
-
-static int
-pmd_flow_query(struct rte_eth_dev *dev __rte_unused,
-	struct rte_flow *flow,
-	const struct rte_flow_action *action __rte_unused,
-	void *data,
-	struct rte_flow_error *error)
-{
-	struct rte_table_action_stats_counters stats;
-	struct softnic_table *table;
-	struct rte_flow_query_count *flow_stats = data;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	if (data == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Null data");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule stats read. */
-	status = rte_table_action_stats_read(table->a,
-		flow->data,
-		&stats,
-		flow_stats->reset);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule stats read failed");
-
-	/* Fill in flow stats. */
-	flow_stats->hits_set =
-		(table->ap->params.stats.n_packets_enabled) ? 1 : 0;
-	flow_stats->bytes_set =
-		(table->ap->params.stats.n_bytes_enabled) ? 1 : 0;
-	flow_stats->hits = stats.n_packets;
-	flow_stats->bytes = stats.n_bytes;
-
-	return 0;
-}
-
-const struct rte_flow_ops pmd_flow_ops = {
-	.validate = pmd_flow_validate,
-	.create = pmd_flow_create,
-	.destroy = pmd_flow_destroy,
-	.flush = pmd_flow_flush,
-	.query = pmd_flow_query,
-	.isolate = NULL,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 03/21] net/softnic: remove the meter support
  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   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
                     ` (17 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device meter API support.

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         |  16 -
 .../net/softnic/rte_eth_softnic_internals.h   | 117 ---
 drivers/net/softnic/rte_eth_softnic_meter.c   | 945 ------------------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  12 -
 5 files changed, 1091 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 4ebe60921c..d466dc7700 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -15,7 +15,6 @@ sources = files(
         'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
-        'rte_eth_softnic_meter.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8e361adbad..a7136bb0c0 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "rte_eth_softnic_internals.h"
@@ -168,8 +167,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	return 0;
 }
 
@@ -191,8 +188,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	rte_free(p);
 }
 
@@ -215,14 +210,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_mtr_ops **)arg = &pmd_mtr_ops;
-
-	return 0;
-}
-
 static const struct eth_dev_ops pmd_ops = {
 	.dev_configure = pmd_dev_configure,
 	.dev_start = pmd_dev_start,
@@ -232,7 +219,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
 static uint16_t
@@ -274,8 +260,6 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	softnic_mtr_init(p);
-
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 4cc98b7aad..d578cb1f25 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -19,8 +19,6 @@
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_flow_driver.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "conn.h"
@@ -40,68 +38,6 @@ struct pmd_params {
 	int sc; /**< Service cores. */
 };
 
-/**
- * Ethdev Flow API
- */
-struct rte_flow;
-
-TAILQ_HEAD(flow_list, rte_flow);
-
-struct flow_attr_map {
-	char pipeline_name[NAME_SIZE];
-	uint32_t table_id;
-	int valid;
-};
-
-#ifndef SOFTNIC_FLOW_MAX_GROUPS
-#define SOFTNIC_FLOW_MAX_GROUPS                            64
-#endif
-
-struct flow_internals {
-	struct flow_attr_map ingress_map[SOFTNIC_FLOW_MAX_GROUPS];
-	struct flow_attr_map egress_map[SOFTNIC_FLOW_MAX_GROUPS];
-};
-
-/**
- * Meter
- */
-
-/* MTR meter profile */
-struct softnic_mtr_meter_profile {
-	TAILQ_ENTRY(softnic_mtr_meter_profile) node;
-	uint32_t meter_profile_id;
-	struct rte_mtr_meter_profile params;
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
-
-/* MTR meter policy */
-struct softnic_mtr_meter_policy {
-	TAILQ_ENTRY(softnic_mtr_meter_policy) node;
-	uint32_t meter_policy_id;
-	enum rte_table_action_policer policer[RTE_COLORS];
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
-
-/* MTR meter object */
-struct softnic_mtr {
-	TAILQ_ENTRY(softnic_mtr) node;
-	uint32_t mtr_id;
-	struct rte_mtr_params params;
-	struct rte_flow *flow;
-};
-
-TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
-
-struct mtr_internals {
-	struct softnic_mtr_meter_profile_list meter_profiles;
-	struct softnic_mtr_meter_policy_list meter_policies;
-	struct softnic_mtr_list mtrs;
-};
-
 /**
  * MEMPOOL
  */
@@ -383,7 +319,6 @@ struct softnic_table {
 	struct softnic_table_params params;
 	struct softnic_table_action_profile *ap;
 	struct rte_table_action *a;
-	struct flow_list flows;
 	struct rte_table_action_dscp_table dscp_table;
 	struct softnic_table_meter_profile_list meter_profiles;
 };
@@ -481,9 +416,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct flow_internals flow;
-	struct mtr_internals mtr;
-
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
@@ -513,46 +445,6 @@ ETHDEV(struct pmd_internals *softnic)
 	return &rte_eth_devices[port_id];
 }
 
-/**
- * Ethdev Flow API
- */
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id);
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress);
-
-extern const struct rte_flow_ops pmd_flow_ops;
-
-/**
- * Meter
- */
-int
-softnic_mtr_init(struct pmd_internals *p);
-
-void
-softnic_mtr_free(struct pmd_internals *p);
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p,
-	uint32_t mtr_id);
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id);
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id);
-
-extern const struct rte_mtr_ops pmd_mtr_ops;
-
 /**
  * MEMPOOL
  */
@@ -814,15 +706,6 @@ struct softnic_table_rule_action {
 	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
 };
 
-struct rte_flow {
-	TAILQ_ENTRY(rte_flow) node;
-	struct softnic_table_rule_match match;
-	struct softnic_table_rule_action action;
-	void *data;
-	struct pipeline *pipeline;
-	uint32_t table_id;
-};
-
 int
 softnic_pipeline_port_in_stats_read(struct pmd_internals *p,
 	const char *pipeline_name,
diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c
deleted file mode 100644
index 6b02f43e31..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_meter.c
+++ /dev/null
@@ -1,945 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_mtr.h>
-#include <rte_mtr_driver.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_mtr_init(struct pmd_internals *p)
-{
-	/* Initialize meter profiles list */
-	TAILQ_INIT(&p->mtr.meter_profiles);
-
-	/* Initialize meter policies list */
-	TAILQ_INIT(&p->mtr.meter_policies);
-
-	/* Initialize MTR objects list */
-	TAILQ_INIT(&p->mtr.mtrs);
-
-	return 0;
-}
-
-void
-softnic_mtr_free(struct pmd_internals *p)
-{
-	/* Remove MTR objects */
-	for ( ; ; ) {
-		struct softnic_mtr *m;
-
-		m = TAILQ_FIRST(&p->mtr.mtrs);
-		if (m == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.mtrs, m, node);
-		free(m);
-	}
-
-	/* Remove meter profiles */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_profile *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_profiles);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-		free(mp);
-	}
-
-	/* Remove meter policies */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_policy *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_policies);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-		free(mp);
-	}
-}
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id)
-{
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_profile_id == mp->meter_profile_id)
-			return mp;
-
-	return NULL;
-}
-
-static int
-meter_profile_check(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile ID must be valid. */
-	if (meter_profile_id == UINT32_MAX)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter profile must not exist. */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter prfile already exists");
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"profile null");
-
-	/* Traffic metering algorithm : TRTCM_RFC2698 */
-	if (profile->alg != RTE_MTR_TRTCM_RFC2698)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"Metering alg not supported");
-
-	/* Not support packet mode, just support byte mode. */
-	if (profile->packet_mode)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
-			NULL,
-			"Meter packet mode not supported");
-
-	return 0;
-}
-
-/* MTR meter profile add */
-static int
-pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-	int status;
-
-	/* Check input params */
-	status = meter_profile_check(dev, meter_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_profile_id = meter_profile_id;
-	memcpy(&mp->params, profile, sizeof(mp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter profile delete */
-static int
-pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id)
-{
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_policy_id == mp->meter_policy_id)
-			return mp;
-
-	return NULL;
-}
-
-/* MTR meter policy add */
-static int
-pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_meter_policy_params *policy,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-	const struct rte_flow_action *act;
-	const struct rte_flow_action_meter_color *recolor;
-	uint32_t i;
-	bool valid_act_found;
-
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY,
-			NULL,
-			"Null meter policy invalid");
-
-	/* Meter policy must not exist. */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy already exists");
-
-	for (i = 0; i < RTE_COLORS; i++) {
-		if (policy->actions[i] == NULL)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"Null action list");
-		for (act = policy->actions[i], valid_act_found = false;
-		     act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
-			if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
-				continue;
-			/*
-			 * Support one (and one only) of
-			 * METER_COLOR or DROP action.
-			 */
-			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
-				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
-				valid_act_found)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_METER_POLICY,
-					NULL,
-					"Action invalid");
-			valid_act_found = true;
-		}
-		if (!valid_act_found)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"No valid action found");
-	}
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_policy_id = meter_policy_id;
-	for (i = 0; i < RTE_COLORS; i++) {
-		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
-		act = policy->actions[i];
-		if (!act)
-			continue;
-		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
-			recolor = act->conf;
-			switch (recolor->color) {
-			case RTE_COLOR_GREEN:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-				break;
-			case RTE_COLOR_YELLOW:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-				break;
-			case RTE_COLOR_RED:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_RED;
-				break;
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter policy delete */
-static int
-pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy *mp;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
-{
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->mtr_id == mtr_id)
-			return m;
-
-	return NULL;
-}
-
-
-static int
-mtr_check(struct pmd_internals *p,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	/* MTR id valid  */
-	if (softnic_mtr_find(p, mtr_id))
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object already exists");
-
-	/* MTR params must not be NULL */
-	if (params == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"MTR object params null");
-
-	/* Previous meter color not supported */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"Previous meter color not supported");
-
-	/* Shared MTR object not supported */
-	if (shared)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_SHARED,
-			NULL,
-			"Shared MTR object not supported");
-
-	return 0;
-}
-
-/* MTR object create */
-static int
-pmd_mtr_create(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr_meter_policy *policy;
-	struct softnic_mtr *m;
-	int status;
-
-	/* Check parameters */
-	status = mtr_check(p, mtr_id, params, shared, error);
-	if (status)
-		return status;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
-	if (policy == NULL) {
-		return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-				NULL,
-				"Meter policy id invalid");
-	}
-
-	/* Memory allocation */
-	m = calloc(1, sizeof(struct softnic_mtr));
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	m->mtr_id = mtr_id;
-	memcpy(&m->params, params, sizeof(m->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(ml, m, node);
-
-	/* Update dependencies */
-	mp->n_users++;
-	policy->n_users++;
-
-	return 0;
-}
-
-/* MTR object destroy */
-static int
-pmd_mtr_destroy(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr *m;
-	struct softnic_mtr_meter_policy *policy;
-
-	/* MTR object must exist */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object must not have any owner */
-	if (m->flow != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"MTR object is being used");
-
-	/* Get meter profile */
-	mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"MTR object meter profile invalid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"MTR object meter policy invalid");
-
-	/* Update dependencies */
-	mp->n_users--;
-	policy->n_users--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(ml, m, node);
-	free(m);
-
-	return 0;
-}
-
-/* MTR object meter profile update */
-static int
-pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp_new, *mp_old;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* Meter profile id must be valid */
-	mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile not valid");
-
-	/* MTR object already set to meter profile id */
-	if (m->params.meter_profile_id == meter_profile_id)
-		return 0;
-
-	/*  MTR object owner table update */
-	if (m->flow) {
-		uint32_t table_id = m->flow->table_id;
-		struct softnic_table *table = &m->flow->pipeline->table[table_id];
-		struct softnic_table_rule_action action;
-
-		if (!softnic_pipeline_table_meter_profile_find(table,
-			meter_profile_id)) {
-			struct rte_table_action_meter_profile profile;
-
-			memset(&profile, 0, sizeof(profile));
-
-			profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-			profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
-			profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
-			profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
-			profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
-
-			/* Add meter profile to pipeline table */
-			status = softnic_pipeline_table_mtr_profile_add(p,
-					m->flow->pipeline->name,
-					table_id,
-					meter_profile_id,
-					&profile);
-			if (status)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"Table meter profile add failed");
-		}
-
-		/* Set meter action */
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		action.mtr.mtr[0].meter_profile_id = meter_profile_id;
-
-		/* Re-add rule */
-		status = softnic_pipeline_table_rule_add(p,
-			m->flow->pipeline->name,
-			table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule add failed");
-
-		/* Flow: update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-	}
-
-	mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-
-	/* Meter: Set meter profile */
-	m->params.meter_profile_id = meter_profile_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-/* MTR object meter DSCP table update */
-static int
-pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	enum rte_color *dscp_table,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_dscp_table dt;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	uint32_t table_id, i;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object owner valid? */
-	if (m->flow == NULL)
-		return 0;
-
-	pipeline = m->flow->pipeline;
-	table_id = m->flow->table_id;
-	table = &pipeline->table[table_id];
-
-	memcpy(&dt, &table->dscp_table, sizeof(dt));
-	for (i = 0; i < RTE_DIM(dt.entry); i++)
-		dt.entry[i].color = (enum rte_color)dscp_table[i];
-
-	/* Update table */
-	status = softnic_pipeline_table_dscp_table_update(p,
-			pipeline->name,
-			table_id,
-			UINT64_MAX,
-			&dt);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Table action dscp table update failed");
-
-	return 0;
-}
-
-/* MTR object policy update */
-static int
-pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr *m;
-	uint32_t i;
-	int status;
-	struct softnic_mtr_meter_policy *mp_new, *mp_old;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	if (m->params.meter_policy_id == meter_policy_id)
-		return 0;
-
-	/* Meter policy must exist */
-	mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* MTR object owner valid? */
-	if (m->flow) {
-		struct pipeline *pipeline = m->flow->pipeline;
-		struct softnic_table *table = &pipeline->table[m->flow->table_id];
-		struct softnic_table_rule_action action;
-
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		/* Set action */
-		for (i = 0; i < RTE_COLORS; i++)
-			action.mtr.mtr[0].policer[i] = mp_new->policer[i];
-
-		/* Re-add the rule */
-		status = softnic_pipeline_table_rule_add(p,
-			pipeline->name,
-			m->flow->table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule re-add failed");
-
-		/* Flow: Update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-
-		/* Reset the meter stats */
-		rte_table_action_meter_read(table->a, m->flow->data,
-			1, NULL, 1);
-	}
-
-	mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp_old == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Old meter policy id invalid");
-
-	/* Meter: Set meter profile */
-	m->params.meter_policy_id = meter_policy_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-#define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
-				RTE_MTR_STATS_N_PKTS_YELLOW | \
-				RTE_MTR_STATS_N_PKTS_RED | \
-				RTE_MTR_STATS_N_PKTS_DROPPED)
-
-#define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
-				RTE_MTR_STATS_N_BYTES_YELLOW | \
-				RTE_MTR_STATS_N_BYTES_RED | \
-				RTE_MTR_STATS_N_BYTES_DROPPED)
-
-/* MTR object stats read */
-static void
-mtr_stats_convert(struct pmd_internals *p,
-	struct softnic_mtr *m,
-	struct rte_table_action_mtr_counters_tc *in,
-	struct rte_mtr_stats *out,
-	uint64_t *out_mask)
-{
-	struct softnic_mtr_meter_policy *mp;
-
-	memset(&out, 0, sizeof(out));
-	*out_mask = 0;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp == NULL)
-		return;
-
-	if (in->n_packets_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_pkts_dropped += in->n_packets[i];
-		}
-
-		*out_mask |= MTR_STATS_PKTS_DEFAULT;
-	}
-
-	if (in->n_bytes_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_bytes_dropped += in->n_bytes[i];
-		}
-
-		*out_mask |= MTR_STATS_BYTES_DEFAULT;
-	}
-}
-
-/* MTR object stats read */
-static int
-pmd_mtr_stats_read(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_mtr_counters counters;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR meter object owner valid? */
-	if (m->flow == NULL) {
-		if (stats != NULL)
-			memset(stats, 0, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = MTR_STATS_PKTS_DEFAULT |
-				MTR_STATS_BYTES_DEFAULT;
-
-		return 0;
-	}
-
-	pipeline = m->flow->pipeline;
-	table = &pipeline->table[m->flow->table_id];
-
-	/* Meter stats read. */
-	status = rte_table_action_meter_read(table->a,
-		m->flow->data,
-		1,
-		&counters,
-		clear);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Meter stats read failed");
-
-	/* Stats format conversion. */
-	if (stats || stats_mask) {
-		struct rte_mtr_stats s;
-		uint64_t s_mask = 0;
-
-		mtr_stats_convert(p,
-			m,
-			&counters.stats[0],
-			&s,
-			&s_mask);
-
-		if (stats)
-			memcpy(stats, &s, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = s_mask;
-	}
-
-	return 0;
-}
-
-const struct rte_mtr_ops pmd_mtr_ops = {
-	.capabilities_get = NULL,
-
-	.meter_profile_add = pmd_mtr_meter_profile_add,
-	.meter_profile_delete = pmd_mtr_meter_profile_delete,
-
-	.meter_policy_add = pmd_mtr_meter_policy_add,
-	.meter_policy_delete = pmd_mtr_meter_policy_delete,
-
-	.create = pmd_mtr_create,
-	.destroy = pmd_mtr_destroy,
-	.meter_enable = NULL,
-	.meter_disable = NULL,
-
-	.meter_profile_update = pmd_mtr_meter_profile_update,
-	.meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
-	.meter_policy_update = pmd_mtr_meter_policy_update,
-	.stats_update = NULL,
-
-	.stats_read = pmd_mtr_stats_read,
-};
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index c7d2a7de19..2cf7fa52d1 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -46,17 +46,6 @@ softnic_pipeline_init(struct pmd_internals *p)
 static void
 softnic_pipeline_table_free(struct softnic_table *table)
 {
-	for ( ; ; ) {
-		struct rte_flow *flow;
-
-		flow = TAILQ_FIRST(&table->flows);
-		if (flow == NULL)
-			break;
-
-		TAILQ_REMOVE(&table->flows, flow, node);
-		free(flow);
-	}
-
 	for ( ; ; ) {
 		struct softnic_table_meter_profile *mp;
 
@@ -1035,7 +1024,6 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 	memcpy(&table->params, params, sizeof(*params));
 	table->ap = ap;
 	table->a = action;
-	TAILQ_INIT(&table->flows);
 	TAILQ_INIT(&table->meter_profiles);
 	memset(&table->dscp_table, 0, sizeof(table->dscp_table));
 	pipeline->n_tables++;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 04/21] net/softnic: remove cryptodev support
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (2 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 03/21] net/softnic: remove the meter support Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 05/21] net/softnic: remove tap support Cristian Dumitrescu
                     ` (16 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the cryptographic device API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |   3 +-
 drivers/net/softnic/rte_eth_softnic.c         |   1 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 171 ------------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   | 168 -----------------
 .../net/softnic/rte_eth_softnic_internals.h   |  54 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  54 ------
 6 files changed, 1 insertion(+), 450 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index d466dc7700..b3d235841d 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -12,7 +12,6 @@ sources = files(
         'rte_eth_softnic.c',
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
@@ -20,4 +19,4 @@ sources = files(
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
-deps += ['pipeline', 'port', 'table', 'cryptodev']
+deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a7136bb0c0..1ea5989223 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -264,7 +264,6 @@ pmd_init(struct pmd_params *params)
 	softnic_swq_init(p);
 	softnic_link_init(p);
 	softnic_tap_init(p);
-	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 671f96cf77..bca0b176d6 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -213,80 +213,6 @@ cmd_tap(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * cryptodev <tap_name> dev <device_name> | dev_id <device_id>
- * queue <n_queues> <queue_size> max_sessions <n_sessions>
- **/
-
-static void
-cmd_cryptodev(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	struct softnic_cryptodev_params params;
-	char *name;
-
-	memset(&params, 0, sizeof(params));
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0)
-		params.dev_name = tokens[3];
-	else if (strcmp(tokens[2], "dev_id") == 0) {
-		if (softnic_parser_read_uint32(&params.dev_id, tokens[3]) < 0) {
-			snprintf(out, out_size,	MSG_ARG_INVALID,
-				"dev_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"cryptodev");
-		return;
-	}
-
-	if (strcmp(tokens[4], "queue")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.n_queues, tokens[5]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.queue_size, tokens[6]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"queue_size");
-		return;
-	}
-
-	if (strcmp(tokens[7], "max_sessions")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.session_pool_size, tokens[8])
-			< 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_cryptodev_create(softnic, name, &params) == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -879,41 +805,6 @@ cmd_table_action_profile(struct pmd_internals *softnic,
 		t0 += 1;
 	} /* decap */
 
-	if (t0 < n_tokens && (strcmp(tokens[t0], "sym_crypto") == 0)) {
-		struct softnic_cryptodev *cryptodev;
-
-		if (n_tokens < t0 + 5 ||
-				strcmp(tokens[t0 + 1], "dev") ||
-				strcmp(tokens[t0 + 3], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		cryptodev = softnic_cryptodev_find(softnic, tokens[t0 + 2]);
-		if (cryptodev == NULL) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.cryptodev_id = cryptodev->dev_id;
-
-		if (softnic_parser_read_uint32(&p.sym_crypto.op_offset,
-				tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-					"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.mp_create = cryptodev->mp_create;
-		p.sym_crypto.mp_init = cryptodev->mp_init;
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-		t0 += 5;
-	} /* sym_crypto */
-
 	if (t0 < n_tokens) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
@@ -985,7 +876,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  | cryptodev <cryptodev_name> rxq <queue_id>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
  */
@@ -1138,27 +1028,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		}
 
 		t0 += 7;
-	} else if (strcmp(tokens[t0], "cryptodev") == 0) {
-		if (n_tokens < t0 + 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in cryptodev");
-			return;
-		}
-
-		p.type = PORT_IN_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-				tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"rxq");
-			return;
-		}
-
-		p.cryptodev.arg_callback = NULL;
-		p.cryptodev.f_callback = NULL;
-
-		t0 += 4;
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -1207,7 +1076,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
- *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
  */
 static void
 cmd_pipeline_port_out(struct pmd_internals *softnic,
@@ -1322,40 +1190,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 				return;
 			}
 		}
-	} else if (strcmp(tokens[6], "cryptodev") == 0) {
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		p.type = PORT_OUT_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.cryptodev.queue_id, tokens[9])
-				!= 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-
-		if (strcmp(tokens[10], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.cryptodev.op_offset,
-				tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -4771,11 +4605,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "cryptodev") == 0) {
-		cmd_cryptodev(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_cryptodev.c b/drivers/net/softnic/rte_eth_softnic_cryptodev.c
deleted file mode 100644
index e4754055e9..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_cryptodev.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <rte_cryptodev.h>
-#include <cryptodev_pmd.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define SOFTNIC_CRYPTO_SESSION_CACHE_SIZE 128
-
-int
-softnic_cryptodev_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->cryptodev_list);
-
-	return 0;
-}
-
-void
-softnic_cryptodev_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = TAILQ_FIRST(&p->cryptodev_list);
-		if (cryptodev == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->cryptodev_list, cryptodev, node);
-		free(cryptodev);
-	}
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_cryptodev *cryptodev;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(cryptodev, &p->cryptodev_list, node)
-		if (strcmp(cryptodev->name, name) == 0)
-			return cryptodev;
-
-	return NULL;
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params)
-{
-	struct rte_cryptodev_info dev_info;
-	struct rte_cryptodev_config dev_conf;
-	struct rte_cryptodev_qp_conf queue_conf;
-	struct softnic_cryptodev *cryptodev;
-	uint32_t dev_id, i;
-	uint32_t socket_id;
-	uint32_t cache_size;
-	char mp_name[NAME_SIZE];
-	int status;
-
-	/* Check input params */
-	if ((name == NULL) ||
-		softnic_cryptodev_find(p, name) ||
-		(params->n_queues == 0) ||
-		(params->queue_size == 0) ||
-		(params->session_pool_size == 0))
-		return NULL;
-
-	if (params->dev_name) {
-		status = rte_cryptodev_get_dev_id(params->dev_name);
-		if (status == -1)
-			return NULL;
-
-		dev_id = (uint32_t)status;
-	} else {
-		if (rte_cryptodev_is_valid_dev(params->dev_id) == 0)
-			return NULL;
-
-		dev_id = params->dev_id;
-	}
-
-	cache_size = (params->session_pool_size / 2 <
-			SOFTNIC_CRYPTO_SESSION_CACHE_SIZE) ?
-					(params->session_pool_size / 2) :
-					SOFTNIC_CRYPTO_SESSION_CACHE_SIZE;
-
-	socket_id = rte_cryptodev_socket_id(dev_id);
-	rte_cryptodev_info_get(dev_id, &dev_info);
-
-	if (dev_info.max_nb_queue_pairs < params->n_queues)
-		return NULL;
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED)
-		return NULL;
-
-	dev_conf.socket_id = socket_id;
-	dev_conf.nb_queue_pairs = params->n_queues;
-
-	status = rte_cryptodev_configure(dev_id, &dev_conf);
-	if (status < 0)
-		return NULL;
-
-	queue_conf.nb_descriptors = params->queue_size;
-	for (i = 0; i < params->n_queues; i++) {
-		status = rte_cryptodev_queue_pair_setup(dev_id, i,
-				&queue_conf, socket_id);
-		if (status < 0)
-			return NULL;
-	}
-
-	if (rte_cryptodev_start(dev_id) < 0)
-		return NULL;
-
-	cryptodev = calloc(1, sizeof(struct softnic_cryptodev));
-	if (cryptodev == NULL) {
-		rte_cryptodev_stop(dev_id);
-		return NULL;
-	}
-
-	strlcpy(cryptodev->name, name, sizeof(cryptodev->name));
-	cryptodev->dev_id = dev_id;
-	cryptodev->n_queues = params->n_queues;
-
-	snprintf(mp_name, NAME_SIZE, "%s_mp%u", name, dev_id);
-	cryptodev->mp_create = rte_cryptodev_sym_session_pool_create(mp_name,
-			params->session_pool_size,
-			0,
-			cache_size,
-			0,
-			socket_id);
-	if (!cryptodev->mp_create)
-		goto error_exit;
-
-	snprintf(mp_name, NAME_SIZE, "%s_priv_mp%u", name, dev_id);
-	cryptodev->mp_init = rte_mempool_create(mp_name,
-			params->session_pool_size,
-			rte_cryptodev_sym_get_private_session_size(dev_id),
-			cache_size,
-			0,
-			NULL,
-			NULL,
-			NULL,
-			NULL,
-			socket_id,
-			0);
-	if (!cryptodev->mp_init)
-		goto error_exit;
-
-	TAILQ_INSERT_TAIL(&p->cryptodev_list, cryptodev, node);
-
-	return cryptodev;
-
-error_exit:
-	rte_mempool_free(cryptodev->mp_create);
-	rte_mempool_free(cryptodev->mp_init);
-
-	free(cryptodev);
-
-	return NULL;
-}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d578cb1f25..ddcde99b98 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -100,28 +100,6 @@ struct softnic_tap {
 
 TAILQ_HEAD(softnic_tap_list, softnic_tap);
 
-/**
- * Cryptodev
- */
-struct softnic_cryptodev_params {
-	const char *dev_name;
-	uint32_t dev_id; /**< Valid only when *dev_name* is NULL. */
-	uint32_t n_queues;
-	uint32_t queue_size;
-	uint32_t session_pool_size;
-};
-
-struct softnic_cryptodev {
-	TAILQ_ENTRY(softnic_cryptodev) node;
-	char name[NAME_SIZE];
-	uint16_t dev_id;
-	uint32_t n_queues;
-	struct rte_mempool *mp_create;
-	struct rte_mempool *mp_init;
-};
-
-TAILQ_HEAD(softnic_cryptodev_list, softnic_cryptodev);
-
 /**
  * Input port action
  */
@@ -187,7 +165,6 @@ enum softnic_port_in_type {
 	PORT_IN_SWQ,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
-	PORT_IN_CRYPTODEV,
 };
 
 struct softnic_port_in_params {
@@ -209,12 +186,6 @@ struct softnic_port_in_params {
 			const char *file_name;
 			uint32_t n_bytes_per_pkt;
 		} source;
-
-		struct {
-			uint16_t queue_id;
-			void *f_callback;
-			void *arg_callback;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 
@@ -227,7 +198,6 @@ enum softnic_port_out_type {
 	PORT_OUT_SWQ,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
-	PORT_OUT_CRYPTODEV,
 };
 
 struct softnic_port_out_params {
@@ -242,11 +212,6 @@ struct softnic_port_out_params {
 			const char *file_name;
 			uint32_t max_n_pkts;
 		} sink;
-
-		struct {
-			uint16_t queue_id;
-			uint32_t op_offset;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 	int retry;
@@ -421,7 +386,6 @@ struct pmd_internals {
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
 	struct softnic_tap_list tap_list;
-	struct softnic_cryptodev_list cryptodev_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;
@@ -519,24 +483,6 @@ struct softnic_tap *
 softnic_tap_create(struct pmd_internals *p,
 	const char *name);
 
-/**
- * Sym Crypto
- */
-int
-softnic_cryptodev_init(struct pmd_internals *p);
-
-void
-softnic_cryptodev_free(struct pmd_internals *p);
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 2cf7fa52d1..51a1ea73c0 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -227,7 +227,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		struct rte_port_sched_reader_params sched;
 		struct rte_port_fd_reader_params fd;
 		struct rte_port_source_params source;
-		struct rte_port_sym_crypto_reader_params cryptodev;
 	} pp;
 
 	struct pipeline *pipeline;
@@ -330,23 +329,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.f_callback = params->cryptodev.f_callback;
-		pp.cryptodev.arg_callback = params->cryptodev.arg_callback;
-		p.ops = &rte_port_sym_crypto_reader_ops;
-		p.arg_create = &pp.cryptodev;
-		break;
-	}
-
 	default:
 		return -1;
 	}
@@ -433,14 +415,12 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		struct rte_port_sched_writer_params sched;
 		struct rte_port_fd_writer_params fd;
 		struct rte_port_sink_params sink;
-		struct rte_port_sym_crypto_writer_params cryptodev;
 	} 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;
-		struct rte_port_sym_crypto_writer_nodrop_params cryptodev;
 	} pp_nodrop;
 
 	struct pipeline *pipeline;
@@ -554,40 +534,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		if (params->cryptodev.queue_id >= cryptodev->n_queues)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.tx_burst_sz = params->burst_size;
-		pp.cryptodev.crypto_op_offset = params->cryptodev.op_offset;
-
-		pp_nodrop.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp_nodrop.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp_nodrop.cryptodev.tx_burst_sz = params->burst_size;
-		pp_nodrop.cryptodev.n_retries = params->retry;
-		pp_nodrop.cryptodev.crypto_op_offset =
-				params->cryptodev.op_offset;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_sym_crypto_writer_ops;
-			p.arg_create = &pp.cryptodev;
-		} else {
-			p.ops = &rte_port_sym_crypto_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.cryptodev;
-		}
-
-		break;
-	}
-
 	default:
 		return -1;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 05/21] net/softnic: remove tap support
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (3 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
                     ` (15 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the TUN/TAP device support. The TUN/TAP devices are still
supported as virtual Ethernet devices through the TAP Poll Mode
Driver.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  76 -----------
 .../net/softnic/rte_eth_softnic_internals.h   |  36 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  44 -------
 drivers/net/softnic/rte_eth_softnic_tap.c     | 118 ------------------
 6 files changed, 278 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index b3d235841d..91f1f3220f 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -16,7 +16,6 @@ sources = files(
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
-        'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
 deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 1ea5989223..eb97ae7185 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -162,7 +162,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
@@ -183,7 +182,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
@@ -263,7 +261,6 @@ pmd_init(struct pmd_params *params)
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tap_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index bca0b176d6..501ef08c4c 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,33 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tap <tap_name>
- */
-static void
-cmd_tap(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tap *tap;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tap = softnic_tap_create(softnic, name);
-	if (tap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -874,7 +847,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
@@ -957,38 +929,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
 		t0 += 2;
-	} else if (strcmp(tokens[t0], "tap") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tap");
-			return;
-		}
-
-		p.type = PORT_IN_TAP;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.tap.mempool_name = tokens[t0 + 3];
-
-		if (strcmp(tokens[t0 + 4], "mtu") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mtu");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tap.mtu,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
-			return;
-		}
-
-		t0 += 6;
 	} else if (strcmp(tokens[t0], "source") == 0) {
 		if (n_tokens < t0 + 6) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1074,7 +1014,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  */
 static void
@@ -1147,16 +1086,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tap") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tap");
-			return;
-		}
-
-		p.type = PORT_OUT_TAP;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "sink") == 0) {
 		if ((n_tokens != 7) && (n_tokens != 11)) {
@@ -4600,11 +4529,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tap") == 0) {
-		cmd_tap(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index ddcde99b98..df74c1fbdc 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -89,17 +89,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TAP
- */
-struct softnic_tap {
-	TAILQ_ENTRY(softnic_tap) node;
-	char name[NAME_SIZE];
-	int fd;
-};
-
-TAILQ_HEAD(softnic_tap_list, softnic_tap);
-
 /**
  * Input port action
  */
@@ -163,7 +152,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 };
 
@@ -176,11 +164,6 @@ struct softnic_port_in_params {
 			uint16_t queue_id;
 		} rxq;
 
-		struct {
-			const char *mempool_name;
-			uint32_t mtu;
-		} tap;
-
 		struct {
 			const char *mempool_name;
 			const char *file_name;
@@ -196,7 +179,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 };
 
@@ -385,7 +367,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tap_list tap_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;
@@ -466,23 +447,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TAP
- */
-int
-softnic_tap_init(struct pmd_internals *p);
-
-void
-softnic_tap_free(struct pmd_internals *p);
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 51a1ea73c0..7a2828b785 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -293,25 +293,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TAP:
-	{
-		struct softnic_tap *tap;
-		struct softnic_mempool *mempool;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		mempool = softnic_mempool_find(softnic, params->tap.mempool_name);
-		if (tap == NULL || mempool == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.mempool = mempool->m;
-		pp.fd.mtu = params->tap.mtu;
-
-		p.ops = &rte_port_fd_reader_ops;
-		p.arg_create = &pp.fd;
-		break;
-	}
-
 	case PORT_IN_SOURCE:
 	{
 		struct softnic_mempool *mempool;
@@ -499,31 +480,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TAP:
-	{
-		struct softnic_tap *tap;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		if (tap == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.tx_burst_sz = params->burst_size;
-
-		pp_nodrop.fd.fd = tap->fd;
-		pp_nodrop.fd.tx_burst_sz = params->burst_size;
-		pp_nodrop.fd.n_retries = params->n_retries;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_fd_writer_ops;
-			p.arg_create = &pp.fd;
-		} else {
-			p.ops = &rte_port_fd_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.fd;
-		}
-		break;
-	}
-
 	case PORT_OUT_SINK:
 	{
 		pp.sink.file_name = params->sink.file_name;
diff --git a/drivers/net/softnic/rte_eth_softnic_tap.c b/drivers/net/softnic/rte_eth_softnic_tap.c
deleted file mode 100644
index 36fe9f0287..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tap.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <netinet/in.h>
-#ifdef RTE_EXEC_ENV_LINUX
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#endif
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define TAP_DEV                                            "/dev/net/tun"
-
-int
-softnic_tap_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tap_list);
-
-	return 0;
-}
-
-void
-softnic_tap_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tap *tap;
-
-		tap = TAILQ_FIRST(&p->tap_list);
-		if (tap == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tap_list, tap, node);
-		free(tap);
-	}
-}
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tap, &p->tap_list, node)
-		if (strcmp(tap->name, name) == 0)
-			return tap;
-
-	return NULL;
-}
-
-#ifndef RTE_EXEC_ENV_LINUX
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p __rte_unused,
-	const char *name __rte_unused)
-{
-	return NULL;
-}
-
-#else
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-	struct ifreq ifr;
-	int fd, status;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tap_find(p, name))
-		return NULL;
-
-	/* Resource create */
-	fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
-	if (fd < 0)
-		return NULL;
-
-	memset(&ifr, 0, sizeof(ifr));
-	ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
-	strlcpy(ifr.ifr_name, name, IFNAMSIZ);
-
-	status = ioctl(fd, TUNSETIFF, (void *)&ifr);
-	if (status < 0) {
-		close(fd);
-		return NULL;
-	}
-
-	/* Node allocation */
-	tap = calloc(1, sizeof(struct softnic_tap));
-	if (tap == NULL) {
-		close(fd);
-		return NULL;
-	}
-	/* Node fill in */
-	strlcpy(tap->name, name, sizeof(tap->name));
-	tap->fd = fd;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tap_list, tap, node);
-
-	return tap;
-}
-
-#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 06/21] net/softnic: remove the legacy pipeline CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (4 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 05/21] net/softnic: remove tap support Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
                     ` (14 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the legacy pipeline CLI commands.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 4527 ---------------------
 1 file changed, 4527 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 501ef08c4c..abe275ec83 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -10,7 +10,6 @@
 #include <rte_common.h>
 #include <rte_cycles.h>
 #include <rte_string_fns.h>
-#include <rte_cryptodev.h>
 
 #include "rte_eth_softnic_internals.h"
 #include "parser.h"
@@ -186,4227 +185,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * port in action profile <profile_name>
- *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
- *  [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
- */
-static void
-cmd_port_in_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_action_profile_params p;
-	struct softnic_port_in_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[2], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[3], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[4];
-
-	t0 = 5;
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "filter") == 0)) {
-		uint32_t size;
-
-		if (n_tokens < t0 + 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "match") == 0) {
-			p.fltr.filter_on_match = 1;
-		} else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
-			p.fltr.filter_on_match = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.fltr.key_mask, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 7],
-			p.fltr.key, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.port_id,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
-		t0 += 10;
-	} /* filter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		uint32_t i;
-
-		if (n_tokens < t0 + 22) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"port in action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		for (i = 0; i < 16; i++)
-			if (softnic_parser_read_uint32(&p.lb.port_id[i],
-			tokens[t0 + 6 + i]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-				return;
-			}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
-		t0 += 22;
-	} /* balance */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_port_in_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * table action profile <profile_name>
- *  ipv4 | ipv6
- *  offset <ip_offset>
- *  fwd
- *  [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
- *  [meter srtcm | trtcm
- *      tc <n_tc>
- *      stats none | pkts | bytes | both]
- *  [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
- *  [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe |
- *      vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]
- *  [nat src | dst
- *      proto udp | tcp]
- *  [ttl drop | fwd
- *      stats none | pkts]
- *  [stats pkts | bytes | both]
- *  [time]
- *  [tag]
- *  [decap]
- *
- */
-static void
-cmd_table_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_action_profile_params p;
-	struct softnic_table_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[3];
-
-	if (strcmp(tokens[4], "ipv4") == 0) {
-		p.common.ip_version = 1;
-	} else if (strcmp(tokens[4], "ipv6") == 0) {
-		p.common.ip_version = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
-		return;
-	}
-
-	if (strcmp(tokens[5], "offset") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.common.ip_offset,
-		tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
-		return;
-	}
-
-	if (strcmp(tokens[7], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
-		return;
-	}
-
-	p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
-
-	t0 = 8;
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		if (n_tokens < t0 + 7) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.out_offset,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
-		t0 += 7;
-	} /* balance */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "meter") == 0)) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile meter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
-		} else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"srtcm or trtcm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "tc") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.mtr.n_tc,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "none") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 5], "both") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
-		t0 += 6;
-	} /* meter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tm") == 0)) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile tm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "spp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_subports_per_port");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "pps") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_pipes_per_subport");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
-		t0 += 5;
-	} /* tm */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "encap") == 0)) {
-		uint32_t n_extra_tokens = 0;
-
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"action profile encap");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "ether") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
-		} else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
-		} else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
-		} else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
-		} else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
-		} else if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
-			if (n_tokens < t0 + 2 + 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					"action profile encap vxlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2], "offset") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: offset");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.encap.vxlan.data_offset,
-				tokens[t0 + 2 + 1]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ether_offset");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
-				p.encap.vxlan.ip_version = 1;
-			else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
-				p.encap.vxlan.ip_version = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ipv4 or ipv6");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: vlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
-				p.encap.vxlan.vlan = 1;
-			else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
-				p.encap.vxlan.vlan = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: on or off");
-				return;
-			}
-
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
-			n_extra_tokens = 5;
-
-		} else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) {
-			p.encap.encap_mask =
-				1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
-		t0 += 2 + n_extra_tokens;
-	} /* encap */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "nat") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile nat");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "src") == 0) {
-			p.nat.source_nat = 1;
-		} else if (strcmp(tokens[t0 + 1], "dst") == 0) {
-			p.nat.source_nat = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"src or dst");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "proto") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "tcp") == 0) {
-			p.nat.proto = 0x06;
-		} else if (strcmp(tokens[t0 + 3], "udp") == 0) {
-			p.nat.proto = 0x11;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"tcp or udp");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
-		t0 += 4;
-	} /* nat */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "ttl") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile ttl");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "drop") == 0) {
-			p.ttl.drop = 1;
-		} else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
-			p.ttl.drop = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"drop or fwd");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "none") == 0) {
-			p.ttl.n_packets_enabled = 0;
-		} else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
-			p.ttl.n_packets_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
-		t0 += 4;
-	} /* ttl */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "stats") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "pkts") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
-			p.stats.n_packets_enabled = 0;
-			p.stats.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 1], "both") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-				"pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
-		t0 += 2;
-	} /* stats */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "time") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
-		t0 += 1;
-	} /* time */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tag") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG;
-		t0 += 1;
-	} /* tag */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "decap") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP;
-		t0 += 1;
-	} /* decap */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_table_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name>
- *  period <timer_period_ms>
- *  offset_port_id <offset_port_id>
- */
-static void
-cmd_pipeline(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct pipeline_params p;
-	char *name;
-	struct pipeline *pipeline;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "period") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.timer_period_ms,
-		tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
-		return;
-	}
-
-	if (strcmp(tokens[4], "offset_port_id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.offset_port_id,
-		tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
-		return;
-	}
-
-	pipeline = softnic_pipeline_create(softnic, name, &p);
-	if (pipeline == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in
- *  bsz <burst_size>
- *  link <link_name> rxq <queue_id>
- *  | swq <swq_name>
- *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  [action <port_in_action_profile_name>]
- *  [disabled]
- */
-static void
-cmd_pipeline_port_in(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int enabled, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	t0 = 6;
-
-	if (strcmp(tokens[t0], "link") == 0) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in link");
-			return;
-		}
-
-		p.type = PORT_IN_RXQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"queue_id");
-			return;
-		}
-		t0 += 4;
-	} else if (strcmp(tokens[t0], "swq") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in swq");
-			return;
-		}
-
-		p.type = PORT_IN_SWQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "source") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in source");
-			return;
-		}
-
-		p.type = PORT_IN_SOURCE;
-
-		if (strcmp(tokens[t0 + 1], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.source.mempool_name = tokens[t0 + 2];
-
-		if (strcmp(tokens[t0 + 3], "file") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"file");
-			return;
-		}
-
-		p.source.file_name = tokens[t0 + 4];
-
-		if (strcmp(tokens[t0 + 5], "bpp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"bpp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_bytes_per_pkt");
-			return;
-		}
-
-		t0 += 7;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	enabled = 1;
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "disabled") == 0)) {
-		enabled = 0;
-
-		t0 += 1;
-	}
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_in_create(softnic,
-		pipeline_name,
-		&p,
-		enabled);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out
- *  bsz <burst_size>
- *  link <link_name> txq <txq_id>
- *  | swq <swq_name>
- *  | sink [file <file_name> pkts <max_n_pkts>]
- */
-static void
-cmd_pipeline_port_out(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_out_params p;
-	char *pipeline_name;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	if (strcmp(tokens[6], "link") == 0) {
-		if (n_tokens != 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out link");
-			return;
-		}
-
-		p.type = PORT_OUT_TXQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.txq.queue_id,
-			tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-	} else if (strcmp(tokens[6], "swq") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out swq");
-			return;
-		}
-
-		p.type = PORT_OUT_SWQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "sink") == 0) {
-		if ((n_tokens != 7) && (n_tokens != 11)) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out sink");
-			return;
-		}
-
-		p.type = PORT_OUT_SINK;
-
-		if (n_tokens == 7) {
-			p.sink.file_name = NULL;
-			p.sink.max_n_pkts = 0;
-		} else {
-			if (strcmp(tokens[7], "file") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"file");
-				return;
-			}
-
-			p.sink.file_name = tokens[8];
-
-			if (strcmp(tokens[9], "pkts") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
-				tokens[10]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
-				return;
-			}
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table
- *      match
- *      acl
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | array
- *          offset <key_offset>
- *          size <n_keys>
- *      | hash
- *          ext | lru
- *          key <key_size>
- *          mask <key_mask>
- *          offset <key_offset>
- *          buckets <n_buckets>
- *          size <n_keys>
- *      | lpm
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | stub
- *  [action <table_action_profile_name>]
- */
-static void
-cmd_pipeline_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (strcmp(tokens[3], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return;
-	}
-
-	t0 = 4;
-	if (strcmp(tokens[t0], "acl") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table acl");
-			return;
-		}
-
-		p.match_type = TABLE_ACL;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.acl.ip_version = 1;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.acl.ip_version = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"ip_header_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "array") == 0) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table array");
-			return;
-		}
-
-		p.match_type = TABLE_ARRAY;
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.n_keys,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 5;
-	} else if (strcmp(tokens[t0], "hash") == 0) {
-		uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-		if (n_tokens < t0 + 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table hash");
-			return;
-		}
-
-		p.match_type = TABLE_HASH;
-
-		if (strcmp(tokens[t0 + 1], "ext") == 0) {
-			p.match.hash.extendable_bucket = 1;
-		} else if (strcmp(tokens[t0 + 1], "lru") == 0) {
-			p.match.hash.extendable_bucket = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ext or lru");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		if ((softnic_parser_read_uint32(&p.match.hash.key_size,
-			tokens[t0 + 3]) != 0) ||
-			p.match.hash.key_size == 0 ||
-			p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.match.hash.key_mask, &key_mask_size) != 0) ||
-			key_mask_size != p.match.hash.key_size) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.key_offset,
-			tokens[t0 + 7]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "buckets") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 10], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_keys,
-			tokens[t0 + 11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 12;
-	} else if (strcmp(tokens[t0], "lpm") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table lpm");
-			return;
-		}
-
-		p.match_type = TABLE_LPM;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.lpm.key_size = 4;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.lpm.key_size = 16;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "stub") == 0) {
-		p.match_type = TABLE_STUB;
-
-		t0 += 1;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	if (n_tokens > t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> table <table_id>
- */
-static void
-cmd_pipeline_port_in_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id, table_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_connect_to_table(softnic,
-		pipeline_name,
-		port_id,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> stats read [clear]
- */
-
-#define MSG_PIPELINE_PORT_IN_STATS                         \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_in_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_in_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_in_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> enable
- */
-static void
-cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "enable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> disable
- */
-static void
-cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "disable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out <port_id> stats read [clear]
- */
-#define MSG_PIPELINE_PORT_OUT_STATS                        \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_out_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_out_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_out_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> stats read [clear]
- */
-#define MSG_PIPELINE_TABLE_STATS                                     \
-	"Pkts in: %" PRIu64 "\n"                                     \
-	"Pkts in with lookup miss: %" PRIu64 "\n"                    \
-	"Pkts in with lookup hit dropped by AH: %" PRIu64 "\n"       \
-	"Pkts in with lookup hit dropped by others: %" PRIu64 "\n"   \
-	"Pkts in with lookup miss dropped by AH: %" PRIu64 "\n"      \
-	"Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_table_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_table_stats stats;
-	char *pipeline_name;
-	uint32_t table_id;
-	int clear, status;
-
-	if (n_tokens != 6 &&
-		n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[5], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 7) {
-		if (strcmp(tokens[6], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_table_stats_read(softnic,
-		pipeline_name,
-		table_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
-		stats.stats.n_pkts_in,
-		stats.stats.n_pkts_lookup_miss,
-		stats.n_pkts_dropped_by_lkp_hit_ah,
-		stats.n_pkts_dropped_lkp_hit,
-		stats.n_pkts_dropped_by_lkp_miss_ah,
-		stats.n_pkts_dropped_lkp_miss);
-}
-
-/**
- * <match> ::=
- *
- * match
- *    acl
- *       priority <priority>
- *       ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
- *       <sp0> <sp1> <dp0> <dp1> <proto>
- *    | array <pos>
- *    | hash
- *       raw <key>
- *       | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv4_addr <addr>
- *       | ipv6_addr <addr>
- *       | qinq <svlan> <cvlan>
- *    | lpm
- *       ipv4 | ipv6 <addr> <depth>
- */
-struct pkt_key_qinq {
-	uint16_t ethertype_svlan;
-	uint16_t svlan;
-	uint16_t ethertype_cvlan;
-	uint16_t cvlan;
-} __rte_packed;
-
-struct pkt_key_ipv4_5tuple {
-	uint8_t time_to_live;
-	uint8_t proto;
-	uint16_t hdr_checksum;
-	uint32_t sa;
-	uint32_t da;
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv6_5tuple {
-	uint16_t payload_length;
-	uint8_t proto;
-	uint8_t hop_limit;
-	uint8_t sa[16];
-	uint8_t da[16];
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv4_addr {
-	uint32_t addr;
-} __rte_packed;
-
-struct pkt_key_ipv6_addr {
-	uint8_t addr[16];
-} __rte_packed;
-
-static uint32_t
-parse_match(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_match *m)
-{
-	memset(m, 0, sizeof(*m));
-
-	if (n_tokens < 2)
-		return 0;
-
-	if (strcmp(tokens[0], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return 0;
-	}
-
-	if (strcmp(tokens[1], "acl") == 0) {
-		if (n_tokens < 14) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ACL;
-
-		if (strcmp(tokens[2], "priority") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.priority,
-			tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-			return 0;
-		}
-
-		if (strcmp(tokens[4], "ipv4") == 0) {
-			struct in_addr saddr, daddr;
-
-			m->match.acl.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
-
-			if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
-		} else if (strcmp(tokens[4], "ipv6") == 0) {
-			struct in6_addr saddr, daddr;
-
-			m->match.acl.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
-
-			if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.sa_depth,
-			tokens[6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.da_depth,
-			tokens[8]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "proto");
-			return 0;
-		}
-
-		m->match.acl.proto_mask = 0xff;
-
-		return 14;
-	} /* acl */
-
-	if (strcmp(tokens[1], "array") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ARRAY;
-
-		if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pos");
-			return 0;
-		}
-
-		return 3;
-	} /* array */
-
-	if (strcmp(tokens[1], "hash") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_HASH;
-
-		if (strcmp(tokens[2], "raw") == 0) {
-			uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_hex_string(tokens[3],
-				m->match.hash.key, &key_size) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "key");
-				return 0;
-			}
-
-			return 4;
-		} /* hash raw */
-
-		if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
-			struct pkt_key_ipv4_5tuple *ipv4 =
-				(struct pkt_key_ipv4_5tuple *)m->match.hash.key;
-			struct in_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			ipv4->sa = saddr.s_addr;
-			ipv4->da = daddr.s_addr;
-			ipv4->sp = rte_cpu_to_be_16(sp);
-			ipv4->dp = rte_cpu_to_be_16(dp);
-			ipv4->proto = proto;
-
-			return 8;
-		} /* hash ipv4_5tuple */
-
-		if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
-			struct pkt_key_ipv6_5tuple *ipv6 =
-				(struct pkt_key_ipv6_5tuple *)m->match.hash.key;
-			struct in6_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			memcpy(ipv6->sa, saddr.s6_addr, 16);
-			memcpy(ipv6->da, daddr.s6_addr, 16);
-			ipv6->sp = rte_cpu_to_be_16(sp);
-			ipv6->dp = rte_cpu_to_be_16(dp);
-			ipv6->proto = proto;
-
-			return 8;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "ipv4_addr") == 0) {
-			struct pkt_key_ipv4_addr *ipv4_addr =
-				(struct pkt_key_ipv4_addr *)m->match.hash.key;
-			struct in_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			ipv4_addr->addr = addr.s_addr;
-
-			return 4;
-		} /* hash ipv4_addr */
-
-		if (strcmp(tokens[2], "ipv6_addr") == 0) {
-			struct pkt_key_ipv6_addr *ipv6_addr =
-				(struct pkt_key_ipv6_addr *)m->match.hash.key;
-			struct in6_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(ipv6_addr->addr, addr.s6_addr, 16);
-
-			return 4;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "qinq") == 0) {
-			struct pkt_key_qinq *qinq =
-				(struct pkt_key_qinq *)m->match.hash.key;
-			uint16_t svlan, cvlan;
-
-			if (n_tokens < 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) ||
-				svlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"svlan");
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) ||
-				cvlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"cvlan");
-				return 0;
-			}
-
-			qinq->svlan = rte_cpu_to_be_16(svlan);
-			qinq->cvlan = rte_cpu_to_be_16(cvlan);
-
-			return 5;
-		} /* hash qinq */
-
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return 0;
-	} /* hash */
-
-	if (strcmp(tokens[1], "lpm") == 0) {
-		if (n_tokens < 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_LPM;
-
-		if (strcmp(tokens[2], "ipv4") == 0) {
-			struct in_addr addr;
-
-			m->match.lpm.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		} else if (strcmp(tokens[2], "ipv6") == 0) {
-			struct in6_addr addr;
-
-			m->match.lpm.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "depth");
-			return 0;
-		}
-
-		return 5;
-	} /* lpm */
-
-	snprintf(out, out_size, MSG_ARG_MISMATCH,
-		"acl or array or hash or lpm");
-	return 0;
-}
-
-/**
- * table_action ::=
- *
- * action
- *    fwd
- *       drop
- *       | port <port_id>
- *       | meta
- *       | table <table_id>
- *    [balance <out0> ... <out7>]
- *    [meter
- *       tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
- *    [tm subport <subport_id> pipe <pipe_id>]
- *    [encap
- *       ether <da> <sa>
- *       | vlan <da> <sa> <pcp> <dei> <vid>
- *       | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
- *       | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id>
- *       | mpls unicast | multicast
- *          <da> <sa>
- *          label0 <label> <tc> <ttl>
- *          [label1 <label> <tc> <ttl>
- *          [label2 <label> <tc> <ttl>
- *          [label3 <label> <tc> <ttl>]]]
- *       | pppoe <da> <sa> <session_id>]
- *       | vxlan ether <da> <sa>
- *          [vlan <pcp> <dei> <vid>]
- *          ipv4 <sa> <da> <dscp> <ttl>
- *          | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit>
- *          udp <sp> <dp>
- *          vxlan <vni>]
- *    [nat ipv4 | ipv6 <addr> <port>]
- *    [ttl dec | keep]
- *    [stats]
- *    [time]
- *    [tag <tag>]
- *    [decap <n>]
- *    [sym_crypto
- *       encrypt | decrypt
- *       type
- *       | cipher
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *       | cipher_auth
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *          auth_algo <algo> auth_key <key> digest_size <size>
- *       | aead
- *          aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad>
- *          digest_size <size>
- *       data_offset <data_offset>]
- *
- * where:
- *    <pa> ::= g | y | r | drop
- */
-static uint32_t
-parse_table_action_fwd(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "fwd") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_DROP;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_balance(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t i;
-
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "balance") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
-		return 0;
-
-	for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
-		if (softnic_parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
-			return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-	return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
-}
-
-static int
-parse_policer_action(char *token, enum rte_table_action_policer *a)
-{
-	if (strcmp(token, "g") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-		return 0;
-	}
-
-	if (strcmp(token, "y") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-		return 0;
-	}
-
-	if (strcmp(token, "r") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
-		return 0;
-	}
-
-	if (strcmp(token, "drop") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_DROP;
-		return 0;
-	}
-
-	return -1;
-}
-
-static uint32_t
-parse_table_action_meter_tc(char **tokens,
-	uint32_t n_tokens,
-	struct rte_table_action_mtr_tc_params *mtr)
-{
-	if (n_tokens < 9 ||
-		strcmp(tokens[0], "meter") ||
-		softnic_parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
-		strcmp(tokens[2], "policer") ||
-		strcmp(tokens[3], "g") ||
-		parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) ||
-		strcmp(tokens[5], "y") ||
-		parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) ||
-		strcmp(tokens[7], "r") ||
-		parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED]))
-		return 0;
-
-	return 9;
-}
-
-static uint32_t
-parse_table_action_meter(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "meter"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < 10 ||
-		strcmp(tokens[0], "tc0") ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1,
-			&a->mtr.mtr[0]) == 0))
-		return 0;
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "tc1")) {
-		a->mtr.tc_mask = 1;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-		return 1 + 10;
-	}
-
-	if (n_tokens < 30 ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
-		strcmp(tokens[10], "tc2") ||
-		(parse_table_action_meter_tc(tokens + 11,
-			n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
-		strcmp(tokens[20], "tc3") ||
-		(parse_table_action_meter_tc(tokens + 21,
-			n_tokens - 21, &a->mtr.mtr[3]) == 0))
-		return 0;
-
-	a->mtr.tc_mask = 0xF;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-	return 1 + 10 + 3 * 10;
-}
-
-static uint32_t
-parse_table_action_tm(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t subport_id, pipe_id;
-
-	if (n_tokens < 5 ||
-		strcmp(tokens[0], "tm") ||
-		strcmp(tokens[1], "subport") ||
-		softnic_parser_read_uint32(&subport_id, tokens[2]) ||
-		strcmp(tokens[3], "pipe") ||
-		softnic_parser_read_uint32(&pipe_id, tokens[4]))
-		return 0;
-
-	a->tm.subport_id = subport_id;
-	a->tm.pipe_id = pipe_id;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
-	return 5;
-}
-
-static uint32_t
-parse_table_action_encap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "encap"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	/* ether */
-	if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
-		if (n_tokens < 3 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 3;
-	}
-
-	/* vlan */
-	if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
-		uint32_t pcp, dei, vid;
-
-		if (n_tokens < 6 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
-			softnic_parser_read_uint32(&pcp, tokens[3]) ||
-			pcp > 0x7 ||
-			softnic_parser_read_uint32(&dei, tokens[4]) ||
-			dei > 0x1 ||
-			softnic_parser_read_uint32(&vid, tokens[5]) ||
-			vid > 0xFFF)
-			return 0;
-
-		a->encap.vlan.vlan.pcp = pcp & 0x7;
-		a->encap.vlan.vlan.dei = dei & 0x1;
-		a->encap.vlan.vlan.vid = vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 6;
-	}
-
-	/* qinq */
-	if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 9 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF)
-			return 0;
-
-		a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 9;
-	}
-
-	/* qinq_pppoe */
-	if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 10 ||
-			softnic_parse_mac_addr(tokens[1],
-				&a->encap.qinq_pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2],
-				&a->encap.qinq_pppoe.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF ||
-			softnic_parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id,
-				tokens[9]))
-			return 0;
-
-		a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 10;
-	}
-
-	/* mpls */
-	if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
-		uint32_t label, tc, ttl;
-
-		if (n_tokens < 8)
-			return 0;
-
-		if (strcmp(tokens[1], "unicast") == 0)
-			a->encap.mpls.unicast = 1;
-		else if (strcmp(tokens[1], "multicast") == 0)
-			a->encap.mpls.unicast = 0;
-		else
-			return 0;
-
-		if (softnic_parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
-			softnic_parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
-			strcmp(tokens[4], "label0") ||
-			softnic_parser_read_uint32(&label, tokens[5]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[6]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[7]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[0].label = label;
-		a->encap.mpls.mpls[0].tc = tc;
-		a->encap.mpls.mpls[0].ttl = ttl;
-
-		tokens += 8;
-		n_tokens -= 8;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label1")) {
-			a->encap.mpls.mpls_count = 1;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[1].label = label;
-		a->encap.mpls.mpls[1].tc = tc;
-		a->encap.mpls.mpls[1].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label2")) {
-			a->encap.mpls.mpls_count = 2;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[2].label = label;
-		a->encap.mpls.mpls[2].tc = tc;
-		a->encap.mpls.mpls[2].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label3")) {
-			a->encap.mpls.mpls_count = 3;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[3].label = label;
-		a->encap.mpls.mpls[3].tc = tc;
-		a->encap.mpls.mpls[3].ttl = ttl;
-
-		a->encap.mpls.mpls_count = 4;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 8 + 4 + 4 + 4;
-	}
-
-	/* pppoe */
-	if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
-		if (n_tokens < 4 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
-			softnic_parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
-				tokens[3]))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 4;
-	}
-
-	/* vxlan */
-	if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) {
-		uint32_t n = 0;
-
-		n_tokens--;
-		tokens++;
-		n++;
-
-		/* ether <da> <sa> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "ether") ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* [vlan <pcp> <dei> <vid>] */
-		if (strcmp(tokens[0], "vlan") == 0) {
-			uint32_t pcp, dei, vid;
-
-			if ((n_tokens < 4) ||
-				softnic_parser_read_uint32(&pcp, tokens[1]) ||
-				(pcp > 7) ||
-				softnic_parser_read_uint32(&dei, tokens[2]) ||
-				(dei > 1) ||
-				softnic_parser_read_uint32(&vid, tokens[3]) ||
-				(vid > 0xFFF))
-				return 0;
-
-			a->encap.vxlan.vlan.pcp = pcp;
-			a->encap.vxlan.vlan.dei = dei;
-			a->encap.vxlan.vlan.vid = vid;
-
-			n_tokens -= 4;
-			tokens += 4;
-			n += 4;
-		}
-
-		/* ipv4 <sa> <da> <dscp> <ttl>
-		   | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */
-		if (strcmp(tokens[0], "ipv4") == 0) {
-			struct in_addr sa, da;
-			uint8_t dscp, ttl;
-
-			if ((n_tokens < 5) ||
-				softnic_parse_ipv4_addr(tokens[1], &sa) ||
-				softnic_parse_ipv4_addr(tokens[2], &da) ||
-				softnic_parser_read_uint8(&dscp, tokens[3]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&ttl, tokens[4]))
-				return 0;
-
-			a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr);
-			a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr);
-			a->encap.vxlan.ipv4.dscp = dscp;
-			a->encap.vxlan.ipv4.ttl = ttl;
-
-			n_tokens -= 5;
-			tokens += 5;
-			n += 5;
-		} else if (strcmp(tokens[0], "ipv6") == 0) {
-			struct in6_addr sa, da;
-			uint32_t flow_label;
-			uint8_t dscp, hop_limit;
-
-			if ((n_tokens < 6) ||
-				softnic_parse_ipv6_addr(tokens[1], &sa) ||
-				softnic_parse_ipv6_addr(tokens[2], &da) ||
-				softnic_parser_read_uint32(&flow_label, tokens[3]) ||
-				softnic_parser_read_uint8(&dscp, tokens[4]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&hop_limit, tokens[5]))
-				return 0;
-
-			memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
-			memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
-			a->encap.vxlan.ipv6.flow_label = flow_label;
-			a->encap.vxlan.ipv6.dscp = dscp;
-			a->encap.vxlan.ipv6.hop_limit = hop_limit;
-
-			n_tokens -= 6;
-			tokens += 6;
-			n += 6;
-		} else
-			return 0;
-
-		/* udp <sp> <dp> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "udp") ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2]))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* vxlan <vni> */
-		if ((n_tokens < 2) ||
-			strcmp(tokens[0], "vxlan") ||
-			softnic_parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) ||
-			(a->encap.vxlan.vxlan.vni > 0xFFFFFF))
-			return 0;
-
-		n_tokens -= 2;
-		tokens += 2;
-		n += 2;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + n;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_nat(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 4 ||
-		strcmp(tokens[0], "nat"))
-		return 0;
-
-	if (strcmp(tokens[1], "ipv4") == 0) {
-		struct in_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv4_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 1;
-		a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	if (strcmp(tokens[1], "ipv6") == 0) {
-		struct in6_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv6_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 0;
-		memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_ttl(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "ttl"))
-		return 0;
-
-	if (strcmp(tokens[1], "dec") == 0)
-		a->ttl.decrement = 1;
-	else if (strcmp(tokens[1], "keep") == 0)
-		a->ttl.decrement = 0;
-	else
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_stats(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "stats"))
-		return 0;
-
-	a->stats.n_packets = 0;
-	a->stats.n_bytes = 0;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-	return 1;
-}
-
-static uint32_t
-parse_table_action_time(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "time"))
-		return 0;
-
-	a->time.time = rte_rdtsc();
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
-	return 1;
-}
-
-static void
-parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
-{
-	struct rte_crypto_sym_xform *xform[2] = {NULL};
-	uint32_t i;
-
-	xform[0] = p->xform;
-	if (xform[0])
-		xform[1] = xform[0]->next;
-
-	for (i = 0; i < 2; i++) {
-		if (xform[i] == NULL)
-			continue;
-
-		switch (xform[i]->type) {
-		case RTE_CRYPTO_SYM_XFORM_CIPHER:
-			free(p->cipher_auth.cipher_iv.val);
-			free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AUTH:
-			if (p->cipher_auth.auth_iv.val)
-				free(p->cipher_auth.cipher_iv.val);
-			if (p->cipher_auth.auth_iv_update.val)
-				free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AEAD:
-			free(p->aead.iv.val);
-			free(p->aead.aad.val);
-			break;
-		default:
-			continue;
-		}
-	}
-
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	int status;
-	size_t len;
-
-	if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") ||
-			strcmp(tokens[3], "cipher_key") ||
-			strcmp(tokens[5], "cipher_iv"))
-		return NULL;
-
-	xform_cipher = calloc(1, sizeof(*xform_cipher));
-	if (xform_cipher == NULL)
-		return NULL;
-
-	xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
-	xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT :
-			RTE_CRYPTO_CIPHER_OP_DECRYPT;
-
-	/* cipher_algo */
-	status = rte_cryptodev_get_cipher_algo_enum(
-			&xform_cipher->cipher.algo, tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* cipher_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.key.data = key;
-	xform_cipher->cipher.key.length = (uint16_t)len;
-
-	/* cipher_iv */
-	len = strlen(tokens[6]);
-
-	p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1);
-	if (p->cipher_auth.cipher_iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6],
-			p->cipher_auth.cipher_iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.iv.length = (uint16_t)len;
-	xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->cipher_auth.cipher_iv.length = (uint32_t)len;
-	*used_n_tokens = 7;
-
-	return xform_cipher;
-
-error_exit:
-	if (p->cipher_auth.cipher_iv.val) {
-		free(p->cipher_auth.cipher_iv.val);
-		p->cipher_auth.cipher_iv.val = NULL;
-	}
-
-	free(xform_cipher);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	struct rte_crypto_sym_xform *xform_auth;
-	int status;
-	size_t len;
-
-	if (n_tokens < 13 ||
-			strcmp(tokens[7], "auth_algo") ||
-			strcmp(tokens[9], "auth_key") ||
-			strcmp(tokens[11], "digest_size"))
-		return NULL;
-
-	xform_auth = calloc(1, sizeof(*xform_auth));
-	if (xform_auth == NULL)
-		return NULL;
-
-	xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH;
-	xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE :
-			RTE_CRYPTO_AUTH_OP_VERIFY;
-
-	/* auth_algo */
-	status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo,
-			tokens[8]);
-	if (status < 0)
-		goto error_exit;
-
-	/* auth_key */
-	len = strlen(tokens[10]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_auth->auth.key.data = key;
-	xform_auth->auth.key.length = (uint16_t)len;
-
-	key += xform_auth->auth.key.length;
-	max_key_len -= xform_auth->auth.key.length;
-
-	if (strcmp(tokens[11], "digest_size"))
-		goto error_exit;
-
-	status = softnic_parser_read_uint16(&xform_auth->auth.digest_length,
-			tokens[12]);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7,
-			encrypt, used_n_tokens);
-	if (xform_cipher == NULL)
-		goto error_exit;
-
-	*used_n_tokens += 6;
-
-	if (encrypt) {
-		xform_cipher->next = xform_auth;
-		return xform_cipher;
-	} else {
-		xform_auth->next = xform_cipher;
-		return xform_auth;
-	}
-
-error_exit:
-	if (p->cipher_auth.auth_iv.val) {
-		free(p->cipher_auth.auth_iv.val);
-		p->cipher_auth.auth_iv.val = 0;
-	}
-
-	free(xform_auth);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_aead;
-	int status;
-	size_t len;
-
-	if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") ||
-			strcmp(tokens[3], "aead_key") ||
-			strcmp(tokens[5], "aead_iv") ||
-			strcmp(tokens[7], "aead_aad") ||
-			strcmp(tokens[9], "digest_size"))
-		return NULL;
-
-	xform_aead = calloc(1, sizeof(*xform_aead));
-	if (xform_aead == NULL)
-		return NULL;
-
-	xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD;
-	xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT :
-			RTE_CRYPTO_AEAD_OP_DECRYPT;
-
-	/* aead_algo */
-	status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo,
-			tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* aead_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.key.data = key;
-	xform_aead->aead.key.length = (uint16_t)len;
-
-	/* aead_iv */
-	len = strlen(tokens[6]);
-	p->aead.iv.val = calloc(1, len / 2 + 1);
-	if (p->aead.iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6], p->aead.iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.iv.length = (uint16_t)len;
-	xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->aead.iv.length = (uint32_t)len;
-
-	/* aead_aad */
-	len = strlen(tokens[8]);
-	p->aead.aad.val = calloc(1, len / 2 + 1);
-	if (p->aead.aad.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.aad_length = (uint16_t)len;
-	p->aead.aad.length = (uint32_t)len;
-
-	/* digest_size */
-	status = softnic_parser_read_uint16(&xform_aead->aead.digest_length,
-			tokens[10]);
-	if (status < 0)
-		goto error_exit;
-
-	*used_n_tokens = 11;
-
-	return xform_aead;
-
-error_exit:
-	if (p->aead.iv.val) {
-		free(p->aead.iv.val);
-		p->aead.iv.val = NULL;
-	}
-	if (p->aead.aad.val) {
-		free(p->aead.aad.val);
-		p->aead.aad.val = NULL;
-	}
-
-	free(xform_aead);
-
-	return NULL;
-}
-
-
-static uint32_t
-parse_table_action_sym_crypto(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
-	struct rte_crypto_sym_xform *xform = NULL;
-	uint8_t *key = a->sym_crypto_key;
-	uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
-	uint32_t used_n_tokens;
-	uint32_t encrypt;
-	int status;
-
-	if ((n_tokens < 12) ||
-		strcmp(tokens[0], "sym_crypto") ||
-		strcmp(tokens[2], "type"))
-		return 0;
-
-	memset(p, 0, sizeof(*p));
-
-	if (strcmp(tokens[1], "encrypt") == 0)
-		encrypt = 1;
-	else
-		encrypt = 0;
-
-	status = softnic_parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]);
-	if (status < 0)
-		return 0;
-
-	if (strcmp(tokens[3], "cipher") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "cipher_auth") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher_auth(p, key, max_key_len,
-				tokens, n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "aead") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_aead(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	}
-
-	if (xform == NULL)
-		return 0;
-
-	p->xform = xform;
-
-	if (strcmp(tokens[used_n_tokens], "data_offset")) {
-		parse_free_sym_crypto_param_data(p);
-		return 0;
-	}
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-	return used_n_tokens + 5;
-}
-
-static uint32_t
-parse_table_action_tag(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "tag"))
-		return 0;
-
-	if (softnic_parser_read_uint32(&a->tag.tag, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_decap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "decap"))
-		return 0;
-
-	if (softnic_parser_read_uint16(&a->decap.n, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-	return 2;
-}
-
-static uint32_t
-parse_table_action(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t n_tokens0 = n_tokens;
-
-	memset(a, 0, sizeof(*a));
-
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "action"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_fwd(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action fwd");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_balance(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action balance");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_meter(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action meter");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tm(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tm");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_encap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action encap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_nat(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action nat");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_ttl(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action ttl");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_stats(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action stats");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_time(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action time");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tag") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tag(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tag");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "decap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_decap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action decap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_sym_crypto(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action sym_crypto");
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens0 - n_tokens == 1) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return 0;
-	}
-
-	return n_tokens0 - n_tokens;
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match <match>
- *    action <table_action>
- */
-static void
-cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	struct softnic_table_rule_action a;
-	char *pipeline_name;
-	void *data;
-	uint32_t table_id, t0, n_tokens_parsed;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	/* action */
-	n_tokens_parsed = parse_table_action(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&a);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (t0 != n_tokens) {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&m,
-		&a,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match
- *       default
- *    action
- *       fwd
- *          drop
- *          | port <port_id>
- *          | meta
- *          | table <table_id>
- */
-static void
-cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_action action;
-	void *data;
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 11 &&
-		n_tokens != 12) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	if (strcmp(tokens[8], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return;
-	}
-
-	if (strcmp(tokens[9], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
-		return;
-	}
-
-	action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
-
-	if (strcmp(tokens[10], "drop") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_DROP;
-	} else if (strcmp(tokens[10], "port") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT;
-		action.fwd.id = id;
-	} else if (strcmp(tokens[10], "meta") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-	} else if (strcmp(tokens[10], "table") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		action.fwd.id = id;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID,
-			"drop or port or meta or table");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add_default(softnic,
-		pipeline_name,
-		table_id,
-		&action,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
- *
- * File <file_name>:
- * - line format: match <match> action <action>
- */
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size);
-
-static void
-cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match *match;
-	struct softnic_table_rule_action *action;
-	void **data;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, n_rules, n_rules_parsed, line_number;
-	int status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "bulk") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
-		return;
-	}
-
-	file_name = tokens[7];
-
-	if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
-		n_rules == 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-		return;
-	}
-
-	/* Memory allocation. */
-	match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
-	action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
-	data = calloc(n_rules, sizeof(void *));
-	if (match == NULL ||
-		action == NULL ||
-		data == NULL) {
-		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Load rule file */
-	n_rules_parsed = n_rules;
-	status = cli_rule_file_process(file_name,
-		1024,
-		match,
-		action,
-		&n_rules_parsed,
-		&line_number,
-		out,
-		out_size);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-	if (n_rules_parsed != n_rules) {
-		snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Rule bulk add */
-	status = softnic_pipeline_table_rule_add_bulk(softnic,
-		pipeline_name,
-		table_id,
-		match,
-		action,
-		data,
-		&n_rules);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Memory free */
-	free(data);
-	free(action);
-	free(match);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match <match>
- */
-static void
-cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	char *pipeline_name;
-	uint32_t table_id, n_tokens_parsed, t0;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete(softnic,
-		pipeline_name,
-		table_id,
-		&m);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match
- *       default
- */
-static void
-cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete_default(softnic,
-		pipeline_name,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read stats [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>
- *  add srtcm cir <cir> cbs <cbs> ebs <ebs>
- *  | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>
- */
-static void
-cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_meter_profile p;
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens < 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[8], "srtcm") == 0) {
-		if (n_tokens != 15) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_SRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[13], "ebs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
-			return;
-		}
-	} else if (strcmp(tokens[8], "trtcm") == 0) {
-		if (n_tokens != 17) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_TRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "pir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pir");
-			return;
-		}
-		if (strcmp(tokens[13], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[15], "pbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_add(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id,
-		&p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id>
- *  meter profile <meter_profile_id> delete
- */
-static void
-cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_delete(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read meter [clear]
- */
-static void
-cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> dscp <file_name>
- *
- * File <file_name>:
- *  - exactly 64 lines
- *  - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r
- */
-static int
-load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
-	const char *file_name,
-	uint32_t *line_number)
-{
-	FILE *f = NULL;
-	uint32_t dscp, l;
-
-	/* Check input arguments */
-	if (dscp_table == NULL ||
-		file_name == NULL ||
-		line_number == NULL) {
-		if (line_number)
-			*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Open input file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Read file */
-	for (dscp = 0, l = 1; ; l++) {
-		char line[64];
-		char *tokens[3];
-		enum rte_color color;
-		uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
-
-		if (fgets(line, sizeof(line), f) == NULL)
-			break;
-
-		if (is_comment(line))
-			continue;
-
-		if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		if (n_tokens == 0)
-			continue;
-
-		if (dscp >= RTE_DIM(dscp_table->entry) ||
-			n_tokens != RTE_DIM(tokens) ||
-			softnic_parser_read_uint32(&tc_id, tokens[0]) ||
-			tc_id >= RTE_TABLE_ACTION_TC_MAX ||
-			softnic_parser_read_uint32(&tc_queue_id, tokens[1]) ||
-			tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX ||
-			(strlen(tokens[2]) != 1)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		switch (tokens[2][0]) {
-		case 'g':
-		case 'G':
-			color = RTE_COLOR_GREEN;
-			break;
-
-		case 'y':
-		case 'Y':
-			color = RTE_COLOR_YELLOW;
-			break;
-
-		case 'r':
-		case 'R':
-			color = RTE_COLOR_RED;
-			break;
-
-		default:
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		dscp_table->entry[dscp].tc_id = tc_id;
-		dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
-		dscp_table->entry[dscp].color = color;
-		dscp++;
-	}
-
-	/* Close file */
-	fclose(f);
-	return 0;
-}
-
-static void
-cmd_pipeline_table_dscp(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_dscp_table dscp_table;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, line_number;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "dscp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
-		return;
-	}
-
-	file_name = tokens[5];
-
-	status = load_dscp_table(&dscp_table, file_name, &line_number);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		return;
-	}
-
-	status = softnic_pipeline_table_dscp_table_update(softnic,
-		pipeline_name,
-		table_id,
-		UINT64_MAX,
-		&dscp_table);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read ttl [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
 /**
  * thread <thread_id> pipeline <pipeline_name> enable
  */
@@ -4529,202 +307,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "port") == 0) {
-		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "table") == 0) {
-		cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "pipeline") == 0) {
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[2], "period") == 0)) {
-			cmd_pipeline(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 4 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[3], "match") == 0)) {
-			cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "table") == 0)) {
-			cmd_pipeline_port_in_table(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_in_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "enable") == 0)) {
-			cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "disable") == 0)) {
-			cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_out_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "stats") == 0)) {
-			cmd_pipeline_table_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_add_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-			}
-
-			cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "bulk") == 0)) {
-			cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "delete") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-				}
-
-			cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "stats") == 0)) {
-			cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "add") == 0)) {
-			cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "delete") == 0)) {
-			cmd_pipeline_table_meter_profile_delete(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "meter") == 0)) {
-			cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "dscp") == 0)) {
-			cmd_pipeline_table_dscp(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "ttl") == 0)) {
-			cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
@@ -4800,112 +382,3 @@ softnic_cli_script_process(struct pmd_internals *softnic,
 	free(msg_in);
 	return 0;
 }
-
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size)
-{
-	FILE *f = NULL;
-	char *line = NULL;
-	uint32_t rule_id, line_id;
-	int status = 0;
-
-	/* Check input arguments */
-	if (file_name == NULL ||
-		(strlen(file_name) == 0) ||
-		line_len_max == 0) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Memory allocation */
-	line = malloc(line_len_max + 1);
-	if (line == NULL) {
-		*line_number = 0;
-		return -ENOMEM;
-	}
-
-	/* Open file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		free(line);
-		return -EIO;
-	}
-
-	/* Read file */
-	for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
-		char *tokens[CMD_MAX_TOKENS];
-		uint32_t n_tokens, n_tokens_parsed, t0;
-
-		/* Read next line from file. */
-		if (fgets(line, line_len_max + 1, f) == NULL)
-			break;
-
-		/* Comment. */
-		if (is_comment(line))
-			continue;
-
-		/* Parse line. */
-		n_tokens = RTE_DIM(tokens);
-		status = softnic_parse_tokenize_string(line, tokens, &n_tokens);
-		if (status) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Empty line. */
-		if (n_tokens == 0)
-			continue;
-		t0 = 0;
-
-		/* Rule match. */
-		n_tokens_parsed = parse_match(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&m[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Rule action. */
-		n_tokens_parsed = parse_table_action(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&a[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Line completed. */
-		if (t0 < n_tokens) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Increment rule count */
-		rule_id++;
-	}
-
-	/* Close file */
-	fclose(f);
-
-	/* Memory free */
-	free(line);
-
-	*n_rules = rule_id;
-	*line_number = line_id;
-	return status;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (5 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
                     ` (13 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 08/21] net/softnic: remove the list of Ethernet devices
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (6 preceding siblings ...)
  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   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
                     ` (12 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

The list of Ethernet devices within this driver is redundant, as the
DPDK global list of Ethernet devices can be used instead.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  49 ---------
 .../net/softnic/rte_eth_softnic_internals.h   |  37 -------
 drivers/net/softnic/rte_eth_softnic_link.c    | 101 ------------------
 5 files changed, 191 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index f0cfc6dc17..0ffe26d671 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -11,7 +11,6 @@ sources = files(
         'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a940952c7a..b1f4edd629 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -160,7 +160,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	/* Firmware */
 	softnic_pipeline_disable_all(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
@@ -178,7 +177,6 @@ pmd_free(struct pmd_internals *p)
 
 	softnic_thread_free(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
@@ -256,7 +254,6 @@ pmd_init(struct pmd_params *params)
 	/* Resources */
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
-	softnic_link_init(p);
 	softnic_pipeline_init(p);
 
 	status = softnic_thread_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 2b00b65c6c..ec9ac133b9 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -102,50 +102,6 @@ cmd_mempool(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * link <link_name>
- *    dev <device_name> | port <port_id>
- */
-static void
-cmd_link(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_link_params p;
-	struct softnic_link *link;
-	char *name;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 4) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0) {
-		p.dev_name = tokens[3];
-	} else if (strcmp(tokens[2], "port") == 0) {
-		p.dev_name = NULL;
-
-		if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
-		return;
-	}
-
-	link = softnic_link_create(softnic, name, &p);
-	if (link == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * swq <swq_name>
  *  size <size>
@@ -309,11 +265,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "link") == 0) {
-		cmd_link(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "swq") == 0) {
 		cmd_swq(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d817883a39..a1c2309589 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -70,24 +70,6 @@ struct softnic_swq {
 
 TAILQ_HEAD(softnic_swq_list, softnic_swq);
 
-/**
- * LINK
- */
-struct softnic_link_params {
-	const char *dev_name;
-	uint16_t port_id; /**< Valid only when *dev_name* is NULL. */
-};
-
-struct softnic_link {
-	TAILQ_ENTRY(softnic_link) node;
-	char name[NAME_SIZE];
-	uint16_t port_id;
-	uint32_t n_rxq;
-	uint32_t n_txq;
-};
-
-TAILQ_HEAD(softnic_link_list, softnic_link);
-
 /**
  * Pipeline
  */
@@ -162,7 +144,6 @@ struct pmd_internals {
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
-	struct softnic_link_list link_list;
 	struct pipeline_list pipeline_list;
 	struct softnic_thread thread[RTE_MAX_LCORE];
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
@@ -223,24 +204,6 @@ softnic_swq_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_swq_params *params);
 
-/**
- * LINK
- */
-int
-softnic_link_init(struct pmd_internals *p);
-
-void
-softnic_link_free(struct pmd_internals *p);
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params);
-
 /**
  * Pipeline
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_link.c b/drivers/net/softnic/rte_eth_softnic_link.c
deleted file mode 100644
index 21a64069f6..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_link.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_ethdev.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_link_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->link_list);
-
-	return 0;
-}
-
-void
-softnic_link_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_link *link;
-
-		link = TAILQ_FIRST(&p->link_list);
-		if (link == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->link_list, link, node);
-		free(link);
-	}
-}
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_link *link;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(link, &p->link_list, node)
-		if (strcmp(link->name, name) == 0)
-			return link;
-
-	return NULL;
-}
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params)
-{
-	struct rte_eth_dev_info port_info;
-	struct softnic_link *link;
-	uint16_t port_id;
-	int ret;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_link_find(p, name) ||
-		params == NULL)
-		return NULL;
-
-	port_id = params->port_id;
-	if (params->dev_name) {
-		int status;
-
-		status = rte_eth_dev_get_port_by_name(params->dev_name,
-			&port_id);
-
-		if (status)
-			return NULL;
-	} else {
-		if (!rte_eth_dev_is_valid_port(port_id))
-			return NULL;
-	}
-
-	ret = rte_eth_dev_info_get(port_id, &port_info);
-	if (ret != 0)
-		return NULL;
-
-	/* Node allocation */
-	link = calloc(1, sizeof(struct softnic_link));
-	if (link == NULL)
-		return NULL;
-
-	/* Node fill in */
-	strlcpy(link->name, name, sizeof(link->name));
-	link->port_id = port_id;
-	link->n_rxq = port_info.nb_rx_queues;
-	link->n_txq = port_info.nb_tx_queues;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->link_list, link, node);
-
-	return link;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 09/21] net/softnic: remove unused text parsing functions
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (7 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
                     ` (11 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the text parsing functions that are not used.

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/parser.c              | 523 ----------------------
 drivers/net/softnic/parser.h              |  68 ---
 drivers/net/softnic/rte_eth_softnic_cli.c |  54 ++-
 4 files changed, 46 insertions(+), 600 deletions(-)
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 0ffe26d671..5dfbd16c77 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -8,7 +8,6 @@ endif
 headers = files('rte_eth_softnic.h')
 sources = files(
         'conn.c',
-        'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_mempool.c',
diff --git a/drivers/net/softnic/parser.c b/drivers/net/softnic/parser.c
deleted file mode 100644
index ebcb10268a..0000000000
--- a/drivers/net/softnic/parser.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 Intel Corporation.
- * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
- * All rights reserved.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-#include <rte_errno.h>
-
-#include "parser.h"
-
-static uint32_t
-get_hex_val(char c)
-{
-	switch (c) {
-	case '0': case '1': case '2': case '3': case '4': case '5':
-	case '6': case '7': case '8': case '9':
-		return c - '0';
-	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-		return c - 'A' + 10;
-	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-		return c - 'a' + 10;
-	default:
-		return 0;
-	}
-}
-
-int
-softnic_parser_read_arg_bool(const char *p)
-{
-	p = skip_white_spaces(p);
-	int result = -EINVAL;
-
-	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
-		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
-		p += 3;
-		result = 1;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'n')) ||
-		((p[0] == 'O') && (p[1] == 'N'))) {
-		p += 2;
-		result = 1;
-	}
-
-	if (((p[0] == 'n') && (p[1] == 'o')) ||
-		((p[0] == 'N') && (p[1] == 'O'))) {
-		p += 2;
-		result = 0;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
-		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
-		p += 3;
-		result = 0;
-	}
-
-	p = skip_white_spaces(p);
-
-	if (p[0] != '\0')
-		return -EINVAL;
-
-	return result;
-}
-
-int
-softnic_parser_read_int32(int32_t *value, const char *p)
-{
-	char *next;
-	int32_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtol(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtoul(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	p = next;
-	switch (*p) {
-	case 'T':
-		val *= 1024ULL;
-		/* fall through */
-	case 'G':
-		val *= 1024ULL;
-		/* fall through */
-	case 'M':
-		val *= 1024ULL;
-		/* fall through */
-	case 'k':
-	case 'K':
-		val *= 1024ULL;
-		p++;
-		break;
-	}
-
-	p = skip_white_spaces(p);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-
-	val = strtoul(p, &next, 16);
-	if (p == next)
-		return -EINVAL;
-
-	p = skip_white_spaces(next);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
-{
-	uint32_t i;
-
-	if (string == NULL ||
-		tokens == NULL ||
-		(*n_tokens < 1))
-		return -EINVAL;
-
-	for (i = 0; i < *n_tokens; i++) {
-		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
-		if (tokens[i] == NULL)
-			break;
-	}
-
-	if (i == *n_tokens &&
-		strtok_r(string, PARSE_DELIMITER, &string) != NULL)
-		return -E2BIG;
-
-	*n_tokens = i;
-	return 0;
-}
-
-int
-softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
-{
-	char *c;
-	uint32_t len, i;
-
-	/* Check input parameters */
-	if (src == NULL ||
-		dst == NULL ||
-		size == NULL ||
-		(*size == 0))
-		return -1;
-
-	len = strlen(src);
-	if (((len & 3) != 0) ||
-		(len > (*size) * 2))
-		return -1;
-	*size = len / 2;
-
-	for (c = src; *c != 0; c++) {
-		if ((((*c) >= '0') && ((*c) <= '9')) ||
-			(((*c) >= 'A') && ((*c) <= 'F')) ||
-			(((*c) >= 'a') && ((*c) <= 'f')))
-			continue;
-
-		return -1;
-	}
-
-	/* Convert chars to bytes */
-	for (i = 0; i < *size; i++)
-		dst[i] = get_hex_val(src[2 * i]) * 16 +
-			get_hex_val(src[2 * i + 1]);
-
-	return 0;
-}
-
-int
-softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
-{
-	uint32_t n_max_labels = *n_labels, count = 0;
-
-	/* Check for void list of labels */
-	if (strcmp(string, "<void>") == 0) {
-		*n_labels = 0;
-		return 0;
-	}
-
-	/* At least one label should be present */
-	for ( ; (*string != '\0'); ) {
-		char *next;
-		int value;
-
-		if (count >= n_max_labels)
-			return -1;
-
-		if (count > 0) {
-			if (string[0] != ':')
-				return -1;
-
-			string++;
-		}
-
-		value = strtol(string, &next, 10);
-		if (next == string)
-			return -1;
-		string = next;
-
-		labels[count++] = (uint32_t)value;
-	}
-
-	*n_labels = count;
-	return 0;
-}
-
-static struct rte_ether_addr *
-my_ether_aton(const char *a)
-{
-	int i;
-	char *end;
-	unsigned long o[RTE_ETHER_ADDR_LEN];
-	static struct rte_ether_addr ether_addr;
-
-	i = 0;
-	do {
-		errno = 0;
-		o[i] = strtoul(a, &end, 16);
-		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
-			return NULL;
-		a = end + 1;
-	} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
-
-	/* Junk at the end of line */
-	if (end[0] != 0)
-		return NULL;
-
-	/* Support the format XX:XX:XX:XX:XX:XX */
-	if (i == RTE_ETHER_ADDR_LEN) {
-		while (i-- != 0) {
-			if (o[i] > UINT8_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i] = (uint8_t)o[i];
-		}
-	/* Support the format XXXX:XXXX:XXXX */
-	} else if (i == RTE_ETHER_ADDR_LEN / 2) {
-		while (i-- != 0) {
-			if (o[i] > UINT16_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
-			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
-		}
-	/* unknown format */
-	} else
-		return NULL;
-
-	return (struct rte_ether_addr *)&ether_addr;
-}
-
-int
-softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
-{
-	if (strlen(token) >= INET_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET, token, ipv4) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
-{
-	if (strlen(token) >= INET6_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET6, token, ipv6) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
-{
-	struct rte_ether_addr *tmp;
-
-	tmp = my_ether_aton(token);
-	if (tmp == NULL)
-		return -1;
-
-	memcpy(addr, tmp, sizeof(struct rte_ether_addr));
-	return 0;
-}
-
-int
-softnic_parse_cpu_core(const char *entry,
-	struct softnic_cpu_core_params *p)
-{
-	size_t num_len;
-	char num[8];
-
-	uint32_t s = 0, c = 0, h = 0, val;
-	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
-	const char *next = skip_white_spaces(entry);
-	char type;
-
-	if (p == NULL)
-		return -EINVAL;
-
-	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
-	while (*next != '\0') {
-		/* If everything parsed nothing should left */
-		if (s_parsed && c_parsed && h_parsed)
-			return -EINVAL;
-
-		type = *next;
-		switch (type) {
-		case 's':
-		case 'S':
-			if (s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-			s_parsed = 1;
-			next++;
-			break;
-		case 'c':
-		case 'C':
-			if (c_parsed || h_parsed)
-				return -EINVAL;
-			c_parsed = 1;
-			next++;
-			break;
-		case 'h':
-		case 'H':
-			if (h_parsed)
-				return -EINVAL;
-			h_parsed = 1;
-			next++;
-			break;
-		default:
-			/* If it start from digit it must be only core id. */
-			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-
-			type = 'C';
-		}
-
-		for (num_len = 0; *next != '\0'; next++, num_len++) {
-			if (num_len == RTE_DIM(num))
-				return -EINVAL;
-
-			if (!isdigit(*next))
-				break;
-
-			num[num_len] = *next;
-		}
-
-		if (num_len == 0 && type != 'h' && type != 'H')
-			return -EINVAL;
-
-		if (num_len != 0 && (type == 'h' || type == 'H'))
-			return -EINVAL;
-
-		num[num_len] = '\0';
-		val = strtol(num, NULL, 10);
-
-		h = 0;
-		switch (type) {
-		case 's':
-		case 'S':
-			s = val;
-			break;
-		case 'c':
-		case 'C':
-			c = val;
-			break;
-		case 'h':
-		case 'H':
-			h = 1;
-			break;
-		}
-	}
-
-	p->socket_id = s;
-	p->core_id = c;
-	p->thread_id = h;
-	return 0;
-}
diff --git a/drivers/net/softnic/parser.h b/drivers/net/softnic/parser.h
deleted file mode 100644
index 6f408b2485..0000000000
--- a/drivers/net/softnic/parser.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
- */
-
-#ifndef __INCLUDE_SOFTNIC_PARSER_H__
-#define __INCLUDE_SOFTNIC_PARSER_H__
-
-#include <stdint.h>
-
-#include <rte_ip.h>
-#include <rte_ether.h>
-
-#define PARSE_DELIMITER				" \f\n\r\t\v"
-
-#define skip_white_spaces(pos)			\
-({						\
-	__typeof__(pos) _p = (pos);		\
-	for ( ; isspace(*_p); _p++)		\
-		;				\
-	_p;					\
-})
-
-static inline size_t
-skip_digits(const char *src)
-{
-	size_t i;
-
-	for (i = 0; isdigit(src[i]); i++)
-		;
-
-	return i;
-}
-
-int softnic_parser_read_arg_bool(const char *p);
-
-int softnic_parser_read_int32(int32_t *value, const char *p);
-
-int softnic_parser_read_uint64(uint64_t *value, const char *p);
-int softnic_parser_read_uint32(uint32_t *value, const char *p);
-int softnic_parser_read_uint16(uint16_t *value, const char *p);
-int softnic_parser_read_uint8(uint8_t *value, const char *p);
-
-int softnic_parser_read_uint64_hex(uint64_t *value, const char *p);
-int softnic_parser_read_uint32_hex(uint32_t *value, const char *p);
-int softnic_parser_read_uint16_hex(uint16_t *value, const char *p);
-int softnic_parser_read_uint8_hex(uint8_t *value, const char *p);
-
-int softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
-
-int softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4);
-int softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6);
-int softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr);
-int softnic_parse_mpls_labels(char *string,
-		uint32_t *labels, uint32_t *n_labels);
-
-struct softnic_cpu_core_params {
-	uint32_t socket_id;
-	uint32_t core_id;
-	uint32_t thread_id;
-};
-
-int softnic_parse_cpu_core(const char *entry,
-		struct softnic_cpu_core_params *p);
-
-int softnic_parse_tokenize_string(char *string,
-		char *tokens[], uint32_t *n_tokens);
-
-#endif
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index ec9ac133b9..9de17fba8f 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -12,7 +12,6 @@
 #include <rte_string_fns.h>
 
 #include "rte_eth_softnic_internals.h"
-#include "parser.h"
 
 #ifndef CMD_MAX_TOKENS
 #define CMD_MAX_TOKENS     256
@@ -30,6 +29,45 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint32_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoul(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+static int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+	uint32_t i;
+
+	if (!string || !tokens || !n_tokens || !*n_tokens)
+		return -EINVAL;
+
+	for (i = 0; i < *n_tokens; i++) {
+		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+		if (!tokens[i])
+			break;
+	}
+
+	if (i == *n_tokens && strtok_r(string, PARSE_DELIMITER, &string))
+		return -E2BIG;
+
+	*n_tokens = i;
+	return 0;
+}
+
 static int
 is_comment(char *in)
 {
@@ -70,7 +108,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
 		return;
 	}
@@ -80,7 +118,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
+	if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
 		return;
 	}
@@ -90,7 +128,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
+	if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
 		return;
 	}
@@ -129,7 +167,7 @@ cmd_swq(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "size");
 		return;
 	}
@@ -161,7 +199,7 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -210,7 +248,7 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -251,7 +289,7 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 	if (is_comment(in))
 		return;
 
-	status = softnic_parse_tokenize_string(in, tokens, &n_tokens);
+	status = parse_tokenize_string(in, tokens, &n_tokens);
 	if (status) {
 		snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
 		return;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 10/21] net/softnic: add pipeline code generation CLI command
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (8 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
                     ` (10 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline code generation.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 57 ++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 9de17fba8f..f2c2721d55 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -180,7 +180,55 @@ cmd_swq(struct pmd_internals *softnic,
 }
 
 /**
- * thread <thread_id> pipeline <pipeline_name> enable
+ * pipeline codegen <spec_file> <code_file>
+ */
+static void
+cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	FILE *spec_file = NULL;
+	FILE *code_file = NULL;
+	uint32_t err_line;
+	const char *err_msg;
+	int status;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	spec_file = fopen(tokens[2], "r");
+	if (!spec_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+		return;
+	}
+
+	code_file = fopen(tokens[3], "w");
+	if (!code_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+		return;
+	}
+
+	status = rte_swx_pipeline_codegen(spec_file,
+					  code_file,
+					  &err_line,
+					  &err_msg);
+
+	fclose(spec_file);
+	fclose(code_file);
+
+	if (status) {
+		snprintf(out, out_size, "Error %d at line %u: %s\n.",
+			status, err_line, err_msg);
+		return;
+	}
+}
+
+/**
+ * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
 static void
 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
@@ -308,6 +356,13 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
+	if (!strcmp(tokens[0], "pipeline")) {
+		if (n_tokens >= 2 && !strcmp(tokens[1], "codegen")) {
+			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+	}
+
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 11/21] net/softnic: add pipeline library build CLI command
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (9 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 12/21] net/softnic: add pipeline " Cristian Dumitrescu
                     ` (9 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline shared library build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 143 ++++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index f2c2721d55..08cca7a8e4 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -6,6 +6,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_cycles.h>
@@ -17,6 +18,10 @@
 #define CMD_MAX_TOKENS     256
 #endif
 
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
 #define MSG_OUT_OF_MEMORY   "Not enough memory.\n"
 #define MSG_CMD_UNKNOWN     "Unknown command \"%s\".\n"
 #define MSG_CMD_UNIMPLEM    "Command \"%s\" not implemented.\n"
@@ -227,6 +232,139 @@ cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
 	}
 }
 
+/**
+ * pipeline libbuild <code_file> <lib_file>
+ */
+static void
+cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+	char *install_dir, *cwd = NULL, *buffer = NULL;
+	size_t length;
+	int status = 0;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		goto free;
+	}
+
+	install_dir = getenv("RTE_INSTALL_DIR");
+	if (!install_dir) {
+		cwd = malloc(MAX_LINE_SIZE);
+		if (!cwd) {
+			snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+			goto free;
+		}
+
+		install_dir = getcwd(cwd, MAX_LINE_SIZE);
+		if (!install_dir) {
+			snprintf(out, out_size, "Error: Path too long.\n");
+			goto free;
+		}
+	}
+
+	snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	code_file = tokens[2];
+	length = strnlen(code_file, MAX_LINE_SIZE);
+	if (length < 3 ||
+	    code_file[length - 2] != '.' ||
+	    code_file[length - 1] != 'c') {
+		snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+		goto free;
+	}
+
+	lib_file = tokens[3];
+	length = strnlen(lib_file, MAX_LINE_SIZE);
+	if (length < 4 ||
+	    lib_file[length - 3] != '.' ||
+	    lib_file[length - 2] != 's' ||
+	    lib_file[length - 1] != 'o') {
+		snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+		goto free;
+	}
+
+	obj_file = malloc(length);
+	log_file = malloc(length + 2);
+	if (!obj_file || !log_file) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		goto free;
+	}
+
+	memcpy(obj_file, lib_file, length - 2);
+	obj_file[length - 2] = 'o';
+	obj_file[length - 1] = 0;
+
+	memcpy(log_file, lib_file, length - 2);
+	log_file[length - 2] = 'l';
+	log_file[length - 1] = 'o';
+	log_file[length] = 'g';
+	log_file[length + 1] = 0;
+
+	buffer = malloc(MAX_LINE_SIZE);
+	if (!buffer) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		return;
+	}
+
+	snprintf(buffer,
+		 MAX_LINE_SIZE,
+		 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+		 "-I %s/lib/pipeline "
+		 "-I %s/lib/eal/include "
+		 "-I %s/lib/eal/x86/include "
+		 "-I %s/lib/eal/include/generic "
+		 "-I %s/lib/meter "
+		 "-I %s/lib/port "
+		 "-I %s/lib/table "
+		 "-I %s/lib/pipeline "
+		 "-I %s/config "
+		 "-I %s/build "
+		 "-I %s/lib/eal/linux/include "
+		 ">%s 2>&1 "
+		 "&& "
+		 "gcc -shared %s -o %s "
+		 ">>%s 2>&1",
+		 obj_file,
+		 code_file,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 log_file,
+		 obj_file,
+		 lib_file,
+		 log_file);
+
+	status = system(buffer);
+	if (status) {
+		snprintf(out,
+			 out_size,
+			 "Library build failed, see file \"%s\" for details.\n",
+			 log_file);
+		goto free;
+	}
+
+free:
+	free(cwd);
+	free(obj_file);
+	free(log_file);
+	free(buffer);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -361,6 +499,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[1], "libbuild")) {
+			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 12/21] net/softnic: add pipeline build CLI command
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (10 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
                     ` (8 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 66 +++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 08cca7a8e4..cf71aa7b96 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -365,6 +365,67 @@ cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
 	free(buffer);
 }
 
+/**
+ * pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>
+ */
+static void
+cmd_softnic_pipeline_build(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p = NULL;
+	char *pipeline_name, *lib_file_name, *iospec_file_name;
+	uint32_t numa_node = 0;
+
+	/* Parsing. */
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+
+	if (strcmp(tokens[2], "build")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
+		return;
+	}
+
+	if (strcmp(tokens[3], "lib")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
+		return;
+	}
+
+	lib_file_name = tokens[4];
+
+	if (strcmp(tokens[5], "io")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
+		return;
+	}
+
+	iospec_file_name = tokens[6];
+
+	if (strcmp(tokens[7], "numa")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
+		return;
+	}
+
+	if (parser_read_uint32(&numa_node, tokens[8])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+		return;
+	}
+
+	/* Pipeline create. */
+	p = softnic_pipeline_create(softnic,
+				    pipeline_name,
+				    lib_file_name,
+				    iospec_file_name,
+				    (int)numa_node);
+	if (!p)
+		snprintf(out, out_size, "Pipeline creation failed.\n");
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -504,6 +565,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "build")) {
+			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 13/21] net/softnic: add pipeline table CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (11 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 12/21] net/softnic: add pipeline " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
                     ` (7 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline table entry management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 370 ++++++++++++++++++++++
 1 file changed, 370 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index cf71aa7b96..4443b62009 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -426,6 +426,354 @@ cmd_softnic_pipeline_build(struct pmd_internals *softnic,
 		snprintf(out, out_size, "Pipeline creation failed.\n");
 }
 
+static void
+table_entry_free(struct rte_swx_table_entry *entry)
+{
+	if (!entry)
+		return;
+
+	free(entry->key);
+	free(entry->key_mask);
+	free(entry->action_data);
+	free(entry);
+}
+
+static int
+pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
+			   const char *table_name,
+			   FILE *file,
+			   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_add(p,
+							      table_name,
+							      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> add <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_add(p->ctl,
+					    table_name,
+					    file,
+					    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p,
+			      const char *table_name,
+			      FILE *file,
+			      uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_delete(p,
+								 table_name,
+								 entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_delete(p->ctl,
+					       table_name,
+					       file,
+					       &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				 const char *table_name,
+				 FILE *file,
+				 uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_default_entry_add(p,
+								      table_name,
+								      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_default_entry_add(p->ctl,
+						  table_name,
+						  file,
+						  &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -570,6 +918,28 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "add")) {
+			cmd_softnic_pipeline_table_add(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "delete")) {
+			cmd_softnic_pipeline_table_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_table_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 14/21] net/softnic: add pipeline selector table CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (12 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
                     ` (6 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for selector tables group and member management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 517 ++++++++++++++++++++++
 1 file changed, 517 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 4443b62009..1e92e251aa 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -774,6 +774,477 @@ cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
 		fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> selector <selector_name> group add
+ */
+static void
+cmd_softnic_pipeline_selector_group_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
+		selector_name,
+		&group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+	else
+		snprintf(out, out_size, "Group ID: %u\n", group_id);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group delete <group_id>
+ */
+static void
+cmd_softnic_pipeline_selector_group_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 7) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete");
+		return;
+	}
+
+	if (parser_read_uint32(&group_id, tokens[6]) != 0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
+		selector_name,
+		group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+}
+
+#define GROUP_MEMBER_INFO_TOKENS_MAX 6
+
+static int
+token_is_comment(const char *token)
+{
+	if ((token[0] == '#') ||
+	    (token[0] == ';') ||
+	    ((token[0] == '/') && (token[1] == '/')))
+		return 1; /* TRUE. */
+
+	return 0; /* FALSE. */
+}
+
+static int
+pipeline_selector_group_member_read(const char *string,
+				    uint32_t *group_id,
+				    uint32_t *member_id,
+				    uint32_t *weight,
+				    int *is_blank_or_comment)
+{
+	char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens;
+	char *s0 = NULL, *s;
+	uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0;
+	int blank_or_comment = 0;
+
+	/* Check input arguments. */
+	if (!string || !string[0])
+		goto error;
+
+	/* Memory allocation. */
+	s0 = strdup(string);
+	if (!s0)
+		goto error;
+
+	/* Parse the string into tokens. */
+	for (s = s0; ; ) {
+		char *token;
+
+		token = strtok_r(s, " \f\n\r\t\v", &s);
+		if (!token || token_is_comment(token))
+			break;
+
+		if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX)
+			goto error;
+
+		token_array[n_tokens] = token;
+		n_tokens++;
+	}
+
+	if (!n_tokens) {
+		blank_or_comment = 1;
+		goto error;
+	}
+
+	tokens = token_array;
+
+	if (n_tokens < 4 ||
+		strcmp(tokens[0], "group") ||
+		strcmp(tokens[2], "member"))
+		goto error;
+
+	/*
+	 * Group ID.
+	 */
+	if (parser_read_uint32(&group_id_val, tokens[1]) != 0)
+		goto error;
+	*group_id = group_id_val;
+
+	/*
+	 * Member ID.
+	 */
+	if (parser_read_uint32(&member_id_val, tokens[3]) != 0)
+		goto error;
+	*member_id = member_id_val;
+
+	tokens += 4;
+	n_tokens -= 4;
+
+	/*
+	 * Weight.
+	 */
+	if (n_tokens && !strcmp(tokens[0], "weight")) {
+		if (n_tokens < 2)
+			goto error;
+
+		if (parser_read_uint32(&weight_val, tokens[1]) != 0)
+			goto error;
+		*weight = weight_val;
+
+		tokens += 2;
+		n_tokens -= 2;
+	}
+
+	if (n_tokens)
+		goto error;
+
+	free(s0);
+	return 0;
+
+error:
+	free(s0);
+	if (is_blank_or_comment)
+		*is_blank_or_comment = blank_or_comment;
+	return -EINVAL;
+}
+
+static int
+pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p,
+				    const char *selector_name,
+				    FILE *file,
+				    uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_add(p,
+			selector_name,
+			group_id,
+			member_id,
+			weight);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member add <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_add(p->ctl,
+		selector_name,
+		file,
+		&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p,
+				       const char *selector_name,
+				       FILE *file,
+				       uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_delete(p,
+			selector_name,
+			group_id,
+			member_id);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_delete(p->ctl,
+							selector_name,
+							file,
+							&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -940,6 +1411,52 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_selector_group_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_selector_group_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 7 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "add")) {
+			cmd_softnic_pipeline_selector_group_member_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 7 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "delete")) {
+			cmd_softnic_pipeline_selector_group_member_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_selector_show(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 15/21] net/softnic: add pipeline learner table CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (13 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
                     ` (5 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for managing the learner table default entry.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 106 ++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 1e92e251aa..4b7d001033 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1245,6 +1245,104 @@ cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
 		fclose(file);
 }
 
+static int
+pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				   const char *learner_name,
+				   FILE *file,
+				   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_learner_default_entry_read(p,
+									learner_name,
+									line,
+									&is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_default_entry_add(p,
+									learner_name,
+									entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> learner <learner_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *learner_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	learner_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_learner_default_entry_add(p->ctl,
+						    learner_name,
+						    file,
+						    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1457,6 +1555,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 5 &&
+			!strcmp(tokens[2], "learner") &&
+			!strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_learner_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 16/21] net/softnic: add pipeline commit and abort CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (14 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
                     ` (4 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline table update commit and abort.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 70 +++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 4b7d001033..7c25a502ec 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1343,6 +1343,66 @@ cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
 	fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> commit
+ */
+static void
+cmd_softnic_pipeline_commit(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
+	if (status)
+		snprintf(out, out_size, "Commit failed. "
+			"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
+}
+
+/**
+ * pipeline <pipeline_name> abort
+ */
+static void
+cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	rte_swx_ctl_pipeline_abort(p->ctl);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1563,6 +1623,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "commit")) {
+			cmd_softnic_pipeline_commit(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "abort")) {
+			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 17/21] net/softnic: add the pipeline register read/write CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (15 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
                     ` (3 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline registers read and write operations.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 127 ++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7c25a502ec..b1f7460f47 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -34,6 +34,22 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint64(uint64_t *value, char *p)
+{
+	uint64_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoull(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
 static int
 parser_read_uint32(uint32_t *value, char *p)
 {
@@ -1403,6 +1419,107 @@ cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
 	rte_swx_ctl_pipeline_abort(p->ctl);
 }
 
+/**
+ * pipeline <pipeline_name> regrd <register_array_name> <index>
+ */
+static void
+cmd_softnic_pipeline_regrd(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 5) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regrd")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+
+	snprintf(out, out_size, "0x%" PRIx64 "\n", value);
+}
+
+/**
+ * pipeline <pipeline_name> regwr <register_array_name> <index> <value>
+ */
+static void
+cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regwr")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	if (parser_read_uint64(&value, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "value");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1633,6 +1750,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "regrd")) {
+			cmd_softnic_pipeline_regrd(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "regwr")) {
+			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 18/21] net/softnic: add the pipeline meter CLI commands
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (16 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
                     ` (2 subsequent siblings)
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline meter configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 423 ++++++++++++++++++++++
 1 file changed, 423 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index b1f7460f47..bbbf3babda 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1520,6 +1520,395 @@ cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> add cir <cir> pir <pir> cbs <cbs> pbs <pbs>
+ */
+static void
+cmd_softnic_pipeline_meter_profile_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_meter_trtcm_params params;
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 14) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+		return;
+	}
+
+	if (strcmp(tokens[6], "cir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cir, tokens[7])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cir");
+		return;
+	}
+
+	if (strcmp(tokens[8], "pir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pir, tokens[9])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pir");
+		return;
+	}
+
+	if (strcmp(tokens[10], "cbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cbs, tokens[11])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
+		return;
+	}
+
+	if (strcmp(tokens[12], "pbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pbs, tokens[13])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_add(p->p, profile_name, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> delete
+ */
+static void
+cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> reset
+ */
+static void
+cmd_softnic_pipeline_meter_reset(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "reset")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
+		return;
+	}
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_reset(p->p, name, idx0);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> set
+ *	profile <profile_name>
+ */
+static void
+cmd_softnic_pipeline_meter_set(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name, *profile_name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "set")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
+		return;
+	}
+
+	if (strcmp(tokens[9], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[10];
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> stats
+ */
+static void
+cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_meter_stats stats;
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	/* Table header. */
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
+		 "METER #",
+		 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
+		 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	/* Table rows. */
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
+		if (status) {
+			snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
+			out_size -= strlen(out);
+			out += strlen(out);
+			return;
+		}
+
+		snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
+			 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
+			 idx0,
+			 stats.n_pkts[RTE_COLOR_GREEN],
+			 stats.n_pkts[RTE_COLOR_YELLOW],
+			 stats.n_pkts[RTE_COLOR_RED],
+			 stats.n_bytes[RTE_COLOR_GREEN],
+			 stats.n_bytes[RTE_COLOR_YELLOW],
+			 stats.n_bytes[RTE_COLOR_RED]);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1760,6 +2149,40 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_meter_profile_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_meter_profile_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "reset")) {
+			cmd_softnic_pipeline_meter_reset(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "set")) {
+			cmd_softnic_pipeline_meter_set(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "stats")) {
+			cmd_softnic_pipeline_meter_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 19/21] net/softnic: add pipeline statistics CLI command
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (17 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
@ 2022-08-26 13:17   ` 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
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline statistics counters query.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 204 ++++++++++++++++++++++
 1 file changed, 204 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index bbbf3babda..da530614db 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1909,6 +1909,206 @@ cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> stats
+ */
+static void
+cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_pipeline_info info;
+	struct pipeline *p;
+	uint32_t i;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_info_get(p->p, &info);
+	if (status) {
+		snprintf(out, out_size, "Pipeline info get error.");
+		return;
+	}
+
+	snprintf(out, out_size, "Input ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_in; i++) {
+		struct rte_swx_port_in_stats stats;
+
+		rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
+
+		snprintf(out, out_size, "\tPort %u:"
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" empty %" PRIu64 "\n",
+			i, stats.n_pkts, stats.n_bytes, stats.n_empty);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nOutput ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_out; i++) {
+		struct rte_swx_port_out_stats stats;
+
+		rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
+
+		if (i != info.n_ports_out - 1)
+			snprintf(out, out_size, "\tPort %u:", i);
+		else
+			snprintf(out, out_size, "\tDROP:");
+
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out,
+			out_size,
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" clone %" PRIu64
+			" clonerr %" PRIu64 "\n",
+			stats.n_pkts,
+			stats.n_bytes,
+			stats.n_pkts_clone,
+			stats.n_pkts_clone_err);
+
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nTables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_tables; i++) {
+		struct rte_swx_ctl_table_info table_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_table_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+		if (status) {
+			snprintf(out, out_size, "Table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tTable %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n",
+			table_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+
+	snprintf(out, out_size, "\nLearner tables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_learners; i++) {
+		struct rte_swx_ctl_learner_info learner_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_learner_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
+		if (status) {
+			snprintf(out, out_size, "Learner table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Learner table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tLearner table %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n"
+			"\t\tLearn OK (packets): %" PRIu64 "\n"
+			"\t\tLearn error (packets): %" PRIu64 "\n"
+			"\t\tRearm (packets): %" PRIu64 "\n"
+			"\t\tForget (packets): %" PRIu64 "\n",
+			learner_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss,
+			stats.n_pkts_learn_ok,
+			stats.n_pkts_learn_err,
+			stats.n_pkts_rearm,
+			stats.n_pkts_forget);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2183,6 +2383,10 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			return;
 		}
 
+		if (n_tokens >= 3 && !strcmp(tokens[2], "stats")) {
+			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 20/21] net/softnic: add pipeline mirroring CLI command
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (18 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  2022-08-26 13:17   ` [PATCH V2 21/21] net/softnic: update the default device program Cristian Dumitrescu
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline mirroring configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 96 +++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index da530614db..e1ff100c9a 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -2109,6 +2109,94 @@ cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow
+ *	truncate <truncation_length>
+ */
+static void
+cmd_softnic_pipeline_mirror_session(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_pipeline_mirroring_session_params params;
+	struct pipeline *p;
+	uint32_t session_id = 0;
+	int status;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	if (strcmp(tokens[0], "pipeline")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "mirror")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
+		return;
+	}
+
+	if (strcmp(tokens[3], "session")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session");
+		return;
+	}
+
+	if (parser_read_uint32(&session_id, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "session_id");
+		return;
+	}
+
+	if (strcmp(tokens[5], "port")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+		return;
+	}
+
+	if (parser_read_uint32(&params.port_id, tokens[6])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+		return;
+	}
+
+	if (strcmp(tokens[7], "clone")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone");
+		return;
+	}
+
+	if (!strcmp(tokens[8], "fast")) {
+		params.fast_clone = 1;
+	} else if (!strcmp(tokens[8], "slow")) {
+		params.fast_clone = 0;
+	} else {
+		snprintf(out, out_size, MSG_ARG_INVALID, "clone");
+		return;
+	}
+
+	if (strcmp(tokens[9], "truncate")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate");
+		return;
+	}
+
+	if (parser_read_uint32(&params.truncation_length, tokens[10])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed!\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2387,6 +2475,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 4 &&
+			!strcmp(tokens[2], "mirror") &&
+			!strcmp(tokens[3], "session")) {
+			cmd_softnic_pipeline_mirror_session(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V2 21/21] net/softnic: update the default device program
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (19 preceding siblings ...)
  2022-08-26 13:17   ` [PATCH V2 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
@ 2022-08-26 13:17   ` Cristian Dumitrescu
  20 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-08-26 13:17 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Update the default device program.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/firmware.cli   | 51 ++++++++++++++++++++----------
 drivers/net/softnic/firmware.spec  | 19 +++++++++++
 drivers/net/softnic/firmware_rx.io | 30 ++++++++++++++++++
 drivers/net/softnic/firmware_tx.io | 30 ++++++++++++++++++
 4 files changed, 114 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io

diff --git a/drivers/net/softnic/firmware.cli b/drivers/net/softnic/firmware.cli
index 300cf6e33f..7d2c1aad21 100644
--- a/drivers/net/softnic/firmware.cli
+++ b/drivers/net/softnic/firmware.cli
@@ -1,21 +1,40 @@
 ; SPDX-License-Identifier: BSD-3-Clause
-; Copyright(c) 2018 Intel Corporation
+; Copyright(c) 2022 Intel Corporation
 
-link LINK dev 0000:02:00.0
+# Example command line for the DPDK test-pmd application. Out of the 3 application cores (see the
+# -c <core_mask> argument), core 0 is running the control thread doing configuration and CLI, core 1
+# is running the forwarding thread, and core 2 is setup as service core (see the -s <core_mask>
+# argument) for the purpose of running the Soft NIC device:
+#
+#	./build/app/dpdk-testpmd -c 7 -s 4 --vdev 'net_softnic0,firmware=./drivers/net/softnic/firmware.cli,cpu_id=0,conn_port=8086' -- -i
+#
+# Commands from within the DPDK test-pmd application:
+#
+# 	testpmd> set portlist <softnic_port_id>
+#	testpmd> show config fwd
+#	testpmd> start
+#
+# To setup the CLI prompt to the Soft NIC device, the DPDK test-pmd application needs to be modified
+# to call the rte_pmd_softnic_manage() function. Once the Soft NIC device is started, the command to
+# get the CLI prompt is:
+#
+#	telnet 0.0.0.0 8086
 
-pipeline RX period 10 offset_port_id 0
-pipeline RX port in bsz 32 link LINK rxq 0
-pipeline RX port out bsz 32 swq RXQ0
-pipeline RX table match stub
-pipeline RX port in 0 table 0
-pipeline RX table 0 rule add match default action fwd port 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./drivers/net/softnic/firmware.spec /tmp/firmware.c
+pipeline libbuild /tmp/firmware.c /tmp/firmware.so
 
-pipeline TX period 10 offset_port_id 0
-pipeline TX port in bsz 32 swq TXQ0
-pipeline TX port out bsz 32 link LINK txq 0
-pipeline TX table match stub
-pipeline TX port in 0 table 0
-pipeline TX table 0 rule add match default action fwd port 0
+;
+; List of pipelines.
+;
+pipeline RX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_rx.io numa 0
+pipeline TX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_tx.io numa 0
 
-thread 1 pipeline RX enable
-thread 1 pipeline TX enable
+;
+; Pipelines-to-threads mapping. For the Soft NIC devices, the pipelines can be mapped to any of the
+; application service cores (see the -s <core_mask> argument):
+;
+thread 2 pipeline RX enable
+thread 2 pipeline TX enable
diff --git a/drivers/net/softnic/firmware.spec b/drivers/net/softnic/firmware.spec
new file mode 100644
index 0000000000..106caae735
--- /dev/null
+++ b/drivers/net/softnic/firmware.spec
@@ -0,0 +1,19 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+//
+// Meta-data.
+//
+struct metadata_t {
+	bit<32> port
+}
+
+metadata instanceof metadata_t
+
+//
+// Pipeline.
+//
+apply {
+	rx m.port
+	tx m.port
+}
diff --git a/drivers/net/softnic/firmware_rx.io b/drivers/net/softnic/firmware_rx.io
new file mode 100644
index 0000000000..9baa4612b1
--- /dev/null
+++ b/drivers/net/softnic/firmware_rx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ring RXQ0 bsz 32
diff --git a/drivers/net/softnic/firmware_tx.io b/drivers/net/softnic/firmware_tx.io
new file mode 100644
index 0000000000..4c4608b105
--- /dev/null
+++ b/drivers/net/softnic/firmware_tx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ring TXQ0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ethdev 0000:18:00.0 txq 0 bsz 32
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline
  2022-08-04 16:58 [PATCH 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                   ` (21 preceding siblings ...)
  2022-08-26 13:17 ` [PATCH V2 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
@ 2022-09-01 14:20 ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 01/21] net/softnic: remove the traffic manager support Cristian Dumitrescu
                     ` (21 more replies)
  22 siblings, 22 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev

The legacy pipeline API is soon going to be marked for deprecation,
hence the Soft NIC driver is updated to support the new SWX pipeline
type.

The SWX pipeline has better encapsulation than the legacy pipeline,
mainly due to P4 language alignment, which results in most of the
functionality being supported directly in the pipeline library, hence
the big number of lines of code deleted from this driver.

Depends-on: series-24117 ("pipeline: pipeline configuration and build improvements")

Change log:

V3:
-Rebased on main latest.

V2:
-Fixed minor style checks and warnings reported by the CI/CD.

Cristian Dumitrescu (21):
  net/softnic: remove the traffic manager support
  net/softnic: remove flow support
  net/softnic: remove the meter support
  net/softnic: remove cryptodev support
  net/softnic: remove tap support
  net/softnic: remove the legacy pipeline CLI commands
  net/softnic: replace the legacy pipeline with the SWX pipeline
  net/softnic: remove the list of Ethernet devices
  net/softnic: remove unused text parsing functions
  net/softnic: add pipeline code generation CLI command
  net/softnic: add pipeline library build CLI command
  net/softnic: add pipeline build CLI command
  net/softnic: add pipeline table CLI commands
  net/softnic: add pipeline selector table CLI commands
  net/softnic: add pipeline learner table CLI commands
  net/softnic: add pipeline commit and abort CLI commands
  net/softnic: add the pipeline register read/write CLI commands
  net/softnic: add the pipeline meter CLI commands
  net/softnic: add pipeline statistics CLI command
  net/softnic: add pipeline mirroring CLI command
  net/softnic: update the default device program

 drivers/net/softnic/firmware.cli              |   51 +-
 drivers/net/softnic/firmware.spec             |   19 +
 drivers/net/softnic/firmware_rx.io            |   30 +
 drivers/net/softnic/firmware_tx.io            |   30 +
 drivers/net/softnic/meson.build               |   10 +-
 drivers/net/softnic/parser.c                  |  523 --
 drivers/net/softnic/parser.h                  |   68 -
 drivers/net/softnic/rte_eth_softnic.c         |  208 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_action.c  |  423 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 6985 ++++-------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   |  168 -
 drivers/net/softnic/rte_eth_softnic_flow.c    | 2293 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  922 +--
 drivers/net/softnic/rte_eth_softnic_link.c    |  101 -
 drivers/net/softnic/rte_eth_softnic_meter.c   |  945 ---
 .../net/softnic/rte_eth_softnic_pipeline.c    | 1129 +--
 drivers/net/softnic/rte_eth_softnic_tap.c     |  118 -
 drivers/net/softnic/rte_eth_softnic_thread.c  | 2594 +-----
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3645 ---------
 20 files changed, 1807 insertions(+), 18465 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_action.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 69+ messages in thread

* [PATCH V3 01/21] net/softnic: remove the traffic manager support
  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   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 02/21] net/softnic: remove flow support Cristian Dumitrescu
                     ` (20 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device traffic manager API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |    3 +-
 drivers/net/softnic/rte_eth_softnic.c         |  170 -
 drivers/net/softnic/rte_eth_softnic.h         |   10 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 1328 ------
 .../net/softnic/rte_eth_softnic_internals.h   |  176 -
 .../net/softnic/rte_eth_softnic_pipeline.c    |   31 -
 drivers/net/softnic/rte_eth_softnic_tm.c      | 3645 -----------------
 7 files changed, 1 insertion(+), 5362 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tm.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index aff5fb3bf2..e2dbd6166e 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -21,6 +21,5 @@ sources = files(
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
-        'rte_eth_softnic_tm.c',
 )
-deps += ['pipeline', 'port', 'table', 'sched', 'cryptodev']
+deps += ['pipeline', 'port', 'table', 'cryptodev']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8c098cad5b..ae3e8b3bcd 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_tm_driver.h>
 #include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
@@ -23,20 +22,6 @@
 #define PMD_PARAM_CONN_PORT                                "conn_port"
 #define PMD_PARAM_CPU_ID                                   "cpu_id"
 #define PMD_PARAM_SC                                       "sc"
-#define PMD_PARAM_TM_N_QUEUES                              "tm_n_queues"
-#define PMD_PARAM_TM_QSIZE0                                "tm_qsize0"
-#define PMD_PARAM_TM_QSIZE1                                "tm_qsize1"
-#define PMD_PARAM_TM_QSIZE2                                "tm_qsize2"
-#define PMD_PARAM_TM_QSIZE3                                "tm_qsize3"
-#define PMD_PARAM_TM_QSIZE4                                "tm_qsize4"
-#define PMD_PARAM_TM_QSIZE5                                "tm_qsize5"
-#define PMD_PARAM_TM_QSIZE6                                "tm_qsize6"
-#define PMD_PARAM_TM_QSIZE7                                "tm_qsize7"
-#define PMD_PARAM_TM_QSIZE8                                "tm_qsize8"
-#define PMD_PARAM_TM_QSIZE9                                "tm_qsize9"
-#define PMD_PARAM_TM_QSIZE10                               "tm_qsize10"
-#define PMD_PARAM_TM_QSIZE11                               "tm_qsize11"
-#define PMD_PARAM_TM_QSIZE12                               "tm_qsize12"
 
 
 static const char * const pmd_valid_args[] = {
@@ -44,20 +29,6 @@ static const char * const pmd_valid_args[] = {
 	PMD_PARAM_CONN_PORT,
 	PMD_PARAM_CPU_ID,
 	PMD_PARAM_SC,
-	PMD_PARAM_TM_N_QUEUES,
-	PMD_PARAM_TM_QSIZE0,
-	PMD_PARAM_TM_QSIZE1,
-	PMD_PARAM_TM_QSIZE2,
-	PMD_PARAM_TM_QSIZE3,
-	PMD_PARAM_TM_QSIZE4,
-	PMD_PARAM_TM_QSIZE5,
-	PMD_PARAM_TM_QSIZE6,
-	PMD_PARAM_TM_QSIZE7,
-	PMD_PARAM_TM_QSIZE8,
-	PMD_PARAM_TM_QSIZE9,
-	PMD_PARAM_TM_QSIZE10,
-	PMD_PARAM_TM_QSIZE11,
-	PMD_PARAM_TM_QSIZE12,
 	NULL
 };
 
@@ -193,12 +164,10 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	return 0;
@@ -218,12 +187,10 @@ pmd_free(struct pmd_internals *p)
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
 	softnic_tap_free(p);
-	softnic_tmgr_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	tm_hierarchy_free(p);
 	softnic_mtr_free(p);
 
 	rte_free(p);
@@ -256,14 +223,6 @@ pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_tm_ops **)arg = &pmd_tm_ops;
-
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -282,7 +241,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
 	.flow_ops_get = pmd_flow_ops_get,
-	.tm_ops_get = pmd_tm_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
@@ -325,13 +283,11 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	tm_hierarchy_init(p);
 	softnic_mtr_init(p);
 
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tmgr_init(p);
 	softnic_tap_init(p);
 	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
@@ -459,20 +415,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 	}
 	p->cpu_id = SOFTNIC_CPU_ID;
 	p->sc = SOFTNIC_SC;
-	p->tm.n_queues = SOFTNIC_TM_N_QUEUES;
-	p->tm.qsize[0] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[1] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[2] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[3] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[4] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[5] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[6] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[7] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[8] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[9] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[10] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[11] = SOFTNIC_TM_QUEUE_SIZE;
-	p->tm.qsize[12] = SOFTNIC_TM_QUEUE_SIZE;
 
 	/* Firmware script (optional) */
 	if (rte_kvargs_count(kvlist, PMD_PARAM_FIRMWARE) == 1) {
@@ -517,104 +459,6 @@ pmd_parse_args(struct pmd_params *p, const char *params)
 			goto out_free;
 	}
 
-	/* TM number of queues (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_N_QUEUES) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_N_QUEUES,
-			&get_uint32, &p->tm.n_queues);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	/* TM queue size 0 .. 3 (optional) */
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE0) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE0,
-			&get_uint32, &p->tm.qsize[0]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE1) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE1,
-			&get_uint32, &p->tm.qsize[1]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE2) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE2,
-			&get_uint32, &p->tm.qsize[2]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE3) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE3,
-			&get_uint32, &p->tm.qsize[3]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE4) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE4,
-			&get_uint32, &p->tm.qsize[4]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE5) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE5,
-			&get_uint32, &p->tm.qsize[5]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE6) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE6,
-			&get_uint32, &p->tm.qsize[6]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE7) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE7,
-			&get_uint32, &p->tm.qsize[7]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE8) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE8,
-			&get_uint32, &p->tm.qsize[8]);
-		if (ret < 0)
-			goto out_free;
-	}
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE9) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE9,
-			&get_uint32, &p->tm.qsize[9]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE10) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE10,
-			&get_uint32, &p->tm.qsize[10]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE11) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE11,
-			&get_uint32, &p->tm.qsize[11]);
-		if (ret < 0)
-			goto out_free;
-	}
-
-	if (rte_kvargs_count(kvlist, PMD_PARAM_TM_QSIZE12) == 1) {
-		ret = rte_kvargs_process(kvlist, PMD_PARAM_TM_QSIZE12,
-			&get_uint32, &p->tm.qsize[12]);
-		if (ret < 0)
-			goto out_free;
-	}
-
 out_free:
 	rte_kvargs_free(kvlist);
 	return ret;
@@ -696,20 +540,6 @@ RTE_PMD_REGISTER_PARAM_STRING(net_softnic,
 	PMD_PARAM_FIRMWARE "=<string> "
 	PMD_PARAM_CONN_PORT "=<uint16> "
 	PMD_PARAM_CPU_ID "=<uint32> "
-	PMD_PARAM_TM_N_QUEUES "=<uint32> "
-	PMD_PARAM_TM_QSIZE0 "=<uint32> "
-	PMD_PARAM_TM_QSIZE1 "=<uint32> "
-	PMD_PARAM_TM_QSIZE2 "=<uint32> "
-	PMD_PARAM_TM_QSIZE3 "=<uint32>"
-	PMD_PARAM_TM_QSIZE4 "=<uint32> "
-	PMD_PARAM_TM_QSIZE5 "=<uint32> "
-	PMD_PARAM_TM_QSIZE6 "=<uint32> "
-	PMD_PARAM_TM_QSIZE7 "=<uint32> "
-	PMD_PARAM_TM_QSIZE8 "=<uint32> "
-	PMD_PARAM_TM_QSIZE9 "=<uint32> "
-	PMD_PARAM_TM_QSIZE10 "=<uint32> "
-	PMD_PARAM_TM_QSIZE11 "=<uint32>"
-	PMD_PARAM_TM_QSIZE12 "=<uint32>"
 );
 
 int
diff --git a/drivers/net/softnic/rte_eth_softnic.h b/drivers/net/softnic/rte_eth_softnic.h
index 6c11d89ab6..3fd80fa571 100644
--- a/drivers/net/softnic/rte_eth_softnic.h
+++ b/drivers/net/softnic/rte_eth_softnic.h
@@ -46,16 +46,6 @@ extern "C" {
 #define SOFTNIC_SC                                         1
 #endif
 
-/** Traffic Manager: Number of scheduler queues. */
-#ifndef SOFTNIC_TM_N_QUEUES
-#define SOFTNIC_TM_N_QUEUES                                (64 * 1024)
-#endif
-
-/** Traffic Manager: Scheduler queue size (per traffic class). */
-#ifndef SOFTNIC_TM_QUEUE_SIZE
-#define SOFTNIC_TM_QUEUE_SIZE                              64
-#endif
-
 /**
  * Soft NIC run.
  *
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7acbeecae7..7556e50831 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,1270 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tmgr shaper profile
- *  id <profile_id>
- *  rate <tb_rate> size <tb_size>
- *  adj <packet_length_adjust>
- */
-static void
-cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_shaper_params sp;
-	struct rte_tm_error error;
-	uint32_t shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
-
-	if (n_tokens != 11) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "rate") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
-		return;
-	}
-
-	if (strcmp(tokens[7], "size") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-		return;
-	}
-
-	if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
-		return;
-	}
-
-	if (strcmp(tokens[9], "adj") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj");
-		return;
-	}
-
-	if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr shared shaper
- *  id <shared_shaper_id>
- *  profile <shaper_profile_id>
- */
-static void
-cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint32_t shared_shaper_id, shaper_profile_id;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[2], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[3], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return;
-
-	status = rte_tm_shared_shaper_add_update(port_id,
-		shared_shaper_id,
-		shaper_profile_id,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr node
- *   id <node_id>
- *   parent <parent_node_id | none>
- *   priority <priority>
- *   weight <weight>
- *   [shaper profile <shaper_profile_id>]
- *   [shared shaper <shared_shaper_id>]
- *   [nonleaf sp <n_sp_priorities>]
- */
-static void
-cmd_tmgr_node(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	struct rte_tm_node_params np;
-	uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id;
-	uint16_t port_id;
-	int status;
-
-	memset(&np, 0, sizeof(struct rte_tm_node_params));
-	np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-	np.nonleaf.n_sp_priorities = 1;
-
-	if (n_tokens < 10) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "node") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
-		return;
-	}
-
-	if (strcmp(tokens[2], "id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "parent") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
-		return;
-	}
-
-	if (strcmp(tokens[5], "none") == 0)
-		parent_node_id = RTE_TM_NODE_ID_NULL;
-	else {
-		if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id");
-			return;
-		}
-	}
-
-	if (strcmp(tokens[6], "priority") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-		return;
-	}
-
-	if (strcmp(tokens[8], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "weight");
-		return;
-	}
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shaper") == 0) &&
-		(strcmp(tokens[1], "profile") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (strcmp(tokens[2], "none") == 0) {
-			np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
-		} else {
-			if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
-				return;
-			}
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shaper profile */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "shared") == 0) &&
-		(strcmp(tokens[1], "shaper") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
-			return;
-		}
-
-		np.shared_shaper_id = &shared_shaper_id;
-		np.n_shared_shapers = 1;
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* shared shaper */
-
-	if (n_tokens >= 2 &&
-		(strcmp(tokens[0], "nonleaf") == 0) &&
-		(strcmp(tokens[1], "sp") == 0)) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
-			return;
-		}
-
-		tokens += 3;
-		n_tokens -= 3;
-	} /* nonleaf sp <n_sp_priorities> */
-
-	if (n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_node_add(port_id,
-		node_id,
-		parent_node_id,
-		priority,
-		weight,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&np,
-		&error);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-static uint32_t
-root_node_id(uint32_t n_spp,
-	uint32_t n_pps)
-{
-	uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_pipes = n_spp * n_pps;
-
-	return n_queues + n_tc + n_pipes + n_spp;
-}
-
-static uint32_t
-subport_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues + n_tc + n_pipes + subport_id;
-}
-
-static uint32_t
-pipe_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		n_tc +
-		pipe_id +
-		subport_id * n_pps;
-}
-
-static uint32_t
-tc_node_id(uint32_t n_spp,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id)
-{
-	uint32_t n_pipes = n_spp * n_pps;
-	uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE;
-
-	return n_queues +
-		tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-}
-
-static uint32_t
-queue_node_id(uint32_t n_spp __rte_unused,
-	uint32_t n_pps,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t tc_id,
-	uint32_t queue_id)
-{
-	return queue_id + tc_id +
-		(pipe_id + subport_id * n_pps) * RTE_SCHED_QUEUES_PER_PIPE;
-}
-
-struct tmgr_hierarchy_default_params {
-	uint32_t n_spp; /**< Number of subports per port. */
-	uint32_t n_pps; /**< Number of pipes per subport. */
-
-	struct {
-		uint32_t port;
-		uint32_t subport;
-		uint32_t pipe;
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shaper_profile_id;
-
-	struct {
-		uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t tc_valid[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} shared_shaper_id;
-
-	struct {
-		uint32_t queue[RTE_SCHED_QUEUES_PER_PIPE];
-	} weight;
-};
-
-static int
-tmgr_hierarchy_default(struct pmd_internals *softnic,
-	struct tmgr_hierarchy_default_params *params)
-{
-	struct rte_tm_node_params root_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.port,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params subport_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.subport,
-		.nonleaf = {
-			.n_sp_priorities = 1,
-		},
-	};
-
-	struct rte_tm_node_params pipe_node_params = {
-		.shaper_profile_id = params->shaper_profile_id.pipe,
-		.nonleaf = {
-			.n_sp_priorities = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-		},
-	};
-
-	uint32_t *shared_shaper_id =
-		(uint32_t *)calloc(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			sizeof(uint32_t));
-
-	if (shared_shaper_id == NULL)
-		return -1;
-
-	memcpy(shared_shaper_id, params->shared_shaper_id.tc,
-		sizeof(params->shared_shaper_id.tc));
-
-	struct rte_tm_node_params tc_node_params[] = {
-		[0] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[0],
-			.shared_shaper_id = &shared_shaper_id[0],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[0]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[1] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[1],
-			.shared_shaper_id = &shared_shaper_id[1],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[1]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[2] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[2],
-			.shared_shaper_id = &shared_shaper_id[2],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[2]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[3] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[3],
-			.shared_shaper_id = &shared_shaper_id[3],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[3]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[4] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[4],
-			.shared_shaper_id = &shared_shaper_id[4],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[4]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[5] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[5],
-			.shared_shaper_id = &shared_shaper_id[5],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[5]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[6] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[6],
-			.shared_shaper_id = &shared_shaper_id[6],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[6]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[7] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[7],
-			.shared_shaper_id = &shared_shaper_id[7],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[7]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[8] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[8],
-			.shared_shaper_id = &shared_shaper_id[8],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[8]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[9] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[9],
-			.shared_shaper_id = &shared_shaper_id[9],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[9]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[10] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[10],
-			.shared_shaper_id = &shared_shaper_id[10],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[10]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[11] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[11],
-			.shared_shaper_id = &shared_shaper_id[11],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[11]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-
-		[12] = {
-			.shaper_profile_id = params->shaper_profile_id.tc[12],
-			.shared_shaper_id = &shared_shaper_id[12],
-			.n_shared_shapers =
-				(params->shared_shaper_id.tc_valid[12]) ? 1 : 0,
-			.nonleaf = {
-				.n_sp_priorities = 1,
-			},
-		},
-	};
-
-	struct rte_tm_node_params queue_node_params = {
-		.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE,
-	};
-
-	struct rte_tm_error error;
-	uint32_t n_spp = params->n_spp, n_pps = params->n_pps, s;
-	int status;
-	uint16_t port_id;
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 0: Root node */
-	status = rte_tm_node_add(port_id,
-		root_node_id(n_spp, n_pps),
-		RTE_TM_NODE_ID_NULL,
-		0,
-		1,
-		RTE_TM_NODE_LEVEL_ID_ANY,
-		&root_node_params,
-		&error);
-	if (status)
-		return -1;
-
-	/* Hierarchy level 1: Subport nodes */
-	for (s = 0; s < params->n_spp; s++) {
-		uint32_t p;
-
-		status = rte_tm_node_add(port_id,
-			subport_node_id(n_spp, n_pps, s),
-			root_node_id(n_spp, n_pps),
-			0,
-			1,
-			RTE_TM_NODE_LEVEL_ID_ANY,
-			&subport_node_params,
-			&error);
-		if (status)
-			return -1;
-
-		/* Hierarchy level 2: Pipe nodes */
-		for (p = 0; p < params->n_pps; p++) {
-			uint32_t t;
-
-			status = rte_tm_node_add(port_id,
-				pipe_node_id(n_spp, n_pps, s, p),
-				subport_node_id(n_spp, n_pps, s),
-				0,
-				1,
-				RTE_TM_NODE_LEVEL_ID_ANY,
-				&pipe_node_params,
-				&error);
-			if (status)
-				return -1;
-
-			/* Hierarchy level 3: Traffic class nodes */
-			for (t = 0; t < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; t++) {
-				uint32_t q;
-
-				status = rte_tm_node_add(port_id,
-					tc_node_id(n_spp, n_pps, s, p, t),
-					pipe_node_id(n_spp, n_pps, s, p),
-					t,
-					1,
-					RTE_TM_NODE_LEVEL_ID_ANY,
-					&tc_node_params[t],
-					&error);
-				if (status)
-					return -1;
-
-				/* Hierarchy level 4: Queue nodes */
-				if (t < RTE_SCHED_TRAFFIC_CLASS_BE) {
-					/* Strict-priority traffic class queues */
-					q = 0;
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-
-					continue;
-				}
-				/* Best-effort traffic class queues */
-				for (q = 0; q < RTE_SCHED_BE_QUEUES_PER_PIPE; q++) {
-					status = rte_tm_node_add(port_id,
-						queue_node_id(n_spp, n_pps, s, p, t, q),
-						tc_node_id(n_spp, n_pps, s, p, t),
-						0,
-						params->weight.queue[q],
-						RTE_TM_NODE_LEVEL_ID_ANY,
-						&queue_node_params,
-						&error);
-					if (status)
-						return -1;
-				}
-			} /* TC */
-		} /* Pipe */
-	} /* Subport */
-
-	return 0;
-}
-
-
-/**
- * tmgr hierarchy-default
- *  spp <n_subports_per_port>
- *  pps <n_pipes_per_subport>
- *  shaper profile
- *   port <profile_id>
- *   subport <profile_id>
- *   pipe <profile_id>
- *   tc0 <profile_id>
- *   tc1 <profile_id>
- *   tc2 <profile_id>
- *   tc3 <profile_id>
- *   tc4 <profile_id>
- *   tc5 <profile_id>
- *   tc6 <profile_id>
- *   tc7 <profile_id>
- *   tc8 <profile_id>
- *   tc9 <profile_id>
- *   tc10 <profile_id>
- *   tc11 <profile_id>
- *   tc12 <profile_id>
- *  shared shaper
- *   tc0 <id | none>
- *   tc1 <id | none>
- *   tc2 <id | none>
- *   tc3 <id | none>
- *   tc4 <id | none>
- *   tc5 <id | none>
- *   tc6 <id | none>
- *   tc7 <id | none>
- *   tc8 <id | none>
- *   tc9 <id | none>
- *   tc10 <id | none>
- *   tc11 <id | none>
- *   tc12 <id | none>
- *  weight
- *   queue  <q12> ... <q15>
- */
-static void
-cmd_tmgr_hierarchy_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct tmgr_hierarchy_default_params p;
-	int i, j, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 74) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy-default") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default");
-		return;
-	}
-
-	if (strcmp(tokens[2], "spp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
-		return;
-	}
-
-	if (strcmp(tokens[4], "pps") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
-		return;
-	}
-
-	/* Shaper profile */
-
-	if (strcmp(tokens[6], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[7], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (strcmp(tokens[8], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port profile id");
-		return;
-	}
-
-	if (strcmp(tokens[10], "subport") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id");
-		return;
-	}
-
-	if (strcmp(tokens[12], "pipe") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[14], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[16], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[18], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[20], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[22], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[4], tokens[23]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc4 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[24], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[5], tokens[25]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc5 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[26], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[6], tokens[27]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc6 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[28], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[7], tokens[29]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc7 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[30], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[8], tokens[31]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc8 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[32], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[9], tokens[33]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc9 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[34], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[10], tokens[35]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc10 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[36], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[11], tokens[37]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc11 profile id");
-		return;
-	}
-
-	if (strcmp(tokens[38], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[12], tokens[39]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "tc12 profile id");
-		return;
-	}
-
-	/* Shared shaper */
-
-	if (strcmp(tokens[40], "shared") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
-		return;
-	}
-
-	if (strcmp(tokens[41], "shaper") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
-		return;
-	}
-
-	if (strcmp(tokens[42], "tc0") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0");
-		return;
-	}
-
-	if (strcmp(tokens[43], "none") == 0)
-		p.shared_shaper_id.tc_valid[0] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0],
-			tokens[43]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[0] = 1;
-	}
-
-	if (strcmp(tokens[44], "tc1") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1");
-		return;
-	}
-
-	if (strcmp(tokens[45], "none") == 0)
-		p.shared_shaper_id.tc_valid[1] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1],
-			tokens[45]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[1] = 1;
-	}
-
-	if (strcmp(tokens[46], "tc2") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2");
-		return;
-	}
-
-	if (strcmp(tokens[47], "none") == 0)
-		p.shared_shaper_id.tc_valid[2] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2],
-			tokens[47]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[2] = 1;
-	}
-
-	if (strcmp(tokens[48], "tc3") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3");
-		return;
-	}
-
-	if (strcmp(tokens[49], "none") == 0)
-		p.shared_shaper_id.tc_valid[3] = 0;
-	else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3],
-			tokens[49]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[3] = 1;
-	}
-
-	if (strcmp(tokens[50], "tc4") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4");
-		return;
-	}
-
-	if (strcmp(tokens[51], "none") == 0) {
-		p.shared_shaper_id.tc_valid[4] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[4],
-			tokens[51]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc4");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[4] = 1;
-	}
-
-	if (strcmp(tokens[52], "tc5") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5");
-		return;
-	}
-
-	if (strcmp(tokens[53], "none") == 0) {
-		p.shared_shaper_id.tc_valid[5] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[5],
-			tokens[53]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc5");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[5] = 1;
-	}
-
-	if (strcmp(tokens[54], "tc6") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6");
-		return;
-	}
-
-	if (strcmp(tokens[55], "none") == 0) {
-		p.shared_shaper_id.tc_valid[6] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[6],
-			tokens[55]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc6");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[6] = 1;
-	}
-
-	if (strcmp(tokens[56], "tc7") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7");
-		return;
-	}
-
-	if (strcmp(tokens[57], "none") == 0) {
-		p.shared_shaper_id.tc_valid[7] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[7],
-			tokens[57]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc7");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[7] = 1;
-	}
-
-	if (strcmp(tokens[58], "tc8") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8");
-		return;
-	}
-
-	if (strcmp(tokens[59], "none") == 0) {
-		p.shared_shaper_id.tc_valid[8] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[8],
-			tokens[59]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc8");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[8] = 1;
-	}
-
-	if (strcmp(tokens[60], "tc9") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9");
-		return;
-	}
-
-	if (strcmp(tokens[61], "none") == 0) {
-		p.shared_shaper_id.tc_valid[9] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[9],
-			tokens[61]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc9");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[9] = 1;
-	}
-
-	if (strcmp(tokens[62], "tc10") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10");
-		return;
-	}
-
-	if (strcmp(tokens[63], "none") == 0) {
-		p.shared_shaper_id.tc_valid[10] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[10],
-			tokens[63]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc10");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[10] = 1;
-	}
-
-	if (strcmp(tokens[64], "tc11") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11");
-		return;
-	}
-
-	if (strcmp(tokens[65], "none") == 0) {
-		p.shared_shaper_id.tc_valid[11] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[11],
-			tokens[65]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc11");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[11] = 1;
-	}
-
-	if (strcmp(tokens[66], "tc12") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12");
-		return;
-	}
-
-	if (strcmp(tokens[67], "none") == 0) {
-		p.shared_shaper_id.tc_valid[12] = 0;
-	} else {
-		if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[12],
-			tokens[67]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc12");
-			return;
-		}
-
-		p.shared_shaper_id.tc_valid[12] = 1;
-	}
-
-	/* Weight */
-
-	if (strcmp(tokens[68], "weight") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
-		return;
-	}
-
-	if (strcmp(tokens[69], "queue") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue");
-		return;
-	}
-
-	for (i = 0, j = 0; i < 16; i++) {
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			p.weight.queue[i] = 1;
-		} else {
-			if (softnic_parser_read_uint32(&p.weight.queue[i],
-				tokens[70 + j]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "weight queue");
-				return;
-			}
-			j++;
-		}
-	}
-
-	status = tmgr_hierarchy_default(softnic, &p);
-	if (status != 0) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr hierarchy commit
- */
-static void
-cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_tm_error error;
-	uint16_t port_id;
-	int status;
-
-	if (n_tokens != 3) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "hierarchy") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
-		return;
-	}
-
-	if (strcmp(tokens[2], "commit") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
-		return;
-	}
-
-	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
-	if (status != 0)
-		return;
-
-	status = rte_tm_hierarchy_commit(port_id, 1, &error);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * tmgr <tmgr_name>
- */
-static void
-cmd_tmgr(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tmgr_port = softnic_tmgr_port_create(softnic, name);
-	if (tmgr_port == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * tap <tap_name>
  */
@@ -2247,7 +983,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  | cryptodev <cryptodev_name> rxq <queue_id>
@@ -2331,18 +1066,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "tmgr") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tmgr");
-			return;
-		}
-
-		p.type = PORT_IN_TMGR;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tap") == 0) {
 		if (n_tokens < t0 + 6) {
@@ -2482,7 +1205,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tmgr <tmgr_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
@@ -2557,16 +1279,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tmgr") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tmgr");
-			return;
-		}
-
-		p.type = PORT_OUT_TMGR;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "tap") == 0) {
 		if (n_tokens != 8) {
@@ -6129,46 +4841,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tmgr") == 0) {
-		if (n_tokens == 2) {
-			cmd_tmgr(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shaper") == 0) &&
-			(strcmp(tokens[2], "profile") == 0)) {
-			cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "shared") == 0) &&
-			(strcmp(tokens[2], "shaper") == 0)) {
-			cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "node") == 0)) {
-			cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 2 &&
-			(strcmp(tokens[1], "hierarchy-default") == 0)) {
-			cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[1], "hierarchy") == 0) &&
-			(strcmp(tokens[2], "commit") == 0)) {
-			cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "tap") == 0) {
 		cmd_tap(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 07285ca315..4cc98b7aad 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -13,14 +13,12 @@
 #include <rte_mbuf.h>
 #include <rte_ring.h>
 #include <rte_ethdev.h>
-#include <rte_sched.h>
 #include <rte_port_in_action.h>
 #include <rte_table_action.h>
 #include <rte_pipeline.h>
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_tm_driver.h>
 #include <rte_flow_driver.h>
 #include <rte_mtr_driver.h>
 
@@ -40,12 +38,6 @@ struct pmd_params {
 	uint16_t conn_port;
 	uint32_t cpu_id;
 	int sc; /**< Service cores. */
-
-	/** Traffic Management (TM) */
-	struct {
-		uint32_t n_queues; /**< Number of queues */
-		uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-	} tm;
 };
 
 /**
@@ -161,134 +153,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TMGR
- */
-
-#ifndef TM_MAX_SUBPORTS
-#define TM_MAX_SUBPORTS					8
-#endif
-
-#ifndef TM_MAX_PIPES_PER_SUBPORT
-#define TM_MAX_PIPES_PER_SUBPORT			4096
-#endif
-
-#ifndef TM_MAX_PIPE_PROFILE
-#define TM_MAX_PIPE_PROFILE				256
-#endif
-
-#ifndef TM_MAX_SUBPORT_PROFILE
-#define TM_MAX_SUBPORT_PROFILE				256
-#endif
-
-struct tm_params {
-	struct rte_sched_port_params port_params;
-	struct rte_sched_subport_params subport_params[TM_MAX_SUBPORTS];
-	struct rte_sched_subport_profile_params
-		subport_profile[TM_MAX_SUBPORT_PROFILE];
-	uint32_t n_subport_profiles;
-	uint32_t subport_to_profile[TM_MAX_SUBPORT_PROFILE];
-	struct rte_sched_pipe_params pipe_profiles[TM_MAX_PIPE_PROFILE];
-	uint32_t n_pipe_profiles;
-	uint32_t pipe_to_profile[TM_MAX_SUBPORTS * TM_MAX_PIPES_PER_SUBPORT];
-};
-
-/* TM Levels */
-enum tm_node_level {
-	TM_NODE_LEVEL_PORT = 0,
-	TM_NODE_LEVEL_SUBPORT,
-	TM_NODE_LEVEL_PIPE,
-	TM_NODE_LEVEL_TC,
-	TM_NODE_LEVEL_QUEUE,
-	TM_NODE_LEVEL_MAX,
-};
-
-/* TM Shaper Profile */
-struct tm_shaper_profile {
-	TAILQ_ENTRY(tm_shaper_profile) node;
-	uint32_t shaper_profile_id;
-	uint32_t n_users;
-	struct rte_tm_shaper_params params;
-};
-
-TAILQ_HEAD(tm_shaper_profile_list, tm_shaper_profile);
-
-/* TM Shared Shaper */
-struct tm_shared_shaper {
-	TAILQ_ENTRY(tm_shared_shaper) node;
-	uint32_t shared_shaper_id;
-	uint32_t n_users;
-	uint32_t shaper_profile_id;
-};
-
-TAILQ_HEAD(tm_shared_shaper_list, tm_shared_shaper);
-
-/* TM WRED Profile */
-struct tm_wred_profile {
-	TAILQ_ENTRY(tm_wred_profile) node;
-	uint32_t wred_profile_id;
-	uint32_t n_users;
-	struct rte_tm_wred_params params;
-};
-
-TAILQ_HEAD(tm_wred_profile_list, tm_wred_profile);
-
-/* TM Node */
-struct tm_node {
-	TAILQ_ENTRY(tm_node) node;
-	uint32_t node_id;
-	uint32_t parent_node_id;
-	uint32_t priority;
-	uint32_t weight;
-	uint32_t level;
-	struct tm_node *parent_node;
-	struct tm_shaper_profile *shaper_profile;
-	struct tm_wred_profile *wred_profile;
-	struct rte_tm_node_params params;
-	struct rte_tm_node_stats stats;
-	uint32_t n_children;
-};
-
-TAILQ_HEAD(tm_node_list, tm_node);
-
-/* TM Hierarchy Specification */
-struct tm_hierarchy {
-	struct tm_shaper_profile_list shaper_profiles;
-	struct tm_shared_shaper_list shared_shapers;
-	struct tm_wred_profile_list wred_profiles;
-	struct tm_node_list nodes;
-
-	uint32_t n_shaper_profiles;
-	uint32_t n_shared_shapers;
-	uint32_t n_wred_profiles;
-	uint32_t n_nodes;
-
-	uint32_t n_tm_nodes[TM_NODE_LEVEL_MAX];
-};
-
-struct tm_internals {
-	/** Hierarchy specification
-	 *
-	 *     -Hierarchy is unfrozen at init and when port is stopped.
-	 *     -Hierarchy is frozen on successful hierarchy commit.
-	 *     -Run-time hierarchy changes are not allowed, therefore it makes
-	 *      sense to keep the hierarchy frozen after the port is started.
-	 */
-	struct tm_hierarchy h;
-	int hierarchy_frozen;
-
-	/** Blueprints */
-	struct tm_params params;
-};
-
-struct softnic_tmgr_port {
-	TAILQ_ENTRY(softnic_tmgr_port) node;
-	char name[NAME_SIZE];
-	struct rte_sched_port *s;
-};
-
-TAILQ_HEAD(softnic_tmgr_port_list, softnic_tmgr_port);
-
 /**
  * TAP
  */
@@ -385,7 +249,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TMGR,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 	PORT_IN_CRYPTODEV,
@@ -426,7 +289,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TMGR,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 	PORT_OUT_CRYPTODEV,
@@ -619,10 +481,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct {
-		struct tm_internals tm; /**< Traffic Management */
-	} soft;
-
 	struct flow_internals flow;
 	struct mtr_internals mtr;
 
@@ -630,7 +488,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tmgr_port_list tmgr_port_list;
 	struct softnic_tap_list tap_list;
 	struct softnic_cryptodev_list cryptodev_list;
 	struct softnic_port_in_action_profile_list port_in_action_profile_list;
@@ -753,39 +610,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TMGR
- */
-int
-softnic_tmgr_init(struct pmd_internals *p);
-
-void
-softnic_tmgr_free(struct pmd_internals *p);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name);
-
-void
-tm_hierarchy_init(struct pmd_internals *p);
-
-void
-tm_hierarchy_free(struct pmd_internals *p);
-
-static inline int
-tm_used(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	return p->soft.tm.h.n_tm_nodes[TM_NODE_LEVEL_PORT];
-}
-
-extern const struct rte_tm_ops pmd_tm_ops;
-
 /**
  * TAP
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 337aa32e57..c7d2a7de19 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -305,21 +305,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-
-		p.ops = &rte_port_sched_reader_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_IN_TAP:
 	{
 		struct softnic_tap *tap;
@@ -545,22 +530,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TMGR:
-	{
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name);
-		if (tmgr_port == NULL)
-			return -1;
-
-		pp.sched.sched = tmgr_port->s;
-		pp.sched.tx_burst_sz = params->burst_size;
-
-		p.ops = &rte_port_sched_writer_ops;
-		p.arg_create = &pp.sched;
-		break;
-	}
-
 	case PORT_OUT_TAP:
 	{
 		struct softnic_tap *tap;
diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c
deleted file mode 100644
index 3e4bed81e9..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tm.c
+++ /dev/null
@@ -1,3645 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define SUBPORT_TC_PERIOD	10
-#define PIPE_TC_PERIOD		40
-
-int
-softnic_tmgr_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tmgr_port_list);
-
-	return 0;
-}
-
-void
-softnic_tmgr_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tmgr_port *tmgr_port;
-
-		tmgr_port = TAILQ_FIRST(&p->tmgr_port_list);
-		if (tmgr_port == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tmgr_port_list, tmgr_port, node);
-		rte_sched_port_free(tmgr_port->s);
-		free(tmgr_port);
-	}
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tmgr_port, &p->tmgr_port_list, node)
-		if (strcmp(tmgr_port->name, name) == 0)
-			return tmgr_port;
-
-	return NULL;
-}
-
-struct softnic_tmgr_port *
-softnic_tmgr_port_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tmgr_port *tmgr_port;
-	struct tm_params *t = &p->soft.tm.params;
-	struct rte_sched_port *sched;
-	uint32_t n_subports, subport_id;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tmgr_port_find(p, name))
-		return NULL;
-
-	/*
-	 * Resource
-	 */
-
-	/* Is hierarchy frozen? */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return NULL;
-
-	/* Port */
-	sched = rte_sched_port_config(&t->port_params);
-	if (sched == NULL)
-		return NULL;
-
-	/* Subport */
-	n_subports = t->port_params.n_subports_per_port;
-	for (subport_id = 0; subport_id < n_subports; subport_id++) {
-		uint32_t n_pipes_per_subport =
-		t->subport_params[subport_id].n_pipes_per_subport_enabled;
-		uint32_t pipe_id;
-		int status;
-
-		status = rte_sched_subport_config(sched,
-			subport_id,
-			&t->subport_params[subport_id],
-			t->subport_to_profile[subport_id]);
-		if (status) {
-			rte_sched_port_free(sched);
-			return NULL;
-		}
-
-		/* Pipe */
-		for (pipe_id = 0; pipe_id < n_pipes_per_subport; pipe_id++) {
-			int pos = subport_id * TM_MAX_PIPES_PER_SUBPORT + pipe_id;
-			int profile_id = t->pipe_to_profile[pos];
-
-			if (profile_id < 0)
-				continue;
-
-			status = rte_sched_pipe_config(sched,
-				subport_id,
-				pipe_id,
-				profile_id);
-			if (status) {
-				rte_sched_port_free(sched);
-				return NULL;
-			}
-		}
-	}
-
-	/* Node allocation */
-	tmgr_port = calloc(1, sizeof(struct softnic_tmgr_port));
-	if (tmgr_port == NULL) {
-		rte_sched_port_free(sched);
-		return NULL;
-	}
-
-	/* Node fill in */
-	strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name));
-	tmgr_port->s = sched;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tmgr_port_list, tmgr_port, node);
-
-	return tmgr_port;
-}
-
-static struct rte_sched_port *
-SCHED(struct pmd_internals *p)
-{
-	struct softnic_tmgr_port *tmgr_port;
-
-	tmgr_port = softnic_tmgr_port_find(p, "TMGR");
-	if (tmgr_port == NULL)
-		return NULL;
-
-	return tmgr_port->s;
-}
-
-void
-tm_hierarchy_init(struct pmd_internals *p)
-{
-	memset(&p->soft.tm, 0, sizeof(p->soft.tm));
-
-	/* Initialize shaper profile list */
-	TAILQ_INIT(&p->soft.tm.h.shaper_profiles);
-
-	/* Initialize shared shaper list */
-	TAILQ_INIT(&p->soft.tm.h.shared_shapers);
-
-	/* Initialize wred profile list */
-	TAILQ_INIT(&p->soft.tm.h.wred_profiles);
-
-	/* Initialize TM node list */
-	TAILQ_INIT(&p->soft.tm.h.nodes);
-}
-
-void
-tm_hierarchy_free(struct pmd_internals *p)
-{
-	/* Remove all nodes*/
-	for ( ; ; ) {
-		struct tm_node *tm_node;
-
-		tm_node = TAILQ_FIRST(&p->soft.tm.h.nodes);
-		if (tm_node == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.nodes, tm_node, node);
-		free(tm_node);
-	}
-
-	/* Remove all WRED profiles */
-	for ( ; ; ) {
-		struct tm_wred_profile *wred_profile;
-
-		wred_profile = TAILQ_FIRST(&p->soft.tm.h.wred_profiles);
-		if (wred_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wred_profile, node);
-		free(wred_profile);
-	}
-
-	/* Remove all shared shapers */
-	for ( ; ; ) {
-		struct tm_shared_shaper *shared_shaper;
-
-		shared_shaper = TAILQ_FIRST(&p->soft.tm.h.shared_shapers);
-		if (shared_shaper == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, shared_shaper, node);
-		free(shared_shaper);
-	}
-
-	/* Remove all shaper profiles */
-	for ( ; ; ) {
-		struct tm_shaper_profile *shaper_profile;
-
-		shaper_profile = TAILQ_FIRST(&p->soft.tm.h.shaper_profiles);
-		if (shaper_profile == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles,
-			shaper_profile, node);
-		free(shaper_profile);
-	}
-
-	tm_hierarchy_init(p);
-}
-
-static struct tm_shaper_profile *
-tm_shaper_profile_search(struct rte_eth_dev *dev, uint32_t shaper_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-
-	TAILQ_FOREACH(sp, spl, node)
-		if (shaper_profile_id == sp->shaper_profile_id)
-			return sp;
-
-	return NULL;
-}
-
-static struct tm_shared_shaper *
-tm_shared_shaper_search(struct rte_eth_dev *dev, uint32_t shared_shaper_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper_list *ssl = &p->soft.tm.h.shared_shapers;
-	struct tm_shared_shaper *ss;
-
-	TAILQ_FOREACH(ss, ssl, node)
-		if (shared_shaper_id == ss->shared_shaper_id)
-			return ss;
-
-	return NULL;
-}
-
-static struct tm_wred_profile *
-tm_wred_profile_search(struct rte_eth_dev *dev, uint32_t wred_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-
-	TAILQ_FOREACH(wp, wpl, node)
-		if (wred_profile_id == wp->wred_profile_id)
-			return wp;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_node_search(struct rte_eth_dev *dev, uint32_t node_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->node_id == node_id)
-			return n;
-
-	return NULL;
-}
-
-static struct tm_node *
-tm_root_node_present(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node)
-		if (n->parent_node_id == RTE_TM_NODE_ID_NULL)
-			return n;
-
-	return NULL;
-}
-
-static uint32_t
-tm_node_subport_id(struct rte_eth_dev *dev, struct tm_node *subport_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->node_id == subport_node->node_id)
-			return subport_id;
-
-		subport_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_pipe_id(struct rte_eth_dev *dev, struct tm_node *pipe_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *np;
-	uint32_t pipe_id;
-
-	pipe_id = 0;
-	TAILQ_FOREACH(np, nl, node) {
-		if (np->level != TM_NODE_LEVEL_PIPE ||
-			np->parent_node_id != pipe_node->parent_node_id)
-			continue;
-
-		if (np->node_id == pipe_node->node_id)
-			return pipe_id;
-
-		pipe_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_node_tc_id(struct rte_eth_dev *dev __rte_unused, struct tm_node *tc_node)
-{
-	return tc_node->priority;
-}
-
-static uint32_t
-tm_node_queue_id(struct rte_eth_dev *dev, struct tm_node *queue_node)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *nq;
-	uint32_t queue_id;
-
-	queue_id = 0;
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node_id != queue_node->parent_node_id)
-			continue;
-
-		if (nq->node_id == queue_node->node_id)
-			return queue_id;
-
-		queue_id++;
-	}
-
-	return UINT32_MAX;
-}
-
-static uint32_t
-tm_level_get_max_nodes(struct rte_eth_dev *dev, enum tm_node_level level)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t n_queues_max = p->params.tm.n_queues;
-	uint32_t n_tc_max =
-		(n_queues_max * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		/ RTE_SCHED_QUEUES_PER_PIPE;
-	uint32_t n_pipes_max = n_tc_max / RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE;
-	uint32_t n_subports_max = n_pipes_max;
-	uint32_t n_root_max = 1;
-
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		return n_root_max;
-	case TM_NODE_LEVEL_SUBPORT:
-		return n_subports_max;
-	case TM_NODE_LEVEL_PIPE:
-		return n_pipes_max;
-	case TM_NODE_LEVEL_TC:
-		return n_tc_max;
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		return n_queues_max;
-	}
-}
-
-/* Traffic manager node type get */
-static int
-pmd_tm_node_type_get(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	int *is_leaf,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	if (is_leaf == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_UNSPECIFIED,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (node_id == RTE_TM_NODE_ID_NULL ||
-		(tm_node_search(dev, node_id) == NULL))
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	*is_leaf = node_id < p->params.tm.n_queues;
-
-	return 0;
-}
-
-#define WRED_SUPPORTED						0
-
-#define STATS_MASK_DEFAULT					\
-	(RTE_TM_STATS_N_PKTS |					\
-	RTE_TM_STATS_N_BYTES |					\
-	RTE_TM_STATS_N_PKTS_GREEN_DROPPED |			\
-	RTE_TM_STATS_N_BYTES_GREEN_DROPPED)
-
-#define STATS_MASK_QUEUE						\
-	(STATS_MASK_DEFAULT |					\
-	RTE_TM_STATS_N_PKTS_QUEUED)
-
-static const struct rte_tm_capabilities tm_cap = {
-	.n_nodes_max = UINT32_MAX,
-	.n_levels_max = TM_NODE_LEVEL_MAX,
-
-	.non_leaf_nodes_identical = 0,
-	.leaf_nodes_identical = 1,
-
-	.shaper_n_max = UINT32_MAX,
-	.shaper_private_n_max = UINT32_MAX,
-	.shaper_private_dual_rate_n_max = 0,
-	.shaper_private_rate_min = 1,
-	.shaper_private_rate_max = UINT32_MAX,
-	.shaper_private_packet_mode_supported = 0,
-	.shaper_private_byte_mode_supported = 1,
-
-	.shaper_shared_n_max = UINT32_MAX,
-	.shaper_shared_n_nodes_per_shaper_max = UINT32_MAX,
-	.shaper_shared_n_shapers_per_node_max = 1,
-	.shaper_shared_dual_rate_n_max = 0,
-	.shaper_shared_rate_min = 1,
-	.shaper_shared_rate_max = UINT32_MAX,
-	.shaper_shared_packet_mode_supported = 0,
-	.shaper_shared_byte_mode_supported = 1,
-
-	.shaper_pkt_length_adjust_min = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-	.shaper_pkt_length_adjust_max = RTE_TM_ETH_FRAMING_OVERHEAD_FCS,
-
-	.sched_n_children_max = UINT32_MAX,
-	.sched_sp_n_priorities_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-	.sched_wfq_n_children_per_group_max = UINT32_MAX,
-	.sched_wfq_n_groups_max = 1,
-	.sched_wfq_weight_max = UINT32_MAX,
-	.sched_wfq_packet_mode_supported = 0,
-	.sched_wfq_byte_mode_supported = 1,
-
-	.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-	.cman_wred_byte_mode_supported = 0,
-	.cman_head_drop_supported = 0,
-	.cman_wred_context_n_max = 0,
-	.cman_wred_context_private_n_max = 0,
-	.cman_wred_context_shared_n_max = 0,
-	.cman_wred_context_shared_n_nodes_per_context_max = 0,
-	.cman_wred_context_shared_n_contexts_per_node_max = 0,
-
-	.mark_vlan_dei_supported = {0, 0, 0},
-	.mark_ip_ecn_tcp_supported = {0, 0, 0},
-	.mark_ip_ecn_sctp_supported = {0, 0, 0},
-	.mark_ip_dscp_supported = {0, 0, 0},
-
-	.dynamic_update_mask = 0,
-
-	.stats_mask = STATS_MASK_QUEUE,
-};
-
-/* Traffic manager capabilities get */
-static int
-pmd_tm_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	struct rte_tm_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_cap, sizeof(*cap));
-
-	cap->n_nodes_max = tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->shaper_private_n_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE) +
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_TC);
-
-	cap->shaper_shared_n_max = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE *
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_SUBPORT);
-
-	cap->shaper_n_max = cap->shaper_private_n_max +
-		cap->shaper_shared_n_max;
-
-	cap->shaper_shared_n_nodes_per_shaper_max =
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE);
-
-	cap->sched_n_children_max = RTE_MAX(
-		tm_level_get_max_nodes(dev, TM_NODE_LEVEL_PIPE),
-		(uint32_t)RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE);
-
-	cap->sched_wfq_n_children_per_group_max = cap->sched_n_children_max;
-
-	if (WRED_SUPPORTED)
-		cap->cman_wred_context_private_n_max =
-			tm_level_get_max_nodes(dev, TM_NODE_LEVEL_QUEUE);
-
-	cap->cman_wred_context_n_max = cap->cman_wred_context_private_n_max +
-		cap->cman_wred_context_shared_n_max;
-
-	return 0;
-}
-
-static const struct rte_tm_level_capabilities tm_level_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.n_nodes_max = 1,
-		.n_nodes_nonleaf_max = 1,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = UINT32_MAX,
-		.n_nodes_leaf_max = 0,
-		.non_leaf_nodes_identical = 1,
-		.leaf_nodes_identical = 0,
-
-		{.nonleaf = {
-			.shaper_private_supported = 1,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 1,
-			.shaper_private_rate_max = UINT32_MAX,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 1,
-			.shaper_shared_n_max = 1,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 1,
-
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-
-			.stats_mask = STATS_MASK_DEFAULT,
-		} },
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.n_nodes_max = UINT32_MAX,
-		.n_nodes_nonleaf_max = 0,
-		.n_nodes_leaf_max = UINT32_MAX,
-		.non_leaf_nodes_identical = 0,
-		.leaf_nodes_identical = 1,
-
-		{.leaf = {
-			.shaper_private_supported = 0,
-			.shaper_private_dual_rate_supported = 0,
-			.shaper_private_rate_min = 0,
-			.shaper_private_rate_max = 0,
-			.shaper_private_packet_mode_supported = 0,
-			.shaper_private_byte_mode_supported = 0,
-			.shaper_shared_n_max = 0,
-			.shaper_shared_packet_mode_supported = 0,
-			.shaper_shared_byte_mode_supported = 0,
-
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-
-			.stats_mask = STATS_MASK_QUEUE,
-		} },
-	},
-};
-
-/* Traffic manager level capabilities get */
-static int
-pmd_tm_level_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t level_id,
-	struct rte_tm_level_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	if (level_id >= TM_NODE_LEVEL_MAX)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_LEVEL_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_level_cap[level_id], sizeof(*cap));
-
-	switch (level_id) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_SUBPORT);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_PIPE);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_TC);
-		cap->n_nodes_nonleaf_max = cap->n_nodes_max;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		cap->n_nodes_max = tm_level_get_max_nodes(dev,
-			TM_NODE_LEVEL_QUEUE);
-		cap->n_nodes_leaf_max = cap->n_nodes_max;
-		break;
-	}
-
-	return 0;
-}
-
-static const struct rte_tm_node_capabilities tm_node_cap[] = {
-	[TM_NODE_LEVEL_PORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_SUBPORT] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max = UINT32_MAX,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max = UINT32_MAX,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_PIPE] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_sp_n_priorities_max =
-				RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-			.sched_wfq_n_children_per_group_max = 1,
-			.sched_wfq_n_groups_max = 0,
-			.sched_wfq_weight_max = 1,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 0,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_TC] = {
-		.shaper_private_supported = 1,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 1,
-		.shaper_private_rate_max = UINT32_MAX,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 1,
-		.shaper_shared_n_max = 1,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 1,
-
-		{.nonleaf = {
-			.sched_n_children_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_sp_n_priorities_max = 1,
-			.sched_wfq_n_children_per_group_max =
-				RTE_SCHED_BE_QUEUES_PER_PIPE,
-			.sched_wfq_n_groups_max = 1,
-			.sched_wfq_weight_max = UINT32_MAX,
-			.sched_wfq_packet_mode_supported = 0,
-			.sched_wfq_byte_mode_supported = 1,
-		} },
-
-		.stats_mask = STATS_MASK_DEFAULT,
-	},
-
-	[TM_NODE_LEVEL_QUEUE] = {
-		.shaper_private_supported = 0,
-		.shaper_private_dual_rate_supported = 0,
-		.shaper_private_rate_min = 0,
-		.shaper_private_rate_max = 0,
-		.shaper_private_packet_mode_supported = 0,
-		.shaper_private_byte_mode_supported = 0,
-		.shaper_shared_n_max = 0,
-		.shaper_shared_packet_mode_supported = 0,
-		.shaper_shared_byte_mode_supported = 0,
-
-
-		{.leaf = {
-			.cman_head_drop_supported = 0,
-			.cman_wred_packet_mode_supported = WRED_SUPPORTED,
-			.cman_wred_byte_mode_supported = 0,
-			.cman_wred_context_private_supported = WRED_SUPPORTED,
-			.cman_wred_context_shared_n_max = 0,
-		} },
-
-		.stats_mask = STATS_MASK_QUEUE,
-	},
-};
-
-/* Traffic manager node capabilities get */
-static int
-pmd_tm_node_capabilities_get(struct rte_eth_dev *dev __rte_unused,
-	uint32_t node_id,
-	struct rte_tm_node_capabilities *cap,
-	struct rte_tm_error *error)
-{
-	struct tm_node *tm_node;
-
-	if (cap == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_CAPABILITIES,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	tm_node = tm_node_search(dev, node_id);
-	if (tm_node == NULL)
-		return -rte_tm_error_set(error,
-		   EINVAL,
-		   RTE_TM_ERROR_TYPE_NODE_ID,
-		   NULL,
-		   rte_strerror(EINVAL));
-
-	memcpy(cap, &tm_node_cap[tm_node->level], sizeof(*cap));
-
-	switch (tm_node->level) {
-	case TM_NODE_LEVEL_PORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_SUBPORT);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		cap->nonleaf.sched_n_children_max =
-			tm_level_get_max_nodes(dev,
-				TM_NODE_LEVEL_PIPE);
-		cap->nonleaf.sched_wfq_n_children_per_group_max =
-			cap->nonleaf.sched_n_children_max;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-	case TM_NODE_LEVEL_TC:
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		break;
-	}
-
-	return 0;
-}
-
-static int
-shaper_profile_check(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_shaper_profile *sp;
-
-	/* Shaper profile ID must not be NONE. */
-	if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must not exist. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak rate: non-zero, 32-bit */
-	if (profile->peak.rate == 0 ||
-		profile->peak.rate >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Peak size: non-zero, 32-bit */
-	if (profile->peak.size == 0 ||
-		profile->peak.size >= UINT32_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Dual-rate profiles are not supported. */
-	if (profile->committed.rate != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet length adjust: 24 bytes */
-	if (profile->pkt_length_adjust != RTE_TM_ETH_FRAMING_OVERHEAD_FCS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PKT_ADJUST_LEN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Packet mode is not supported. */
-	if (profile->packet_mode != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PACKET_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-	return 0;
-}
-
-/* Traffic manager shaper profile add */
-static int
-pmd_tm_shaper_profile_add(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_shaper_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile_list *spl = &p->soft.tm.h.shaper_profiles;
-	struct tm_shaper_profile *sp;
-	int status;
-
-	/* Check input params */
-	status = shaper_profile_check(dev, shaper_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	sp = calloc(1, sizeof(struct tm_shaper_profile));
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	sp->shaper_profile_id = shaper_profile_id;
-	memcpy(&sp->params, profile, sizeof(sp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(spl, sp, node);
-	p->soft.tm.h.n_shaper_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager shaper profile delete */
-static int
-pmd_tm_shaper_profile_delete(struct rte_eth_dev *dev,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp;
-
-	/* Check existing */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (sp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shaper_profiles, sp, node);
-	p->soft.tm.h.n_shaper_profiles--;
-	free(sp);
-
-	return 0;
-}
-
-static struct tm_node *
-tm_shared_shaper_get_tc(struct rte_eth_dev *dev,
-	struct tm_shared_shaper *ss)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	/* Subport: each TC uses shared shaper  */
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->params.n_shared_shapers == 0 ||
-			n->params.shared_shaper_id[0] != ss->shared_shaper_id)
-			continue;
-
-		return n;
-	}
-
-	return NULL;
-}
-
-static int
-subport_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_subport_profiles; i++)
-		if (memcmp(&t->subport_profile[i], sp, sizeof(*sp)) == 0) {
-			if (subport_profile_id)
-				*subport_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static int
-update_subport_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shared_shaper *ss,
-	struct tm_shaper_profile *sp_new)
-{
-	struct rte_sched_subport_profile_params subport_profile;
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-	struct tm_node *np = nt->parent_node;
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_profile_id;
-	struct tm_shaper_profile *sp_old = tm_shaper_profile_search(dev,
-		ss->shaper_profile_id);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return -1;
-
-	subport_profile_id = t->subport_to_profile[subport_id];
-
-	/* Derive new subport configuration. */
-	memcpy(&subport_profile,
-		&p->soft.tm.params.subport_profile[subport_profile_id],
-		sizeof(subport_profile));
-	subport_profile.tc_rate[tc_id] = sp_new->params.peak.rate;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p),
-		subport_id, NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	sp_old->n_users--;
-
-	ss->shaper_profile_id = sp_new->shaper_profile_id;
-	sp_new->n_users++;
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&subport_profile,
-		sizeof(subport_profile));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper add/update */
-static int
-pmd_tm_shared_shaper_add_update(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-	struct tm_shaper_profile *sp;
-	struct tm_node *nt;
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * Add new shared shaper
-	 */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL) {
-		struct tm_shared_shaper_list *ssl =
-			&p->soft.tm.h.shared_shapers;
-
-		/* Hierarchy must not be frozen */
-		if (p->soft.tm.hierarchy_frozen)
-			return -rte_tm_error_set(error,
-				EBUSY,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EBUSY));
-
-		/* Memory allocation */
-		ss = calloc(1, sizeof(struct tm_shared_shaper));
-		if (ss == NULL)
-			return -rte_tm_error_set(error,
-				ENOMEM,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(ENOMEM));
-
-		/* Fill in */
-		ss->shared_shaper_id = shared_shaper_id;
-		ss->shaper_profile_id = shaper_profile_id;
-
-		/* Add to list */
-		TAILQ_INSERT_TAIL(ssl, ss, node);
-		p->soft.tm.h.n_shared_shapers++;
-
-		return 0;
-	}
-
-	/**
-	 * Update existing shared shaper
-	 */
-	/* Hierarchy must be frozen (run-time update) */
-	if (p->soft.tm.hierarchy_frozen == 0)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-
-	/* Propagate change. */
-	nt = tm_shared_shaper_get_tc(dev, ss);
-	if (update_subport_tc_rate(dev, nt, ss, sp))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-/* Traffic manager shared shaper delete */
-static int
-pmd_tm_shared_shaper_delete(struct rte_eth_dev *dev,
-	uint32_t shared_shaper_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shared_shaper *ss;
-
-	/* Check existing */
-	ss = tm_shared_shaper_search(dev, shared_shaper_id);
-	if (ss == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (ss->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.shared_shapers, ss, node);
-	p->soft.tm.h.n_shared_shapers--;
-	free(ss);
-
-	return 0;
-}
-
-static int
-wred_profile_check(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct tm_wred_profile *wp;
-	enum rte_color color;
-
-	/* WRED profile ID must not be NONE. */
-	if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WRED profile must not exist. */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp)
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-        /* WRED profile should be in packet mode */
-        if (profile->packet_mode == 0)
-                return -rte_tm_error_set(error,
-                        ENOTSUP,
-                        RTE_TM_ERROR_TYPE_WRED_PROFILE,
-                        NULL,
-                        rte_strerror(ENOTSUP));
-
-	/* min_th <= max_th, max_th > 0  */
-	for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-		uint32_t min_th = profile->red_params[color].min_th;
-		uint32_t max_th = profile->red_params[color].max_th;
-
-		if (min_th > max_th ||
-			max_th == 0 ||
-			min_th > UINT16_MAX ||
-			max_th > UINT16_MAX)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_WRED_PROFILE,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager WRED profile add */
-static int
-pmd_tm_wred_profile_add(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_wred_params *profile,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile_list *wpl = &p->soft.tm.h.wred_profiles;
-	struct tm_wred_profile *wp;
-	int status;
-
-	/* Check input params */
-	status = wred_profile_check(dev, wred_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	wp = calloc(1, sizeof(struct tm_wred_profile));
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	wp->wred_profile_id = wred_profile_id;
-	memcpy(&wp->params, profile, sizeof(wp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(wpl, wp, node);
-	p->soft.tm.h.n_wred_profiles++;
-
-	return 0;
-}
-
-/* Traffic manager WRED profile delete */
-static int
-pmd_tm_wred_profile_delete(struct rte_eth_dev *dev,
-	uint32_t wred_profile_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_wred_profile *wp;
-
-	/* Check existing */
-	wp = tm_wred_profile_search(dev, wred_profile_id);
-	if (wp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (wp->n_users)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_WRED_PROFILE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.wred_profiles, wp, node);
-	p->soft.tm.h.n_wred_profiles--;
-	free(wp);
-
-	return 0;
-}
-
-static int
-node_add_check_port(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_shaper_profile *sp = tm_shaper_profile_search(dev,
-		params->shaper_profile_id);
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_subport(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_pipe(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of SP priorities must be 4 */
-	if (params->nonleaf.n_sp_priorities !=
-		RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* WFQ mode must be byte mode */
-	if (params->nonleaf.wfq_weight_mode != NULL &&
-		params->nonleaf.wfq_weight_mode[0] != 0 &&
-		params->nonleaf.wfq_weight_mode[1] != 0 &&
-		params->nonleaf.wfq_weight_mode[2] != 0 &&
-		params->nonleaf.wfq_weight_mode[3] != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_tc(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority __rte_unused,
-	uint32_t weight,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: non-leaf */
-	if (node_id < p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Weight must be 1 */
-	if (weight != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper must be valid */
-	if (params->shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE ||
-		(!tm_shaper_profile_search(dev, params->shaper_profile_id)))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Single valid shared shaper */
-	if (params->n_shared_shapers > 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (params->n_shared_shapers == 1 &&
-		(params->shared_shaper_id == NULL ||
-		(!tm_shared_shaper_search(dev, params->shared_shaper_id[0]))))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of priorities must be 1 */
-	if (params->nonleaf.n_sp_priorities != 1)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_DEFAULT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check_queue(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id __rte_unused,
-	uint32_t priority,
-	uint32_t weight __rte_unused,
-	uint32_t level_id __rte_unused,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	/* node type: leaf */
-	if (node_id >= p->params.tm.n_queues)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be 0 */
-	if (priority != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shaper */
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHAPER_PROFILE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* No shared shapers */
-	if (params->n_shared_shapers != 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management must not be head drop */
-	if (params->leaf.cman == RTE_TM_CMAN_HEAD_DROP)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Congestion management set to WRED */
-	if (params->leaf.cman == RTE_TM_CMAN_WRED) {
-		uint32_t wred_profile_id = params->leaf.wred.wred_profile_id;
-		struct tm_wred_profile *wp = tm_wred_profile_search(dev,
-			wred_profile_id);
-
-		/* WRED profile (for private WRED context) must be valid */
-		if (wred_profile_id == RTE_TM_WRED_PROFILE_ID_NONE ||
-			wp == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-
-		/* No shared WRED contexts */
-		if (params->leaf.wred.n_shared_wred_contexts != 0)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Stats */
-	if (params->stats_mask & ~STATS_MASK_QUEUE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	return 0;
-}
-
-static int
-node_add_check(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct tm_node *pn;
-	uint32_t level;
-	int status;
-
-	/* node_id, parent_node_id:
-	 *    -node_id must not be RTE_TM_NODE_ID_NULL
-	 *    -node_id must not be in use
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -root node must not exist
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -parent_node_id must be valid
-	 */
-	if (node_id == RTE_TM_NODE_ID_NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	if (tm_node_search(dev, node_id))
-		return -rte_tm_error_set(error,
-			EEXIST,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EEXIST));
-
-	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
-		pn = NULL;
-		if (tm_root_node_present(dev))
-			return -rte_tm_error_set(error,
-				EEXIST,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EEXIST));
-	} else {
-		pn = tm_node_search(dev, parent_node_id);
-		if (pn == NULL)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* priority: must be 0 .. 3 */
-	if (priority >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* level_id: if valid, then
-	 *    -root node add (parent_node_id is RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be zero
-	 *    -non-root node add (parent_node_id is not RTE_TM_NODE_ID_NULL):
-	 *        -level_id must be parent level ID plus one
-	 */
-	level = (pn == NULL) ? 0 : pn->level + 1;
-	if (level_id != RTE_TM_NODE_LEVEL_ID_ANY && level_id != level)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: must not be NULL */
-	if (params == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARAMS,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* params: per level checks */
-	switch (level) {
-	case TM_NODE_LEVEL_PORT:
-		status = node_add_check_port(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		status = node_add_check_subport(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_PIPE:
-		status = node_add_check_pipe(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_TC:
-		status = node_add_check_tc(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	case TM_NODE_LEVEL_QUEUE:
-		status = node_add_check_queue(dev, node_id,
-			parent_node_id, priority, weight, level_id,
-			params, error);
-		if (status)
-			return status;
-		break;
-
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-
-	return 0;
-}
-
-/* Traffic manager node add */
-static int
-pmd_tm_node_add(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	uint32_t level_id,
-	struct rte_tm_node_params *params,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-	uint32_t i;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = node_add_check(dev, node_id, parent_node_id, priority, weight,
-		level_id, params, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	n = calloc(1, sizeof(struct tm_node));
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			ENOMEM,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(ENOMEM));
-
-	/* Fill in */
-	n->node_id = node_id;
-	n->parent_node_id = parent_node_id;
-	n->priority = priority;
-	n->weight = weight;
-
-	if (parent_node_id != RTE_TM_NODE_ID_NULL) {
-		n->parent_node = tm_node_search(dev, parent_node_id);
-		n->level = n->parent_node->level + 1;
-	}
-
-	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE)
-		n->shaper_profile = tm_shaper_profile_search(dev,
-			params->shaper_profile_id);
-
-	if (n->level == TM_NODE_LEVEL_QUEUE &&
-		params->leaf.cman == RTE_TM_CMAN_WRED)
-		n->wred_profile = tm_wred_profile_search(dev,
-			params->leaf.wred.wred_profile_id);
-
-	memcpy(&n->params, params, sizeof(n->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(nl, n, node);
-	p->soft.tm.h.n_nodes++;
-
-	/* Update dependencies */
-	if (n->parent_node)
-		n->parent_node->n_children++;
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users++;
-
-	for (i = 0; i < params->n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev, params->shared_shaper_id[i]);
-		ss->n_users++;
-	}
-
-	if (n->wred_profile)
-		n->wred_profile->n_users++;
-
-	p->soft.tm.h.n_tm_nodes[n->level]++;
-
-	return 0;
-}
-
-/* Traffic manager node delete */
-static int
-pmd_tm_node_delete(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node *n;
-	uint32_t i;
-
-	/* Check hierarchy changes are currently allowed */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Check existing */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Check unused */
-	if (n->n_children)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Update dependencies */
-	p->soft.tm.h.n_tm_nodes[n->level]--;
-
-	if (n->wred_profile)
-		n->wred_profile->n_users--;
-
-	for (i = 0; i < n->params.n_shared_shapers; i++) {
-		struct tm_shared_shaper *ss;
-
-		ss = tm_shared_shaper_search(dev,
-				n->params.shared_shaper_id[i]);
-		ss->n_users--;
-	}
-
-	if (n->shaper_profile)
-		n->shaper_profile->n_users--;
-
-	if (n->parent_node)
-		n->parent_node->n_children--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->soft.tm.h.nodes, n, node);
-	p->soft.tm.h.n_nodes--;
-	free(n);
-
-	return 0;
-}
-
-
-static void
-pipe_profile_build(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_sched_pipe_params *pp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nt, *nq;
-
-	memset(pp, 0, sizeof(*pp));
-
-	/* Pipe */
-	pp->tb_rate = np->shaper_profile->params.peak.rate;
-	pp->tb_size = np->shaper_profile->params.peak.size;
-
-	/* Traffic Class (TC) */
-	pp->tc_period = PIPE_TC_PERIOD;
-
-	pp->tc_ov_weight = np->weight;
-
-	TAILQ_FOREACH(nt, nl, node) {
-		uint32_t queue_id = 0;
-
-		if (nt->level != TM_NODE_LEVEL_TC ||
-			nt->parent_node_id != np->node_id)
-			continue;
-
-		pp->tc_rate[nt->priority] =
-			nt->shaper_profile->params.peak.rate;
-
-		/* Queue */
-		TAILQ_FOREACH(nq, nl, node) {
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE ||
-				nq->parent_node_id != nt->node_id)
-				continue;
-
-			if (nt->priority == RTE_SCHED_TRAFFIC_CLASS_BE)
-				pp->wrr_weights[queue_id] = nq->weight;
-
-			queue_id++;
-		}
-	}
-}
-
-static int
-pipe_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_pipe_profiles < TM_MAX_PIPE_PROFILE) {
-		*pipe_profile_id = t->n_pipe_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static int
-pipe_profile_exists(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t *pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t i;
-
-	for (i = 0; i < t->n_pipe_profiles; i++)
-		if (memcmp(&t->pipe_profiles[i], pp, sizeof(*pp)) == 0) {
-			if (pipe_profile_id)
-				*pipe_profile_id = i;
-			return 1;
-		}
-
-	return 0;
-}
-
-static void
-pipe_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_pipe_params *pp,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->pipe_profiles[pipe_profile_id], pp, sizeof(*pp));
-	t->n_pipe_profiles++;
-}
-
-static void
-pipe_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t pipe_id,
-	uint32_t pipe_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport, pos;
-
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	pos = subport_id * n_pipes_per_subport + pipe_id;
-
-	t->pipe_to_profile[pos] = pipe_profile_id;
-}
-
-static struct rte_sched_pipe_params *
-pipe_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	uint32_t pos = subport_id * n_pipes_per_subport + pipe_id;
-	uint32_t pipe_profile_id = t->pipe_to_profile[pos];
-
-	return &t->pipe_profiles[pipe_profile_id];
-}
-
-static int
-pipe_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns, *np;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - pipe_profiles
-	 *    - n_pipe_profiles
-	 *    - pipe_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		uint32_t pipe_id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		pipe_id = 0;
-		TAILQ_FOREACH(np, nl, node) {
-			struct rte_sched_pipe_params pp;
-			uint32_t pos;
-
-			memset(&pp, 0, sizeof(pp));
-
-			if (np->level != TM_NODE_LEVEL_PIPE ||
-				np->parent_node_id != ns->node_id)
-				continue;
-
-			pipe_profile_build(dev, np, &pp);
-
-			if (!pipe_profile_exists(dev, &pp, &pos)) {
-				if (!pipe_profile_free_exists(dev, &pos))
-					return -1;
-
-				pipe_profile_install(dev, &pp, pos);
-			}
-
-			pipe_profile_mark(dev, subport_id, pipe_id, pos);
-
-			pipe_id++;
-		}
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-static struct tm_wred_profile *
-tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *nq;
-
-	TAILQ_FOREACH(nq, nl, node) {
-		if (nq->level != TM_NODE_LEVEL_QUEUE ||
-			nq->parent_node->priority != tc_id)
-			continue;
-
-		return nq->wred_profile;
-	}
-
-	return NULL;
-}
-
-static void
-wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_subport_params *pp =
-		&p->soft.tm.params.subport_params[subport_id];
-
-	uint32_t tc_id;
-	enum rte_color color;
-
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++)
-		for (color = RTE_COLOR_GREEN; color < RTE_COLORS; color++) {
-			struct rte_red_params *dst =
-				&pp->cman_params->red_params[tc_id][color];
-			struct tm_wred_profile *src_wp =
-				tm_tc_wred_profile_get(dev, tc_id);
-			struct rte_tm_red_params *src =
-				&src_wp->params.red_params[color];
-
-			memcpy(dst, src, sizeof(*dst));
-		}
-}
-
-static struct tm_shared_shaper *
-tm_tc_shared_shaper_get(struct rte_eth_dev *dev, struct tm_node *tc_node)
-{
-	return (tc_node->params.n_shared_shapers) ?
-		tm_shared_shaper_search(dev,
-			tc_node->params.shared_shaper_id[0]) :
-		NULL;
-}
-
-static struct tm_shared_shaper *
-tm_subport_tc_shared_shaper_get(struct rte_eth_dev *dev,
-	struct tm_node *subport_node,
-	uint32_t tc_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_node_list *nl = &p->soft.tm.h.nodes;
-	struct tm_node *n;
-
-	TAILQ_FOREACH(n, nl, node) {
-		if (n->level != TM_NODE_LEVEL_TC ||
-			n->parent_node->parent_node_id !=
-				subport_node->node_id ||
-			n->priority != tc_id)
-			continue;
-
-		return tm_tc_shared_shaper_get(dev, n);
-	}
-
-	return NULL;
-}
-
-static struct rte_sched_subport_profile_params *
-subport_profile_get(struct rte_eth_dev *dev, struct tm_node *np)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	uint32_t subport_id = tm_node_subport_id(dev, np->parent_node);
-
-	if (subport_id >= TM_MAX_SUBPORT_PROFILE)
-		return NULL;
-
-	return &t->subport_profile[subport_id];
-}
-
-static void
-subport_profile_mark(struct rte_eth_dev *dev,
-	uint32_t subport_id,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	t->subport_to_profile[subport_id] = subport_profile_id;
-}
-
-static void
-subport_profile_install(struct rte_eth_dev *dev,
-	struct rte_sched_subport_profile_params *sp,
-	uint32_t subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	memcpy(&t->subport_profile[subport_profile_id],
-		sp, sizeof(*sp));
-	t->n_subport_profiles++;
-}
-
-static int
-subport_profile_free_exists(struct rte_eth_dev *dev,
-	uint32_t *subport_profile_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-
-	if (t->n_subport_profiles < TM_MAX_SUBPORT_PROFILE) {
-		*subport_profile_id = t->n_subport_profiles;
-		return 1;
-	}
-
-	return 0;
-}
-
-static void
-subport_profile_build(struct rte_eth_dev *dev, struct tm_node *np,
-	struct rte_sched_subport_profile_params *sp)
-{
-	uint32_t i;
-	memset(sp, 0, sizeof(*sp));
-
-	sp->tb_rate = np->shaper_profile->params.peak.rate;
-	sp->tb_size = np->shaper_profile->params.peak.size;
-
-	for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) {
-		struct tm_shared_shaper *ss;
-		struct tm_shaper_profile *ssp;
-
-		ss = tm_subport_tc_shared_shaper_get(dev, np, i);
-		ssp = (ss) ? tm_shaper_profile_search(dev,
-			ss->shaper_profile_id) :
-			np->shaper_profile;
-		sp->tc_rate[i] = ssp->params.peak.rate;
-	}
-
-	/* Traffic Class (TC) */
-	sp->tc_period = SUBPORT_TC_PERIOD;
-}
-
-static int
-subport_profiles_generate(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *ns;
-	uint32_t subport_id;
-
-	/* Objective: Fill in the following fields in struct tm_params:
-	 *    - subport_profiles
-	 *    - n_subport_profiles
-	 *    - subport_to_profile
-	 */
-
-	subport_id = 0;
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		struct rte_sched_subport_profile_params sp;
-		uint32_t pos;
-
-		memset(&sp, 0, sizeof(sp));
-
-		subport_profile_build(dev, ns, &sp);
-
-		if (!subport_profile_exists(dev, &sp, &pos)) {
-			if (!subport_profile_free_exists(dev, &pos))
-				return -1;
-
-			subport_profile_install(dev, &sp, pos);
-		}
-
-		subport_profile_mark(dev, subport_id, pos);
-
-		subport_id++;
-	}
-
-	return 0;
-}
-
-
-static int
-hierarchy_commit_check(struct rte_eth_dev *dev, struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_shared_shaper_list *ssl = &h->shared_shapers;
-	struct tm_wred_profile_list *wpl = &h->wred_profiles;
-	struct tm_node *nr = tm_root_node_present(dev), *ns, *np, *nt, *nq;
-	struct tm_shared_shaper *ss;
-
-	uint32_t n_pipes_per_subport;
-
-	/* Root node exists. */
-	if (nr == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one subport, max is not exceeded. */
-	if (nr->n_children == 0 || nr->n_children > TM_MAX_SUBPORTS)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* There is at least one pipe. */
-	if (h->n_tm_nodes[TM_NODE_LEVEL_PIPE] == 0)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_LEVEL_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Number of pipes is the same for all subports. Maximum number of pipes
-	 * per subport is not exceeded.
-	 */
-	n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-		h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	if (n_pipes_per_subport > TM_MAX_PIPES_PER_SUBPORT)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	TAILQ_FOREACH(ns, nl, node) {
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		if (ns->n_children != n_pipes_per_subport)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Each pipe has exactly 13 TCs, with exactly one TC for each priority */
-	TAILQ_FOREACH(np, nl, node) {
-		uint32_t mask = 0, mask_expected =
-			RTE_LEN2MASK(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE,
-				uint32_t);
-
-		if (np->level != TM_NODE_LEVEL_PIPE)
-			continue;
-
-		if (np->n_children != RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-
-		TAILQ_FOREACH(nt, nl, node) {
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node_id != np->node_id)
-				continue;
-
-			mask |= 1 << nt->priority;
-		}
-
-		if (mask != mask_expected)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/** Each Strict priority TC has exactly 1 packet queues while
-	 *	lowest priority TC (Best-effort) has 4 queues.
-	 */
-	TAILQ_FOREACH(nt, nl, node) {
-		if (nt->level != TM_NODE_LEVEL_TC)
-			continue;
-
-		if (nt->n_children != 1 && nt->n_children != RTE_SCHED_BE_QUEUES_PER_PIPE)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/**
-	 * Shared shapers:
-	 *    -For each TC #i, all pipes in the same subport use the same
-	 *     shared shaper (or no shared shaper) for their TC#i.
-	 *    -Each shared shaper needs to have at least one user. All its
-	 *     users have to be TC nodes with the same priority and the same
-	 *     subport.
-	 */
-	TAILQ_FOREACH(ns, nl, node) {
-		struct tm_shared_shaper *s[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		if (ns->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++)
-			s[id] = tm_subport_tc_shared_shaper_get(dev, ns, id);
-
-		TAILQ_FOREACH(nt, nl, node) {
-			struct tm_shared_shaper *subport_ss, *tc_ss;
-
-			if (nt->level != TM_NODE_LEVEL_TC ||
-				nt->parent_node->parent_node_id !=
-					ns->node_id)
-				continue;
-
-			subport_ss = s[nt->priority];
-			tc_ss = tm_tc_shared_shaper_get(dev, nt);
-
-			if (subport_ss == NULL && tc_ss == NULL)
-				continue;
-
-			if ((subport_ss == NULL && tc_ss != NULL) ||
-				(subport_ss != NULL && tc_ss == NULL) ||
-				subport_ss->shared_shaper_id !=
-					tc_ss->shared_shaper_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	TAILQ_FOREACH(ss, ssl, node) {
-		struct tm_node *nt_any = tm_shared_shaper_get_tc(dev, ss);
-		uint32_t n_users = 0;
-
-		if (nt_any != NULL)
-			TAILQ_FOREACH(nt, nl, node) {
-				if (nt->level != TM_NODE_LEVEL_TC ||
-					nt->priority != nt_any->priority ||
-					nt->parent_node->parent_node_id !=
-					nt_any->parent_node->parent_node_id)
-					continue;
-
-				n_users++;
-			}
-
-		if (ss->n_users == 0 || ss->n_users != n_users)
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-	}
-
-	/* Not too many subport profiles. */
-	if (subport_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-
-	/* Not too many pipe profiles. */
-	if (pipe_profiles_generate(dev))
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/**
-	 * WRED (when used, i.e. at least one WRED profile defined):
-	 *    -Each WRED profile must have at least one user.
-	 *    -All leaf nodes must have their private WRED context enabled.
-	 *    -For each TC #i, all leaf nodes must use the same WRED profile
-	 *     for their private WRED context.
-	 */
-	if (h->n_wred_profiles) {
-		struct tm_wred_profile *wp;
-		struct tm_wred_profile *w[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE];
-		uint32_t id;
-
-		TAILQ_FOREACH(wp, wpl, node)
-			if (wp->n_users == 0)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			w[id] = tm_tc_wred_profile_get(dev, id);
-
-			if (w[id] == NULL)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-
-		TAILQ_FOREACH(nq, nl, node) {
-			uint32_t id;
-
-			if (nq->level != TM_NODE_LEVEL_QUEUE)
-				continue;
-
-			id = nq->parent_node->priority;
-
-			if (nq->wred_profile == NULL ||
-				nq->wred_profile->wred_profile_id !=
-					w[id]->wred_profile_id)
-				return -rte_tm_error_set(error,
-					EINVAL,
-					RTE_TM_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					rte_strerror(EINVAL));
-		}
-	}
-
-	return 0;
-}
-
-static void
-hierarchy_blueprints_create(struct rte_eth_dev *dev)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_params *t = &p->soft.tm.params;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-
-	struct tm_node_list *nl = &h->nodes;
-	struct tm_node *root = tm_root_node_present(dev), *n;
-
-	uint32_t subport_id;
-
-	t->port_params = (struct rte_sched_port_params) {
-		.name = dev->data->name,
-		.socket = dev->data->numa_node,
-		.rate = root->shaper_profile->params.peak.rate,
-		.mtu = dev->data->mtu,
-		.frame_overhead =
-			root->shaper_profile->params.pkt_length_adjust,
-		.n_subports_per_port = root->n_children,
-		.n_subport_profiles = t->n_subport_profiles,
-		.subport_profiles = t->subport_profile,
-		.n_max_subport_profiles = TM_MAX_SUBPORT_PROFILE,
-		.n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT,
-	};
-
-	subport_id = 0;
-	TAILQ_FOREACH(n, nl, node) {
-
-		if (n->level != TM_NODE_LEVEL_SUBPORT)
-			continue;
-
-		t->subport_params[subport_id] =
-			(struct rte_sched_subport_params) {
-				.n_pipes_per_subport_enabled =
-					h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-					h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT],
-				.qsize = {p->params.tm.qsize[0],
-					p->params.tm.qsize[1],
-					p->params.tm.qsize[2],
-					p->params.tm.qsize[3],
-					p->params.tm.qsize[4],
-					p->params.tm.qsize[5],
-					p->params.tm.qsize[6],
-					p->params.tm.qsize[7],
-					p->params.tm.qsize[8],
-					p->params.tm.qsize[9],
-					p->params.tm.qsize[10],
-					p->params.tm.qsize[11],
-					p->params.tm.qsize[12],
-				},
-				.pipe_profiles = t->pipe_profiles,
-				.n_pipe_profiles = t->n_pipe_profiles,
-				.n_max_pipe_profiles = TM_MAX_PIPE_PROFILE,
-		};
-		wred_profiles_set(dev, subport_id);
-		subport_id++;
-	}
-}
-
-/* Traffic manager hierarchy commit */
-static int
-pmd_tm_hierarchy_commit(struct rte_eth_dev *dev,
-	int clear_on_fail,
-	struct rte_tm_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	int status;
-
-	/* Checks */
-	if (p->soft.tm.hierarchy_frozen)
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	status = hierarchy_commit_check(dev, error);
-	if (status) {
-		if (clear_on_fail)
-			tm_hierarchy_free(p);
-
-		return status;
-	}
-
-	/* Create blueprints */
-	hierarchy_blueprints_create(dev);
-
-	/* Freeze hierarchy */
-	p->soft.tm.hierarchy_frozen = 1;
-
-	return 0;
-}
-
-static int
-update_pipe_weight(struct rte_eth_dev *dev, struct tm_node *np, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_ov_weight = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->weight = weight;
-
-	return 0;
-}
-
-static int
-update_queue_weight(struct rte_eth_dev *dev,
-	struct tm_node *nq, uint32_t weight)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	uint32_t pipe_be_queue_id =
-		queue_id - RTE_SCHED_TRAFFIC_CLASS_BE;
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.wrr_weights[pipe_be_queue_id] = (uint8_t)weight;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set
-	 * of pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nq->weight = weight;
-
-	return 0;
-}
-
-/* Traffic manager node parent update */
-static int
-pmd_tm_node_parent_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t parent_node_id,
-	uint32_t priority,
-	uint32_t weight,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Parent node must be the same */
-	if (n->parent_node_id != parent_node_id)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Priority must be the same */
-	if (n->priority != priority)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_PRIORITY,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* weight: must be 1 .. 255 */
-	if (weight == 0 || weight >= UINT8_MAX)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_WEIGHT,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		if (update_queue_weight(dev, n, weight))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-static int
-update_subport_rate(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_subport_profile_params *profile0 =
-					subport_profile_get(dev, ns);
-	struct rte_sched_subport_profile_params profile1;
-	uint32_t subport_profile_id;
-
-	if (profile0 == NULL)
-		return -1;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more subport profiles
-	 * after port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (subport_profile_exists(dev, &profile1, &subport_profile_id) == 0)
-		return -1;
-
-	/* Update the subport configuration. */
-	if (rte_sched_subport_config(SCHED(p), subport_id,
-		NULL, subport_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	ns->shaper_profile->n_users--;
-
-	ns->shaper_profile = sp;
-	ns->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	subport_profile_mark(dev, subport_id, subport_profile_id);
-
-	memcpy(&p->soft.tm.params.subport_profile[subport_profile_id],
-		&profile1,
-		sizeof(profile1));
-
-	return 0;
-}
-
-static int
-update_pipe_rate(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tb_rate = sp->params.peak.rate;
-	profile1.tb_size = sp->params.peak.size;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	np->shaper_profile->n_users--;
-	np->shaper_profile = sp;
-	np->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-static int
-update_tc_rate(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct tm_shaper_profile *sp)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	struct rte_sched_pipe_params *profile0 = pipe_profile_get(dev, np);
-	struct rte_sched_pipe_params profile1;
-	uint32_t pipe_profile_id;
-
-	/* Derive new pipe profile. */
-	memcpy(&profile1, profile0, sizeof(profile1));
-	profile1.tc_rate[tc_id] = sp->params.peak.rate;
-
-	/* Since implementation does not allow adding more pipe profiles after
-	 * port configuration, the pipe configuration can be successfully
-	 * updated only if the new profile is also part of the existing set of
-	 * pipe profiles.
-	 */
-	if (pipe_profile_exists(dev, &profile1, &pipe_profile_id) == 0)
-		return -1;
-
-	/* Update the pipe profile used by the current pipe. */
-	if (rte_sched_pipe_config(SCHED(p), subport_id, pipe_id,
-		(int32_t)pipe_profile_id))
-		return -1;
-
-	/* Commit changes. */
-	pipe_profile_mark(dev, subport_id, pipe_id, pipe_profile_id);
-	nt->shaper_profile->n_users--;
-	nt->shaper_profile = sp;
-	nt->params.shaper_profile_id = sp->shaper_profile_id;
-	sp->n_users++;
-
-	return 0;
-}
-
-/* Traffic manager node shaper update */
-static int
-pmd_tm_node_shaper_update(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	uint32_t shaper_profile_id,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-	struct tm_shaper_profile *sp;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	/* Shaper profile must be valid. */
-	sp = tm_shaper_profile_search(dev, shaper_profile_id);
-	if (sp == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_SHAPER_PROFILE,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-		/* fall-through */
-	case TM_NODE_LEVEL_SUBPORT:
-		if (update_subport_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_PIPE:
-		if (update_pipe_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_TC:
-		if (update_tc_rate(dev, n, sp))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-		/* fall-through */
-	case TM_NODE_LEVEL_QUEUE:
-		/* fall-through */
-	default:
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EINVAL));
-	}
-}
-
-static inline uint32_t
-tm_port_queue_id(struct rte_eth_dev *dev,
-	uint32_t port_subport_id,
-	uint32_t subport_pipe_id,
-	uint32_t pipe_tc_id,
-	uint32_t tc_queue_id)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] /
-			h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-
-	uint32_t port_pipe_id =
-		port_subport_id * n_pipes_per_subport + subport_pipe_id;
-
-	uint32_t port_queue_id =
-		port_pipe_id * RTE_SCHED_QUEUES_PER_PIPE + pipe_tc_id + tc_queue_id;
-
-	return port_queue_id;
-}
-
-static int
-read_port_stats(struct rte_eth_dev *dev,
-	struct tm_node *nr,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct tm_hierarchy *h = &p->soft.tm.h;
-	uint32_t n_subports_per_port = h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT];
-	uint32_t subport_id;
-
-	for (subport_id = 0; subport_id < n_subports_per_port; subport_id++) {
-		struct rte_sched_subport_stats s;
-		uint32_t tc_ov, id;
-
-		/* Stats read */
-		int status = rte_sched_subport_read_stats(SCHED(p),
-			subport_id,
-			&s,
-			&tc_ov);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		for (id = 0; id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; id++) {
-			nr->stats.n_pkts +=
-				s.n_pkts_tc[id] - s.n_pkts_tc_dropped[id];
-			nr->stats.n_bytes +=
-				s.n_bytes_tc[id] - s.n_bytes_tc_dropped[id];
-			nr->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_tc_dropped[id];
-			nr->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_tc_dropped[id];
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nr->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nr->stats, 0, sizeof(nr->stats));
-
-	return 0;
-}
-
-static int
-read_subport_stats(struct rte_eth_dev *dev,
-	struct tm_node *ns,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_subport_stats s;
-	uint32_t tc_ov, tc_id;
-
-	/* Stats read */
-	int status = rte_sched_subport_read_stats(SCHED(p),
-		subport_id,
-		&s,
-		&tc_ov);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	for (tc_id = 0; tc_id < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; tc_id++) {
-		ns->stats.n_pkts +=
-			s.n_pkts_tc[tc_id] - s.n_pkts_tc_dropped[tc_id];
-		ns->stats.n_bytes +=
-			s.n_bytes_tc[tc_id] - s.n_bytes_tc_dropped[tc_id];
-		ns->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-			s.n_pkts_tc_dropped[tc_id];
-		ns->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_tc_dropped[tc_id];
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &ns->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&ns->stats, 0, sizeof(ns->stats));
-
-	return 0;
-}
-
-static int
-read_pipe_stats(struct rte_eth_dev *dev,
-	struct tm_node *np,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	uint32_t tc_id, queue_id;
-	uint32_t i;
-
-	/* Stats read */
-	for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) {
-		struct rte_sched_queue_stats s;
-		uint16_t qlen;
-
-		if (i < RTE_SCHED_TRAFFIC_CLASS_BE) {
-			tc_id = i;
-			queue_id = i;
-		} else {
-			tc_id = RTE_SCHED_TRAFFIC_CLASS_BE;
-			queue_id = i - tc_id;
-		}
-
-		uint32_t qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			queue_id);
-
-		int status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		np->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		np->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		np->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		np->stats.leaf.n_pkts_queued = qlen;
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &np->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&np->stats, 0, sizeof(np->stats));
-
-	return 0;
-}
-
-static int
-read_tc_stats(struct rte_eth_dev *dev,
-	struct tm_node *nt,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-	struct rte_sched_queue_stats s;
-	uint32_t qid, i;
-	uint16_t qlen;
-	int status;
-
-	/* Stats read */
-	if (tc_id < RTE_SCHED_TRAFFIC_CLASS_BE) {
-		qid = tm_port_queue_id(dev,
-			subport_id,
-			pipe_id,
-			tc_id,
-			0);
-
-		status = rte_sched_queue_read_stats(SCHED(p),
-			qid,
-			&s,
-			&qlen);
-		if (status)
-			return status;
-
-		/* Stats accumulate */
-		nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-		nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-		nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-			s.n_bytes_dropped;
-		nt->stats.leaf.n_pkts_queued = qlen;
-	} else {
-		for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) {
-			qid = tm_port_queue_id(dev,
-				subport_id,
-				pipe_id,
-				tc_id,
-				i);
-
-			status = rte_sched_queue_read_stats(SCHED(p),
-				qid,
-				&s,
-				&qlen);
-			if (status)
-				return status;
-
-			/* Stats accumulate */
-			nt->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-			nt->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] +=
-				s.n_pkts_dropped;
-			nt->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-				s.n_bytes_dropped;
-			nt->stats.leaf.n_pkts_queued = qlen;
-		}
-	}
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nt->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_DEFAULT;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nt->stats, 0, sizeof(nt->stats));
-
-	return 0;
-}
-
-static int
-read_queue_stats(struct rte_eth_dev *dev,
-	struct tm_node *nq,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_sched_queue_stats s;
-	uint16_t qlen;
-
-	uint32_t queue_id = tm_node_queue_id(dev, nq);
-
-	struct tm_node *nt = nq->parent_node;
-	uint32_t tc_id = tm_node_tc_id(dev, nt);
-
-	struct tm_node *np = nt->parent_node;
-	uint32_t pipe_id = tm_node_pipe_id(dev, np);
-
-	struct tm_node *ns = np->parent_node;
-	uint32_t subport_id = tm_node_subport_id(dev, ns);
-
-	/* Stats read */
-	uint32_t qid = tm_port_queue_id(dev,
-		subport_id,
-		pipe_id,
-		tc_id,
-		queue_id);
-
-	int status = rte_sched_queue_read_stats(SCHED(p),
-		qid,
-		&s,
-		&qlen);
-	if (status)
-		return status;
-
-	/* Stats accumulate */
-	nq->stats.n_pkts += s.n_pkts - s.n_pkts_dropped;
-	nq->stats.n_bytes += s.n_bytes - s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_dropped[RTE_COLOR_GREEN] += s.n_pkts_dropped;
-	nq->stats.leaf.n_bytes_dropped[RTE_COLOR_GREEN] +=
-		s.n_bytes_dropped;
-	nq->stats.leaf.n_pkts_queued = qlen;
-
-	/* Stats copy */
-	if (stats)
-		memcpy(stats, &nq->stats, sizeof(*stats));
-
-	if (stats_mask)
-		*stats_mask = STATS_MASK_QUEUE;
-
-	/* Stats clear */
-	if (clear)
-		memset(&nq->stats, 0, sizeof(nq->stats));
-
-	return 0;
-}
-
-/* Traffic manager read stats counters for specific node */
-static int
-pmd_tm_node_stats_read(struct rte_eth_dev *dev,
-	uint32_t node_id,
-	struct rte_tm_node_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_tm_error *error)
-{
-	struct tm_node *n;
-
-	/* Port must be started and TM used. */
-	if (dev->data->dev_started == 0 && (tm_used(dev) == 0))
-		return -rte_tm_error_set(error,
-			EBUSY,
-			RTE_TM_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			rte_strerror(EBUSY));
-
-	/* Node must be valid */
-	n = tm_node_search(dev, node_id);
-	if (n == NULL)
-		return -rte_tm_error_set(error,
-			EINVAL,
-			RTE_TM_ERROR_TYPE_NODE_ID,
-			NULL,
-			rte_strerror(EINVAL));
-
-	switch (n->level) {
-	case TM_NODE_LEVEL_PORT:
-		if (read_port_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_SUBPORT:
-		if (read_subport_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_PIPE:
-		if (read_pipe_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_TC:
-		if (read_tc_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-
-	case TM_NODE_LEVEL_QUEUE:
-	default:
-		if (read_queue_stats(dev, n, stats, stats_mask, clear))
-			return -rte_tm_error_set(error,
-				EINVAL,
-				RTE_TM_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				rte_strerror(EINVAL));
-		return 0;
-	}
-}
-
-const struct rte_tm_ops pmd_tm_ops = {
-	.node_type_get = pmd_tm_node_type_get,
-	.capabilities_get = pmd_tm_capabilities_get,
-	.level_capabilities_get = pmd_tm_level_capabilities_get,
-	.node_capabilities_get = pmd_tm_node_capabilities_get,
-
-	.wred_profile_add = pmd_tm_wred_profile_add,
-	.wred_profile_delete = pmd_tm_wred_profile_delete,
-	.shared_wred_context_add_update = NULL,
-	.shared_wred_context_delete = NULL,
-
-	.shaper_profile_add = pmd_tm_shaper_profile_add,
-	.shaper_profile_delete = pmd_tm_shaper_profile_delete,
-	.shared_shaper_add_update = pmd_tm_shared_shaper_add_update,
-	.shared_shaper_delete = pmd_tm_shared_shaper_delete,
-
-	.node_add = pmd_tm_node_add,
-	.node_delete = pmd_tm_node_delete,
-	.node_suspend = NULL,
-	.node_resume = NULL,
-	.hierarchy_commit = pmd_tm_hierarchy_commit,
-
-	.node_parent_update = pmd_tm_node_parent_update,
-	.node_shaper_update = pmd_tm_node_shaper_update,
-	.node_shared_shaper_update = NULL,
-	.node_stats_update = NULL,
-	.node_wfq_weight_mode_update = NULL,
-	.node_cman_update = NULL,
-	.node_wred_context_update = NULL,
-	.node_shared_wred_context_update = NULL,
-
-	.node_stats_read = pmd_tm_node_stats_read,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 02/21] net/softnic: remove flow support
  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   ` Cristian Dumitrescu
  2022-11-30 11:18     ` Ferruh Yigit
  2022-09-01 14:20   ` [PATCH V3 03/21] net/softnic: remove the meter support Cristian Dumitrescu
                     ` (19 subsequent siblings)
  21 siblings, 1 reply; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device flow API support.

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      |    9 -
 drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -
 drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------
 4 files changed, 2384 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index e2dbd6166e..4ebe60921c 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -13,7 +13,6 @@ sources = files(
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_cryptodev.c',
-        'rte_eth_softnic_flow.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_meter.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index ae3e8b3bcd..8e361adbad 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -215,14 +215,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
-		 const struct rte_flow_ops **ops)
-{
-	*ops = &pmd_flow_ops;
-	return 0;
-}
-
 static int
 pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -240,7 +232,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.flow_ops_get = pmd_flow_ops_get,
 	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7556e50831..671f96cf77 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4731,81 +4731,6 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * flowapi map
- *  group <group_id>
- *  ingress | egress
- *  pipeline <pipeline_name>
- *  table <table_id>
- */
-static void
-cmd_softnic_flowapi_map(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t group_id, table_id;
-	int ingress, status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "map") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "map");
-		return;
-	}
-
-	if (strcmp(tokens[2], "group") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "ingress") == 0) {
-		ingress = 1;
-	} else if (strcmp(tokens[4], "egress") == 0) {
-		ingress = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ingress | egress");
-		return;
-	}
-
-	if (strcmp(tokens[5], "pipeline") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
-		return;
-	}
-
-	pipeline_name = tokens[6];
-
-	if (strcmp(tokens[7], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = flow_attr_map_set(softnic,
-			group_id,
-			ingress,
-			pipeline_name,
-			table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 void
 softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 {
@@ -5063,12 +4988,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		}
 	}
 
-	if (strcmp(tokens[0], "flowapi") == 0) {
-		cmd_softnic_flowapi_map(softnic, tokens, n_tokens, out,
-					out_size);
-		return;
-	}
-
 	snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
 }
 
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
deleted file mode 100644
index ad96288e7e..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ /dev/null
@@ -1,2293 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_common.h>
-#include <rte_byteorder.h>
-#include <rte_malloc.h>
-#include <rte_string_fns.h>
-#include <rte_flow.h>
-#include <rte_flow_driver.h>
-#include <rte_tailq.h>
-
-#include "rte_eth_softnic_internals.h"
-#include "rte_eth_softnic.h"
-
-#define rte_htons rte_cpu_to_be_16
-#define rte_htonl rte_cpu_to_be_32
-
-#define rte_ntohs rte_be_to_cpu_16
-#define rte_ntohl rte_be_to_cpu_32
-
-static struct rte_flow *
-softnic_flow_find(struct softnic_table *table,
-	struct softnic_table_rule_match *rule_match)
-{
-	struct rte_flow *flow;
-
-	TAILQ_FOREACH(flow, &table->flows, node)
-		if (memcmp(&flow->match, rule_match, sizeof(*rule_match)) == 0)
-			return flow;
-
-	return NULL;
-}
-
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id)
-{
-	struct pipeline *pipeline;
-	struct flow_attr_map *map;
-
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS ||
-			pipeline_name == NULL)
-		return -1;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL ||
-			table_id >= pipeline->n_tables)
-		return -1;
-
-	map = (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-	strlcpy(map->pipeline_name, pipeline_name, sizeof(map->pipeline_name));
-	map->table_id = table_id;
-	map->valid = 1;
-
-	return 0;
-}
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress)
-{
-	if (group_id >= SOFTNIC_FLOW_MAX_GROUPS)
-		return NULL;
-
-	return (ingress) ? &softnic->flow.ingress_map[group_id] :
-		&softnic->flow.egress_map[group_id];
-}
-
-static int
-flow_pipeline_table_get(struct pmd_internals *softnic,
-		const struct rte_flow_attr *attr,
-		const char **pipeline_name,
-		uint32_t *table_id,
-		struct rte_flow_error *error)
-{
-	struct flow_attr_map *map;
-
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL,
-				"Null attr");
-
-	if (!attr->ingress && !attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Ingress/egress not specified");
-
-	if (attr->ingress && attr->egress)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr,
-				"Setting both ingress and egress is not allowed");
-
-	map = flow_attr_map_get(softnic,
-			attr->group,
-			attr->ingress);
-	if (map == NULL ||
-			map->valid == 0)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
-				attr,
-				"Invalid group ID");
-
-	if (pipeline_name)
-		*pipeline_name = map->pipeline_name;
-
-	if (table_id)
-		*table_id = map->table_id;
-
-	return 0;
-}
-
-union flow_item {
-	uint8_t raw[TABLE_RULE_MATCH_SIZE_MAX];
-	struct rte_flow_item_eth eth;
-	struct rte_flow_item_vlan vlan;
-	struct rte_flow_item_ipv4 ipv4;
-	struct rte_flow_item_ipv6 ipv6;
-	struct rte_flow_item_icmp icmp;
-	struct rte_flow_item_udp udp;
-	struct rte_flow_item_tcp tcp;
-	struct rte_flow_item_sctp sctp;
-	struct rte_flow_item_vxlan vxlan;
-	struct rte_flow_item_e_tag e_tag;
-	struct rte_flow_item_nvgre nvgre;
-	struct rte_flow_item_mpls mpls;
-	struct rte_flow_item_gre gre;
-	struct rte_flow_item_gtp gtp;
-	struct rte_flow_item_esp esp;
-	struct rte_flow_item_geneve geneve;
-	struct rte_flow_item_vxlan_gpe vxlan_gpe;
-	struct rte_flow_item_arp_eth_ipv4 arp_eth_ipv4;
-	struct rte_flow_item_ipv6_ext ipv6_ext;
-	struct rte_flow_item_icmp6 icmp6;
-	struct rte_flow_item_icmp6_nd_ns icmp6_nd_ns;
-	struct rte_flow_item_icmp6_nd_na icmp6_nd_na;
-	struct rte_flow_item_icmp6_nd_opt icmp6_nd_opt;
-	struct rte_flow_item_icmp6_nd_opt_sla_eth icmp6_nd_opt_sla_eth;
-	struct rte_flow_item_icmp6_nd_opt_tla_eth icmp6_nd_opt_tla_eth;
-};
-
-static const union flow_item flow_item_raw_mask;
-
-static int
-flow_item_is_proto(enum rte_flow_item_type type,
-	const void **mask,
-	size_t *size)
-{
-	switch (type) {
-	case RTE_FLOW_ITEM_TYPE_RAW:
-		*mask = &flow_item_raw_mask;
-		*size = sizeof(flow_item_raw_mask);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_ETH:
-		*mask = &rte_flow_item_eth_mask;
-		*size = sizeof(struct rte_ether_hdr);
-		return 1; /* TRUE */
-
-	case RTE_FLOW_ITEM_TYPE_VLAN:
-		*mask = &rte_flow_item_vlan_mask;
-		*size = sizeof(struct rte_vlan_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-		*mask = &rte_flow_item_ipv4_mask;
-		*size = sizeof(struct rte_ipv4_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-		*mask = &rte_flow_item_ipv6_mask;
-		*size = sizeof(struct rte_ipv6_hdr);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP:
-		*mask = &rte_flow_item_icmp_mask;
-		*size = sizeof(struct rte_flow_item_icmp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-		*mask = &rte_flow_item_udp_mask;
-		*size = sizeof(struct rte_flow_item_udp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_TCP:
-		*mask = &rte_flow_item_tcp_mask;
-		*size = sizeof(struct rte_flow_item_tcp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-		*mask = &rte_flow_item_sctp_mask;
-		*size = sizeof(struct rte_flow_item_sctp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN:
-		*mask = &rte_flow_item_vxlan_mask;
-		*size = sizeof(struct rte_flow_item_vxlan);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_E_TAG:
-		*mask = &rte_flow_item_e_tag_mask;
-		*size = sizeof(struct rte_flow_item_e_tag);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_NVGRE:
-		*mask = &rte_flow_item_nvgre_mask;
-		*size = sizeof(struct rte_flow_item_nvgre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_MPLS:
-		*mask = &rte_flow_item_mpls_mask;
-		*size = sizeof(struct rte_flow_item_mpls);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GRE:
-		*mask = &rte_flow_item_gre_mask;
-		*size = sizeof(struct rte_flow_item_gre);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GTP:
-	case RTE_FLOW_ITEM_TYPE_GTPC:
-	case RTE_FLOW_ITEM_TYPE_GTPU:
-		*mask = &rte_flow_item_gtp_mask;
-		*size = sizeof(struct rte_flow_item_gtp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ESP:
-		*mask = &rte_flow_item_esp_mask;
-		*size = sizeof(struct rte_flow_item_esp);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_GENEVE:
-		*mask = &rte_flow_item_geneve_mask;
-		*size = sizeof(struct rte_flow_item_geneve);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
-		*mask = &rte_flow_item_vxlan_gpe_mask;
-		*size = sizeof(struct rte_flow_item_vxlan_gpe);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4:
-		*mask = &rte_flow_item_arp_eth_ipv4_mask;
-		*size = sizeof(struct rte_flow_item_arp_eth_ipv4);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_IPV6_EXT:
-		*mask = &rte_flow_item_ipv6_ext_mask;
-		*size = sizeof(struct rte_flow_item_ipv6_ext);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6:
-		*mask = &rte_flow_item_icmp6_mask;
-		*size = sizeof(struct rte_flow_item_icmp6);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS:
-		*mask = &rte_flow_item_icmp6_nd_ns_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_ns);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA:
-		*mask = &rte_flow_item_icmp6_nd_na_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_na);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT:
-		*mask = &rte_flow_item_icmp6_nd_opt_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_sla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth);
-		return 1;
-
-	case RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH:
-		*mask = &rte_flow_item_icmp6_nd_opt_tla_eth_mask;
-		*size = sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth);
-		return 1;
-
-	default: return 0; /* FALSE */
-	}
-}
-
-static int
-flow_item_raw_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const struct rte_flow_item_raw *item_raw_spec = item->spec;
-	const struct rte_flow_item_raw *item_raw_mask = item->mask;
-	const uint8_t *pattern;
-	const uint8_t *pattern_mask;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t pattern_length, pattern_offset, i;
-	int disabled;
-
-	if (!item->spec)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Null specification");
-
-	if (item->last)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Range not allowed (last must be NULL)");
-
-	if (item_raw_spec->relative == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Absolute offset not supported");
-
-	if (item_raw_spec->search)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Search not supported");
-
-	if (item_raw_spec->offset < 0)
-		return rte_flow_error_set(error,
-			ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Negative offset not supported");
-
-	if (item_raw_spec->length == 0)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Zero pattern length");
-
-	if (item_raw_spec->offset + item_raw_spec->length >
-		TABLE_RULE_MATCH_SIZE_MAX)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Item too big");
-
-	if (!item_raw_spec->pattern && item_raw_mask && item_raw_mask->pattern)
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"RAW: Non-NULL pattern mask not allowed with NULL pattern");
-
-	pattern = item_raw_spec->pattern;
-	pattern_mask = (item_raw_mask) ? item_raw_mask->pattern : NULL;
-	pattern_length = (size_t)item_raw_spec->length;
-	pattern_offset = (size_t)item_raw_spec->offset;
-
-	disabled = 0;
-	if (pattern_mask == NULL)
-		disabled = 1;
-	else
-		for (i = 0; i < pattern_length; i++)
-			if ((pattern)[i])
-				disabled = 1;
-
-	memset(spec, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern)
-		memcpy(&spec[pattern_offset], pattern, pattern_length);
-
-	memset(mask, 0, TABLE_RULE_MATCH_SIZE_MAX);
-	if (pattern_mask)
-		memcpy(&mask[pattern_offset], pattern_mask, pattern_length);
-
-	*item_size = pattern_offset + pattern_length;
-	*item_disabled = disabled;
-
-	return 0;
-}
-
-static int
-flow_item_proto_preprocess(const struct rte_flow_item *item,
-	union flow_item *item_spec,
-	union flow_item *item_mask,
-	size_t *item_size,
-	int *item_disabled,
-	struct rte_flow_error *error)
-{
-	const void *mask_default;
-	uint8_t *spec = (uint8_t *)item_spec;
-	uint8_t *mask = (uint8_t *)item_mask;
-	size_t size, i;
-
-	if (!flow_item_is_proto(item->type, &mask_default, &size))
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"Item type not supported");
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_RAW)
-		return flow_item_raw_preprocess(item,
-			item_spec,
-			item_mask,
-			item_size,
-			item_disabled,
-			error);
-
-	/* spec */
-	if (!item->spec) {
-		/* If spec is NULL, then last and mask also have to be NULL. */
-		if (item->last || item->mask)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"Invalid item (NULL spec with non-NULL last or mask)");
-
-		memset(item_spec, 0, size);
-		memset(item_mask, 0, size);
-		*item_size = size;
-		*item_disabled = 1; /* TRUE */
-		return 0;
-	}
-
-	memcpy(spec, item->spec, size);
-	*item_size = size;
-
-	/* mask */
-	if (item->mask)
-		memcpy(mask, item->mask, size);
-	else
-		memcpy(mask, mask_default, size);
-
-	/* disabled */
-	for (i = 0; i < size; i++)
-		if (mask[i])
-			break;
-	*item_disabled = (i == size) ? 1 : 0;
-
-	/* Apply mask over spec. */
-	for (i = 0; i < size; i++)
-		spec[i] &= mask[i];
-
-	/* last */
-	if (item->last) {
-		uint8_t last[size];
-
-		/* init last */
-		memcpy(last, item->last, size);
-		for (i = 0; i < size; i++)
-			last[i] &= mask[i];
-
-		/* check for range */
-		for (i = 0; i < size; i++)
-			if (last[i] != spec[i])
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"Range not supported");
-	}
-
-	return 0;
-}
-
-/***
- * Skip disabled protocol items and VOID items
- * until any of the mutually exclusive conditions
- * from the list below takes place:
- *    (A) A protocol present in the proto_mask
- *        is met (either ENABLED or DISABLED);
- *    (B) A protocol NOT present in the proto_mask is met in ENABLED state;
- *    (C) The END item is met.
- */
-static int
-flow_item_skip_disabled_protos(const struct rte_flow_item **item,
-	uint64_t proto_mask,
-	size_t *length,
-	struct rte_flow_error *error)
-{
-	size_t len = 0;
-
-	for ( ; (*item)->type != RTE_FLOW_ITEM_TYPE_END; (*item)++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled = 0, status;
-
-		if ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(*item,
-				&spec,
-				&mask,
-				&size,
-				&disabled,
-				error);
-		if (status)
-			return status;
-
-		if ((proto_mask & (1LLU << (*item)->type)) ||
-				!disabled)
-			break;
-
-		len += size;
-	}
-
-	if (length)
-		*length = len;
-
-	return 0;
-}
-
-#define FLOW_ITEM_PROTO_IP \
-	((1LLU << RTE_FLOW_ITEM_TYPE_IPV4) | \
-	 (1LLU << RTE_FLOW_ITEM_TYPE_IPV6))
-
-static void
-flow_item_skip_void(const struct rte_flow_item **item)
-{
-	for ( ; ; (*item)++)
-		if ((*item)->type != RTE_FLOW_ITEM_TYPE_VOID)
-			return;
-}
-
-#define IP_PROTOCOL_TCP 0x06
-#define IP_PROTOCOL_UDP 0x11
-#define IP_PROTOCOL_SCTP 0x84
-
-static int
-mask_to_depth(uint64_t mask,
-		uint32_t *depth)
-{
-	uint64_t n;
-
-	if (mask == UINT64_MAX) {
-		if (depth)
-			*depth = 64;
-
-		return 0;
-	}
-
-	mask = ~mask;
-
-	if (mask & (mask + 1))
-		return -1;
-
-	n = __builtin_popcountll(mask);
-	if (depth)
-		*depth = (uint32_t)(64 - n);
-
-	return 0;
-}
-
-static int
-ipv4_mask_to_depth(uint32_t mask,
-		uint32_t *depth)
-{
-	uint32_t d;
-	int status;
-
-	status = mask_to_depth(mask | (UINT64_MAX << 32), &d);
-	if (status)
-		return status;
-
-	d -= 32;
-	if (depth)
-		*depth = d;
-
-	return 0;
-}
-
-static int
-ipv6_mask_to_depth(uint8_t *mask,
-	uint32_t *depth)
-{
-	uint64_t *m = (uint64_t *)mask;
-	uint64_t m0 = rte_be_to_cpu_64(m[0]);
-	uint64_t m1 = rte_be_to_cpu_64(m[1]);
-	uint32_t d0, d1;
-	int status;
-
-	status = mask_to_depth(m0, &d0);
-	if (status)
-		return status;
-
-	status = mask_to_depth(m1, &d1);
-	if (status)
-		return status;
-
-	if (d0 < 64 && d1)
-		return -1;
-
-	if (depth)
-		*depth = d0 + d1;
-
-	return 0;
-}
-
-static int
-port_mask_to_range(uint16_t port,
-	uint16_t port_mask,
-	uint16_t *port0,
-	uint16_t *port1)
-{
-	int status;
-	uint16_t p0, p1;
-
-	status = mask_to_depth(port_mask | (UINT64_MAX << 16), NULL);
-	if (status)
-		return -1;
-
-	p0 = port & port_mask;
-	p1 = p0 | ~port_mask;
-
-	if (port0)
-		*port0 = p0;
-
-	if (port1)
-		*port1 = p1;
-
-	return 0;
-}
-
-static int
-flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
-		struct pipeline *pipeline __rte_unused,
-		struct softnic_table *table __rte_unused,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	union flow_item spec, mask;
-	size_t size, length = 0;
-	int disabled = 0, status;
-	uint8_t ip_proto, ip_proto_mask;
-
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_ACL;
-	rule_match->match.acl.priority = attr->priority;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item,
-			FLOW_ITEM_PROTO_IP, &length, error);
-	if (status)
-		return status;
-
-	/* IP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_IPV4:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.src_addr),
-				&sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header source address mask");
-
-		status = ipv4_mask_to_depth(rte_ntohl(mask.ipv4.hdr.dst_addr),
-				&da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv4 header destination address mask");
-
-		ip_proto = spec.ipv4.hdr.next_proto_id;
-		ip_proto_mask = mask.ipv4.hdr.next_proto_id;
-
-		rule_match->match.acl.ip_version = 1;
-		rule_match->match.acl.ipv4.sa =
-			rte_ntohl(spec.ipv4.hdr.src_addr);
-		rule_match->match.acl.ipv4.da =
-			rte_ntohl(spec.ipv4.hdr.dst_addr);
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV4 */
-
-	case RTE_FLOW_ITEM_TYPE_IPV6:
-	{
-		uint32_t sa_depth, da_depth;
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.src_addr, &sa_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header source address mask");
-
-		status = ipv6_mask_to_depth(mask.ipv6.hdr.dst_addr, &da_depth);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal IPv6 header destination address mask");
-
-		ip_proto = spec.ipv6.hdr.proto;
-		ip_proto_mask = mask.ipv6.hdr.proto;
-
-		rule_match->match.acl.ip_version = 0;
-		memcpy(rule_match->match.acl.ipv6.sa,
-			spec.ipv6.hdr.src_addr,
-			sizeof(spec.ipv6.hdr.src_addr));
-		memcpy(rule_match->match.acl.ipv6.da,
-			spec.ipv6.hdr.dst_addr,
-			sizeof(spec.ipv6.hdr.dst_addr));
-		rule_match->match.acl.sa_depth = sa_depth;
-		rule_match->match.acl.da_depth = da_depth;
-		rule_match->match.acl.proto = ip_proto;
-		rule_match->match.acl.proto_mask = ip_proto_mask;
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_IPV6 */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: IP protocol required");
-	} /* switch */
-
-	if (ip_proto_mask != UINT8_MAX)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Illegal IP protocol mask");
-
-	item++;
-
-	/* VOID only, if any. */
-	flow_item_skip_void(&item);
-
-	/* TCP/UDP/SCTP only. */
-	status = flow_item_proto_preprocess(item, &spec, &mask,
-			&size, &disabled, error);
-	if (status)
-		return status;
-
-	switch (item->type) {
-	case RTE_FLOW_ITEM_TYPE_TCP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_TCP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is TCP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.src_port),
-				rte_ntohs(mask.tcp.hdr.src_port),
-				&sp0,
-				&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.tcp.hdr.dst_port),
-				rte_ntohs(mask.tcp.hdr.dst_port),
-				&dp0,
-				&dp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal TCP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_TCP */
-
-	case RTE_FLOW_ITEM_TYPE_UDP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_UDP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is UDP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.src_port),
-			rte_ntohs(mask.udp.hdr.src_port),
-			&sp0,
-			&sp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.udp.hdr.dst_port),
-			rte_ntohs(mask.udp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal UDP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_UDP */
-
-	case RTE_FLOW_ITEM_TYPE_SCTP:
-	{
-		uint16_t sp0, sp1, dp0, dp1;
-
-		if (ip_proto != IP_PROTOCOL_SCTP)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Item type is SCTP, but IP protocol is not");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.src_port),
-			rte_ntohs(mask.sctp.hdr.src_port),
-			&sp0,
-			&sp1);
-
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP source port mask");
-
-		status = port_mask_to_range(rte_ntohs(spec.sctp.hdr.dst_port),
-			rte_ntohs(mask.sctp.hdr.dst_port),
-			&dp0,
-			&dp1);
-		if (status)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"ACL: Illegal SCTP destination port mask");
-
-		rule_match->match.acl.sp0 = sp0;
-		rule_match->match.acl.sp1 = sp1;
-		rule_match->match.acl.dp0 = dp0;
-		rule_match->match.acl.dp1 = dp1;
-
-		break;
-	} /* RTE_FLOW_ITEM_TYPE_SCTP */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: TCP/UDP/SCTP required");
-	} /* switch */
-
-	item++;
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-	if (status)
-		return status;
-
-	/* END only. */
-	if (item->type != RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"ACL: Expecting END item");
-
-	return 0;
-}
-
-/***
- * Both *tmask* and *fmask* are byte arrays of size *tsize* and *fsize*
- * respectively.
- * They are located within a larger buffer at offsets *toffset* and *foffset*
- * respectively. Both *tmask* and *fmask* represent bitmasks for the larger
- * buffer.
- * Question: are the two masks equivalent?
- *
- * Notes:
- * 1. Offset basically indicates that the first offset bytes in the buffer
- *    are "don't care", so offset is equivalent to pre-pending an "all-zeros"
- *    array of *offset* bytes to the *mask*.
- * 2. Each *mask* might contain a number of zero bytes at the beginning or
- *    at the end.
- * 3. Bytes in the larger buffer after the end of the *mask* are also considered
- *    "don't care", so they are equivalent to appending an "all-zeros" array of
- *    bytes to the *mask*.
- *
- * Example:
- * Buffer = [xx xx xx xx xx xx xx xx], buffer size = 8 bytes
- * tmask = [00 22 00 33 00], toffset = 2, tsize = 5
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * fmask = [22 00 33], foffset = 3, fsize = 3 =>
- *    => buffer mask = [00 00 00 22 00 33 00 00]
- * Therefore, the tmask and fmask from this example are equivalent.
- */
-static int
-hash_key_mask_is_same(uint8_t *tmask,
-	size_t toffset,
-	size_t tsize,
-	uint8_t *fmask,
-	size_t foffset,
-	size_t fsize,
-	size_t *toffset_plus,
-	size_t *foffset_plus)
-{
-	size_t tpos; /* Position of first non-zero byte in the tmask buffer. */
-	size_t fpos; /* Position of first non-zero byte in the fmask buffer. */
-
-	/* Compute tpos and fpos. */
-	for (tpos = 0; tmask[tpos] == 0; tpos++)
-		;
-	for (fpos = 0; fmask[fpos] == 0; fpos++)
-		;
-
-	if (toffset + tpos != foffset + fpos)
-		return 0; /* FALSE */
-
-	tsize -= tpos;
-	fsize -= fpos;
-
-	if (tsize < fsize) {
-		size_t i;
-
-		for (i = 0; i < tsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < fsize; i++)
-			if (fmask[fpos + i])
-				return 0; /* FALSE */
-	} else {
-		size_t i;
-
-		for (i = 0; i < fsize; i++)
-			if (tmask[tpos + i] != fmask[fpos + i])
-				return 0; /* FALSE */
-
-		for ( ; i < tsize; i++)
-			if (tmask[tpos + i])
-				return 0; /* FALSE */
-	}
-
-	if (toffset_plus)
-		*toffset_plus = tpos;
-
-	if (foffset_plus)
-		*foffset_plus = fpos;
-
-	return 1; /* TRUE */
-}
-
-static int
-flow_rule_match_hash_get(struct pmd_internals *softnic __rte_unused,
-	struct pipeline *pipeline __rte_unused,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr __rte_unused,
-	const struct rte_flow_item *item,
-	struct softnic_table_rule_match *rule_match,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match_hash key, key_mask;
-	struct softnic_table_hash_params *params = &table->params.match.hash;
-	size_t offset = 0, length = 0, tpos, fpos;
-	int status;
-
-	memset(&key, 0, sizeof(key));
-	memset(&key_mask, 0, sizeof(key_mask));
-
-	/* VOID or disabled protos only, if any. */
-	status = flow_item_skip_disabled_protos(&item, 0, &offset, error);
-	if (status)
-		return status;
-
-	if (item->type == RTE_FLOW_ITEM_TYPE_END)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			item,
-			"HASH: END detected too early");
-
-	/* VOID or any protocols (enabled or disabled). */
-	for ( ; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
-		union flow_item spec, mask;
-		size_t size;
-		int disabled, status;
-
-		if (item->type == RTE_FLOW_ITEM_TYPE_VOID)
-			continue;
-
-		status = flow_item_proto_preprocess(item,
-			&spec,
-			&mask,
-			&size,
-			&disabled,
-			error);
-		if (status)
-			return status;
-
-		if (length + size > sizeof(key)) {
-			if (disabled)
-				break;
-
-			return rte_flow_error_set(error,
-				ENOTSUP,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Item too big");
-		}
-
-		memcpy(&key.key[length], &spec, size);
-		memcpy(&key_mask.key[length], &mask, size);
-		length += size;
-	}
-
-	if (item->type != RTE_FLOW_ITEM_TYPE_END) {
-		/* VOID or disabled protos only, if any. */
-		status = flow_item_skip_disabled_protos(&item, 0, NULL, error);
-		if (status)
-			return status;
-
-		/* END only. */
-		if (item->type != RTE_FLOW_ITEM_TYPE_END)
-			return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				item,
-				"HASH: Expecting END item");
-	}
-
-	/* Compare flow key mask against table key mask. */
-	offset += sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM;
-
-	if (!hash_key_mask_is_same(params->key_mask,
-		params->key_offset,
-		params->key_size,
-		key_mask.key,
-		offset,
-		length,
-		&tpos,
-		&fpos))
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"HASH: Item list is not observing the match format");
-
-	/* Rule match. */
-	memset(rule_match, 0, sizeof(*rule_match));
-	rule_match->match_type = TABLE_HASH;
-	memcpy(&rule_match->match.hash.key[tpos],
-		&key.key[fpos],
-		RTE_MIN(sizeof(rule_match->match.hash.key) - tpos,
-			length - fpos));
-
-	return 0;
-}
-
-static int
-flow_rule_match_get(struct pmd_internals *softnic,
-		struct pipeline *pipeline,
-		struct softnic_table *table,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item *item,
-		struct softnic_table_rule_match *rule_match,
-		struct rte_flow_error *error)
-{
-	switch (table->params.match_type) {
-	case TABLE_ACL:
-		return flow_rule_match_acl_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	case TABLE_HASH:
-		return flow_rule_match_hash_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			rule_match,
-			error);
-
-		/* FALLTHROUGH */
-
-	default:
-		return rte_flow_error_set(error,
-			ENOTSUP,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Unsupported pipeline table match type");
-	}
-}
-
-static int
-flow_rule_action_get(struct pmd_internals *softnic,
-	struct pipeline *pipeline,
-	struct softnic_table *table,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_action *action,
-	struct softnic_table_rule_action *rule_action,
-	struct rte_flow_error *error)
-{
-	struct softnic_table_action_profile *profile;
-	struct softnic_table_action_profile_params *params;
-	struct softnic_mtr_meter_policy *policy;
-	int n_jump_queue_rss_drop = 0;
-	int n_count = 0;
-	int n_mark = 0;
-	int n_vxlan_decap = 0;
-
-	profile = softnic_table_action_profile_find(softnic,
-		table->params.action_profile_name);
-	if (profile == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			action,
-			"JUMP: Table action profile");
-
-	params = &profile->params;
-
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
-		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
-			continue;
-
-		switch (action->type) {
-		case RTE_FLOW_ACTION_TYPE_JUMP:
-		{
-			const struct rte_flow_action_jump *conf = action->conf;
-			struct flow_attr_map *map;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"JUMP: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is"
-					" allowed per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			map = flow_attr_map_get(softnic,
-				conf->group,
-				attr->ingress);
-			if (map == NULL || map->valid == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Invalid group mapping");
-
-			if (strcmp(pipeline->name, map->pipeline_name) != 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"JUMP: Jump to table in different pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-			rule_action->fwd.id = map->table_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_JUMP */
-
-		case RTE_FLOW_ACTION_TYPE_QUEUE:
-		{
-			char name[NAME_SIZE];
-			struct rte_eth_dev *dev;
-			const struct rte_flow_action_queue *conf = action->conf;
-			uint32_t port_id;
-			int status;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Null configuration");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed"
-					" per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"QUEUE action not enabled for this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			dev = ETHDEV(softnic);
-			if (dev == NULL ||
-				conf->index >= dev->data->nb_rx_queues)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: Invalid RX queue ID");
-
-			snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->index);
-
-			status = softnic_pipeline_port_out_find(softnic,
-				pipeline->name,
-				name,
-				&port_id);
-			if (status)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"QUEUE: RX queue not accessible from this pipeline");
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT;
-			rule_action->fwd.id = port_id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /*RTE_FLOW_ACTION_TYPE_QUEUE */
-
-		case RTE_FLOW_ACTION_TYPE_RSS:
-		{
-			const struct rte_flow_action_rss *conf = action->conf;
-			uint32_t i;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"RSS: Null configuration");
-
-			if (!rte_is_power_of_2(conf->queue_num))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues must be a power of 2");
-
-			if (conf->queue_num > RTE_DIM(rule_action->lb.out))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					conf,
-					"RSS: Number of queues too big");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-
-			if (((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0) ||
-				((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_LB)) == 0))
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this table");
-
-			if (params->lb.out_offset !=
-				pipeline->params.offset_port_id)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"RSS action not supported by this pipeline");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_LB */
-			for (i = 0; i < conf->queue_num; i++) {
-				char name[NAME_SIZE];
-				struct rte_eth_dev *dev;
-				uint32_t port_id;
-				int status;
-
-				dev = ETHDEV(softnic);
-				if (dev == NULL ||
-					conf->queue[i] >=
-						dev->data->nb_rx_queues)
-					return rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: Invalid RX queue ID");
-
-				snprintf(name, sizeof(name), "RXQ%u",
-					(uint32_t)conf->queue[i]);
-
-				status = softnic_pipeline_port_out_find(softnic,
-					pipeline->name,
-					name,
-					&port_id);
-				if (status)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ACTION,
-						action,
-						"RSS: RX queue not accessible from this pipeline");
-
-				rule_action->lb.out[i] = port_id;
-			}
-
-			for ( ; i < RTE_DIM(rule_action->lb.out); i++)
-				rule_action->lb.out[i] =
-				rule_action->lb.out[i % conf->queue_num];
-
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_RSS */
-
-		case RTE_FLOW_ACTION_TYPE_DROP:
-		{
-			const void *conf = action->conf;
-
-			if (conf != NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"DROP: No configuration required");
-
-			if (n_jump_queue_rss_drop)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one termination action is allowed per flow");
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_FWD)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"DROP action not supported by this table");
-
-			n_jump_queue_rss_drop = 1;
-
-			/* RTE_TABLE_ACTION_FWD */
-			rule_action->fwd.action = RTE_PIPELINE_ACTION_DROP;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_DROP */
-
-		case RTE_FLOW_ACTION_TYPE_COUNT:
-		{
-			const struct rte_flow_action_count *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"COUNT: Null configuration");
-
-			if (n_count)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one COUNT action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_STATS)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"COUNT action not supported by this table");
-
-			n_count = 1;
-
-			/* RTE_TABLE_ACTION_STATS */
-			rule_action->stats.n_packets = 0;
-			rule_action->stats.n_bytes = 0;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_COUNT */
-
-		case RTE_FLOW_ACTION_TYPE_MARK:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"MARK: Null configuration");
-
-			if (n_mark)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one MARK action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_TAG)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"MARK action not supported by this table");
-
-			n_mark = 1;
-
-			/* RTE_TABLE_ACTION_TAG */
-			rule_action->tag.tag = conf->id;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_MARK */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
-		{
-			const struct rte_flow_action_mark *conf = action->conf;
-
-			if (conf)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN DECAP: Non-null configuration");
-
-			if (n_vxlan_decap)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"Only one VXLAN DECAP action per flow");
-
-			if ((params->action_mask &
-				(1LLU << RTE_TABLE_ACTION_DECAP)) == 0)
-				return rte_flow_error_set(error,
-					ENOTSUP,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN DECAP action not supported by this table");
-
-			n_vxlan_decap = 1;
-
-			/* RTE_TABLE_ACTION_DECAP */
-			rule_action->decap.n = 50; /* Ether/IPv4/UDP/VXLAN */
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_DECAP */
-
-		case RTE_FLOW_ACTION_TYPE_METER:
-		{
-			const struct rte_flow_action_meter *conf = action->conf;
-			struct softnic_mtr_meter_profile *mp;
-			struct softnic_mtr *m;
-			uint32_t table_id = table - pipeline->table;
-			uint32_t meter_profile_id;
-			int status;
-
-			if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) == 0)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Table action not supported");
-
-			if (params->mtr.n_tc != 1)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"METER: Multiple TCs not supported");
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"METER: Null configuration");
-
-			m = softnic_mtr_find(softnic, conf->mtr_id);
-
-			if (m == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Invalid meter ID");
-
-			if (m->flow)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
-					NULL,
-					"METER: Meter already attached to a flow");
-
-			meter_profile_id = m->params.meter_profile_id;
-			mp = softnic_mtr_meter_profile_find(softnic, meter_profile_id);
-
-			/* Add meter profile to pipeline table */
-			if (!softnic_pipeline_table_meter_profile_find(table,
-					meter_profile_id)) {
-				struct rte_table_action_meter_profile profile;
-
-				memset(&profile, 0, sizeof(profile));
-				profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-				profile.trtcm.cir = mp->params.trtcm_rfc2698.cir;
-				profile.trtcm.pir = mp->params.trtcm_rfc2698.pir;
-				profile.trtcm.cbs = mp->params.trtcm_rfc2698.cbs;
-				profile.trtcm.pbs = mp->params.trtcm_rfc2698.pbs;
-
-				status = softnic_pipeline_table_mtr_profile_add(softnic,
-						pipeline->name,
-						table_id,
-						meter_profile_id,
-						&profile);
-				if (status) {
-					rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: Table meter profile add failed");
-					return -1;
-				}
-			}
-			/* Meter policy must exist */
-			policy = softnic_mtr_meter_policy_find(softnic,
-					m->params.meter_policy_id);
-			if (policy == NULL) {
-				rte_flow_error_set(error,
-						EINVAL,
-						RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-						NULL,
-						"METER: fail to find meter policy");
-				return -1;
-			}
-			/* RTE_TABLE_ACTION_METER */
-			rule_action->mtr.mtr[0].meter_profile_id = meter_profile_id;
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_GREEN] =
-				policy->policer[RTE_COLOR_GREEN];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_YELLOW] =
-				policy->policer[RTE_COLOR_YELLOW];
-			rule_action->mtr.mtr[0].policer[RTE_COLOR_RED] =
-				policy->policer[RTE_COLOR_RED];
-			rule_action->mtr.tc_mask = 1;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_METER */
-
-		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
-		{
-			const struct rte_flow_action_vxlan_encap *conf =
-				action->conf;
-			const struct rte_flow_item *item;
-			union flow_item spec, mask;
-			int disabled = 0, status;
-			size_t size;
-
-			if (conf == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration");
-
-			item = conf->definition;
-			if (item == NULL)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ACTION,
-					action,
-					"VXLAN ENCAP: Null configuration definition");
-
-			if (!(params->action_mask &
-					(1LLU << RTE_TABLE_ACTION_ENCAP)))
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"VXLAN ENCAP: Encap action not enabled for this table");
-
-			/* Check for Ether. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-				&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: first encap item should be ether");
-			}
-			rte_ether_addr_copy(&spec.eth.dst,
-					&rule_action->encap.vxlan.ether.da);
-			rte_ether_addr_copy(&spec.eth.src,
-					&rule_action->encap.vxlan.ether.sa);
-
-			item++;
-
-			/* Check for VLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type == RTE_FLOW_ITEM_TYPE_VLAN) {
-				if (!params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: vlan encap not supported by table");
-
-				uint16_t tci = rte_ntohs(spec.vlan.tci);
-				rule_action->encap.vxlan.vlan.pcp =
-					tci >> 13;
-				rule_action->encap.vxlan.vlan.dei =
-					(tci >> 12) & 0x1;
-				rule_action->encap.vxlan.vlan.vid =
-					tci & 0xfff;
-
-				item++;
-
-				flow_item_skip_void(&item);
-				status = flow_item_proto_preprocess(item, &spec,
-						&mask, &size, &disabled, error);
-				if (status)
-					return status;
-			} else {
-				if (params->encap.vxlan.vlan)
-					return rte_flow_error_set(error,
-						ENOTSUP,
-						RTE_FLOW_ERROR_TYPE_ITEM,
-						item,
-						"VXLAN ENCAP: expecting vlan encap item");
-			}
-
-			/* Check for IPV4/IPV6. */
-			switch (item->type) {
-			case RTE_FLOW_ITEM_TYPE_IPV4:
-			{
-				rule_action->encap.vxlan.ipv4.sa =
-					rte_ntohl(spec.ipv4.hdr.src_addr);
-				rule_action->encap.vxlan.ipv4.da =
-					rte_ntohl(spec.ipv4.hdr.dst_addr);
-				rule_action->encap.vxlan.ipv4.dscp =
-					spec.ipv4.hdr.type_of_service >> 2;
-				rule_action->encap.vxlan.ipv4.ttl =
-					spec.ipv4.hdr.time_to_live;
-				break;
-			}
-			case RTE_FLOW_ITEM_TYPE_IPV6:
-			{
-				uint32_t vtc_flow;
-
-				memcpy(&rule_action->encap.vxlan.ipv6.sa,
-						&spec.ipv6.hdr.src_addr,
-						sizeof(spec.ipv6.hdr.src_addr));
-				memcpy(&rule_action->encap.vxlan.ipv6.da,
-						&spec.ipv6.hdr.dst_addr,
-						sizeof(spec.ipv6.hdr.dst_addr));
-				vtc_flow = rte_ntohl(spec.ipv6.hdr.vtc_flow);
-				rule_action->encap.vxlan.ipv6.flow_label =
-						vtc_flow & 0xfffff;
-				rule_action->encap.vxlan.ipv6.dscp =
-						(vtc_flow >> 22) & 0x3f;
-				rule_action->encap.vxlan.ipv6.hop_limit =
-					spec.ipv6.hdr.hop_limits;
-				break;
-			}
-			default:
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ether should be ipv4/ipv6");
-			}
-
-			item++;
-
-			/* Check for UDP. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_UDP) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after ipv4/ipv6 should be udp");
-			}
-			rule_action->encap.vxlan.udp.sp =
-				rte_ntohs(spec.udp.hdr.src_port);
-			rule_action->encap.vxlan.udp.dp =
-				rte_ntohs(spec.udp.hdr.dst_port);
-
-			item++;
-
-			/* Check for VXLAN. */
-			flow_item_skip_void(&item);
-			status = flow_item_proto_preprocess(item, &spec, &mask,
-					&size, &disabled, error);
-			if (status)
-				return status;
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: encap item after udp should be vxlan");
-			}
-			rule_action->encap.vxlan.vxlan.vni =
-				(spec.vxlan.vni[0] << 16U |
-					spec.vxlan.vni[1] << 8U
-					| spec.vxlan.vni[2]);
-
-			item++;
-
-			/* Check for END. */
-			flow_item_skip_void(&item);
-
-			if (item->type != RTE_FLOW_ITEM_TYPE_END)
-				return rte_flow_error_set(error,
-					EINVAL,
-					RTE_FLOW_ERROR_TYPE_ITEM,
-					item,
-					"VXLAN ENCAP: expecting END item");
-
-			rule_action->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-			rule_action->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			break;
-		} /* RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP */
-
-		default:
-			return -ENOTSUP;
-		}
-	}
-
-	if (n_jump_queue_rss_drop == 0)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			action,
-			"Flow does not have any terminating action");
-
-	return 0;
-}
-
-static int
-pmd_flow_validate(struct rte_eth_dev *dev,
-		const struct rte_flow_attr *attr,
-		const struct rte_flow_item item[],
-		const struct rte_flow_action action[],
-		struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int status;
-
-	/* Check input parameters. */
-	if (attr == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ATTR,
-				NULL, "Null attr");
-
-	if (item == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ITEM,
-				NULL,
-				"Null item");
-
-	if (action == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_ACTION,
-				NULL,
-				"Null action");
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return status;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline name");
-
-	if (table_id >= pipeline->n_tables)
-		return rte_flow_error_set(error,
-				EINVAL,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Invalid pipeline table ID");
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-			pipeline,
-			table,
-			attr,
-			item,
-			&rule_match,
-			error);
-	if (status)
-		return status;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return status;
-
-	return 0;
-}
-
-static struct softnic_mtr *
-flow_action_meter_get(struct pmd_internals *softnic,
-	const struct rte_flow_action *action)
-{
-	for ( ; action->type != RTE_FLOW_ACTION_TYPE_END; action++)
-		if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
-			const struct rte_flow_action_meter *conf = action->conf;
-
-			if (conf == NULL)
-				return NULL;
-
-			return softnic_mtr_find(softnic, conf->mtr_id);
-		}
-
-	return NULL;
-}
-
-static void
-flow_meter_owner_reset(struct pmd_internals *softnic,
-	struct rte_flow *flow)
-{
-	struct softnic_mtr_list *ml = &softnic->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->flow == flow) {
-			m->flow = NULL;
-			break;
-		}
-}
-
-static void
-flow_meter_owner_set(struct pmd_internals *softnic,
-	struct rte_flow *flow,
-	struct softnic_mtr *mtr)
-{
-	/* Reset current flow meter  */
-	flow_meter_owner_reset(softnic, flow);
-
-	/* Set new flow meter */
-	mtr->flow = flow;
-}
-
-static int
-is_meter_action_enable(struct pmd_internals *softnic,
-	struct softnic_table *table)
-{
-	struct softnic_table_action_profile *profile =
-		softnic_table_action_profile_find(softnic,
-			table->params.action_profile_name);
-	struct softnic_table_action_profile_params *params = &profile->params;
-
-	return (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) ? 1 : 0;
-}
-
-static struct rte_flow *
-pmd_flow_create(struct rte_eth_dev *dev,
-	const struct rte_flow_attr *attr,
-	const struct rte_flow_item item[],
-	const struct rte_flow_action action[],
-	struct rte_flow_error *error)
-{
-	struct softnic_table_rule_match rule_match;
-	struct softnic_table_rule_action rule_action;
-	void *rule_data;
-
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct rte_flow *flow;
-	struct softnic_mtr *mtr;
-	const char *pipeline_name = NULL;
-	uint32_t table_id = 0;
-	int new_flow, status;
-
-	/* Check input parameters. */
-	if (attr == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ATTR,
-			NULL,
-			"Null attr");
-		return NULL;
-	}
-
-	if (item == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ITEM,
-			NULL,
-			"Null item");
-		return NULL;
-	}
-
-	if (action == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_ACTION,
-			NULL,
-			"Null action");
-		return NULL;
-	}
-
-	/* Identify the pipeline table to add this flow to. */
-	status = flow_pipeline_table_get(softnic, attr, &pipeline_name,
-					&table_id, error);
-	if (status)
-		return NULL;
-
-	pipeline = softnic_pipeline_find(softnic, pipeline_name);
-	if (pipeline == NULL) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline name");
-		return NULL;
-	}
-
-	if (table_id >= pipeline->n_tables) {
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Invalid pipeline table ID");
-		return NULL;
-	}
-
-	table = &pipeline->table[table_id];
-
-	/* Rule match. */
-	memset(&rule_match, 0, sizeof(rule_match));
-	status = flow_rule_match_get(softnic,
-		pipeline,
-		table,
-		attr,
-		item,
-		&rule_match,
-		error);
-	if (status)
-		return NULL;
-
-	/* Rule action. */
-	memset(&rule_action, 0, sizeof(rule_action));
-	status = flow_rule_action_get(softnic,
-		pipeline,
-		table,
-		attr,
-		action,
-		&rule_action,
-		error);
-	if (status)
-		return NULL;
-
-	/* Flow find/allocate. */
-	new_flow = 0;
-	flow = softnic_flow_find(table, &rule_match);
-	if (flow == NULL) {
-		new_flow = 1;
-		flow = calloc(1, sizeof(struct rte_flow));
-		if (flow == NULL) {
-			rte_flow_error_set(error,
-				ENOMEM,
-				RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Not enough memory for new flow");
-			return NULL;
-		}
-	}
-
-	/* Rule add. */
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&rule_match,
-		&rule_action,
-		&rule_data);
-	if (status) {
-		if (new_flow)
-			free(flow);
-
-		rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule add failed");
-		return NULL;
-	}
-
-	/* Flow fill in. */
-	memcpy(&flow->match, &rule_match, sizeof(rule_match));
-	memcpy(&flow->action, &rule_action, sizeof(rule_action));
-	flow->data = rule_data;
-	flow->pipeline = pipeline;
-	flow->table_id = table_id;
-
-	mtr = flow_action_meter_get(softnic, action);
-	if (mtr)
-		flow_meter_owner_set(softnic, flow, mtr);
-
-	/* Flow add to list. */
-	if (new_flow)
-		TAILQ_INSERT_TAIL(&table->flows, flow, node);
-
-	return flow;
-}
-
-static int
-pmd_flow_destroy(struct rte_eth_dev *dev,
-	struct rte_flow *flow,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct softnic_table *table;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule delete. */
-	status = softnic_pipeline_table_rule_delete(softnic,
-		flow->pipeline->name,
-		flow->table_id,
-		&flow->match);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule delete failed");
-
-	/* Update dependencies */
-	if (is_meter_action_enable(softnic, table))
-		flow_meter_owner_reset(softnic, flow);
-
-	/* Flow delete. */
-	TAILQ_REMOVE(&table->flows, flow, node);
-	free(flow);
-
-	return 0;
-}
-
-static int
-pmd_flow_flush(struct rte_eth_dev *dev,
-	struct rte_flow_error *error)
-{
-	struct pmd_internals *softnic = dev->data->dev_private;
-	struct pipeline *pipeline;
-	int fail_to_del_rule = 0;
-	uint32_t i;
-
-	TAILQ_FOREACH(pipeline, &softnic->pipeline_list, node) {
-		/* Remove all the flows added to the tables. */
-		for (i = 0; i < pipeline->n_tables; i++) {
-			struct softnic_table *table = &pipeline->table[i];
-			struct rte_flow *flow;
-			void *temp;
-			int status;
-
-			RTE_TAILQ_FOREACH_SAFE(flow, &table->flows, node,
-				temp) {
-				/* Rule delete. */
-				status = softnic_pipeline_table_rule_delete
-						(softnic,
-						pipeline->name,
-						i,
-						&flow->match);
-				if (status)
-					fail_to_del_rule = 1;
-				/* Update dependencies */
-				if (is_meter_action_enable(softnic, table))
-					flow_meter_owner_reset(softnic, flow);
-
-				/* Flow delete. */
-				TAILQ_REMOVE(&table->flows, flow, node);
-				free(flow);
-			}
-		}
-	}
-
-	if (fail_to_del_rule)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Some of the rules could not be deleted");
-
-	return 0;
-}
-
-static int
-pmd_flow_query(struct rte_eth_dev *dev __rte_unused,
-	struct rte_flow *flow,
-	const struct rte_flow_action *action __rte_unused,
-	void *data,
-	struct rte_flow_error *error)
-{
-	struct rte_table_action_stats_counters stats;
-	struct softnic_table *table;
-	struct rte_flow_query_count *flow_stats = data;
-	int status;
-
-	/* Check input parameters. */
-	if (flow == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_HANDLE,
-			NULL,
-			"Null flow");
-
-	if (data == NULL)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Null data");
-
-	table = &flow->pipeline->table[flow->table_id];
-
-	/* Rule stats read. */
-	status = rte_table_action_stats_read(table->a,
-		flow->data,
-		&stats,
-		flow_stats->reset);
-	if (status)
-		return rte_flow_error_set(error,
-			EINVAL,
-			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Pipeline table rule stats read failed");
-
-	/* Fill in flow stats. */
-	flow_stats->hits_set =
-		(table->ap->params.stats.n_packets_enabled) ? 1 : 0;
-	flow_stats->bytes_set =
-		(table->ap->params.stats.n_bytes_enabled) ? 1 : 0;
-	flow_stats->hits = stats.n_packets;
-	flow_stats->bytes = stats.n_bytes;
-
-	return 0;
-}
-
-const struct rte_flow_ops pmd_flow_ops = {
-	.validate = pmd_flow_validate,
-	.create = pmd_flow_create,
-	.destroy = pmd_flow_destroy,
-	.flush = pmd_flow_flush,
-	.query = pmd_flow_query,
-	.isolate = NULL,
-};
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 03/21] net/softnic: remove the meter support
  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-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
                     ` (18 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the Ethernet device meter API support.

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         |  16 -
 .../net/softnic/rte_eth_softnic_internals.h   | 117 ---
 drivers/net/softnic/rte_eth_softnic_meter.c   | 945 ------------------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  12 -
 5 files changed, 1091 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_meter.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 4ebe60921c..d466dc7700 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -15,7 +15,6 @@ sources = files(
         'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
-        'rte_eth_softnic_meter.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
         'rte_eth_softnic_tap.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 8e361adbad..a7136bb0c0 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -13,7 +13,6 @@
 #include <rte_kvargs.h>
 #include <rte_errno.h>
 #include <rte_ring.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "rte_eth_softnic_internals.h"
@@ -168,8 +167,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	return 0;
 }
 
@@ -191,8 +188,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
-	softnic_mtr_free(p);
-
 	rte_free(p);
 }
 
@@ -215,14 +210,6 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
-static int
-pmd_mtr_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
-{
-	*(const struct rte_mtr_ops **)arg = &pmd_mtr_ops;
-
-	return 0;
-}
-
 static const struct eth_dev_ops pmd_ops = {
 	.dev_configure = pmd_dev_configure,
 	.dev_start = pmd_dev_start,
@@ -232,7 +219,6 @@ static const struct eth_dev_ops pmd_ops = {
 	.dev_infos_get = pmd_dev_infos_get,
 	.rx_queue_setup = pmd_rx_queue_setup,
 	.tx_queue_setup = pmd_tx_queue_setup,
-	.mtr_ops_get = pmd_mtr_ops_get,
 };
 
 static uint16_t
@@ -274,8 +260,6 @@ pmd_init(struct pmd_params *params)
 	memcpy(&p->params, params, sizeof(p->params));
 
 	/* Resources */
-	softnic_mtr_init(p);
-
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 4cc98b7aad..d578cb1f25 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -19,8 +19,6 @@
 
 #include <rte_ethdev_core.h>
 #include <ethdev_driver.h>
-#include <rte_flow_driver.h>
-#include <rte_mtr_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "conn.h"
@@ -40,68 +38,6 @@ struct pmd_params {
 	int sc; /**< Service cores. */
 };
 
-/**
- * Ethdev Flow API
- */
-struct rte_flow;
-
-TAILQ_HEAD(flow_list, rte_flow);
-
-struct flow_attr_map {
-	char pipeline_name[NAME_SIZE];
-	uint32_t table_id;
-	int valid;
-};
-
-#ifndef SOFTNIC_FLOW_MAX_GROUPS
-#define SOFTNIC_FLOW_MAX_GROUPS                            64
-#endif
-
-struct flow_internals {
-	struct flow_attr_map ingress_map[SOFTNIC_FLOW_MAX_GROUPS];
-	struct flow_attr_map egress_map[SOFTNIC_FLOW_MAX_GROUPS];
-};
-
-/**
- * Meter
- */
-
-/* MTR meter profile */
-struct softnic_mtr_meter_profile {
-	TAILQ_ENTRY(softnic_mtr_meter_profile) node;
-	uint32_t meter_profile_id;
-	struct rte_mtr_meter_profile params;
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_profile_list, softnic_mtr_meter_profile);
-
-/* MTR meter policy */
-struct softnic_mtr_meter_policy {
-	TAILQ_ENTRY(softnic_mtr_meter_policy) node;
-	uint32_t meter_policy_id;
-	enum rte_table_action_policer policer[RTE_COLORS];
-	uint32_t n_users;
-};
-
-TAILQ_HEAD(softnic_mtr_meter_policy_list, softnic_mtr_meter_policy);
-
-/* MTR meter object */
-struct softnic_mtr {
-	TAILQ_ENTRY(softnic_mtr) node;
-	uint32_t mtr_id;
-	struct rte_mtr_params params;
-	struct rte_flow *flow;
-};
-
-TAILQ_HEAD(softnic_mtr_list, softnic_mtr);
-
-struct mtr_internals {
-	struct softnic_mtr_meter_profile_list meter_profiles;
-	struct softnic_mtr_meter_policy_list meter_policies;
-	struct softnic_mtr_list mtrs;
-};
-
 /**
  * MEMPOOL
  */
@@ -383,7 +319,6 @@ struct softnic_table {
 	struct softnic_table_params params;
 	struct softnic_table_action_profile *ap;
 	struct rte_table_action *a;
-	struct flow_list flows;
 	struct rte_table_action_dscp_table dscp_table;
 	struct softnic_table_meter_profile_list meter_profiles;
 };
@@ -481,9 +416,6 @@ struct pmd_internals {
 	/** Params */
 	struct pmd_params params;
 
-	struct flow_internals flow;
-	struct mtr_internals mtr;
-
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
@@ -513,46 +445,6 @@ ETHDEV(struct pmd_internals *softnic)
 	return &rte_eth_devices[port_id];
 }
 
-/**
- * Ethdev Flow API
- */
-int
-flow_attr_map_set(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress,
-		const char *pipeline_name,
-		uint32_t table_id);
-
-struct flow_attr_map *
-flow_attr_map_get(struct pmd_internals *softnic,
-		uint32_t group_id,
-		int ingress);
-
-extern const struct rte_flow_ops pmd_flow_ops;
-
-/**
- * Meter
- */
-int
-softnic_mtr_init(struct pmd_internals *p);
-
-void
-softnic_mtr_free(struct pmd_internals *p);
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p,
-	uint32_t mtr_id);
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id);
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id);
-
-extern const struct rte_mtr_ops pmd_mtr_ops;
-
 /**
  * MEMPOOL
  */
@@ -814,15 +706,6 @@ struct softnic_table_rule_action {
 	uint8_t sym_crypto_key[SYM_CRYPTO_MAX_KEY_SIZE];
 };
 
-struct rte_flow {
-	TAILQ_ENTRY(rte_flow) node;
-	struct softnic_table_rule_match match;
-	struct softnic_table_rule_action action;
-	void *data;
-	struct pipeline *pipeline;
-	uint32_t table_id;
-};
-
 int
 softnic_pipeline_port_in_stats_read(struct pmd_internals *p,
 	const char *pipeline_name,
diff --git a/drivers/net/softnic/rte_eth_softnic_meter.c b/drivers/net/softnic/rte_eth_softnic_meter.c
deleted file mode 100644
index 6b02f43e31..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_meter.c
+++ /dev/null
@@ -1,945 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_mtr.h>
-#include <rte_mtr_driver.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_mtr_init(struct pmd_internals *p)
-{
-	/* Initialize meter profiles list */
-	TAILQ_INIT(&p->mtr.meter_profiles);
-
-	/* Initialize meter policies list */
-	TAILQ_INIT(&p->mtr.meter_policies);
-
-	/* Initialize MTR objects list */
-	TAILQ_INIT(&p->mtr.mtrs);
-
-	return 0;
-}
-
-void
-softnic_mtr_free(struct pmd_internals *p)
-{
-	/* Remove MTR objects */
-	for ( ; ; ) {
-		struct softnic_mtr *m;
-
-		m = TAILQ_FIRST(&p->mtr.mtrs);
-		if (m == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.mtrs, m, node);
-		free(m);
-	}
-
-	/* Remove meter profiles */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_profile *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_profiles);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-		free(mp);
-	}
-
-	/* Remove meter policies */
-	for ( ; ; ) {
-		struct softnic_mtr_meter_policy *mp;
-
-		mp = TAILQ_FIRST(&p->mtr.meter_policies);
-		if (mp == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-		free(mp);
-	}
-}
-
-struct softnic_mtr_meter_profile *
-softnic_mtr_meter_profile_find(struct pmd_internals *p,
-	uint32_t meter_profile_id)
-{
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_profile_id == mp->meter_profile_id)
-			return mp;
-
-	return NULL;
-}
-
-static int
-meter_profile_check(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile ID must be valid. */
-	if (meter_profile_id == UINT32_MAX)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter profile must not exist. */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter prfile already exists");
-
-	/* Profile must not be NULL. */
-	if (profile == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"profile null");
-
-	/* Traffic metering algorithm : TRTCM_RFC2698 */
-	if (profile->alg != RTE_MTR_TRTCM_RFC2698)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE,
-			NULL,
-			"Metering alg not supported");
-
-	/* Not support packet mode, just support byte mode. */
-	if (profile->packet_mode)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_PACKET_MODE,
-			NULL,
-			"Meter packet mode not supported");
-
-	return 0;
-}
-
-/* MTR meter profile add */
-static int
-pmd_mtr_meter_profile_add(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_meter_profile *profile,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile_list *mpl = &p->mtr.meter_profiles;
-	struct softnic_mtr_meter_profile *mp;
-	int status;
-
-	/* Check input params */
-	status = meter_profile_check(dev, meter_profile_id, profile, error);
-	if (status)
-		return status;
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_profile));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_profile_id = meter_profile_id;
-	memcpy(&mp->params, profile, sizeof(mp->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter profile delete */
-static int
-pmd_mtr_meter_profile_delete(struct rte_eth_dev *dev,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_profiles, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr_meter_policy *
-softnic_mtr_meter_policy_find(struct pmd_internals *p,
-	uint32_t meter_policy_id)
-{
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-
-	TAILQ_FOREACH(mp, mpl, node)
-		if (meter_policy_id == mp->meter_policy_id)
-			return mp;
-
-	return NULL;
-}
-
-/* MTR meter policy add */
-static int
-pmd_mtr_meter_policy_add(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_meter_policy_params *policy,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy_list *mpl = &p->mtr.meter_policies;
-	struct softnic_mtr_meter_policy *mp;
-	const struct rte_flow_action *act;
-	const struct rte_flow_action_meter_color *recolor;
-	uint32_t i;
-	bool valid_act_found;
-
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY,
-			NULL,
-			"Null meter policy invalid");
-
-	/* Meter policy must not exist. */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy already exists");
-
-	for (i = 0; i < RTE_COLORS; i++) {
-		if (policy->actions[i] == NULL)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"Null action list");
-		for (act = policy->actions[i], valid_act_found = false;
-		     act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
-			if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
-				continue;
-			/*
-			 * Support one (and one only) of
-			 * METER_COLOR or DROP action.
-			 */
-			if ((act->type != RTE_FLOW_ACTION_TYPE_METER_COLOR &&
-				act->type != RTE_FLOW_ACTION_TYPE_DROP) ||
-				valid_act_found)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_METER_POLICY,
-					NULL,
-					"Action invalid");
-			valid_act_found = true;
-		}
-		if (!valid_act_found)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY,
-				NULL,
-				"No valid action found");
-	}
-
-	/* Memory allocation */
-	mp = calloc(1, sizeof(struct softnic_mtr_meter_policy));
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	mp->meter_policy_id = meter_policy_id;
-	for (i = 0; i < RTE_COLORS; i++) {
-		mp->policer[i] = RTE_TABLE_ACTION_POLICER_DROP;
-		act = policy->actions[i];
-		if (!act)
-			continue;
-		if (act->type == RTE_FLOW_ACTION_TYPE_METER_COLOR) {
-			recolor = act->conf;
-			switch (recolor->color) {
-			case RTE_COLOR_GREEN:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-				break;
-			case RTE_COLOR_YELLOW:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-				break;
-			case RTE_COLOR_RED:
-				mp->policer[i] =
-				RTE_TABLE_ACTION_POLICER_COLOR_RED;
-				break;
-			default:
-				break;
-			}
-		}
-	}
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(mpl, mp, node);
-
-	return 0;
-}
-
-/* MTR meter policy delete */
-static int
-pmd_mtr_meter_policy_delete(struct rte_eth_dev *dev,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_policy *mp;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* Check unused */
-	if (mp->n_users)
-		return -rte_mtr_error_set(error,
-			EBUSY,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy in use");
-
-	/* Remove from list */
-	TAILQ_REMOVE(&p->mtr.meter_policies, mp, node);
-	free(mp);
-
-	return 0;
-}
-
-struct softnic_mtr *
-softnic_mtr_find(struct pmd_internals *p, uint32_t mtr_id)
-{
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr *m;
-
-	TAILQ_FOREACH(m, ml, node)
-		if (m->mtr_id == mtr_id)
-			return m;
-
-	return NULL;
-}
-
-
-static int
-mtr_check(struct pmd_internals *p,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	/* MTR id valid  */
-	if (softnic_mtr_find(p, mtr_id))
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object already exists");
-
-	/* MTR params must not be NULL */
-	if (params == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"MTR object params null");
-
-	/* Previous meter color not supported */
-	if (params->use_prev_mtr_color)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_MTR_PARAMS,
-			NULL,
-			"Previous meter color not supported");
-
-	/* Shared MTR object not supported */
-	if (shared)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_SHARED,
-			NULL,
-			"Shared MTR object not supported");
-
-	return 0;
-}
-
-/* MTR object create */
-static int
-pmd_mtr_create(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_params *params,
-	int shared,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr_meter_policy *policy;
-	struct softnic_mtr *m;
-	int status;
-
-	/* Check parameters */
-	status = mtr_check(p, mtr_id, params, shared, error);
-	if (status)
-		return status;
-
-	/* Meter profile must exist */
-	mp = softnic_mtr_meter_profile_find(p, params->meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile id not valid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, params->meter_policy_id);
-	if (policy == NULL) {
-		return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-				NULL,
-				"Meter policy id invalid");
-	}
-
-	/* Memory allocation */
-	m = calloc(1, sizeof(struct softnic_mtr));
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			ENOMEM,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Memory alloc failed");
-
-	/* Fill in */
-	m->mtr_id = mtr_id;
-	memcpy(&m->params, params, sizeof(m->params));
-
-	/* Add to list */
-	TAILQ_INSERT_TAIL(ml, m, node);
-
-	/* Update dependencies */
-	mp->n_users++;
-	policy->n_users++;
-
-	return 0;
-}
-
-/* MTR object destroy */
-static int
-pmd_mtr_destroy(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_list *ml = &p->mtr.mtrs;
-	struct softnic_mtr_meter_profile *mp;
-	struct softnic_mtr *m;
-	struct softnic_mtr_meter_policy *policy;
-
-	/* MTR object must exist */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object must not have any owner */
-	if (m->flow != NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"MTR object is being used");
-
-	/* Get meter profile */
-	mp = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-	if (mp == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"MTR object meter profile invalid");
-
-	/* Meter policy must exist */
-	policy = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (policy == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"MTR object meter policy invalid");
-
-	/* Update dependencies */
-	mp->n_users--;
-	policy->n_users--;
-
-	/* Remove from list */
-	TAILQ_REMOVE(ml, m, node);
-	free(m);
-
-	return 0;
-}
-
-/* MTR object meter profile update */
-static int
-pmd_mtr_meter_profile_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_profile_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr_meter_profile *mp_new, *mp_old;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* Meter profile id must be valid */
-	mp_new = softnic_mtr_meter_profile_find(p, meter_profile_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_PROFILE_ID,
-			NULL,
-			"Meter profile not valid");
-
-	/* MTR object already set to meter profile id */
-	if (m->params.meter_profile_id == meter_profile_id)
-		return 0;
-
-	/*  MTR object owner table update */
-	if (m->flow) {
-		uint32_t table_id = m->flow->table_id;
-		struct softnic_table *table = &m->flow->pipeline->table[table_id];
-		struct softnic_table_rule_action action;
-
-		if (!softnic_pipeline_table_meter_profile_find(table,
-			meter_profile_id)) {
-			struct rte_table_action_meter_profile profile;
-
-			memset(&profile, 0, sizeof(profile));
-
-			profile.alg = RTE_TABLE_ACTION_METER_TRTCM;
-			profile.trtcm.cir = mp_new->params.trtcm_rfc2698.cir;
-			profile.trtcm.pir = mp_new->params.trtcm_rfc2698.pir;
-			profile.trtcm.cbs = mp_new->params.trtcm_rfc2698.cbs;
-			profile.trtcm.pbs = mp_new->params.trtcm_rfc2698.pbs;
-
-			/* Add meter profile to pipeline table */
-			status = softnic_pipeline_table_mtr_profile_add(p,
-					m->flow->pipeline->name,
-					table_id,
-					meter_profile_id,
-					&profile);
-			if (status)
-				return -rte_mtr_error_set(error,
-					EINVAL,
-					RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-					NULL,
-					"Table meter profile add failed");
-		}
-
-		/* Set meter action */
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		action.mtr.mtr[0].meter_profile_id = meter_profile_id;
-
-		/* Re-add rule */
-		status = softnic_pipeline_table_rule_add(p,
-			m->flow->pipeline->name,
-			table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule add failed");
-
-		/* Flow: update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-	}
-
-	mp_old = softnic_mtr_meter_profile_find(p, m->params.meter_profile_id);
-
-	/* Meter: Set meter profile */
-	m->params.meter_profile_id = meter_profile_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-/* MTR object meter DSCP table update */
-static int
-pmd_mtr_meter_dscp_table_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	enum rte_color *dscp_table,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_dscp_table dt;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	uint32_t table_id, i;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR object owner valid? */
-	if (m->flow == NULL)
-		return 0;
-
-	pipeline = m->flow->pipeline;
-	table_id = m->flow->table_id;
-	table = &pipeline->table[table_id];
-
-	memcpy(&dt, &table->dscp_table, sizeof(dt));
-	for (i = 0; i < RTE_DIM(dt.entry); i++)
-		dt.entry[i].color = (enum rte_color)dscp_table[i];
-
-	/* Update table */
-	status = softnic_pipeline_table_dscp_table_update(p,
-			pipeline->name,
-			table_id,
-			UINT64_MAX,
-			&dt);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Table action dscp table update failed");
-
-	return 0;
-}
-
-/* MTR object policy update */
-static int
-pmd_mtr_meter_policy_update(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	uint32_t meter_policy_id,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct softnic_mtr *m;
-	uint32_t i;
-	int status;
-	struct softnic_mtr_meter_policy *mp_new, *mp_old;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	if (m->params.meter_policy_id == meter_policy_id)
-		return 0;
-
-	/* Meter policy must exist */
-	mp_new = softnic_mtr_meter_policy_find(p, meter_policy_id);
-	if (mp_new == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Meter policy id invalid");
-
-	/* MTR object owner valid? */
-	if (m->flow) {
-		struct pipeline *pipeline = m->flow->pipeline;
-		struct softnic_table *table = &pipeline->table[m->flow->table_id];
-		struct softnic_table_rule_action action;
-
-		memcpy(&action, &m->flow->action, sizeof(action));
-
-		/* Set action */
-		for (i = 0; i < RTE_COLORS; i++)
-			action.mtr.mtr[0].policer[i] = mp_new->policer[i];
-
-		/* Re-add the rule */
-		status = softnic_pipeline_table_rule_add(p,
-			pipeline->name,
-			m->flow->table_id,
-			&m->flow->match,
-			&action,
-			&m->flow->data);
-		if (status)
-			return -rte_mtr_error_set(error,
-				EINVAL,
-				RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-				NULL,
-				"Pipeline table rule re-add failed");
-
-		/* Flow: Update meter action */
-		memcpy(&m->flow->action, &action, sizeof(m->flow->action));
-
-		/* Reset the meter stats */
-		rte_table_action_meter_read(table->a, m->flow->data,
-			1, NULL, 1);
-	}
-
-	mp_old = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp_old == NULL)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_METER_POLICY_ID,
-			NULL,
-			"Old meter policy id invalid");
-
-	/* Meter: Set meter profile */
-	m->params.meter_policy_id = meter_policy_id;
-
-	/* Update dependencies*/
-	mp_old->n_users--;
-	mp_new->n_users++;
-
-	return 0;
-}
-
-#define MTR_STATS_PKTS_DEFAULT (RTE_MTR_STATS_N_PKTS_GREEN | \
-				RTE_MTR_STATS_N_PKTS_YELLOW | \
-				RTE_MTR_STATS_N_PKTS_RED | \
-				RTE_MTR_STATS_N_PKTS_DROPPED)
-
-#define MTR_STATS_BYTES_DEFAULT (RTE_MTR_STATS_N_BYTES_GREEN | \
-				RTE_MTR_STATS_N_BYTES_YELLOW | \
-				RTE_MTR_STATS_N_BYTES_RED | \
-				RTE_MTR_STATS_N_BYTES_DROPPED)
-
-/* MTR object stats read */
-static void
-mtr_stats_convert(struct pmd_internals *p,
-	struct softnic_mtr *m,
-	struct rte_table_action_mtr_counters_tc *in,
-	struct rte_mtr_stats *out,
-	uint64_t *out_mask)
-{
-	struct softnic_mtr_meter_policy *mp;
-
-	memset(&out, 0, sizeof(out));
-	*out_mask = 0;
-
-	/* Meter policy must exist */
-	mp = softnic_mtr_meter_policy_find(p, m->params.meter_policy_id);
-	if (mp == NULL)
-		return;
-
-	if (in->n_packets_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_pkts[RTE_COLOR_GREEN] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_pkts[RTE_COLOR_YELLOW] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_pkts[RTE_COLOR_RED] += in->n_packets[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_pkts_dropped += in->n_packets[i];
-		}
-
-		*out_mask |= MTR_STATS_PKTS_DEFAULT;
-	}
-
-	if (in->n_bytes_valid) {
-		uint32_t i;
-
-		for (i = 0; i < RTE_COLORS; i++) {
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_GREEN)
-				out->n_bytes[RTE_COLOR_GREEN] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_YELLOW)
-				out->n_bytes[RTE_COLOR_YELLOW] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_COLOR_RED)
-				out->n_bytes[RTE_COLOR_RED] += in->n_bytes[i];
-
-			if (mp->policer[i] ==
-				RTE_TABLE_ACTION_POLICER_DROP)
-				out->n_bytes_dropped += in->n_bytes[i];
-		}
-
-		*out_mask |= MTR_STATS_BYTES_DEFAULT;
-	}
-}
-
-/* MTR object stats read */
-static int
-pmd_mtr_stats_read(struct rte_eth_dev *dev,
-	uint32_t mtr_id,
-	struct rte_mtr_stats *stats,
-	uint64_t *stats_mask,
-	int clear,
-	struct rte_mtr_error *error)
-{
-	struct pmd_internals *p = dev->data->dev_private;
-	struct rte_table_action_mtr_counters counters;
-	struct pipeline *pipeline;
-	struct softnic_table *table;
-	struct softnic_mtr *m;
-	int status;
-
-	/* MTR object id must be valid */
-	m = softnic_mtr_find(p, mtr_id);
-	if (m == NULL)
-		return -rte_mtr_error_set(error,
-			EEXIST,
-			RTE_MTR_ERROR_TYPE_MTR_ID,
-			NULL,
-			"MTR object id not valid");
-
-	/* MTR meter object owner valid? */
-	if (m->flow == NULL) {
-		if (stats != NULL)
-			memset(stats, 0, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = MTR_STATS_PKTS_DEFAULT |
-				MTR_STATS_BYTES_DEFAULT;
-
-		return 0;
-	}
-
-	pipeline = m->flow->pipeline;
-	table = &pipeline->table[m->flow->table_id];
-
-	/* Meter stats read. */
-	status = rte_table_action_meter_read(table->a,
-		m->flow->data,
-		1,
-		&counters,
-		clear);
-	if (status)
-		return -rte_mtr_error_set(error,
-			EINVAL,
-			RTE_MTR_ERROR_TYPE_UNSPECIFIED,
-			NULL,
-			"Meter stats read failed");
-
-	/* Stats format conversion. */
-	if (stats || stats_mask) {
-		struct rte_mtr_stats s;
-		uint64_t s_mask = 0;
-
-		mtr_stats_convert(p,
-			m,
-			&counters.stats[0],
-			&s,
-			&s_mask);
-
-		if (stats)
-			memcpy(stats, &s, sizeof(*stats));
-
-		if (stats_mask)
-			*stats_mask = s_mask;
-	}
-
-	return 0;
-}
-
-const struct rte_mtr_ops pmd_mtr_ops = {
-	.capabilities_get = NULL,
-
-	.meter_profile_add = pmd_mtr_meter_profile_add,
-	.meter_profile_delete = pmd_mtr_meter_profile_delete,
-
-	.meter_policy_add = pmd_mtr_meter_policy_add,
-	.meter_policy_delete = pmd_mtr_meter_policy_delete,
-
-	.create = pmd_mtr_create,
-	.destroy = pmd_mtr_destroy,
-	.meter_enable = NULL,
-	.meter_disable = NULL,
-
-	.meter_profile_update = pmd_mtr_meter_profile_update,
-	.meter_dscp_table_update = pmd_mtr_meter_dscp_table_update,
-	.meter_policy_update = pmd_mtr_meter_policy_update,
-	.stats_update = NULL,
-
-	.stats_read = pmd_mtr_stats_read,
-};
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index c7d2a7de19..2cf7fa52d1 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -46,17 +46,6 @@ softnic_pipeline_init(struct pmd_internals *p)
 static void
 softnic_pipeline_table_free(struct softnic_table *table)
 {
-	for ( ; ; ) {
-		struct rte_flow *flow;
-
-		flow = TAILQ_FIRST(&table->flows);
-		if (flow == NULL)
-			break;
-
-		TAILQ_REMOVE(&table->flows, flow, node);
-		free(flow);
-	}
-
 	for ( ; ; ) {
 		struct softnic_table_meter_profile *mp;
 
@@ -1035,7 +1024,6 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 	memcpy(&table->params, params, sizeof(*params));
 	table->ap = ap;
 	table->a = action;
-	TAILQ_INIT(&table->flows);
 	TAILQ_INIT(&table->meter_profiles);
 	memset(&table->dscp_table, 0, sizeof(table->dscp_table));
 	pipeline->n_tables++;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 04/21] net/softnic: remove cryptodev support
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (2 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 03/21] net/softnic: remove the meter support Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 05/21] net/softnic: remove tap support Cristian Dumitrescu
                     ` (17 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the cryptographic device API support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/meson.build               |   3 +-
 drivers/net/softnic/rte_eth_softnic.c         |   1 -
 drivers/net/softnic/rte_eth_softnic_cli.c     | 171 ------------------
 .../net/softnic/rte_eth_softnic_cryptodev.c   | 168 -----------------
 .../net/softnic/rte_eth_softnic_internals.h   |  54 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  54 ------
 6 files changed, 1 insertion(+), 450 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_cryptodev.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index d466dc7700..b3d235841d 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -12,7 +12,6 @@ sources = files(
         'rte_eth_softnic.c',
         'rte_eth_softnic_action.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_cryptodev.c',
         'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
@@ -20,4 +19,4 @@ sources = files(
         'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
-deps += ['pipeline', 'port', 'table', 'cryptodev']
+deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a7136bb0c0..1ea5989223 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -264,7 +264,6 @@ pmd_init(struct pmd_params *params)
 	softnic_swq_init(p);
 	softnic_link_init(p);
 	softnic_tap_init(p);
-	softnic_cryptodev_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 671f96cf77..bca0b176d6 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -213,80 +213,6 @@ cmd_tap(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * cryptodev <tap_name> dev <device_name> | dev_id <device_id>
- * queue <n_queues> <queue_size> max_sessions <n_sessions>
- **/
-
-static void
-cmd_cryptodev(struct pmd_internals *softnic,
-		char **tokens,
-		uint32_t n_tokens,
-		char *out,
-		size_t out_size)
-{
-	struct softnic_cryptodev_params params;
-	char *name;
-
-	memset(&params, 0, sizeof(params));
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0)
-		params.dev_name = tokens[3];
-	else if (strcmp(tokens[2], "dev_id") == 0) {
-		if (softnic_parser_read_uint32(&params.dev_id, tokens[3]) < 0) {
-			snprintf(out, out_size,	MSG_ARG_INVALID,
-				"dev_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"cryptodev");
-		return;
-	}
-
-	if (strcmp(tokens[4], "queue")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.n_queues, tokens[5]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.queue_size, tokens[6]) < 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"queue_size");
-		return;
-	}
-
-	if (strcmp(tokens[7], "max_sessions")) {
-		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-			"4");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&params.session_pool_size, tokens[8])
-			< 0) {
-		snprintf(out, out_size,	MSG_ARG_INVALID,
-			"q");
-		return;
-	}
-
-	if (softnic_cryptodev_create(softnic, name, &params) == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -879,41 +805,6 @@ cmd_table_action_profile(struct pmd_internals *softnic,
 		t0 += 1;
 	} /* decap */
 
-	if (t0 < n_tokens && (strcmp(tokens[t0], "sym_crypto") == 0)) {
-		struct softnic_cryptodev *cryptodev;
-
-		if (n_tokens < t0 + 5 ||
-				strcmp(tokens[t0 + 1], "dev") ||
-				strcmp(tokens[t0 + 3], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		cryptodev = softnic_cryptodev_find(softnic, tokens[t0 + 2]);
-		if (cryptodev == NULL) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.cryptodev_id = cryptodev->dev_id;
-
-		if (softnic_parser_read_uint32(&p.sym_crypto.op_offset,
-				tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-					"table action profile sym_crypto");
-			return;
-		}
-
-		p.sym_crypto.mp_create = cryptodev->mp_create;
-		p.sym_crypto.mp_init = cryptodev->mp_init;
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-		t0 += 5;
-	} /* sym_crypto */
-
 	if (t0 < n_tokens) {
 		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
 		return;
@@ -985,7 +876,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  | cryptodev <cryptodev_name> rxq <queue_id>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
  */
@@ -1138,27 +1028,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		}
 
 		t0 += 7;
-	} else if (strcmp(tokens[t0], "cryptodev") == 0) {
-		if (n_tokens < t0 + 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in cryptodev");
-			return;
-		}
-
-		p.type = PORT_IN_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-				tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"rxq");
-			return;
-		}
-
-		p.cryptodev.arg_callback = NULL;
-		p.cryptodev.f_callback = NULL;
-
-		t0 += 4;
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -1207,7 +1076,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  | swq <swq_name>
  *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
- *  | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>
  */
 static void
 cmd_pipeline_port_out(struct pmd_internals *softnic,
@@ -1322,40 +1190,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 				return;
 			}
 		}
-	} else if (strcmp(tokens[6], "cryptodev") == 0) {
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		p.type = PORT_OUT_CRYPTODEV;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.cryptodev.queue_id, tokens[9])
-				!= 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-
-		if (strcmp(tokens[10], "offset")) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out cryptodev");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.cryptodev.op_offset,
-				tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
 	} else {
 		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
 		return;
@@ -4771,11 +4605,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "cryptodev") == 0) {
-		cmd_cryptodev(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_cryptodev.c b/drivers/net/softnic/rte_eth_softnic_cryptodev.c
deleted file mode 100644
index e4754055e9..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_cryptodev.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <rte_cryptodev.h>
-#include <cryptodev_pmd.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define SOFTNIC_CRYPTO_SESSION_CACHE_SIZE 128
-
-int
-softnic_cryptodev_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->cryptodev_list);
-
-	return 0;
-}
-
-void
-softnic_cryptodev_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = TAILQ_FIRST(&p->cryptodev_list);
-		if (cryptodev == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->cryptodev_list, cryptodev, node);
-		free(cryptodev);
-	}
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_cryptodev *cryptodev;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(cryptodev, &p->cryptodev_list, node)
-		if (strcmp(cryptodev->name, name) == 0)
-			return cryptodev;
-
-	return NULL;
-}
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params)
-{
-	struct rte_cryptodev_info dev_info;
-	struct rte_cryptodev_config dev_conf;
-	struct rte_cryptodev_qp_conf queue_conf;
-	struct softnic_cryptodev *cryptodev;
-	uint32_t dev_id, i;
-	uint32_t socket_id;
-	uint32_t cache_size;
-	char mp_name[NAME_SIZE];
-	int status;
-
-	/* Check input params */
-	if ((name == NULL) ||
-		softnic_cryptodev_find(p, name) ||
-		(params->n_queues == 0) ||
-		(params->queue_size == 0) ||
-		(params->session_pool_size == 0))
-		return NULL;
-
-	if (params->dev_name) {
-		status = rte_cryptodev_get_dev_id(params->dev_name);
-		if (status == -1)
-			return NULL;
-
-		dev_id = (uint32_t)status;
-	} else {
-		if (rte_cryptodev_is_valid_dev(params->dev_id) == 0)
-			return NULL;
-
-		dev_id = params->dev_id;
-	}
-
-	cache_size = (params->session_pool_size / 2 <
-			SOFTNIC_CRYPTO_SESSION_CACHE_SIZE) ?
-					(params->session_pool_size / 2) :
-					SOFTNIC_CRYPTO_SESSION_CACHE_SIZE;
-
-	socket_id = rte_cryptodev_socket_id(dev_id);
-	rte_cryptodev_info_get(dev_id, &dev_info);
-
-	if (dev_info.max_nb_queue_pairs < params->n_queues)
-		return NULL;
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_HW_ACCELERATED)
-		return NULL;
-
-	dev_conf.socket_id = socket_id;
-	dev_conf.nb_queue_pairs = params->n_queues;
-
-	status = rte_cryptodev_configure(dev_id, &dev_conf);
-	if (status < 0)
-		return NULL;
-
-	queue_conf.nb_descriptors = params->queue_size;
-	for (i = 0; i < params->n_queues; i++) {
-		status = rte_cryptodev_queue_pair_setup(dev_id, i,
-				&queue_conf, socket_id);
-		if (status < 0)
-			return NULL;
-	}
-
-	if (rte_cryptodev_start(dev_id) < 0)
-		return NULL;
-
-	cryptodev = calloc(1, sizeof(struct softnic_cryptodev));
-	if (cryptodev == NULL) {
-		rte_cryptodev_stop(dev_id);
-		return NULL;
-	}
-
-	strlcpy(cryptodev->name, name, sizeof(cryptodev->name));
-	cryptodev->dev_id = dev_id;
-	cryptodev->n_queues = params->n_queues;
-
-	snprintf(mp_name, NAME_SIZE, "%s_mp%u", name, dev_id);
-	cryptodev->mp_create = rte_cryptodev_sym_session_pool_create(mp_name,
-			params->session_pool_size,
-			0,
-			cache_size,
-			0,
-			socket_id);
-	if (!cryptodev->mp_create)
-		goto error_exit;
-
-	snprintf(mp_name, NAME_SIZE, "%s_priv_mp%u", name, dev_id);
-	cryptodev->mp_init = rte_mempool_create(mp_name,
-			params->session_pool_size,
-			rte_cryptodev_sym_get_private_session_size(dev_id),
-			cache_size,
-			0,
-			NULL,
-			NULL,
-			NULL,
-			NULL,
-			socket_id,
-			0);
-	if (!cryptodev->mp_init)
-		goto error_exit;
-
-	TAILQ_INSERT_TAIL(&p->cryptodev_list, cryptodev, node);
-
-	return cryptodev;
-
-error_exit:
-	rte_mempool_free(cryptodev->mp_create);
-	rte_mempool_free(cryptodev->mp_init);
-
-	free(cryptodev);
-
-	return NULL;
-}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d578cb1f25..ddcde99b98 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -100,28 +100,6 @@ struct softnic_tap {
 
 TAILQ_HEAD(softnic_tap_list, softnic_tap);
 
-/**
- * Cryptodev
- */
-struct softnic_cryptodev_params {
-	const char *dev_name;
-	uint32_t dev_id; /**< Valid only when *dev_name* is NULL. */
-	uint32_t n_queues;
-	uint32_t queue_size;
-	uint32_t session_pool_size;
-};
-
-struct softnic_cryptodev {
-	TAILQ_ENTRY(softnic_cryptodev) node;
-	char name[NAME_SIZE];
-	uint16_t dev_id;
-	uint32_t n_queues;
-	struct rte_mempool *mp_create;
-	struct rte_mempool *mp_init;
-};
-
-TAILQ_HEAD(softnic_cryptodev_list, softnic_cryptodev);
-
 /**
  * Input port action
  */
@@ -187,7 +165,6 @@ enum softnic_port_in_type {
 	PORT_IN_SWQ,
 	PORT_IN_TAP,
 	PORT_IN_SOURCE,
-	PORT_IN_CRYPTODEV,
 };
 
 struct softnic_port_in_params {
@@ -209,12 +186,6 @@ struct softnic_port_in_params {
 			const char *file_name;
 			uint32_t n_bytes_per_pkt;
 		} source;
-
-		struct {
-			uint16_t queue_id;
-			void *f_callback;
-			void *arg_callback;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 
@@ -227,7 +198,6 @@ enum softnic_port_out_type {
 	PORT_OUT_SWQ,
 	PORT_OUT_TAP,
 	PORT_OUT_SINK,
-	PORT_OUT_CRYPTODEV,
 };
 
 struct softnic_port_out_params {
@@ -242,11 +212,6 @@ struct softnic_port_out_params {
 			const char *file_name;
 			uint32_t max_n_pkts;
 		} sink;
-
-		struct {
-			uint16_t queue_id;
-			uint32_t op_offset;
-		} cryptodev;
 	};
 	uint32_t burst_size;
 	int retry;
@@ -421,7 +386,6 @@ struct pmd_internals {
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
 	struct softnic_tap_list tap_list;
-	struct softnic_cryptodev_list cryptodev_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;
@@ -519,24 +483,6 @@ struct softnic_tap *
 softnic_tap_create(struct pmd_internals *p,
 	const char *name);
 
-/**
- * Sym Crypto
- */
-int
-softnic_cryptodev_init(struct pmd_internals *p);
-
-void
-softnic_cryptodev_free(struct pmd_internals *p);
-
-struct softnic_cryptodev *
-softnic_cryptodev_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_cryptodev *
-softnic_cryptodev_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_cryptodev_params *params);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 2cf7fa52d1..51a1ea73c0 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -227,7 +227,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		struct rte_port_sched_reader_params sched;
 		struct rte_port_fd_reader_params fd;
 		struct rte_port_source_params source;
-		struct rte_port_sym_crypto_reader_params cryptodev;
 	} pp;
 
 	struct pipeline *pipeline;
@@ -330,23 +329,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.f_callback = params->cryptodev.f_callback;
-		pp.cryptodev.arg_callback = params->cryptodev.arg_callback;
-		p.ops = &rte_port_sym_crypto_reader_ops;
-		p.arg_create = &pp.cryptodev;
-		break;
-	}
-
 	default:
 		return -1;
 	}
@@ -433,14 +415,12 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		struct rte_port_sched_writer_params sched;
 		struct rte_port_fd_writer_params fd;
 		struct rte_port_sink_params sink;
-		struct rte_port_sym_crypto_writer_params cryptodev;
 	} 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;
-		struct rte_port_sym_crypto_writer_nodrop_params cryptodev;
 	} pp_nodrop;
 
 	struct pipeline *pipeline;
@@ -554,40 +534,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_CRYPTODEV:
-	{
-		struct softnic_cryptodev *cryptodev;
-
-		cryptodev = softnic_cryptodev_find(softnic, params->dev_name);
-		if (cryptodev == NULL)
-			return -1;
-
-		if (params->cryptodev.queue_id >= cryptodev->n_queues)
-			return -1;
-
-		pp.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp.cryptodev.tx_burst_sz = params->burst_size;
-		pp.cryptodev.crypto_op_offset = params->cryptodev.op_offset;
-
-		pp_nodrop.cryptodev.cryptodev_id = cryptodev->dev_id;
-		pp_nodrop.cryptodev.queue_id = params->cryptodev.queue_id;
-		pp_nodrop.cryptodev.tx_burst_sz = params->burst_size;
-		pp_nodrop.cryptodev.n_retries = params->retry;
-		pp_nodrop.cryptodev.crypto_op_offset =
-				params->cryptodev.op_offset;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_sym_crypto_writer_ops;
-			p.arg_create = &pp.cryptodev;
-		} else {
-			p.ops = &rte_port_sym_crypto_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.cryptodev;
-		}
-
-		break;
-	}
-
 	default:
 		return -1;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 05/21] net/softnic: remove tap support
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (3 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 04/21] net/softnic: remove cryptodev support Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
                     ` (16 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the TUN/TAP device support. The TUN/TAP devices are still
supported as virtual Ethernet devices through the TAP Poll Mode
Driver.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  76 -----------
 .../net/softnic/rte_eth_softnic_internals.h   |  36 ------
 .../net/softnic/rte_eth_softnic_pipeline.c    |  44 -------
 drivers/net/softnic/rte_eth_softnic_tap.c     | 118 ------------------
 6 files changed, 278 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_tap.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index b3d235841d..91f1f3220f 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -16,7 +16,6 @@ sources = files(
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
-        'rte_eth_softnic_tap.c',
         'rte_eth_softnic_thread.c',
 )
 deps += ['pipeline', 'port', 'table']
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 1ea5989223..eb97ae7185 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -162,7 +162,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
@@ -183,7 +182,6 @@ pmd_free(struct pmd_internals *p)
 	softnic_pipeline_free(p);
 	softnic_table_action_profile_free(p);
 	softnic_port_in_action_profile_free(p);
-	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
@@ -263,7 +261,6 @@ pmd_init(struct pmd_params *params)
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
-	softnic_tap_init(p);
 	softnic_port_in_action_profile_init(p);
 	softnic_table_action_profile_init(p);
 	softnic_pipeline_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index bca0b176d6..501ef08c4c 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -186,33 +186,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * tap <tap_name>
- */
-static void
-cmd_tap(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *name;
-	struct softnic_tap *tap;
-
-	if (n_tokens != 2) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	tap = softnic_tap_create(softnic, name);
-	if (tap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * port in action profile <profile_name>
  *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
@@ -874,7 +847,6 @@ cmd_pipeline(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> rxq <queue_id>
  *  | swq <swq_name>
- *  | tap <tap_name> mempool <mempool_name> mtu <mtu>
  *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
  *  [action <port_in_action_profile_name>]
  *  [disabled]
@@ -957,38 +929,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
 
 		t0 += 2;
-	} else if (strcmp(tokens[t0], "tap") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in tap");
-			return;
-		}
-
-		p.type = PORT_IN_TAP;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.tap.mempool_name = tokens[t0 + 3];
-
-		if (strcmp(tokens[t0 + 4], "mtu") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mtu");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tap.mtu,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
-			return;
-		}
-
-		t0 += 6;
 	} else if (strcmp(tokens[t0], "source") == 0) {
 		if (n_tokens < t0 + 6) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1074,7 +1014,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
  *  bsz <burst_size>
  *  link <link_name> txq <txq_id>
  *  | swq <swq_name>
- *  | tap <tap_name>
  *  | sink [file <file_name> pkts <max_n_pkts>]
  */
 static void
@@ -1147,16 +1086,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "tap") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out tap");
-			return;
-		}
-
-		p.type = PORT_OUT_TAP;
-
 		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
 	} else if (strcmp(tokens[6], "sink") == 0) {
 		if ((n_tokens != 7) && (n_tokens != 11)) {
@@ -4600,11 +4529,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "tap") == 0) {
-		cmd_tap(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "port") == 0) {
 		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index ddcde99b98..df74c1fbdc 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -89,17 +89,6 @@ struct softnic_link {
 
 TAILQ_HEAD(softnic_link_list, softnic_link);
 
-/**
- * TAP
- */
-struct softnic_tap {
-	TAILQ_ENTRY(softnic_tap) node;
-	char name[NAME_SIZE];
-	int fd;
-};
-
-TAILQ_HEAD(softnic_tap_list, softnic_tap);
-
 /**
  * Input port action
  */
@@ -163,7 +152,6 @@ struct pipeline_params {
 enum softnic_port_in_type {
 	PORT_IN_RXQ,
 	PORT_IN_SWQ,
-	PORT_IN_TAP,
 	PORT_IN_SOURCE,
 };
 
@@ -176,11 +164,6 @@ struct softnic_port_in_params {
 			uint16_t queue_id;
 		} rxq;
 
-		struct {
-			const char *mempool_name;
-			uint32_t mtu;
-		} tap;
-
 		struct {
 			const char *mempool_name;
 			const char *file_name;
@@ -196,7 +179,6 @@ struct softnic_port_in_params {
 enum softnic_port_out_type {
 	PORT_OUT_TXQ,
 	PORT_OUT_SWQ,
-	PORT_OUT_TAP,
 	PORT_OUT_SINK,
 };
 
@@ -385,7 +367,6 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
-	struct softnic_tap_list tap_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;
@@ -466,23 +447,6 @@ softnic_link_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_link_params *params);
 
-/**
- * TAP
- */
-int
-softnic_tap_init(struct pmd_internals *p);
-
-void
-softnic_tap_free(struct pmd_internals *p);
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name);
-
 /**
  * Input port action
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 51a1ea73c0..7a2828b785 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -293,25 +293,6 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_IN_TAP:
-	{
-		struct softnic_tap *tap;
-		struct softnic_mempool *mempool;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		mempool = softnic_mempool_find(softnic, params->tap.mempool_name);
-		if (tap == NULL || mempool == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.mempool = mempool->m;
-		pp.fd.mtu = params->tap.mtu;
-
-		p.ops = &rte_port_fd_reader_ops;
-		p.arg_create = &pp.fd;
-		break;
-	}
-
 	case PORT_IN_SOURCE:
 	{
 		struct softnic_mempool *mempool;
@@ -499,31 +480,6 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		break;
 	}
 
-	case PORT_OUT_TAP:
-	{
-		struct softnic_tap *tap;
-
-		tap = softnic_tap_find(softnic, params->dev_name);
-		if (tap == NULL)
-			return -1;
-
-		pp.fd.fd = tap->fd;
-		pp.fd.tx_burst_sz = params->burst_size;
-
-		pp_nodrop.fd.fd = tap->fd;
-		pp_nodrop.fd.tx_burst_sz = params->burst_size;
-		pp_nodrop.fd.n_retries = params->n_retries;
-
-		if (params->retry == 0) {
-			p.ops = &rte_port_fd_writer_ops;
-			p.arg_create = &pp.fd;
-		} else {
-			p.ops = &rte_port_fd_writer_nodrop_ops;
-			p.arg_create = &pp_nodrop.fd;
-		}
-		break;
-	}
-
 	case PORT_OUT_SINK:
 	{
 		pp.sink.file_name = params->sink.file_name;
diff --git a/drivers/net/softnic/rte_eth_softnic_tap.c b/drivers/net/softnic/rte_eth_softnic_tap.c
deleted file mode 100644
index 36fe9f0287..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_tap.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <netinet/in.h>
-#ifdef RTE_EXEC_ENV_LINUX
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#endif
-#include <sys/ioctl.h>
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-#define TAP_DEV                                            "/dev/net/tun"
-
-int
-softnic_tap_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->tap_list);
-
-	return 0;
-}
-
-void
-softnic_tap_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_tap *tap;
-
-		tap = TAILQ_FIRST(&p->tap_list);
-		if (tap == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->tap_list, tap, node);
-		free(tap);
-	}
-}
-
-struct softnic_tap *
-softnic_tap_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(tap, &p->tap_list, node)
-		if (strcmp(tap->name, name) == 0)
-			return tap;
-
-	return NULL;
-}
-
-#ifndef RTE_EXEC_ENV_LINUX
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p __rte_unused,
-	const char *name __rte_unused)
-{
-	return NULL;
-}
-
-#else
-
-struct softnic_tap *
-softnic_tap_create(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_tap *tap;
-	struct ifreq ifr;
-	int fd, status;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_tap_find(p, name))
-		return NULL;
-
-	/* Resource create */
-	fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
-	if (fd < 0)
-		return NULL;
-
-	memset(&ifr, 0, sizeof(ifr));
-	ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
-	strlcpy(ifr.ifr_name, name, IFNAMSIZ);
-
-	status = ioctl(fd, TUNSETIFF, (void *)&ifr);
-	if (status < 0) {
-		close(fd);
-		return NULL;
-	}
-
-	/* Node allocation */
-	tap = calloc(1, sizeof(struct softnic_tap));
-	if (tap == NULL) {
-		close(fd);
-		return NULL;
-	}
-	/* Node fill in */
-	strlcpy(tap->name, name, sizeof(tap->name));
-	tap->fd = fd;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->tap_list, tap, node);
-
-	return tap;
-}
-
-#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 06/21] net/softnic: remove the legacy pipeline CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (4 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 05/21] net/softnic: remove tap support Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
                     ` (15 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the legacy pipeline CLI commands.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 4527 ---------------------
 1 file changed, 4527 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 501ef08c4c..abe275ec83 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -10,7 +10,6 @@
 #include <rte_common.h>
 #include <rte_cycles.h>
 #include <rte_string_fns.h>
-#include <rte_cryptodev.h>
 
 #include "rte_eth_softnic_internals.h"
 #include "parser.h"
@@ -186,4227 +185,6 @@ cmd_swq(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * port in action profile <profile_name>
- *  [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
- *  [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
- */
-static void
-cmd_port_in_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_action_profile_params p;
-	struct softnic_port_in_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[2], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[3], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[4];
-
-	t0 = 5;
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "filter") == 0)) {
-		uint32_t size;
-
-		if (n_tokens < t0 + 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "match") == 0) {
-			p.fltr.filter_on_match = 1;
-		} else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
-			p.fltr.filter_on_match = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.fltr.key_mask, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
-		if ((softnic_parse_hex_string(tokens[t0 + 7],
-			p.fltr.key, &size) != 0) ||
-			size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.fltr.port_id,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
-		t0 += 10;
-	} /* filter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		uint32_t i;
-
-		if (n_tokens < t0 + 22) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"port in action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "port") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-			return;
-		}
-
-		for (i = 0; i < 16; i++)
-			if (softnic_parser_read_uint32(&p.lb.port_id[i],
-			tokens[t0 + 6 + i]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-				return;
-			}
-
-		p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
-		t0 += 22;
-	} /* balance */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_port_in_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * table action profile <profile_name>
- *  ipv4 | ipv6
- *  offset <ip_offset>
- *  fwd
- *  [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
- *  [meter srtcm | trtcm
- *      tc <n_tc>
- *      stats none | pkts | bytes | both]
- *  [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
- *  [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe |
- *      vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]
- *  [nat src | dst
- *      proto udp | tcp]
- *  [ttl drop | fwd
- *      stats none | pkts]
- *  [stats pkts | bytes | both]
- *  [time]
- *  [tag]
- *  [decap]
- *
- */
-static void
-cmd_table_action_profile(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_action_profile_params p;
-	struct softnic_table_action_profile *ap;
-	char *name;
-	uint32_t t0;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	if (strcmp(tokens[1], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
-		return;
-	}
-
-	if (strcmp(tokens[2], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	name = tokens[3];
-
-	if (strcmp(tokens[4], "ipv4") == 0) {
-		p.common.ip_version = 1;
-	} else if (strcmp(tokens[4], "ipv6") == 0) {
-		p.common.ip_version = 0;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
-		return;
-	}
-
-	if (strcmp(tokens[5], "offset") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.common.ip_offset,
-		tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
-		return;
-	}
-
-	if (strcmp(tokens[7], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
-		return;
-	}
-
-	p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
-
-	t0 = 8;
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "balance") == 0)) {
-		if (n_tokens < t0 + 7) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
-		if (softnic_parse_hex_string(tokens[t0 + 4],
-			p.lb.key_mask, &p.lb.key_size) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.lb.out_offset,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
-		t0 += 7;
-	} /* balance */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "meter") == 0)) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile meter");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
-		} else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
-			p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"srtcm or trtcm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "tc") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.mtr.n_tc,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 5], "none") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
-			p.mtr.n_packets_enabled = 0;
-			p.mtr.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 5], "both") == 0) {
-			p.mtr.n_packets_enabled = 1;
-			p.mtr.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
-		t0 += 6;
-	} /* meter */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tm") == 0)) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile tm");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "spp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_subports_per_port");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "pps") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_pipes_per_subport");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
-		t0 += 5;
-	} /* tm */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "encap") == 0)) {
-		uint32_t n_extra_tokens = 0;
-
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"action profile encap");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "ether") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
-		} else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
-		} else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
-		} else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
-		} else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
-		} else if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
-			if (n_tokens < t0 + 2 + 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					"action profile encap vxlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2], "offset") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: offset");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.encap.vxlan.data_offset,
-				tokens[t0 + 2 + 1]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ether_offset");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
-				p.encap.vxlan.ip_version = 1;
-			else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
-				p.encap.vxlan.ip_version = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: ipv4 or ipv6");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"vxlan: vlan");
-				return;
-			}
-
-			if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
-				p.encap.vxlan.vlan = 1;
-			else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
-				p.encap.vxlan.vlan = 0;
-			else {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"vxlan: on or off");
-				return;
-			}
-
-			p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
-			n_extra_tokens = 5;
-
-		} else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) {
-			p.encap.encap_mask =
-				1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
-		t0 += 2 + n_extra_tokens;
-	} /* encap */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "nat") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile nat");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "src") == 0) {
-			p.nat.source_nat = 1;
-		} else if (strcmp(tokens[t0 + 1], "dst") == 0) {
-			p.nat.source_nat = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"src or dst");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "proto") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "tcp") == 0) {
-			p.nat.proto = 0x06;
-		} else if (strcmp(tokens[t0 + 3], "udp") == 0) {
-			p.nat.proto = 0x11;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"tcp or udp");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
-		t0 += 4;
-	} /* nat */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "ttl") == 0)) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile ttl");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "drop") == 0) {
-			p.ttl.drop = 1;
-		} else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
-			p.ttl.drop = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"drop or fwd");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "stats") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "none") == 0) {
-			p.ttl.n_packets_enabled = 0;
-		} else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
-			p.ttl.n_packets_enabled = 1;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"none or pkts");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
-		t0 += 4;
-	} /* ttl */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "stats") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"table action profile stats");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 1], "pkts") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 0;
-		} else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
-			p.stats.n_packets_enabled = 0;
-			p.stats.n_bytes_enabled = 1;
-		} else if (strcmp(tokens[t0 + 1], "both") == 0) {
-			p.stats.n_packets_enabled = 1;
-			p.stats.n_bytes_enabled = 1;
-		} else {
-			snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
-				"pkts or bytes or both");
-			return;
-		}
-
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
-		t0 += 2;
-	} /* stats */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "time") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
-		t0 += 1;
-	} /* time */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "tag") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG;
-		t0 += 1;
-	} /* tag */
-
-	if (t0 < n_tokens &&
-		(strcmp(tokens[t0], "decap") == 0)) {
-		p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP;
-		t0 += 1;
-	} /* decap */
-
-	if (t0 < n_tokens) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	ap = softnic_table_action_profile_create(softnic, name, &p);
-	if (ap == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name>
- *  period <timer_period_ms>
- *  offset_port_id <offset_port_id>
- */
-static void
-cmd_pipeline(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct pipeline_params p;
-	char *name;
-	struct pipeline *pipeline;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "period") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.timer_period_ms,
-		tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
-		return;
-	}
-
-	if (strcmp(tokens[4], "offset_port_id") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.offset_port_id,
-		tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
-		return;
-	}
-
-	pipeline = softnic_pipeline_create(softnic, name, &p);
-	if (pipeline == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in
- *  bsz <burst_size>
- *  link <link_name> rxq <queue_id>
- *  | swq <swq_name>
- *  | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
- *  [action <port_in_action_profile_name>]
- *  [disabled]
- */
-static void
-cmd_pipeline_port_in(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_in_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int enabled, status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	t0 = 6;
-
-	if (strcmp(tokens[t0], "link") == 0) {
-		if (n_tokens < t0 + 4) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in link");
-			return;
-		}
-
-		p.type = PORT_IN_RXQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.rxq.queue_id,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"queue_id");
-			return;
-		}
-		t0 += 4;
-	} else if (strcmp(tokens[t0], "swq") == 0) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in swq");
-			return;
-		}
-
-		p.type = PORT_IN_SWQ;
-
-		strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name));
-
-		t0 += 2;
-	} else if (strcmp(tokens[t0], "source") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port in source");
-			return;
-		}
-
-		p.type = PORT_IN_SOURCE;
-
-		if (strcmp(tokens[t0 + 1], "mempool") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"mempool");
-			return;
-		}
-
-		p.source.mempool_name = tokens[t0 + 2];
-
-		if (strcmp(tokens[t0 + 3], "file") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"file");
-			return;
-		}
-
-		p.source.file_name = tokens[t0 + 4];
-
-		if (strcmp(tokens[t0 + 5], "bpp") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"bpp");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
-			tokens[t0 + 6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"n_bytes_per_pkt");
-			return;
-		}
-
-		t0 += 7;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	enabled = 1;
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "disabled") == 0)) {
-		enabled = 0;
-
-		t0 += 1;
-	}
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_in_create(softnic,
-		pipeline_name,
-		&p,
-		enabled);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out
- *  bsz <burst_size>
- *  link <link_name> txq <txq_id>
- *  | swq <swq_name>
- *  | sink [file <file_name> pkts <max_n_pkts>]
- */
-static void
-cmd_pipeline_port_out(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_port_out_params p;
-	char *pipeline_name;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (strcmp(tokens[4], "bsz") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
-		return;
-	}
-
-	if (strcmp(tokens[6], "link") == 0) {
-		if (n_tokens != 10) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out link");
-			return;
-		}
-
-		p.type = PORT_OUT_TXQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-
-		if (strcmp(tokens[8], "txq") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
-			return;
-		}
-
-		if (softnic_parser_read_uint16(&p.txq.queue_id,
-			tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
-			return;
-		}
-	} else if (strcmp(tokens[6], "swq") == 0) {
-		if (n_tokens != 8) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out swq");
-			return;
-		}
-
-		p.type = PORT_OUT_SWQ;
-
-		strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name));
-	} else if (strcmp(tokens[6], "sink") == 0) {
-		if ((n_tokens != 7) && (n_tokens != 11)) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline port out sink");
-			return;
-		}
-
-		p.type = PORT_OUT_SINK;
-
-		if (n_tokens == 7) {
-			p.sink.file_name = NULL;
-			p.sink.max_n_pkts = 0;
-		} else {
-			if (strcmp(tokens[7], "file") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-					"file");
-				return;
-			}
-
-			p.sink.file_name = tokens[8];
-
-			if (strcmp(tokens[9], "pkts") != 0) {
-				snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
-				return;
-			}
-
-			if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
-				tokens[10]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
-				return;
-			}
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table
- *      match
- *      acl
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | array
- *          offset <key_offset>
- *          size <n_keys>
- *      | hash
- *          ext | lru
- *          key <key_size>
- *          mask <key_mask>
- *          offset <key_offset>
- *          buckets <n_buckets>
- *          size <n_keys>
- *      | lpm
- *          ipv4 | ipv6
- *          offset <ip_header_offset>
- *          size <n_rules>
- *      | stub
- *  [action <table_action_profile_name>]
- */
-static void
-cmd_pipeline_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_params p;
-	char *pipeline_name;
-	uint32_t t0;
-	int status;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens < 5) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (strcmp(tokens[3], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return;
-	}
-
-	t0 = 4;
-	if (strcmp(tokens[t0], "acl") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table acl");
-			return;
-		}
-
-		p.match_type = TABLE_ACL;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.acl.ip_version = 1;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.acl.ip_version = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"ip_header_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.acl.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "array") == 0) {
-		if (n_tokens < t0 + 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table array");
-			return;
-		}
-
-		p.match_type = TABLE_ARRAY;
-
-		if (strcmp(tokens[t0 + 1], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.key_offset,
-			tokens[t0 + 2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 3], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.array.n_keys,
-			tokens[t0 + 4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 5;
-	} else if (strcmp(tokens[t0], "hash") == 0) {
-		uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-		if (n_tokens < t0 + 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table hash");
-			return;
-		}
-
-		p.match_type = TABLE_HASH;
-
-		if (strcmp(tokens[t0 + 1], "ext") == 0) {
-			p.match.hash.extendable_bucket = 1;
-		} else if (strcmp(tokens[t0 + 1], "lru") == 0) {
-			p.match.hash.extendable_bucket = 0;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ext or lru");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "key") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
-			return;
-		}
-
-		if ((softnic_parser_read_uint32(&p.match.hash.key_size,
-			tokens[t0 + 3]) != 0) ||
-			p.match.hash.key_size == 0 ||
-			p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "mask") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
-			return;
-		}
-
-		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			p.match.hash.key_mask, &key_mask_size) != 0) ||
-			key_mask_size != p.match.hash.key_size) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 6], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.key_offset,
-			tokens[t0 + 7]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 8], "buckets") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
-			tokens[t0 + 9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 10], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.hash.n_keys,
-			tokens[t0 + 11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
-			return;
-		}
-
-		t0 += 12;
-	} else if (strcmp(tokens[t0], "lpm") == 0) {
-		if (n_tokens < t0 + 6) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"pipeline table lpm");
-			return;
-		}
-
-		p.match_type = TABLE_LPM;
-
-		if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
-			p.match.lpm.key_size = 4;
-		} else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
-			p.match.lpm.key_size = 16;
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 2], "offset") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
-			tokens[t0 + 3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
-			return;
-		}
-
-		if (strcmp(tokens[t0 + 4], "size") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
-			tokens[t0 + 5]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-			return;
-		}
-
-		t0 += 6;
-	} else if (strcmp(tokens[t0], "stub") == 0) {
-		p.match_type = TABLE_STUB;
-
-		t0 += 1;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	if (n_tokens > t0 &&
-		(strcmp(tokens[t0], "action") == 0)) {
-		if (n_tokens < t0 + 2) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
-			return;
-		}
-
-		strlcpy(p.action_profile_name, tokens[t0 + 1],
-			sizeof(p.action_profile_name));
-
-		t0 += 2;
-	}
-
-	if (n_tokens > t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> table <table_id>
- */
-static void
-cmd_pipeline_port_in_table(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id, table_id;
-	int status;
-
-	if (n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_connect_to_table(softnic,
-		pipeline_name,
-		port_id,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> stats read [clear]
- */
-
-#define MSG_PIPELINE_PORT_IN_STATS                         \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_in_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_in_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_in_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> enable
- */
-static void
-cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "enable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port in <port_id> disable
- */
-static void
-cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t port_id;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "in") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "disable") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
-		return;
-	}
-
-	status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> port out <port_id> stats read [clear]
- */
-#define MSG_PIPELINE_PORT_OUT_STATS                        \
-	"Pkts in: %" PRIu64 "\n"                           \
-	"Pkts dropped by AH: %" PRIu64 "\n"                \
-	"Pkts dropped by other: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_port_out_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_port_out_stats stats;
-	char *pipeline_name;
-	uint32_t port_id;
-	int clear, status;
-
-	if (n_tokens != 7 &&
-		n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "port") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (strcmp(tokens[3], "out") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-		return;
-	}
-
-	if (strcmp(tokens[5], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[6], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 8) {
-		if (strcmp(tokens[7], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_port_out_stats_read(softnic,
-		pipeline_name,
-		port_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
-		stats.stats.n_pkts_in,
-		stats.n_pkts_dropped_by_ah,
-		stats.stats.n_pkts_drop);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> stats read [clear]
- */
-#define MSG_PIPELINE_TABLE_STATS                                     \
-	"Pkts in: %" PRIu64 "\n"                                     \
-	"Pkts in with lookup miss: %" PRIu64 "\n"                    \
-	"Pkts in with lookup hit dropped by AH: %" PRIu64 "\n"       \
-	"Pkts in with lookup hit dropped by others: %" PRIu64 "\n"   \
-	"Pkts in with lookup miss dropped by AH: %" PRIu64 "\n"      \
-	"Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
-
-static void
-cmd_pipeline_table_stats(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_pipeline_table_stats stats;
-	char *pipeline_name;
-	uint32_t table_id;
-	int clear, status;
-
-	if (n_tokens != 6 &&
-		n_tokens != 7) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "stats") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
-		return;
-	}
-
-	if (strcmp(tokens[5], "read") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
-		return;
-	}
-
-	clear = 0;
-	if (n_tokens == 7) {
-		if (strcmp(tokens[6], "clear") != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "clear");
-			return;
-		}
-
-		clear = 1;
-	}
-
-	status = softnic_pipeline_table_stats_read(softnic,
-		pipeline_name,
-		table_id,
-		&stats,
-		clear);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-
-	snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
-		stats.stats.n_pkts_in,
-		stats.stats.n_pkts_lookup_miss,
-		stats.n_pkts_dropped_by_lkp_hit_ah,
-		stats.n_pkts_dropped_lkp_hit,
-		stats.n_pkts_dropped_by_lkp_miss_ah,
-		stats.n_pkts_dropped_lkp_miss);
-}
-
-/**
- * <match> ::=
- *
- * match
- *    acl
- *       priority <priority>
- *       ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
- *       <sp0> <sp1> <dp0> <dp1> <proto>
- *    | array <pos>
- *    | hash
- *       raw <key>
- *       | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
- *       | ipv4_addr <addr>
- *       | ipv6_addr <addr>
- *       | qinq <svlan> <cvlan>
- *    | lpm
- *       ipv4 | ipv6 <addr> <depth>
- */
-struct pkt_key_qinq {
-	uint16_t ethertype_svlan;
-	uint16_t svlan;
-	uint16_t ethertype_cvlan;
-	uint16_t cvlan;
-} __rte_packed;
-
-struct pkt_key_ipv4_5tuple {
-	uint8_t time_to_live;
-	uint8_t proto;
-	uint16_t hdr_checksum;
-	uint32_t sa;
-	uint32_t da;
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv6_5tuple {
-	uint16_t payload_length;
-	uint8_t proto;
-	uint8_t hop_limit;
-	uint8_t sa[16];
-	uint8_t da[16];
-	uint16_t sp;
-	uint16_t dp;
-} __rte_packed;
-
-struct pkt_key_ipv4_addr {
-	uint32_t addr;
-} __rte_packed;
-
-struct pkt_key_ipv6_addr {
-	uint8_t addr[16];
-} __rte_packed;
-
-static uint32_t
-parse_match(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_match *m)
-{
-	memset(m, 0, sizeof(*m));
-
-	if (n_tokens < 2)
-		return 0;
-
-	if (strcmp(tokens[0], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
-		return 0;
-	}
-
-	if (strcmp(tokens[1], "acl") == 0) {
-		if (n_tokens < 14) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ACL;
-
-		if (strcmp(tokens[2], "priority") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.priority,
-			tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "priority");
-			return 0;
-		}
-
-		if (strcmp(tokens[4], "ipv4") == 0) {
-			struct in_addr saddr, daddr;
-
-			m->match.acl.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
-
-			if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
-		} else if (strcmp(tokens[4], "ipv6") == 0) {
-			struct in6_addr saddr, daddr;
-
-			m->match.acl.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
-
-			if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-			memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.sa_depth,
-			tokens[6]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint32(&m->match.acl.da_depth,
-			tokens[8]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "proto");
-			return 0;
-		}
-
-		m->match.acl.proto_mask = 0xff;
-
-		return 14;
-	} /* acl */
-
-	if (strcmp(tokens[1], "array") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_ARRAY;
-
-		if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pos");
-			return 0;
-		}
-
-		return 3;
-	} /* array */
-
-	if (strcmp(tokens[1], "hash") == 0) {
-		if (n_tokens < 3) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_HASH;
-
-		if (strcmp(tokens[2], "raw") == 0) {
-			uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_hex_string(tokens[3],
-				m->match.hash.key, &key_size) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "key");
-				return 0;
-			}
-
-			return 4;
-		} /* hash raw */
-
-		if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
-			struct pkt_key_ipv4_5tuple *ipv4 =
-				(struct pkt_key_ipv4_5tuple *)m->match.hash.key;
-			struct in_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			ipv4->sa = saddr.s_addr;
-			ipv4->da = daddr.s_addr;
-			ipv4->sp = rte_cpu_to_be_16(sp);
-			ipv4->dp = rte_cpu_to_be_16(dp);
-			ipv4->proto = proto;
-
-			return 8;
-		} /* hash ipv4_5tuple */
-
-		if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
-			struct pkt_key_ipv6_5tuple *ipv6 =
-				(struct pkt_key_ipv6_5tuple *)m->match.hash.key;
-			struct in6_addr saddr, daddr;
-			uint16_t sp, dp;
-			uint8_t proto;
-
-			if (n_tokens < 8) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sa");
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "da");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "sp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID, "dp");
-				return 0;
-			}
-
-			if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"proto");
-				return 0;
-			}
-
-			memcpy(ipv6->sa, saddr.s6_addr, 16);
-			memcpy(ipv6->da, daddr.s6_addr, 16);
-			ipv6->sp = rte_cpu_to_be_16(sp);
-			ipv6->dp = rte_cpu_to_be_16(dp);
-			ipv6->proto = proto;
-
-			return 8;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "ipv4_addr") == 0) {
-			struct pkt_key_ipv4_addr *ipv4_addr =
-				(struct pkt_key_ipv4_addr *)m->match.hash.key;
-			struct in_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			ipv4_addr->addr = addr.s_addr;
-
-			return 4;
-		} /* hash ipv4_addr */
-
-		if (strcmp(tokens[2], "ipv6_addr") == 0) {
-			struct pkt_key_ipv6_addr *ipv6_addr =
-				(struct pkt_key_ipv6_addr *)m->match.hash.key;
-			struct in6_addr addr;
-
-			if (n_tokens < 4) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(ipv6_addr->addr, addr.s6_addr, 16);
-
-			return 4;
-		} /* hash ipv6_5tuple */
-
-		if (strcmp(tokens[2], "qinq") == 0) {
-			struct pkt_key_qinq *qinq =
-				(struct pkt_key_qinq *)m->match.hash.key;
-			uint16_t svlan, cvlan;
-
-			if (n_tokens < 5) {
-				snprintf(out, out_size, MSG_ARG_MISMATCH,
-					tokens[0]);
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) ||
-				svlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"svlan");
-				return 0;
-			}
-
-			if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) ||
-				cvlan > 0xFFF) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"cvlan");
-				return 0;
-			}
-
-			qinq->svlan = rte_cpu_to_be_16(svlan);
-			qinq->cvlan = rte_cpu_to_be_16(cvlan);
-
-			return 5;
-		} /* hash qinq */
-
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return 0;
-	} /* hash */
-
-	if (strcmp(tokens[1], "lpm") == 0) {
-		if (n_tokens < 5) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return 0;
-		}
-
-		m->match_type = TABLE_LPM;
-
-		if (strcmp(tokens[2], "ipv4") == 0) {
-			struct in_addr addr;
-
-			m->match.lpm.ip_version = 1;
-
-			if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		} else if (strcmp(tokens[2], "ipv6") == 0) {
-			struct in6_addr addr;
-
-			m->match.lpm.ip_version = 0;
-
-			if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
-				snprintf(out, out_size, MSG_ARG_INVALID,
-					"addr");
-				return 0;
-			}
-
-			memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
-		} else {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				"ipv4 or ipv6");
-			return 0;
-		}
-
-		if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "depth");
-			return 0;
-		}
-
-		return 5;
-	} /* lpm */
-
-	snprintf(out, out_size, MSG_ARG_MISMATCH,
-		"acl or array or hash or lpm");
-	return 0;
-}
-
-/**
- * table_action ::=
- *
- * action
- *    fwd
- *       drop
- *       | port <port_id>
- *       | meta
- *       | table <table_id>
- *    [balance <out0> ... <out7>]
- *    [meter
- *       tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
- *       tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
- *    [tm subport <subport_id> pipe <pipe_id>]
- *    [encap
- *       ether <da> <sa>
- *       | vlan <da> <sa> <pcp> <dei> <vid>
- *       | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
- *       | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id>
- *       | mpls unicast | multicast
- *          <da> <sa>
- *          label0 <label> <tc> <ttl>
- *          [label1 <label> <tc> <ttl>
- *          [label2 <label> <tc> <ttl>
- *          [label3 <label> <tc> <ttl>]]]
- *       | pppoe <da> <sa> <session_id>]
- *       | vxlan ether <da> <sa>
- *          [vlan <pcp> <dei> <vid>]
- *          ipv4 <sa> <da> <dscp> <ttl>
- *          | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit>
- *          udp <sp> <dp>
- *          vxlan <vni>]
- *    [nat ipv4 | ipv6 <addr> <port>]
- *    [ttl dec | keep]
- *    [stats]
- *    [time]
- *    [tag <tag>]
- *    [decap <n>]
- *    [sym_crypto
- *       encrypt | decrypt
- *       type
- *       | cipher
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *       | cipher_auth
- *          cipher_algo <algo> cipher_key <key> cipher_iv <iv>
- *          auth_algo <algo> auth_key <key> digest_size <size>
- *       | aead
- *          aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad>
- *          digest_size <size>
- *       data_offset <data_offset>]
- *
- * where:
- *    <pa> ::= g | y | r | drop
- */
-static uint32_t
-parse_table_action_fwd(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "fwd") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_DROP;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
-		a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 1;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
-		uint32_t id;
-
-		if (n_tokens < 2 ||
-			softnic_parser_read_uint32(&id, tokens[1]))
-			return 0;
-
-		a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		a->fwd.id = id;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
-		return 1 + 2;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_balance(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t i;
-
-	if (n_tokens == 0 ||
-		(strcmp(tokens[0], "balance") != 0))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
-		return 0;
-
-	for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
-		if (softnic_parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
-			return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
-	return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
-}
-
-static int
-parse_policer_action(char *token, enum rte_table_action_policer *a)
-{
-	if (strcmp(token, "g") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
-		return 0;
-	}
-
-	if (strcmp(token, "y") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
-		return 0;
-	}
-
-	if (strcmp(token, "r") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
-		return 0;
-	}
-
-	if (strcmp(token, "drop") == 0) {
-		*a = RTE_TABLE_ACTION_POLICER_DROP;
-		return 0;
-	}
-
-	return -1;
-}
-
-static uint32_t
-parse_table_action_meter_tc(char **tokens,
-	uint32_t n_tokens,
-	struct rte_table_action_mtr_tc_params *mtr)
-{
-	if (n_tokens < 9 ||
-		strcmp(tokens[0], "meter") ||
-		softnic_parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
-		strcmp(tokens[2], "policer") ||
-		strcmp(tokens[3], "g") ||
-		parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) ||
-		strcmp(tokens[5], "y") ||
-		parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) ||
-		strcmp(tokens[7], "r") ||
-		parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED]))
-		return 0;
-
-	return 9;
-}
-
-static uint32_t
-parse_table_action_meter(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "meter"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens < 10 ||
-		strcmp(tokens[0], "tc0") ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1,
-			&a->mtr.mtr[0]) == 0))
-		return 0;
-
-	tokens += 10;
-	n_tokens -= 10;
-
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "tc1")) {
-		a->mtr.tc_mask = 1;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-		return 1 + 10;
-	}
-
-	if (n_tokens < 30 ||
-		(parse_table_action_meter_tc(tokens + 1,
-			n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
-		strcmp(tokens[10], "tc2") ||
-		(parse_table_action_meter_tc(tokens + 11,
-			n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
-		strcmp(tokens[20], "tc3") ||
-		(parse_table_action_meter_tc(tokens + 21,
-			n_tokens - 21, &a->mtr.mtr[3]) == 0))
-		return 0;
-
-	a->mtr.tc_mask = 0xF;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
-	return 1 + 10 + 3 * 10;
-}
-
-static uint32_t
-parse_table_action_tm(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t subport_id, pipe_id;
-
-	if (n_tokens < 5 ||
-		strcmp(tokens[0], "tm") ||
-		strcmp(tokens[1], "subport") ||
-		softnic_parser_read_uint32(&subport_id, tokens[2]) ||
-		strcmp(tokens[3], "pipe") ||
-		softnic_parser_read_uint32(&pipe_id, tokens[4]))
-		return 0;
-
-	a->tm.subport_id = subport_id;
-	a->tm.pipe_id = pipe_id;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
-	return 5;
-}
-
-static uint32_t
-parse_table_action_encap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens == 0 ||
-		strcmp(tokens[0], "encap"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	/* ether */
-	if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
-		if (n_tokens < 3 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 3;
-	}
-
-	/* vlan */
-	if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
-		uint32_t pcp, dei, vid;
-
-		if (n_tokens < 6 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
-			softnic_parser_read_uint32(&pcp, tokens[3]) ||
-			pcp > 0x7 ||
-			softnic_parser_read_uint32(&dei, tokens[4]) ||
-			dei > 0x1 ||
-			softnic_parser_read_uint32(&vid, tokens[5]) ||
-			vid > 0xFFF)
-			return 0;
-
-		a->encap.vlan.vlan.pcp = pcp & 0x7;
-		a->encap.vlan.vlan.dei = dei & 0x1;
-		a->encap.vlan.vlan.vid = vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 6;
-	}
-
-	/* qinq */
-	if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 9 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF)
-			return 0;
-
-		a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 9;
-	}
-
-	/* qinq_pppoe */
-	if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) {
-		uint32_t svlan_pcp, svlan_dei, svlan_vid;
-		uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
-
-		if (n_tokens < 10 ||
-			softnic_parse_mac_addr(tokens[1],
-				&a->encap.qinq_pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2],
-				&a->encap.qinq_pppoe.ether.sa) ||
-			softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
-			svlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
-			svlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
-			svlan_vid > 0xFFF ||
-			softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
-			cvlan_pcp > 0x7 ||
-			softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
-			cvlan_dei > 0x1 ||
-			softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
-			cvlan_vid > 0xFFF ||
-			softnic_parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id,
-				tokens[9]))
-			return 0;
-
-		a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7;
-		a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1;
-		a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF;
-		a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7;
-		a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1;
-		a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 10;
-	}
-
-	/* mpls */
-	if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
-		uint32_t label, tc, ttl;
-
-		if (n_tokens < 8)
-			return 0;
-
-		if (strcmp(tokens[1], "unicast") == 0)
-			a->encap.mpls.unicast = 1;
-		else if (strcmp(tokens[1], "multicast") == 0)
-			a->encap.mpls.unicast = 0;
-		else
-			return 0;
-
-		if (softnic_parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
-			softnic_parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
-			strcmp(tokens[4], "label0") ||
-			softnic_parser_read_uint32(&label, tokens[5]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[6]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[7]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[0].label = label;
-		a->encap.mpls.mpls[0].tc = tc;
-		a->encap.mpls.mpls[0].ttl = ttl;
-
-		tokens += 8;
-		n_tokens -= 8;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label1")) {
-			a->encap.mpls.mpls_count = 1;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[1].label = label;
-		a->encap.mpls.mpls[1].tc = tc;
-		a->encap.mpls.mpls[1].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label2")) {
-			a->encap.mpls.mpls_count = 2;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[2].label = label;
-		a->encap.mpls.mpls[2].tc = tc;
-		a->encap.mpls.mpls[2].ttl = ttl;
-
-		tokens += 4;
-		n_tokens -= 4;
-
-		if (n_tokens == 0 ||
-			strcmp(tokens[0], "label3")) {
-			a->encap.mpls.mpls_count = 3;
-			a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-			a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-			return 1 + 8 + 4 + 4;
-		}
-
-		if (n_tokens < 4 ||
-			softnic_parser_read_uint32(&label, tokens[1]) ||
-			label > 0xFFFFF ||
-			softnic_parser_read_uint32(&tc, tokens[2]) ||
-			tc > 0x7 ||
-			softnic_parser_read_uint32(&ttl, tokens[3]) ||
-			ttl > 0x3F)
-			return 0;
-
-		a->encap.mpls.mpls[3].label = label;
-		a->encap.mpls.mpls[3].tc = tc;
-		a->encap.mpls.mpls[3].ttl = ttl;
-
-		a->encap.mpls.mpls_count = 4;
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 8 + 4 + 4 + 4;
-	}
-
-	/* pppoe */
-	if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
-		if (n_tokens < 4 ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
-			softnic_parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
-				tokens[3]))
-			return 0;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + 4;
-	}
-
-	/* vxlan */
-	if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) {
-		uint32_t n = 0;
-
-		n_tokens--;
-		tokens++;
-		n++;
-
-		/* ether <da> <sa> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "ether") ||
-			softnic_parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) ||
-			softnic_parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* [vlan <pcp> <dei> <vid>] */
-		if (strcmp(tokens[0], "vlan") == 0) {
-			uint32_t pcp, dei, vid;
-
-			if ((n_tokens < 4) ||
-				softnic_parser_read_uint32(&pcp, tokens[1]) ||
-				(pcp > 7) ||
-				softnic_parser_read_uint32(&dei, tokens[2]) ||
-				(dei > 1) ||
-				softnic_parser_read_uint32(&vid, tokens[3]) ||
-				(vid > 0xFFF))
-				return 0;
-
-			a->encap.vxlan.vlan.pcp = pcp;
-			a->encap.vxlan.vlan.dei = dei;
-			a->encap.vxlan.vlan.vid = vid;
-
-			n_tokens -= 4;
-			tokens += 4;
-			n += 4;
-		}
-
-		/* ipv4 <sa> <da> <dscp> <ttl>
-		   | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */
-		if (strcmp(tokens[0], "ipv4") == 0) {
-			struct in_addr sa, da;
-			uint8_t dscp, ttl;
-
-			if ((n_tokens < 5) ||
-				softnic_parse_ipv4_addr(tokens[1], &sa) ||
-				softnic_parse_ipv4_addr(tokens[2], &da) ||
-				softnic_parser_read_uint8(&dscp, tokens[3]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&ttl, tokens[4]))
-				return 0;
-
-			a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr);
-			a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr);
-			a->encap.vxlan.ipv4.dscp = dscp;
-			a->encap.vxlan.ipv4.ttl = ttl;
-
-			n_tokens -= 5;
-			tokens += 5;
-			n += 5;
-		} else if (strcmp(tokens[0], "ipv6") == 0) {
-			struct in6_addr sa, da;
-			uint32_t flow_label;
-			uint8_t dscp, hop_limit;
-
-			if ((n_tokens < 6) ||
-				softnic_parse_ipv6_addr(tokens[1], &sa) ||
-				softnic_parse_ipv6_addr(tokens[2], &da) ||
-				softnic_parser_read_uint32(&flow_label, tokens[3]) ||
-				softnic_parser_read_uint8(&dscp, tokens[4]) ||
-				(dscp > 64) ||
-				softnic_parser_read_uint8(&hop_limit, tokens[5]))
-				return 0;
-
-			memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
-			memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
-			a->encap.vxlan.ipv6.flow_label = flow_label;
-			a->encap.vxlan.ipv6.dscp = dscp;
-			a->encap.vxlan.ipv6.hop_limit = hop_limit;
-
-			n_tokens -= 6;
-			tokens += 6;
-			n += 6;
-		} else
-			return 0;
-
-		/* udp <sp> <dp> */
-		if ((n_tokens < 3) ||
-			strcmp(tokens[0], "udp") ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) ||
-			softnic_parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2]))
-			return 0;
-
-		n_tokens -= 3;
-		tokens += 3;
-		n += 3;
-
-		/* vxlan <vni> */
-		if ((n_tokens < 2) ||
-			strcmp(tokens[0], "vxlan") ||
-			softnic_parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) ||
-			(a->encap.vxlan.vxlan.vni > 0xFFFFFF))
-			return 0;
-
-		n_tokens -= 2;
-		tokens += 2;
-		n += 2;
-
-		a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
-		return 1 + n;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_nat(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 4 ||
-		strcmp(tokens[0], "nat"))
-		return 0;
-
-	if (strcmp(tokens[1], "ipv4") == 0) {
-		struct in_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv4_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 1;
-		a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	if (strcmp(tokens[1], "ipv6") == 0) {
-		struct in6_addr addr;
-		uint16_t port;
-
-		if (softnic_parse_ipv6_addr(tokens[2], &addr) ||
-			softnic_parser_read_uint16(&port, tokens[3]))
-			return 0;
-
-		a->nat.ip_version = 0;
-		memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
-		a->nat.port = port;
-		a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
-		return 4;
-	}
-
-	return 0;
-}
-
-static uint32_t
-parse_table_action_ttl(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "ttl"))
-		return 0;
-
-	if (strcmp(tokens[1], "dec") == 0)
-		a->ttl.decrement = 1;
-	else if (strcmp(tokens[1], "keep") == 0)
-		a->ttl.decrement = 0;
-	else
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_stats(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "stats"))
-		return 0;
-
-	a->stats.n_packets = 0;
-	a->stats.n_bytes = 0;
-	a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
-	return 1;
-}
-
-static uint32_t
-parse_table_action_time(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 1 ||
-		strcmp(tokens[0], "time"))
-		return 0;
-
-	a->time.time = rte_rdtsc();
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
-	return 1;
-}
-
-static void
-parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
-{
-	struct rte_crypto_sym_xform *xform[2] = {NULL};
-	uint32_t i;
-
-	xform[0] = p->xform;
-	if (xform[0])
-		xform[1] = xform[0]->next;
-
-	for (i = 0; i < 2; i++) {
-		if (xform[i] == NULL)
-			continue;
-
-		switch (xform[i]->type) {
-		case RTE_CRYPTO_SYM_XFORM_CIPHER:
-			free(p->cipher_auth.cipher_iv.val);
-			free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AUTH:
-			if (p->cipher_auth.auth_iv.val)
-				free(p->cipher_auth.cipher_iv.val);
-			if (p->cipher_auth.auth_iv_update.val)
-				free(p->cipher_auth.cipher_iv_update.val);
-			break;
-		case RTE_CRYPTO_SYM_XFORM_AEAD:
-			free(p->aead.iv.val);
-			free(p->aead.aad.val);
-			break;
-		default:
-			continue;
-		}
-	}
-
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	int status;
-	size_t len;
-
-	if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") ||
-			strcmp(tokens[3], "cipher_key") ||
-			strcmp(tokens[5], "cipher_iv"))
-		return NULL;
-
-	xform_cipher = calloc(1, sizeof(*xform_cipher));
-	if (xform_cipher == NULL)
-		return NULL;
-
-	xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
-	xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT :
-			RTE_CRYPTO_CIPHER_OP_DECRYPT;
-
-	/* cipher_algo */
-	status = rte_cryptodev_get_cipher_algo_enum(
-			&xform_cipher->cipher.algo, tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* cipher_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.key.data = key;
-	xform_cipher->cipher.key.length = (uint16_t)len;
-
-	/* cipher_iv */
-	len = strlen(tokens[6]);
-
-	p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1);
-	if (p->cipher_auth.cipher_iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6],
-			p->cipher_auth.cipher_iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher->cipher.iv.length = (uint16_t)len;
-	xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->cipher_auth.cipher_iv.length = (uint32_t)len;
-	*used_n_tokens = 7;
-
-	return xform_cipher;
-
-error_exit:
-	if (p->cipher_auth.cipher_iv.val) {
-		free(p->cipher_auth.cipher_iv.val);
-		p->cipher_auth.cipher_iv.val = NULL;
-	}
-
-	free(xform_cipher);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_cipher;
-	struct rte_crypto_sym_xform *xform_auth;
-	int status;
-	size_t len;
-
-	if (n_tokens < 13 ||
-			strcmp(tokens[7], "auth_algo") ||
-			strcmp(tokens[9], "auth_key") ||
-			strcmp(tokens[11], "digest_size"))
-		return NULL;
-
-	xform_auth = calloc(1, sizeof(*xform_auth));
-	if (xform_auth == NULL)
-		return NULL;
-
-	xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH;
-	xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE :
-			RTE_CRYPTO_AUTH_OP_VERIFY;
-
-	/* auth_algo */
-	status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo,
-			tokens[8]);
-	if (status < 0)
-		goto error_exit;
-
-	/* auth_key */
-	len = strlen(tokens[10]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_auth->auth.key.data = key;
-	xform_auth->auth.key.length = (uint16_t)len;
-
-	key += xform_auth->auth.key.length;
-	max_key_len -= xform_auth->auth.key.length;
-
-	if (strcmp(tokens[11], "digest_size"))
-		goto error_exit;
-
-	status = softnic_parser_read_uint16(&xform_auth->auth.digest_length,
-			tokens[12]);
-	if (status < 0)
-		goto error_exit;
-
-	xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7,
-			encrypt, used_n_tokens);
-	if (xform_cipher == NULL)
-		goto error_exit;
-
-	*used_n_tokens += 6;
-
-	if (encrypt) {
-		xform_cipher->next = xform_auth;
-		return xform_cipher;
-	} else {
-		xform_auth->next = xform_cipher;
-		return xform_auth;
-	}
-
-error_exit:
-	if (p->cipher_auth.auth_iv.val) {
-		free(p->cipher_auth.auth_iv.val);
-		p->cipher_auth.auth_iv.val = 0;
-	}
-
-	free(xform_auth);
-
-	return NULL;
-}
-
-static struct rte_crypto_sym_xform *
-parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
-		uint8_t *key, uint32_t max_key_len, char **tokens,
-		uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
-{
-	struct rte_crypto_sym_xform *xform_aead;
-	int status;
-	size_t len;
-
-	if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") ||
-			strcmp(tokens[3], "aead_key") ||
-			strcmp(tokens[5], "aead_iv") ||
-			strcmp(tokens[7], "aead_aad") ||
-			strcmp(tokens[9], "digest_size"))
-		return NULL;
-
-	xform_aead = calloc(1, sizeof(*xform_aead));
-	if (xform_aead == NULL)
-		return NULL;
-
-	xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD;
-	xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT :
-			RTE_CRYPTO_AEAD_OP_DECRYPT;
-
-	/* aead_algo */
-	status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo,
-			tokens[2]);
-	if (status < 0)
-		goto error_exit;
-
-	/* aead_key */
-	len = strlen(tokens[4]);
-	if (len / 2 > max_key_len) {
-		status = -ENOMEM;
-		goto error_exit;
-	}
-
-	status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.key.data = key;
-	xform_aead->aead.key.length = (uint16_t)len;
-
-	/* aead_iv */
-	len = strlen(tokens[6]);
-	p->aead.iv.val = calloc(1, len / 2 + 1);
-	if (p->aead.iv.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[6], p->aead.iv.val,
-			(uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.iv.length = (uint16_t)len;
-	xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
-	p->aead.iv.length = (uint32_t)len;
-
-	/* aead_aad */
-	len = strlen(tokens[8]);
-	p->aead.aad.val = calloc(1, len / 2 + 1);
-	if (p->aead.aad.val == NULL)
-		goto error_exit;
-
-	status = softnic_parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len);
-	if (status < 0)
-		goto error_exit;
-
-	xform_aead->aead.aad_length = (uint16_t)len;
-	p->aead.aad.length = (uint32_t)len;
-
-	/* digest_size */
-	status = softnic_parser_read_uint16(&xform_aead->aead.digest_length,
-			tokens[10]);
-	if (status < 0)
-		goto error_exit;
-
-	*used_n_tokens = 11;
-
-	return xform_aead;
-
-error_exit:
-	if (p->aead.iv.val) {
-		free(p->aead.iv.val);
-		p->aead.iv.val = NULL;
-	}
-	if (p->aead.aad.val) {
-		free(p->aead.aad.val);
-		p->aead.aad.val = NULL;
-	}
-
-	free(xform_aead);
-
-	return NULL;
-}
-
-
-static uint32_t
-parse_table_action_sym_crypto(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
-	struct rte_crypto_sym_xform *xform = NULL;
-	uint8_t *key = a->sym_crypto_key;
-	uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
-	uint32_t used_n_tokens;
-	uint32_t encrypt;
-	int status;
-
-	if ((n_tokens < 12) ||
-		strcmp(tokens[0], "sym_crypto") ||
-		strcmp(tokens[2], "type"))
-		return 0;
-
-	memset(p, 0, sizeof(*p));
-
-	if (strcmp(tokens[1], "encrypt") == 0)
-		encrypt = 1;
-	else
-		encrypt = 0;
-
-	status = softnic_parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]);
-	if (status < 0)
-		return 0;
-
-	if (strcmp(tokens[3], "cipher") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "cipher_auth") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_cipher_auth(p, key, max_key_len,
-				tokens, n_tokens, encrypt, &used_n_tokens);
-	} else if (strcmp(tokens[3], "aead") == 0) {
-		tokens += 3;
-		n_tokens -= 3;
-
-		xform = parse_table_action_aead(p, key, max_key_len, tokens,
-				n_tokens, encrypt, &used_n_tokens);
-	}
-
-	if (xform == NULL)
-		return 0;
-
-	p->xform = xform;
-
-	if (strcmp(tokens[used_n_tokens], "data_offset")) {
-		parse_free_sym_crypto_param_data(p);
-		return 0;
-	}
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO;
-
-	return used_n_tokens + 5;
-}
-
-static uint32_t
-parse_table_action_tag(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "tag"))
-		return 0;
-
-	if (softnic_parser_read_uint32(&a->tag.tag, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
-	return 2;
-}
-
-static uint32_t
-parse_table_action_decap(char **tokens,
-	uint32_t n_tokens,
-	struct softnic_table_rule_action *a)
-{
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "decap"))
-		return 0;
-
-	if (softnic_parser_read_uint16(&a->decap.n, tokens[1]))
-		return 0;
-
-	a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
-	return 2;
-}
-
-static uint32_t
-parse_table_action(char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size,
-	struct softnic_table_rule_action *a)
-{
-	uint32_t n_tokens0 = n_tokens;
-
-	memset(a, 0, sizeof(*a));
-
-	if (n_tokens < 2 ||
-		strcmp(tokens[0], "action"))
-		return 0;
-
-	tokens++;
-	n_tokens--;
-
-	if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_fwd(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action fwd");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_balance(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action balance");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_meter(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action meter");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tm(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tm");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_encap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action encap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_nat(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action nat");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_ttl(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action ttl");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_stats(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action stats");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_time(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action time");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "tag") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_tag(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action tag");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "decap") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_decap(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action decap");
-			return 0;
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) {
-		uint32_t n;
-
-		n = parse_table_action_sym_crypto(tokens, n_tokens, a);
-		if (n == 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID,
-				"action sym_crypto");
-		}
-
-		tokens += n;
-		n_tokens -= n;
-	}
-
-	if (n_tokens0 - n_tokens == 1) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return 0;
-	}
-
-	return n_tokens0 - n_tokens;
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match <match>
- *    action <table_action>
- */
-static void
-cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	struct softnic_table_rule_action a;
-	char *pipeline_name;
-	void *data;
-	uint32_t table_id, t0, n_tokens_parsed;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	/* action */
-	n_tokens_parsed = parse_table_action(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&a);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (t0 != n_tokens) {
-		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add(softnic,
-		pipeline_name,
-		table_id,
-		&m,
-		&a,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add
- *    match
- *       default
- *    action
- *       fwd
- *          drop
- *          | port <port_id>
- *          | meta
- *          | table <table_id>
- */
-static void
-cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_action action;
-	void *data;
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 11 &&
-		n_tokens != 12) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	if (strcmp(tokens[8], "action") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "action");
-		return;
-	}
-
-	if (strcmp(tokens[9], "fwd") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
-		return;
-	}
-
-	action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
-
-	if (strcmp(tokens[10], "drop") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_DROP;
-	} else if (strcmp(tokens[10], "port") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT;
-		action.fwd.id = id;
-	} else if (strcmp(tokens[10], "meta") == 0) {
-		if (n_tokens != 11) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
-	} else if (strcmp(tokens[10], "table") == 0) {
-		uint32_t id;
-
-		if (n_tokens != 12) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-			return;
-		}
-
-		action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
-		action.fwd.id = id;
-	} else {
-		snprintf(out, out_size, MSG_ARG_INVALID,
-			"drop or port or meta or table");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_add_default(softnic,
-		pipeline_name,
-		table_id,
-		&action,
-		&data);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
- *
- * File <file_name>:
- * - line format: match <match> action <action>
- */
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size);
-
-static void
-cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match *match;
-	struct softnic_table_rule_action *action;
-	void **data;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, n_rules, n_rules_parsed, line_number;
-	int status;
-
-	if (n_tokens != 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[6], "bulk") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
-		return;
-	}
-
-	file_name = tokens[7];
-
-	if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
-		n_rules == 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
-		return;
-	}
-
-	/* Memory allocation. */
-	match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
-	action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
-	data = calloc(n_rules, sizeof(void *));
-	if (match == NULL ||
-		action == NULL ||
-		data == NULL) {
-		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Load rule file */
-	n_rules_parsed = n_rules;
-	status = cli_rule_file_process(file_name,
-		1024,
-		match,
-		action,
-		&n_rules_parsed,
-		&line_number,
-		out,
-		out_size);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-	if (n_rules_parsed != n_rules) {
-		snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Rule bulk add */
-	status = softnic_pipeline_table_rule_add_bulk(softnic,
-		pipeline_name,
-		table_id,
-		match,
-		action,
-		data,
-		&n_rules);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		free(data);
-		free(action);
-		free(match);
-		return;
-	}
-
-	/* Memory free */
-	free(data);
-	free(action);
-	free(match);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match <match>
- */
-static void
-cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_table_rule_match m;
-	char *pipeline_name;
-	uint32_t table_id, n_tokens_parsed, t0;
-	int status;
-
-	if (n_tokens < 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	t0 = 6;
-
-	/* match */
-	n_tokens_parsed = parse_match(tokens + t0,
-		n_tokens - t0,
-		out,
-		out_size,
-		&m);
-	if (n_tokens_parsed == 0)
-		return;
-	t0 += n_tokens_parsed;
-
-	if (n_tokens != t0) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete(softnic,
-		pipeline_name,
-		table_id,
-		&m);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule delete
- *    match
- *       default
- */
-static void
-cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "rule") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
-		return;
-	}
-
-	if (strcmp(tokens[5], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	if (strcmp(tokens[6], "match") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "match");
-		return;
-	}
-
-	if (strcmp(tokens[7], "default") != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "default");
-		return;
-	}
-
-	status = softnic_pipeline_table_rule_delete_default(softnic,
-		pipeline_name,
-		table_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read stats [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>
- *  add srtcm cir <cir> cbs <cbs> ebs <ebs>
- *  | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>
- */
-static void
-cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_meter_profile p;
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens < 9) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "add") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
-		return;
-	}
-
-	if (strcmp(tokens[8], "srtcm") == 0) {
-		if (n_tokens != 15) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH,
-				tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_SRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[13], "ebs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
-			return;
-		}
-	} else if (strcmp(tokens[8], "trtcm") == 0) {
-		if (n_tokens != 17) {
-			snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-			return;
-		}
-
-		p.alg = RTE_TABLE_ACTION_METER_TRTCM;
-
-		if (strcmp(tokens[9], "cir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cir");
-			return;
-		}
-
-		if (strcmp(tokens[11], "pir") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pir");
-			return;
-		}
-		if (strcmp(tokens[13], "cbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
-			return;
-		}
-
-		if (strcmp(tokens[15], "pbs") != 0) {
-			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
-			return;
-		}
-
-		if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_add(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id,
-		&p);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id>
- *  meter profile <meter_profile_id> delete
- */
-static void
-cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	char *pipeline_name;
-	uint32_t table_id, meter_profile_id;
-	int status;
-
-	if (n_tokens != 8) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "meter") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
-		return;
-	}
-
-	if (strcmp(tokens[5], "profile") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
-		return;
-	}
-
-	if (strcmp(tokens[7], "delete") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
-		return;
-	}
-
-	status = softnic_pipeline_table_mtr_profile_delete(softnic,
-		pipeline_name,
-		table_id,
-		meter_profile_id);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read meter [clear]
- */
-static void
-cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> dscp <file_name>
- *
- * File <file_name>:
- *  - exactly 64 lines
- *  - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r
- */
-static int
-load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
-	const char *file_name,
-	uint32_t *line_number)
-{
-	FILE *f = NULL;
-	uint32_t dscp, l;
-
-	/* Check input arguments */
-	if (dscp_table == NULL ||
-		file_name == NULL ||
-		line_number == NULL) {
-		if (line_number)
-			*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Open input file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Read file */
-	for (dscp = 0, l = 1; ; l++) {
-		char line[64];
-		char *tokens[3];
-		enum rte_color color;
-		uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
-
-		if (fgets(line, sizeof(line), f) == NULL)
-			break;
-
-		if (is_comment(line))
-			continue;
-
-		if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		if (n_tokens == 0)
-			continue;
-
-		if (dscp >= RTE_DIM(dscp_table->entry) ||
-			n_tokens != RTE_DIM(tokens) ||
-			softnic_parser_read_uint32(&tc_id, tokens[0]) ||
-			tc_id >= RTE_TABLE_ACTION_TC_MAX ||
-			softnic_parser_read_uint32(&tc_queue_id, tokens[1]) ||
-			tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX ||
-			(strlen(tokens[2]) != 1)) {
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		switch (tokens[2][0]) {
-		case 'g':
-		case 'G':
-			color = RTE_COLOR_GREEN;
-			break;
-
-		case 'y':
-		case 'Y':
-			color = RTE_COLOR_YELLOW;
-			break;
-
-		case 'r':
-		case 'R':
-			color = RTE_COLOR_RED;
-			break;
-
-		default:
-			*line_number = l;
-			fclose(f);
-			return -EINVAL;
-		}
-
-		dscp_table->entry[dscp].tc_id = tc_id;
-		dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
-		dscp_table->entry[dscp].color = color;
-		dscp++;
-	}
-
-	/* Close file */
-	fclose(f);
-	return 0;
-}
-
-static void
-cmd_pipeline_table_dscp(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct rte_table_action_dscp_table dscp_table;
-	char *pipeline_name, *file_name;
-	uint32_t table_id, line_number;
-	int status;
-
-	if (n_tokens != 6) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-
-	pipeline_name = tokens[1];
-
-	if (strcmp(tokens[2], "table") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
-		return;
-	}
-
-	if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
-		snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
-		return;
-	}
-
-	if (strcmp(tokens[4], "dscp") != 0) {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
-		return;
-	}
-
-	file_name = tokens[5];
-
-	status = load_dscp_table(&dscp_table, file_name, &line_number);
-	if (status) {
-		snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
-		return;
-	}
-
-	status = softnic_pipeline_table_dscp_table_update(softnic,
-		pipeline_name,
-		table_id,
-		UINT64_MAX,
-		&dscp_table);
-	if (status) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
-/**
- * pipeline <pipeline_name> table <table_id> rule read ttl [clear]
- */
-static void
-cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused,
-	char **tokens,
-	uint32_t n_tokens __rte_unused,
-	char *out,
-	size_t out_size)
-{
-	snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
-}
-
 /**
  * thread <thread_id> pipeline <pipeline_name> enable
  */
@@ -4529,202 +307,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "port") == 0) {
-		cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "table") == 0) {
-		cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
-	if (strcmp(tokens[0], "pipeline") == 0) {
-		if (n_tokens >= 3 &&
-			(strcmp(tokens[2], "period") == 0)) {
-			cmd_pipeline(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[4], "bsz") == 0)) {
-			cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 4 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[3], "match") == 0)) {
-			cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "table") == 0)) {
-			cmd_pipeline_port_in_table(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_in_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "enable") == 0)) {
-			cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "in") == 0) &&
-			(strcmp(tokens[5], "disable") == 0)) {
-			cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 6 &&
-			(strcmp(tokens[2], "port") == 0) &&
-			(strcmp(tokens[3], "out") == 0) &&
-			(strcmp(tokens[5], "stats") == 0)) {
-			cmd_pipeline_port_out_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "stats") == 0)) {
-			cmd_pipeline_table_stats(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_add_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-			}
-
-			cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "add") == 0) &&
-			(strcmp(tokens[6], "bulk") == 0)) {
-			cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "delete") == 0) &&
-			(strcmp(tokens[6], "match") == 0)) {
-			if (n_tokens >= 8 &&
-				(strcmp(tokens[7], "default") == 0)) {
-				cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens,
-					n_tokens, out, out_size);
-				return;
-				}
-
-			cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "stats") == 0)) {
-			cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "add") == 0)) {
-			cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 8 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "meter") == 0) &&
-			(strcmp(tokens[5], "profile") == 0) &&
-			(strcmp(tokens[7], "delete") == 0)) {
-			cmd_pipeline_table_meter_profile_delete(softnic, tokens,
-				n_tokens, out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "meter") == 0)) {
-			cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 5 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "dscp") == 0)) {
-			cmd_pipeline_table_dscp(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-
-		if (n_tokens >= 7 &&
-			(strcmp(tokens[2], "table") == 0) &&
-			(strcmp(tokens[4], "rule") == 0) &&
-			(strcmp(tokens[5], "read") == 0) &&
-			(strcmp(tokens[6], "ttl") == 0)) {
-			cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens,
-				out, out_size);
-			return;
-		}
-	}
-
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
@@ -4800,112 +382,3 @@ softnic_cli_script_process(struct pmd_internals *softnic,
 	free(msg_in);
 	return 0;
 }
-
-static int
-cli_rule_file_process(const char *file_name,
-	size_t line_len_max,
-	struct softnic_table_rule_match *m,
-	struct softnic_table_rule_action *a,
-	uint32_t *n_rules,
-	uint32_t *line_number,
-	char *out,
-	size_t out_size)
-{
-	FILE *f = NULL;
-	char *line = NULL;
-	uint32_t rule_id, line_id;
-	int status = 0;
-
-	/* Check input arguments */
-	if (file_name == NULL ||
-		(strlen(file_name) == 0) ||
-		line_len_max == 0) {
-		*line_number = 0;
-		return -EINVAL;
-	}
-
-	/* Memory allocation */
-	line = malloc(line_len_max + 1);
-	if (line == NULL) {
-		*line_number = 0;
-		return -ENOMEM;
-	}
-
-	/* Open file */
-	f = fopen(file_name, "r");
-	if (f == NULL) {
-		*line_number = 0;
-		free(line);
-		return -EIO;
-	}
-
-	/* Read file */
-	for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
-		char *tokens[CMD_MAX_TOKENS];
-		uint32_t n_tokens, n_tokens_parsed, t0;
-
-		/* Read next line from file. */
-		if (fgets(line, line_len_max + 1, f) == NULL)
-			break;
-
-		/* Comment. */
-		if (is_comment(line))
-			continue;
-
-		/* Parse line. */
-		n_tokens = RTE_DIM(tokens);
-		status = softnic_parse_tokenize_string(line, tokens, &n_tokens);
-		if (status) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Empty line. */
-		if (n_tokens == 0)
-			continue;
-		t0 = 0;
-
-		/* Rule match. */
-		n_tokens_parsed = parse_match(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&m[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Rule action. */
-		n_tokens_parsed = parse_table_action(tokens + t0,
-			n_tokens - t0,
-			out,
-			out_size,
-			&a[rule_id]);
-		if (n_tokens_parsed == 0) {
-			status = -EINVAL;
-			break;
-		}
-		t0 += n_tokens_parsed;
-
-		/* Line completed. */
-		if (t0 < n_tokens) {
-			status = -EINVAL;
-			break;
-		}
-
-		/* Increment rule count */
-		rule_id++;
-	}
-
-	/* Close file */
-	fclose(f);
-
-	/* Memory free */
-	free(line);
-
-	*n_rules = rule_id;
-	*line_number = line_id;
-	return status;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (5 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 06/21] net/softnic: remove the legacy pipeline CLI commands Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
                     ` (14 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

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


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 08/21] net/softnic: remove the list of Ethernet devices
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (6 preceding siblings ...)
  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   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
                     ` (13 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

The list of Ethernet devices within this driver is redundant, as the
DPDK global list of Ethernet devices can be used instead.

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         |   3 -
 drivers/net/softnic/rte_eth_softnic_cli.c     |  49 ---------
 .../net/softnic/rte_eth_softnic_internals.h   |  37 -------
 drivers/net/softnic/rte_eth_softnic_link.c    | 101 ------------------
 5 files changed, 191 deletions(-)
 delete mode 100644 drivers/net/softnic/rte_eth_softnic_link.c

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index f0cfc6dc17..0ffe26d671 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -11,7 +11,6 @@ sources = files(
         'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
-        'rte_eth_softnic_link.c',
         'rte_eth_softnic_mempool.c',
         'rte_eth_softnic_pipeline.c',
         'rte_eth_softnic_swq.c',
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index a940952c7a..b1f4edd629 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -160,7 +160,6 @@ pmd_dev_stop(struct rte_eth_dev *dev)
 	/* Firmware */
 	softnic_pipeline_disable_all(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_softnic_swq_free_keep_rxq_txq(p);
 	softnic_mempool_free(p);
 
@@ -178,7 +177,6 @@ pmd_free(struct pmd_internals *p)
 
 	softnic_thread_free(p);
 	softnic_pipeline_free(p);
-	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
 
@@ -256,7 +254,6 @@ pmd_init(struct pmd_params *params)
 	/* Resources */
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
-	softnic_link_init(p);
 	softnic_pipeline_init(p);
 
 	status = softnic_thread_init(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 2b00b65c6c..ec9ac133b9 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -102,50 +102,6 @@ cmd_mempool(struct pmd_internals *softnic,
 	}
 }
 
-/**
- * link <link_name>
- *    dev <device_name> | port <port_id>
- */
-static void
-cmd_link(struct pmd_internals *softnic,
-	char **tokens,
-	uint32_t n_tokens,
-	char *out,
-	size_t out_size)
-{
-	struct softnic_link_params p;
-	struct softnic_link *link;
-	char *name;
-
-	memset(&p, 0, sizeof(p));
-
-	if (n_tokens != 4) {
-		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
-		return;
-	}
-	name = tokens[1];
-
-	if (strcmp(tokens[2], "dev") == 0) {
-		p.dev_name = tokens[3];
-	} else if (strcmp(tokens[2], "port") == 0) {
-		p.dev_name = NULL;
-
-		if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) {
-			snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
-			return;
-		}
-	} else {
-		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
-		return;
-	}
-
-	link = softnic_link_create(softnic, name, &p);
-	if (link == NULL) {
-		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
-		return;
-	}
-}
-
 /**
  * swq <swq_name>
  *  size <size>
@@ -309,11 +265,6 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
-	if (strcmp(tokens[0], "link") == 0) {
-		cmd_link(softnic, tokens, n_tokens, out, out_size);
-		return;
-	}
-
 	if (strcmp(tokens[0], "swq") == 0) {
 		cmd_swq(softnic, tokens, n_tokens, out, out_size);
 		return;
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d817883a39..a1c2309589 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -70,24 +70,6 @@ struct softnic_swq {
 
 TAILQ_HEAD(softnic_swq_list, softnic_swq);
 
-/**
- * LINK
- */
-struct softnic_link_params {
-	const char *dev_name;
-	uint16_t port_id; /**< Valid only when *dev_name* is NULL. */
-};
-
-struct softnic_link {
-	TAILQ_ENTRY(softnic_link) node;
-	char name[NAME_SIZE];
-	uint16_t port_id;
-	uint32_t n_rxq;
-	uint32_t n_txq;
-};
-
-TAILQ_HEAD(softnic_link_list, softnic_link);
-
 /**
  * Pipeline
  */
@@ -162,7 +144,6 @@ struct pmd_internals {
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
-	struct softnic_link_list link_list;
 	struct pipeline_list pipeline_list;
 	struct softnic_thread thread[RTE_MAX_LCORE];
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
@@ -223,24 +204,6 @@ softnic_swq_create(struct pmd_internals *p,
 	const char *name,
 	struct softnic_swq_params *params);
 
-/**
- * LINK
- */
-int
-softnic_link_init(struct pmd_internals *p);
-
-void
-softnic_link_free(struct pmd_internals *p);
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name);
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params);
-
 /**
  * Pipeline
  */
diff --git a/drivers/net/softnic/rte_eth_softnic_link.c b/drivers/net/softnic/rte_eth_softnic_link.c
deleted file mode 100644
index 21a64069f6..0000000000
--- a/drivers/net/softnic/rte_eth_softnic_link.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2018 Intel Corporation
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <rte_ethdev.h>
-#include <rte_string_fns.h>
-
-#include "rte_eth_softnic_internals.h"
-
-int
-softnic_link_init(struct pmd_internals *p)
-{
-	TAILQ_INIT(&p->link_list);
-
-	return 0;
-}
-
-void
-softnic_link_free(struct pmd_internals *p)
-{
-	for ( ; ; ) {
-		struct softnic_link *link;
-
-		link = TAILQ_FIRST(&p->link_list);
-		if (link == NULL)
-			break;
-
-		TAILQ_REMOVE(&p->link_list, link, node);
-		free(link);
-	}
-}
-
-struct softnic_link *
-softnic_link_find(struct pmd_internals *p,
-	const char *name)
-{
-	struct softnic_link *link;
-
-	if (name == NULL)
-		return NULL;
-
-	TAILQ_FOREACH(link, &p->link_list, node)
-		if (strcmp(link->name, name) == 0)
-			return link;
-
-	return NULL;
-}
-
-struct softnic_link *
-softnic_link_create(struct pmd_internals *p,
-	const char *name,
-	struct softnic_link_params *params)
-{
-	struct rte_eth_dev_info port_info;
-	struct softnic_link *link;
-	uint16_t port_id;
-	int ret;
-
-	/* Check input params */
-	if (name == NULL ||
-		softnic_link_find(p, name) ||
-		params == NULL)
-		return NULL;
-
-	port_id = params->port_id;
-	if (params->dev_name) {
-		int status;
-
-		status = rte_eth_dev_get_port_by_name(params->dev_name,
-			&port_id);
-
-		if (status)
-			return NULL;
-	} else {
-		if (!rte_eth_dev_is_valid_port(port_id))
-			return NULL;
-	}
-
-	ret = rte_eth_dev_info_get(port_id, &port_info);
-	if (ret != 0)
-		return NULL;
-
-	/* Node allocation */
-	link = calloc(1, sizeof(struct softnic_link));
-	if (link == NULL)
-		return NULL;
-
-	/* Node fill in */
-	strlcpy(link->name, name, sizeof(link->name));
-	link->port_id = port_id;
-	link->n_rxq = port_info.nb_rx_queues;
-	link->n_txq = port_info.nb_tx_queues;
-
-	/* Node add to list */
-	TAILQ_INSERT_TAIL(&p->link_list, link, node);
-
-	return link;
-}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 09/21] net/softnic: remove unused text parsing functions
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (7 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 08/21] net/softnic: remove the list of Ethernet devices Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
                     ` (12 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Remove the text parsing functions that are not used.

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/parser.c              | 523 ----------------------
 drivers/net/softnic/parser.h              |  68 ---
 drivers/net/softnic/rte_eth_softnic_cli.c |  54 ++-
 4 files changed, 46 insertions(+), 600 deletions(-)
 delete mode 100644 drivers/net/softnic/parser.c
 delete mode 100644 drivers/net/softnic/parser.h

diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index 0ffe26d671..5dfbd16c77 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -8,7 +8,6 @@ endif
 headers = files('rte_eth_softnic.h')
 sources = files(
         'conn.c',
-        'parser.c',
         'rte_eth_softnic.c',
         'rte_eth_softnic_cli.c',
         'rte_eth_softnic_mempool.c',
diff --git a/drivers/net/softnic/parser.c b/drivers/net/softnic/parser.c
deleted file mode 100644
index ebcb10268a..0000000000
--- a/drivers/net/softnic/parser.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2016 Intel Corporation.
- * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
- * All rights reserved.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <getopt.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <libgen.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-
-#include <rte_errno.h>
-
-#include "parser.h"
-
-static uint32_t
-get_hex_val(char c)
-{
-	switch (c) {
-	case '0': case '1': case '2': case '3': case '4': case '5':
-	case '6': case '7': case '8': case '9':
-		return c - '0';
-	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
-		return c - 'A' + 10;
-	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
-		return c - 'a' + 10;
-	default:
-		return 0;
-	}
-}
-
-int
-softnic_parser_read_arg_bool(const char *p)
-{
-	p = skip_white_spaces(p);
-	int result = -EINVAL;
-
-	if (((p[0] == 'y') && (p[1] == 'e') && (p[2] == 's')) ||
-		((p[0] == 'Y') && (p[1] == 'E') && (p[2] == 'S'))) {
-		p += 3;
-		result = 1;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'n')) ||
-		((p[0] == 'O') && (p[1] == 'N'))) {
-		p += 2;
-		result = 1;
-	}
-
-	if (((p[0] == 'n') && (p[1] == 'o')) ||
-		((p[0] == 'N') && (p[1] == 'O'))) {
-		p += 2;
-		result = 0;
-	}
-
-	if (((p[0] == 'o') && (p[1] == 'f') && (p[2] == 'f')) ||
-		((p[0] == 'O') && (p[1] == 'F') && (p[2] == 'F'))) {
-		p += 3;
-		result = 0;
-	}
-
-	p = skip_white_spaces(p);
-
-	if (p[0] != '\0')
-		return -EINVAL;
-
-	return result;
-}
-
-int
-softnic_parser_read_int32(int32_t *value, const char *p)
-{
-	char *next;
-	int32_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtol(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-	if (!isdigit(*p))
-		return -EINVAL;
-
-	val = strtoul(p, &next, 10);
-	if (p == next)
-		return -EINVAL;
-
-	p = next;
-	switch (*p) {
-	case 'T':
-		val *= 1024ULL;
-		/* fall through */
-	case 'G':
-		val *= 1024ULL;
-		/* fall through */
-	case 'M':
-		val *= 1024ULL;
-		/* fall through */
-	case 'k':
-	case 'K':
-		val *= 1024ULL;
-		p++;
-		break;
-	}
-
-	p = skip_white_spaces(p);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint64_hex(uint64_t *value, const char *p)
-{
-	char *next;
-	uint64_t val;
-
-	p = skip_white_spaces(p);
-
-	val = strtoul(p, &next, 16);
-	if (p == next)
-		return -EINVAL;
-
-	p = skip_white_spaces(next);
-	if (*p != '\0')
-		return -EINVAL;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint32_hex(uint32_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT32_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint16_hex(uint16_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT16_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parser_read_uint8_hex(uint8_t *value, const char *p)
-{
-	uint64_t val = 0;
-	int ret = softnic_parser_read_uint64_hex(&val, p);
-
-	if (ret < 0)
-		return ret;
-
-	if (val > UINT8_MAX)
-		return -ERANGE;
-
-	*value = val;
-	return 0;
-}
-
-int
-softnic_parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
-{
-	uint32_t i;
-
-	if (string == NULL ||
-		tokens == NULL ||
-		(*n_tokens < 1))
-		return -EINVAL;
-
-	for (i = 0; i < *n_tokens; i++) {
-		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
-		if (tokens[i] == NULL)
-			break;
-	}
-
-	if (i == *n_tokens &&
-		strtok_r(string, PARSE_DELIMITER, &string) != NULL)
-		return -E2BIG;
-
-	*n_tokens = i;
-	return 0;
-}
-
-int
-softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size)
-{
-	char *c;
-	uint32_t len, i;
-
-	/* Check input parameters */
-	if (src == NULL ||
-		dst == NULL ||
-		size == NULL ||
-		(*size == 0))
-		return -1;
-
-	len = strlen(src);
-	if (((len & 3) != 0) ||
-		(len > (*size) * 2))
-		return -1;
-	*size = len / 2;
-
-	for (c = src; *c != 0; c++) {
-		if ((((*c) >= '0') && ((*c) <= '9')) ||
-			(((*c) >= 'A') && ((*c) <= 'F')) ||
-			(((*c) >= 'a') && ((*c) <= 'f')))
-			continue;
-
-		return -1;
-	}
-
-	/* Convert chars to bytes */
-	for (i = 0; i < *size; i++)
-		dst[i] = get_hex_val(src[2 * i]) * 16 +
-			get_hex_val(src[2 * i + 1]);
-
-	return 0;
-}
-
-int
-softnic_parse_mpls_labels(char *string, uint32_t *labels, uint32_t *n_labels)
-{
-	uint32_t n_max_labels = *n_labels, count = 0;
-
-	/* Check for void list of labels */
-	if (strcmp(string, "<void>") == 0) {
-		*n_labels = 0;
-		return 0;
-	}
-
-	/* At least one label should be present */
-	for ( ; (*string != '\0'); ) {
-		char *next;
-		int value;
-
-		if (count >= n_max_labels)
-			return -1;
-
-		if (count > 0) {
-			if (string[0] != ':')
-				return -1;
-
-			string++;
-		}
-
-		value = strtol(string, &next, 10);
-		if (next == string)
-			return -1;
-		string = next;
-
-		labels[count++] = (uint32_t)value;
-	}
-
-	*n_labels = count;
-	return 0;
-}
-
-static struct rte_ether_addr *
-my_ether_aton(const char *a)
-{
-	int i;
-	char *end;
-	unsigned long o[RTE_ETHER_ADDR_LEN];
-	static struct rte_ether_addr ether_addr;
-
-	i = 0;
-	do {
-		errno = 0;
-		o[i] = strtoul(a, &end, 16);
-		if (errno != 0 || end == a || (end[0] != ':' && end[0] != 0))
-			return NULL;
-		a = end + 1;
-	} while (++i != sizeof(o) / sizeof(o[0]) && end[0] != 0);
-
-	/* Junk at the end of line */
-	if (end[0] != 0)
-		return NULL;
-
-	/* Support the format XX:XX:XX:XX:XX:XX */
-	if (i == RTE_ETHER_ADDR_LEN) {
-		while (i-- != 0) {
-			if (o[i] > UINT8_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i] = (uint8_t)o[i];
-		}
-	/* Support the format XXXX:XXXX:XXXX */
-	} else if (i == RTE_ETHER_ADDR_LEN / 2) {
-		while (i-- != 0) {
-			if (o[i] > UINT16_MAX)
-				return NULL;
-			ether_addr.addr_bytes[i * 2] = (uint8_t)(o[i] >> 8);
-			ether_addr.addr_bytes[i * 2 + 1] = (uint8_t)(o[i] & 0xff);
-		}
-	/* unknown format */
-	} else
-		return NULL;
-
-	return (struct rte_ether_addr *)&ether_addr;
-}
-
-int
-softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4)
-{
-	if (strlen(token) >= INET_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET, token, ipv4) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6)
-{
-	if (strlen(token) >= INET6_ADDRSTRLEN)
-		return -EINVAL;
-
-	if (inet_pton(AF_INET6, token, ipv6) != 1)
-		return -EINVAL;
-
-	return 0;
-}
-
-int
-softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr)
-{
-	struct rte_ether_addr *tmp;
-
-	tmp = my_ether_aton(token);
-	if (tmp == NULL)
-		return -1;
-
-	memcpy(addr, tmp, sizeof(struct rte_ether_addr));
-	return 0;
-}
-
-int
-softnic_parse_cpu_core(const char *entry,
-	struct softnic_cpu_core_params *p)
-{
-	size_t num_len;
-	char num[8];
-
-	uint32_t s = 0, c = 0, h = 0, val;
-	uint8_t s_parsed = 0, c_parsed = 0, h_parsed = 0;
-	const char *next = skip_white_spaces(entry);
-	char type;
-
-	if (p == NULL)
-		return -EINVAL;
-
-	/* Expect <CORE> or [sX][cY][h]. At least one parameter is required. */
-	while (*next != '\0') {
-		/* If everything parsed nothing should left */
-		if (s_parsed && c_parsed && h_parsed)
-			return -EINVAL;
-
-		type = *next;
-		switch (type) {
-		case 's':
-		case 'S':
-			if (s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-			s_parsed = 1;
-			next++;
-			break;
-		case 'c':
-		case 'C':
-			if (c_parsed || h_parsed)
-				return -EINVAL;
-			c_parsed = 1;
-			next++;
-			break;
-		case 'h':
-		case 'H':
-			if (h_parsed)
-				return -EINVAL;
-			h_parsed = 1;
-			next++;
-			break;
-		default:
-			/* If it start from digit it must be only core id. */
-			if (!isdigit(*next) || s_parsed || c_parsed || h_parsed)
-				return -EINVAL;
-
-			type = 'C';
-		}
-
-		for (num_len = 0; *next != '\0'; next++, num_len++) {
-			if (num_len == RTE_DIM(num))
-				return -EINVAL;
-
-			if (!isdigit(*next))
-				break;
-
-			num[num_len] = *next;
-		}
-
-		if (num_len == 0 && type != 'h' && type != 'H')
-			return -EINVAL;
-
-		if (num_len != 0 && (type == 'h' || type == 'H'))
-			return -EINVAL;
-
-		num[num_len] = '\0';
-		val = strtol(num, NULL, 10);
-
-		h = 0;
-		switch (type) {
-		case 's':
-		case 'S':
-			s = val;
-			break;
-		case 'c':
-		case 'C':
-			c = val;
-			break;
-		case 'h':
-		case 'H':
-			h = 1;
-			break;
-		}
-	}
-
-	p->socket_id = s;
-	p->core_id = c;
-	p->thread_id = h;
-	return 0;
-}
diff --git a/drivers/net/softnic/parser.h b/drivers/net/softnic/parser.h
deleted file mode 100644
index 6f408b2485..0000000000
--- a/drivers/net/softnic/parser.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2010-2016 Intel Corporation
- */
-
-#ifndef __INCLUDE_SOFTNIC_PARSER_H__
-#define __INCLUDE_SOFTNIC_PARSER_H__
-
-#include <stdint.h>
-
-#include <rte_ip.h>
-#include <rte_ether.h>
-
-#define PARSE_DELIMITER				" \f\n\r\t\v"
-
-#define skip_white_spaces(pos)			\
-({						\
-	__typeof__(pos) _p = (pos);		\
-	for ( ; isspace(*_p); _p++)		\
-		;				\
-	_p;					\
-})
-
-static inline size_t
-skip_digits(const char *src)
-{
-	size_t i;
-
-	for (i = 0; isdigit(src[i]); i++)
-		;
-
-	return i;
-}
-
-int softnic_parser_read_arg_bool(const char *p);
-
-int softnic_parser_read_int32(int32_t *value, const char *p);
-
-int softnic_parser_read_uint64(uint64_t *value, const char *p);
-int softnic_parser_read_uint32(uint32_t *value, const char *p);
-int softnic_parser_read_uint16(uint16_t *value, const char *p);
-int softnic_parser_read_uint8(uint8_t *value, const char *p);
-
-int softnic_parser_read_uint64_hex(uint64_t *value, const char *p);
-int softnic_parser_read_uint32_hex(uint32_t *value, const char *p);
-int softnic_parser_read_uint16_hex(uint16_t *value, const char *p);
-int softnic_parser_read_uint8_hex(uint8_t *value, const char *p);
-
-int softnic_parse_hex_string(char *src, uint8_t *dst, uint32_t *size);
-
-int softnic_parse_ipv4_addr(const char *token, struct in_addr *ipv4);
-int softnic_parse_ipv6_addr(const char *token, struct in6_addr *ipv6);
-int softnic_parse_mac_addr(const char *token, struct rte_ether_addr *addr);
-int softnic_parse_mpls_labels(char *string,
-		uint32_t *labels, uint32_t *n_labels);
-
-struct softnic_cpu_core_params {
-	uint32_t socket_id;
-	uint32_t core_id;
-	uint32_t thread_id;
-};
-
-int softnic_parse_cpu_core(const char *entry,
-		struct softnic_cpu_core_params *p);
-
-int softnic_parse_tokenize_string(char *string,
-		char *tokens[], uint32_t *n_tokens);
-
-#endif
diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index ec9ac133b9..9de17fba8f 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -12,7 +12,6 @@
 #include <rte_string_fns.h>
 
 #include "rte_eth_softnic_internals.h"
-#include "parser.h"
 
 #ifndef CMD_MAX_TOKENS
 #define CMD_MAX_TOKENS     256
@@ -30,6 +29,45 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint32(uint32_t *value, char *p)
+{
+	uint32_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoul(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
+#define PARSE_DELIMITER " \f\n\r\t\v"
+
+static int
+parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
+{
+	uint32_t i;
+
+	if (!string || !tokens || !n_tokens || !*n_tokens)
+		return -EINVAL;
+
+	for (i = 0; i < *n_tokens; i++) {
+		tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
+		if (!tokens[i])
+			break;
+	}
+
+	if (i == *n_tokens && strtok_r(string, PARSE_DELIMITER, &string))
+		return -E2BIG;
+
+	*n_tokens = i;
+	return 0;
+}
+
 static int
 is_comment(char *in)
 {
@@ -70,7 +108,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
 		return;
 	}
@@ -80,7 +118,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
+	if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
 		return;
 	}
@@ -90,7 +128,7 @@ cmd_mempool(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
+	if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
 		return;
 	}
@@ -129,7 +167,7 @@ cmd_swq(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) {
+	if (parser_read_uint32(&p.size, tokens[3]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "size");
 		return;
 	}
@@ -161,7 +199,7 @@ cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -210,7 +248,7 @@ cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
 		return;
 	}
 
-	if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
+	if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
 		snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
 		return;
 	}
@@ -251,7 +289,7 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 	if (is_comment(in))
 		return;
 
-	status = softnic_parse_tokenize_string(in, tokens, &n_tokens);
+	status = parse_tokenize_string(in, tokens, &n_tokens);
 	if (status) {
 		snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
 		return;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 10/21] net/softnic: add pipeline code generation CLI command
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (8 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 09/21] net/softnic: remove unused text parsing functions Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
                     ` (11 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline code generation.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 57 ++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 9de17fba8f..f2c2721d55 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -180,7 +180,55 @@ cmd_swq(struct pmd_internals *softnic,
 }
 
 /**
- * thread <thread_id> pipeline <pipeline_name> enable
+ * pipeline codegen <spec_file> <code_file>
+ */
+static void
+cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	FILE *spec_file = NULL;
+	FILE *code_file = NULL;
+	uint32_t err_line;
+	const char *err_msg;
+	int status;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	spec_file = fopen(tokens[2], "r");
+	if (!spec_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
+		return;
+	}
+
+	code_file = fopen(tokens[3], "w");
+	if (!code_file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
+		return;
+	}
+
+	status = rte_swx_pipeline_codegen(spec_file,
+					  code_file,
+					  &err_line,
+					  &err_msg);
+
+	fclose(spec_file);
+	fclose(code_file);
+
+	if (status) {
+		snprintf(out, out_size, "Error %d at line %u: %s\n.",
+			status, err_line, err_msg);
+		return;
+	}
+}
+
+/**
+ * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
 static void
 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
@@ -308,6 +356,13 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 		return;
 	}
 
+	if (!strcmp(tokens[0], "pipeline")) {
+		if (n_tokens >= 2 && !strcmp(tokens[1], "codegen")) {
+			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+	}
+
 	if (strcmp(tokens[0], "thread") == 0) {
 		if (n_tokens >= 5 &&
 			(strcmp(tokens[4], "enable") == 0)) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 11/21] net/softnic: add pipeline library build CLI command
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (9 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 10/21] net/softnic: add pipeline code generation CLI command Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 12/21] net/softnic: add pipeline " Cristian Dumitrescu
                     ` (10 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline shared library build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 143 ++++++++++++++++++++++
 1 file changed, 143 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index f2c2721d55..08cca7a8e4 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -6,6 +6,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_cycles.h>
@@ -17,6 +18,10 @@
 #define CMD_MAX_TOKENS     256
 #endif
 
+#ifndef MAX_LINE_SIZE
+#define MAX_LINE_SIZE 2048
+#endif
+
 #define MSG_OUT_OF_MEMORY   "Not enough memory.\n"
 #define MSG_CMD_UNKNOWN     "Unknown command \"%s\".\n"
 #define MSG_CMD_UNIMPLEM    "Command \"%s\" not implemented.\n"
@@ -227,6 +232,139 @@ cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
 	}
 }
 
+/**
+ * pipeline libbuild <code_file> <lib_file>
+ */
+static void
+cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
+	char *install_dir, *cwd = NULL, *buffer = NULL;
+	size_t length;
+	int status = 0;
+
+	if (n_tokens != 4) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		goto free;
+	}
+
+	install_dir = getenv("RTE_INSTALL_DIR");
+	if (!install_dir) {
+		cwd = malloc(MAX_LINE_SIZE);
+		if (!cwd) {
+			snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+			goto free;
+		}
+
+		install_dir = getcwd(cwd, MAX_LINE_SIZE);
+		if (!install_dir) {
+			snprintf(out, out_size, "Error: Path too long.\n");
+			goto free;
+		}
+	}
+
+	snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	code_file = tokens[2];
+	length = strnlen(code_file, MAX_LINE_SIZE);
+	if (length < 3 ||
+	    code_file[length - 2] != '.' ||
+	    code_file[length - 1] != 'c') {
+		snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
+		goto free;
+	}
+
+	lib_file = tokens[3];
+	length = strnlen(lib_file, MAX_LINE_SIZE);
+	if (length < 4 ||
+	    lib_file[length - 3] != '.' ||
+	    lib_file[length - 2] != 's' ||
+	    lib_file[length - 1] != 'o') {
+		snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
+		goto free;
+	}
+
+	obj_file = malloc(length);
+	log_file = malloc(length + 2);
+	if (!obj_file || !log_file) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		goto free;
+	}
+
+	memcpy(obj_file, lib_file, length - 2);
+	obj_file[length - 2] = 'o';
+	obj_file[length - 1] = 0;
+
+	memcpy(log_file, lib_file, length - 2);
+	log_file[length - 2] = 'l';
+	log_file[length - 1] = 'o';
+	log_file[length] = 'g';
+	log_file[length + 1] = 0;
+
+	buffer = malloc(MAX_LINE_SIZE);
+	if (!buffer) {
+		snprintf(out, out_size, MSG_OUT_OF_MEMORY);
+		return;
+	}
+
+	snprintf(buffer,
+		 MAX_LINE_SIZE,
+		 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
+		 "-I %s/lib/pipeline "
+		 "-I %s/lib/eal/include "
+		 "-I %s/lib/eal/x86/include "
+		 "-I %s/lib/eal/include/generic "
+		 "-I %s/lib/meter "
+		 "-I %s/lib/port "
+		 "-I %s/lib/table "
+		 "-I %s/lib/pipeline "
+		 "-I %s/config "
+		 "-I %s/build "
+		 "-I %s/lib/eal/linux/include "
+		 ">%s 2>&1 "
+		 "&& "
+		 "gcc -shared %s -o %s "
+		 ">>%s 2>&1",
+		 obj_file,
+		 code_file,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 install_dir,
+		 log_file,
+		 obj_file,
+		 lib_file,
+		 log_file);
+
+	status = system(buffer);
+	if (status) {
+		snprintf(out,
+			 out_size,
+			 "Library build failed, see file \"%s\" for details.\n",
+			 log_file);
+		goto free;
+	}
+
+free:
+	free(cwd);
+	free(obj_file);
+	free(log_file);
+	free(buffer);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -361,6 +499,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[1], "libbuild")) {
+			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 12/21] net/softnic: add pipeline build CLI command
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (10 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 11/21] net/softnic: add pipeline library build " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
                     ` (9 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline build.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 66 +++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 08cca7a8e4..cf71aa7b96 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -365,6 +365,67 @@ cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
 	free(buffer);
 }
 
+/**
+ * pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>
+ */
+static void
+cmd_softnic_pipeline_build(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p = NULL;
+	char *pipeline_name, *lib_file_name, *iospec_file_name;
+	uint32_t numa_node = 0;
+
+	/* Parsing. */
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+
+	if (strcmp(tokens[2], "build")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
+		return;
+	}
+
+	if (strcmp(tokens[3], "lib")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
+		return;
+	}
+
+	lib_file_name = tokens[4];
+
+	if (strcmp(tokens[5], "io")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
+		return;
+	}
+
+	iospec_file_name = tokens[6];
+
+	if (strcmp(tokens[7], "numa")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
+		return;
+	}
+
+	if (parser_read_uint32(&numa_node, tokens[8])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
+		return;
+	}
+
+	/* Pipeline create. */
+	p = softnic_pipeline_create(softnic,
+				    pipeline_name,
+				    lib_file_name,
+				    iospec_file_name,
+				    (int)numa_node);
+	if (!p)
+		snprintf(out, out_size, "Pipeline creation failed.\n");
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -504,6 +565,11 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "build")) {
+			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 13/21] net/softnic: add pipeline table CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (11 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 12/21] net/softnic: add pipeline " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
                     ` (8 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline table entry management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 370 ++++++++++++++++++++++
 1 file changed, 370 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index cf71aa7b96..4443b62009 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -426,6 +426,354 @@ cmd_softnic_pipeline_build(struct pmd_internals *softnic,
 		snprintf(out, out_size, "Pipeline creation failed.\n");
 }
 
+static void
+table_entry_free(struct rte_swx_table_entry *entry)
+{
+	if (!entry)
+		return;
+
+	free(entry->key);
+	free(entry->key_mask);
+	free(entry->action_data);
+	free(entry);
+}
+
+static int
+pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
+			   const char *table_name,
+			   FILE *file,
+			   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_add(p,
+							      table_name,
+							      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> add <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_add(p->ctl,
+					    table_name,
+					    file,
+					    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p,
+			      const char *table_name,
+			      FILE *file,
+			      uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_entry_delete(p,
+								 table_name,
+								 entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_entries_delete(p->ctl,
+					       table_name,
+					       file,
+					       &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				 const char *table_name,
+				 FILE *file,
+				 uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_table_entry_read(p,
+							      table_name,
+							      line,
+							      &is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_table_default_entry_add(p,
+								      table_name,
+								      entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_table_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_table_default_entry_add(p->ctl,
+						  table_name,
+						  file,
+						  &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> table <table_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *table_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	table_name = tokens[3];
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -570,6 +918,28 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "add")) {
+			cmd_softnic_pipeline_table_add(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "delete")) {
+			cmd_softnic_pipeline_table_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_table_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 14/21] net/softnic: add pipeline selector table CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (12 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 13/21] net/softnic: add pipeline table CLI commands Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
                     ` (7 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for selector tables group and member management.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 517 ++++++++++++++++++++++
 1 file changed, 517 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 4443b62009..1e92e251aa 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -774,6 +774,477 @@ cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
 		fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> selector <selector_name> group add
+ */
+static void
+cmd_softnic_pipeline_selector_group_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
+		selector_name,
+		&group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+	else
+		snprintf(out, out_size, "Group ID: %u\n", group_id);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group delete <group_id>
+ */
+static void
+cmd_softnic_pipeline_selector_group_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	uint32_t group_id;
+	int status;
+
+	if (n_tokens != 7) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete");
+		return;
+	}
+
+	if (parser_read_uint32(&group_id, tokens[6]) != 0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
+		selector_name,
+		group_id);
+	if (status)
+		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
+}
+
+#define GROUP_MEMBER_INFO_TOKENS_MAX 6
+
+static int
+token_is_comment(const char *token)
+{
+	if ((token[0] == '#') ||
+	    (token[0] == ';') ||
+	    ((token[0] == '/') && (token[1] == '/')))
+		return 1; /* TRUE. */
+
+	return 0; /* FALSE. */
+}
+
+static int
+pipeline_selector_group_member_read(const char *string,
+				    uint32_t *group_id,
+				    uint32_t *member_id,
+				    uint32_t *weight,
+				    int *is_blank_or_comment)
+{
+	char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens;
+	char *s0 = NULL, *s;
+	uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0;
+	int blank_or_comment = 0;
+
+	/* Check input arguments. */
+	if (!string || !string[0])
+		goto error;
+
+	/* Memory allocation. */
+	s0 = strdup(string);
+	if (!s0)
+		goto error;
+
+	/* Parse the string into tokens. */
+	for (s = s0; ; ) {
+		char *token;
+
+		token = strtok_r(s, " \f\n\r\t\v", &s);
+		if (!token || token_is_comment(token))
+			break;
+
+		if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX)
+			goto error;
+
+		token_array[n_tokens] = token;
+		n_tokens++;
+	}
+
+	if (!n_tokens) {
+		blank_or_comment = 1;
+		goto error;
+	}
+
+	tokens = token_array;
+
+	if (n_tokens < 4 ||
+		strcmp(tokens[0], "group") ||
+		strcmp(tokens[2], "member"))
+		goto error;
+
+	/*
+	 * Group ID.
+	 */
+	if (parser_read_uint32(&group_id_val, tokens[1]) != 0)
+		goto error;
+	*group_id = group_id_val;
+
+	/*
+	 * Member ID.
+	 */
+	if (parser_read_uint32(&member_id_val, tokens[3]) != 0)
+		goto error;
+	*member_id = member_id_val;
+
+	tokens += 4;
+	n_tokens -= 4;
+
+	/*
+	 * Weight.
+	 */
+	if (n_tokens && !strcmp(tokens[0], "weight")) {
+		if (n_tokens < 2)
+			goto error;
+
+		if (parser_read_uint32(&weight_val, tokens[1]) != 0)
+			goto error;
+		*weight = weight_val;
+
+		tokens += 2;
+		n_tokens -= 2;
+	}
+
+	if (n_tokens)
+		goto error;
+
+	free(s0);
+	return 0;
+
+error:
+	free(s0);
+	if (is_blank_or_comment)
+		*is_blank_or_comment = blank_or_comment;
+	return -EINVAL;
+}
+
+static int
+pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p,
+				    const char *selector_name,
+				    FILE *file,
+				    uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_add(p,
+			selector_name,
+			group_id,
+			member_id,
+			weight);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member add <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_add(p->ctl,
+		selector_name,
+		file,
+		&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+static int
+pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p,
+				       const char *selector_name,
+				       FILE *file,
+				       uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		uint32_t group_id, member_id, weight;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		status = pipeline_selector_group_member_read(line,
+							     &group_id,
+							     &member_id,
+							     &weight,
+							     &is_blank_or_comment);
+		if (status) {
+			if (is_blank_or_comment)
+				continue;
+
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_selector_group_member_delete(p,
+			selector_name,
+			group_id,
+			member_id);
+		if (status)
+			goto error;
+	}
+
+error:
+	free(line);
+	*file_line_number = line_id;
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> group member delete <file_name>
+ */
+static void
+cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 8) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "selector") != 0) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	if (strcmp(tokens[4], "group") ||
+		strcmp(tokens[5], "member") ||
+		strcmp(tokens[6], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete");
+		return;
+	}
+
+	file_name = tokens[7];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_selector_group_members_delete(p->ctl,
+							selector_name,
+							file,
+							&file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
+/**
+ * pipeline <pipeline_name> selector <selector_name> show [filename]
+ */
+static void
+cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *selector_name;
+	FILE *file = NULL;
+	int status;
+
+	if (n_tokens != 5 && n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	selector_name = tokens[3];
+
+	file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
+	if (status)
+		snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
+
+	if (file)
+		fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -940,6 +1411,52 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_selector_group_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_selector_group_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 7 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "add")) {
+			cmd_softnic_pipeline_selector_group_member_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 7 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "group") &&
+			!strcmp(tokens[5], "member") &&
+			!strcmp(tokens[6], "delete")) {
+			cmd_softnic_pipeline_selector_group_member_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 5 &&
+			!strcmp(tokens[2], "selector") &&
+			!strcmp(tokens[4], "show")) {
+			cmd_softnic_pipeline_selector_show(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 15/21] net/softnic: add pipeline learner table CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (13 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 14/21] net/softnic: add pipeline selector " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
                     ` (6 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for managing the learner table default entry.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 106 ++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 1e92e251aa..4b7d001033 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1245,6 +1245,104 @@ cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
 		fclose(file);
 }
 
+static int
+pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p,
+				   const char *learner_name,
+				   FILE *file,
+				   uint32_t *file_line_number)
+{
+	char *line = NULL;
+	uint32_t line_id = 0;
+	int status = 0;
+
+	/* Buffer allocation. */
+	line = malloc(MAX_LINE_SIZE);
+	if (!line)
+		return -ENOMEM;
+
+	/* File read. */
+	for (line_id = 1; ; line_id++) {
+		struct rte_swx_table_entry *entry;
+		int is_blank_or_comment;
+
+		if (fgets(line, MAX_LINE_SIZE, file) == NULL)
+			break;
+
+		entry = rte_swx_ctl_pipeline_learner_default_entry_read(p,
+									learner_name,
+									line,
+									&is_blank_or_comment);
+		if (!entry) {
+			if (is_blank_or_comment)
+				continue;
+
+			status = -EINVAL;
+			goto error;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_default_entry_add(p,
+									learner_name,
+									entry);
+		table_entry_free(entry);
+		if (status)
+			goto error;
+	}
+
+error:
+	*file_line_number = line_id;
+	free(line);
+	return status;
+}
+
+/**
+ * pipeline <pipeline_name> learner <learner_name> default <file_name>
+ */
+static void
+cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name, *learner_name, *file_name;
+	FILE *file = NULL;
+	uint32_t file_line_number = 0;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	learner_name = tokens[3];
+
+	file_name = tokens[5];
+	file = fopen(file_name, "r");
+	if (!file) {
+		snprintf(out, out_size, "Cannot open file %s.\n", file_name);
+		return;
+	}
+
+	status = pipeline_learner_default_entry_add(p->ctl,
+						    learner_name,
+						    file,
+						    &file_line_number);
+	if (status)
+		snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
+			 file_name,
+			 file_line_number);
+
+	fclose(file);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1457,6 +1555,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 5 &&
+			!strcmp(tokens[2], "learner") &&
+			!strcmp(tokens[4], "default")) {
+			cmd_softnic_pipeline_learner_default(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 16/21] net/softnic: add pipeline commit and abort CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (14 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 15/21] net/softnic: add pipeline learner " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
                     ` (5 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline table update commit and abort.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 70 +++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 4b7d001033..7c25a502ec 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1343,6 +1343,66 @@ cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
 	fclose(file);
 }
 
+/**
+ * pipeline <pipeline_name> commit
+ */
+static void
+cmd_softnic_pipeline_commit(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
+	if (status)
+		snprintf(out, out_size, "Commit failed. "
+			"Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
+}
+
+/**
+ * pipeline <pipeline_name> abort
+ */
+static void
+cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	char *pipeline_name;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	rte_swx_ctl_pipeline_abort(p->ctl);
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1563,6 +1623,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 				out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "commit")) {
+			cmd_softnic_pipeline_commit(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "abort")) {
+			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 17/21] net/softnic: add the pipeline register read/write CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (15 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 16/21] net/softnic: add pipeline commit and abort " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
                     ` (4 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline registers read and write operations.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 127 ++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 7c25a502ec..b1f7460f47 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -34,6 +34,22 @@
 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
 #define MSG_CMD_FAIL        "Command \"%s\" failed.\n"
 
+static int
+parser_read_uint64(uint64_t *value, char *p)
+{
+	uint64_t val = 0;
+
+	if (!value || !p || !p[0])
+		return -EINVAL;
+
+	val = strtoull(p, &p, 0);
+	if (p[0])
+		return -EINVAL;
+
+	*value = val;
+	return 0;
+}
+
 static int
 parser_read_uint32(uint32_t *value, char *p)
 {
@@ -1403,6 +1419,107 @@ cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
 	rte_swx_ctl_pipeline_abort(p->ctl);
 }
 
+/**
+ * pipeline <pipeline_name> regrd <register_array_name> <index>
+ */
+static void
+cmd_softnic_pipeline_regrd(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 5) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regrd")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+
+	snprintf(out, out_size, "0x%" PRIx64 "\n", value);
+}
+
+/**
+ * pipeline <pipeline_name> regwr <register_array_name> <index> <value>
+ */
+static void
+cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *pipeline_name, *name;
+	uint64_t value;
+	uint32_t idx;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	pipeline_name = tokens[1];
+	p = softnic_pipeline_find(softnic, pipeline_name);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "regwr")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (parser_read_uint32(&idx, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index");
+		return;
+	}
+
+	if (parser_read_uint64(&value, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "value");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1633,6 +1750,16 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "regrd")) {
+			cmd_softnic_pipeline_regrd(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 3 && !strcmp(tokens[2], "regwr")) {
+			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 18/21] net/softnic: add the pipeline meter CLI commands
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (16 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 17/21] net/softnic: add the pipeline register read/write " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
                     ` (3 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI commands for pipeline meter configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 423 ++++++++++++++++++++++
 1 file changed, 423 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index b1f7460f47..bbbf3babda 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1520,6 +1520,395 @@ cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> add cir <cir> pir <pir> cbs <cbs> pbs <pbs>
+ */
+static void
+cmd_softnic_pipeline_meter_profile_add(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_meter_trtcm_params params;
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 14) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "add")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
+		return;
+	}
+
+	if (strcmp(tokens[6], "cir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cir, tokens[7])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cir");
+		return;
+	}
+
+	if (strcmp(tokens[8], "pir")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pir, tokens[9])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pir");
+		return;
+	}
+
+	if (strcmp(tokens[10], "cbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.cbs, tokens[11])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
+		return;
+	}
+
+	if (strcmp(tokens[12], "pbs")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
+		return;
+	}
+
+	if (parser_read_uint64(&params.pbs, tokens[13])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_add(p->p, profile_name, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter profile <profile_name> delete
+ */
+static void
+cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *profile_name;
+	int status;
+
+	if (n_tokens != 6) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	if (strcmp(tokens[3], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[4];
+
+	if (strcmp(tokens[5], "delete")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
+		return;
+	}
+
+	status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
+	if (status) {
+		snprintf(out, out_size, "Command failed.\n");
+		return;
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> reset
+ */
+static void
+cmd_softnic_pipeline_meter_reset(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "reset")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
+		return;
+	}
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_reset(p->p, name, idx0);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> set
+ *	profile <profile_name>
+ */
+static void
+cmd_softnic_pipeline_meter_set(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct pipeline *p;
+	const char *name, *profile_name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "set")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
+		return;
+	}
+
+	if (strcmp(tokens[9], "profile")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
+		return;
+	}
+
+	profile_name = tokens[10];
+
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
+		if (status) {
+			snprintf(out, out_size, "Command failed for index %u.\n", idx0);
+			return;
+		}
+	}
+}
+
+/**
+ * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> stats
+ */
+static void
+cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_meter_stats stats;
+	struct pipeline *p;
+	const char *name;
+	uint32_t idx0 = 0, idx1 = 0;
+
+	if (n_tokens != 9) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "meter")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
+		return;
+	}
+
+	name = tokens[3];
+
+	if (strcmp(tokens[4], "from")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
+		return;
+	}
+
+	if (parser_read_uint32(&idx0, tokens[5])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index0");
+		return;
+	}
+
+	if (strcmp(tokens[6], "to")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
+		return;
+	}
+
+	if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "index1");
+		return;
+	}
+
+	if (strcmp(tokens[8], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	/* Table header. */
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
+		 "METER #",
+		 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
+		 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
+		 "-------",
+		 "----------------", "----------------", "----------------",
+		 "----------------", "----------------", "----------------");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	/* Table rows. */
+	for ( ; idx0 <= idx1; idx0++) {
+		int status;
+
+		status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
+		if (status) {
+			snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
+			out_size -= strlen(out);
+			out += strlen(out);
+			return;
+		}
+
+		snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
+			 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
+			 idx0,
+			 stats.n_pkts[RTE_COLOR_GREEN],
+			 stats.n_pkts[RTE_COLOR_YELLOW],
+			 stats.n_pkts[RTE_COLOR_RED],
+			 stats.n_bytes[RTE_COLOR_GREEN],
+			 stats.n_bytes[RTE_COLOR_YELLOW],
+			 stats.n_bytes[RTE_COLOR_RED]);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -1760,6 +2149,40 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "add")) {
+			cmd_softnic_pipeline_meter_profile_add(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 6 &&
+			!strcmp(tokens[2], "meter") &&
+			!strcmp(tokens[3], "profile") &&
+			!strcmp(tokens[5], "delete")) {
+			cmd_softnic_pipeline_meter_profile_delete(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "reset")) {
+			cmd_softnic_pipeline_meter_reset(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "set")) {
+			cmd_softnic_pipeline_meter_set(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
+		if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "stats")) {
+			cmd_softnic_pipeline_meter_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
+
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 19/21] net/softnic: add pipeline statistics CLI command
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (17 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 18/21] net/softnic: add the pipeline meter " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-01 14:20   ` [PATCH V3 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
                     ` (2 subsequent siblings)
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline statistics counters query.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 204 ++++++++++++++++++++++
 1 file changed, 204 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index bbbf3babda..da530614db 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1909,6 +1909,206 @@ cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> stats
+ */
+static void
+cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_ctl_pipeline_info info;
+	struct pipeline *p;
+	uint32_t i;
+	int status;
+
+	if (n_tokens != 3) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "stats")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_info_get(p->p, &info);
+	if (status) {
+		snprintf(out, out_size, "Pipeline info get error.");
+		return;
+	}
+
+	snprintf(out, out_size, "Input ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_in; i++) {
+		struct rte_swx_port_in_stats stats;
+
+		rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
+
+		snprintf(out, out_size, "\tPort %u:"
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" empty %" PRIu64 "\n",
+			i, stats.n_pkts, stats.n_bytes, stats.n_empty);
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nOutput ports:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_ports_out; i++) {
+		struct rte_swx_port_out_stats stats;
+
+		rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
+
+		if (i != info.n_ports_out - 1)
+			snprintf(out, out_size, "\tPort %u:", i);
+		else
+			snprintf(out, out_size, "\tDROP:");
+
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		snprintf(out,
+			out_size,
+			" packets %" PRIu64
+			" bytes %" PRIu64
+			" clone %" PRIu64
+			" clonerr %" PRIu64 "\n",
+			stats.n_pkts,
+			stats.n_bytes,
+			stats.n_pkts_clone,
+			stats.n_pkts_clone_err);
+
+		out_size -= strlen(out);
+		out += strlen(out);
+	}
+
+	snprintf(out, out_size, "\nTables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_tables; i++) {
+		struct rte_swx_ctl_table_info table_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_table_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
+		if (status) {
+			snprintf(out, out_size, "Table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tTable %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n",
+			table_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+
+	snprintf(out, out_size, "\nLearner tables:\n");
+	out_size -= strlen(out);
+	out += strlen(out);
+
+	for (i = 0; i < info.n_learners; i++) {
+		struct rte_swx_ctl_learner_info learner_info;
+		uint64_t n_pkts_action[info.n_actions];
+		struct rte_swx_learner_stats stats = {
+			.n_pkts_hit = 0,
+			.n_pkts_miss = 0,
+			.n_pkts_action = n_pkts_action,
+		};
+		uint32_t j;
+
+		status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
+		if (status) {
+			snprintf(out, out_size, "Learner table info get error.");
+			return;
+		}
+
+		status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
+		if (status) {
+			snprintf(out, out_size, "Learner table stats read error.");
+			return;
+		}
+
+		snprintf(out, out_size, "\tLearner table %s:\n"
+			"\t\tHit (packets): %" PRIu64 "\n"
+			"\t\tMiss (packets): %" PRIu64 "\n"
+			"\t\tLearn OK (packets): %" PRIu64 "\n"
+			"\t\tLearn error (packets): %" PRIu64 "\n"
+			"\t\tRearm (packets): %" PRIu64 "\n"
+			"\t\tForget (packets): %" PRIu64 "\n",
+			learner_info.name,
+			stats.n_pkts_hit,
+			stats.n_pkts_miss,
+			stats.n_pkts_learn_ok,
+			stats.n_pkts_learn_err,
+			stats.n_pkts_rearm,
+			stats.n_pkts_forget);
+		out_size -= strlen(out);
+		out += strlen(out);
+
+		for (j = 0; j < info.n_actions; j++) {
+			struct rte_swx_ctl_action_info action_info;
+
+			status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
+			if (status) {
+				snprintf(out, out_size, "Action info get error.");
+				return;
+			}
+
+			snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
+				action_info.name,
+				stats.n_pkts_action[j]);
+			out_size -= strlen(out);
+			out += strlen(out);
+		}
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2183,6 +2383,10 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			return;
 		}
 
+		if (n_tokens >= 3 && !strcmp(tokens[2], "stats")) {
+			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 20/21] net/softnic: add pipeline mirroring CLI command
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (18 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 19/21] net/softnic: add pipeline statistics CLI command Cristian Dumitrescu
@ 2022-09-01 14:20   ` 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
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Add CLI command for pipeline mirroring configuration.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 96 +++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index da530614db..e1ff100c9a 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -2109,6 +2109,94 @@ cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
 	}
 }
 
+/**
+ * pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow
+ *	truncate <truncation_length>
+ */
+static void
+cmd_softnic_pipeline_mirror_session(struct pmd_internals *softnic,
+	char **tokens,
+	uint32_t n_tokens,
+	char *out,
+	size_t out_size)
+{
+	struct rte_swx_pipeline_mirroring_session_params params;
+	struct pipeline *p;
+	uint32_t session_id = 0;
+	int status;
+
+	if (n_tokens != 11) {
+		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
+		return;
+	}
+
+	if (strcmp(tokens[0], "pipeline")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
+		return;
+	}
+
+	p = softnic_pipeline_find(softnic, tokens[1]);
+	if (!p) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
+		return;
+	}
+
+	if (strcmp(tokens[2], "mirror")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
+		return;
+	}
+
+	if (strcmp(tokens[3], "session")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session");
+		return;
+	}
+
+	if (parser_read_uint32(&session_id, tokens[4])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "session_id");
+		return;
+	}
+
+	if (strcmp(tokens[5], "port")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
+		return;
+	}
+
+	if (parser_read_uint32(&params.port_id, tokens[6])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
+		return;
+	}
+
+	if (strcmp(tokens[7], "clone")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone");
+		return;
+	}
+
+	if (!strcmp(tokens[8], "fast")) {
+		params.fast_clone = 1;
+	} else if (!strcmp(tokens[8], "slow")) {
+		params.fast_clone = 0;
+	} else {
+		snprintf(out, out_size, MSG_ARG_INVALID, "clone");
+		return;
+	}
+
+	if (strcmp(tokens[9], "truncate")) {
+		snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate");
+		return;
+	}
+
+	if (parser_read_uint32(&params.truncation_length, tokens[10])) {
+		snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length");
+		return;
+	}
+
+	status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, &params);
+	if (status) {
+		snprintf(out, out_size, "Command failed!\n");
+		return;
+	}
+}
+
 /**
  * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
  */
@@ -2387,6 +2475,14 @@ softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
 			cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
 			return;
 		}
+
+		if (n_tokens >= 4 &&
+			!strcmp(tokens[2], "mirror") &&
+			!strcmp(tokens[3], "session")) {
+			cmd_softnic_pipeline_mirror_session(softnic, tokens, n_tokens,
+				out, out_size);
+			return;
+		}
 	}
 
 	if (strcmp(tokens[0], "thread") == 0) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* [PATCH V3 21/21] net/softnic: update the default device program
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (19 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 20/21] net/softnic: add pipeline mirroring " Cristian Dumitrescu
@ 2022-09-01 14:20   ` Cristian Dumitrescu
  2022-09-21 11:48   ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Thomas Monjalon
  21 siblings, 0 replies; 69+ messages in thread
From: Cristian Dumitrescu @ 2022-09-01 14:20 UTC (permalink / raw)
  To: dev; +Cc: Yogesh Jangra

Update the default device program.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Yogesh Jangra <yogesh.jangra@intel.com>
---
 drivers/net/softnic/firmware.cli   | 51 ++++++++++++++++++++----------
 drivers/net/softnic/firmware.spec  | 19 +++++++++++
 drivers/net/softnic/firmware_rx.io | 30 ++++++++++++++++++
 drivers/net/softnic/firmware_tx.io | 30 ++++++++++++++++++
 4 files changed, 114 insertions(+), 16 deletions(-)
 create mode 100644 drivers/net/softnic/firmware.spec
 create mode 100644 drivers/net/softnic/firmware_rx.io
 create mode 100644 drivers/net/softnic/firmware_tx.io

diff --git a/drivers/net/softnic/firmware.cli b/drivers/net/softnic/firmware.cli
index 300cf6e33f..7d2c1aad21 100644
--- a/drivers/net/softnic/firmware.cli
+++ b/drivers/net/softnic/firmware.cli
@@ -1,21 +1,40 @@
 ; SPDX-License-Identifier: BSD-3-Clause
-; Copyright(c) 2018 Intel Corporation
+; Copyright(c) 2022 Intel Corporation
 
-link LINK dev 0000:02:00.0
+# Example command line for the DPDK test-pmd application. Out of the 3 application cores (see the
+# -c <core_mask> argument), core 0 is running the control thread doing configuration and CLI, core 1
+# is running the forwarding thread, and core 2 is setup as service core (see the -s <core_mask>
+# argument) for the purpose of running the Soft NIC device:
+#
+#	./build/app/dpdk-testpmd -c 7 -s 4 --vdev 'net_softnic0,firmware=./drivers/net/softnic/firmware.cli,cpu_id=0,conn_port=8086' -- -i
+#
+# Commands from within the DPDK test-pmd application:
+#
+# 	testpmd> set portlist <softnic_port_id>
+#	testpmd> show config fwd
+#	testpmd> start
+#
+# To setup the CLI prompt to the Soft NIC device, the DPDK test-pmd application needs to be modified
+# to call the rte_pmd_softnic_manage() function. Once the Soft NIC device is started, the command to
+# get the CLI prompt is:
+#
+#	telnet 0.0.0.0 8086
 
-pipeline RX period 10 offset_port_id 0
-pipeline RX port in bsz 32 link LINK rxq 0
-pipeline RX port out bsz 32 swq RXQ0
-pipeline RX table match stub
-pipeline RX port in 0 table 0
-pipeline RX table 0 rule add match default action fwd port 0
+;
+; Pipeline code generation & shared object library build.
+;
+pipeline codegen ./drivers/net/softnic/firmware.spec /tmp/firmware.c
+pipeline libbuild /tmp/firmware.c /tmp/firmware.so
 
-pipeline TX period 10 offset_port_id 0
-pipeline TX port in bsz 32 swq TXQ0
-pipeline TX port out bsz 32 link LINK txq 0
-pipeline TX table match stub
-pipeline TX port in 0 table 0
-pipeline TX table 0 rule add match default action fwd port 0
+;
+; List of pipelines.
+;
+pipeline RX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_rx.io numa 0
+pipeline TX build lib /tmp/firmware.so io ./drivers/net/softnic/firmware_tx.io numa 0
 
-thread 1 pipeline RX enable
-thread 1 pipeline TX enable
+;
+; Pipelines-to-threads mapping. For the Soft NIC devices, the pipelines can be mapped to any of the
+; application service cores (see the -s <core_mask> argument):
+;
+thread 2 pipeline RX enable
+thread 2 pipeline TX enable
diff --git a/drivers/net/softnic/firmware.spec b/drivers/net/softnic/firmware.spec
new file mode 100644
index 0000000000..106caae735
--- /dev/null
+++ b/drivers/net/softnic/firmware.spec
@@ -0,0 +1,19 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+//
+// Meta-data.
+//
+struct metadata_t {
+	bit<32> port
+}
+
+metadata instanceof metadata_t
+
+//
+// Pipeline.
+//
+apply {
+	rx m.port
+	tx m.port
+}
diff --git a/drivers/net/softnic/firmware_rx.io b/drivers/net/softnic/firmware_rx.io
new file mode 100644
index 0000000000..9baa4612b1
--- /dev/null
+++ b/drivers/net/softnic/firmware_rx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ethdev 0000:18:00.0 rxq 0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ring RXQ0 bsz 32
diff --git a/drivers/net/softnic/firmware_tx.io b/drivers/net/softnic/firmware_tx.io
new file mode 100644
index 0000000000..4c4608b105
--- /dev/null
+++ b/drivers/net/softnic/firmware_tx.io
@@ -0,0 +1,30 @@
+; SPDX-License-Identifier: BSD-3-Clause
+; Copyright(c) 2022 Intel Corporation
+
+;
+; Pipeline input ports.
+;
+; Syntax:
+;
+;    port in <port_id> ethdev <ethdev_name> rxq <queue_id> bsz <burst_size>
+;    port in <port_id> ring <ring_name> bsz <burst_size>
+;    port in <port_id> source mempool <mempool_name> file <file_name> loop <n_loops> packets <n_pkts_max>
+;    port in <port_id> fd <file_descriptor> mtu <mtu> mempool <mempool_name> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port in 0 ring TXQ0 bsz 32
+
+;
+; Pipeline output ports.
+;
+; Syntax:
+;
+;    port out <port_id> ethdev <ethdev_name> txq <queue_id> bsz <burst_size>
+;    port out <port_id> ring <ring_name> bsz <burst_size>
+;    port out <port_id> sink file <file_name> | none
+;    port out <port_id> fd <file_descriptor> bsz <burst_size>
+;
+; Note: Customize the parameters below to match your setup.
+;
+port out 0 ethdev 0000:18:00.0 txq 0 bsz 32
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 69+ messages in thread

* Re: [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline
  2022-09-01 14:20 ` [PATCH V3 00/21] net/softnic: replace the legacy pipeline with SWX pipeline Cristian Dumitrescu
                     ` (20 preceding siblings ...)
  2022-09-01 14:20   ` [PATCH V3 21/21] net/softnic: update the default device program Cristian Dumitrescu
@ 2022-09-21 11:48   ` Thomas Monjalon
  21 siblings, 0 replies; 69+ messages in thread
From: Thomas Monjalon @ 2022-09-21 11:48 UTC (permalink / raw)
  To: Cristian Dumitrescu; +Cc: dev

01/09/2022 16:20, Cristian Dumitrescu:
> The legacy pipeline API is soon going to be marked for deprecation,
> hence the Soft NIC driver is updated to support the new SWX pipeline
> type.
> 
> The SWX pipeline has better encapsulation than the legacy pipeline,
> mainly due to P4 language alignment, which results in most of the
> functionality being supported directly in the pipeline library, hence
> the big number of lines of code deleted from this driver.

Applied, thanks.





^ permalink raw reply	[flat|nested] 69+ messages in thread

* Re: [PATCH V3 02/21] net/softnic: remove flow support
  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
  0 siblings, 1 reply; 69+ messages in thread
From: Ferruh Yigit @ 2022-11-30 11:18 UTC (permalink / raw)
  To: Cristian Dumitrescu, Thomas Monjalon; +Cc: Yogesh Jangra, dev

On 9/1/2022 3:20 PM, Cristian Dumitrescu wrote:
> Remove the Ethernet device flow API support.
> 
> 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      |    9 -
>  drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -
>  drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------
>  4 files changed, 2384 deletions(-)
>  delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

Hi Cristian,

I can still see some flow API reference in the softnic documentation
[1], is the latest documentation up to date?


[1]
https://doc.dpdk.org/guides/nics/softnic.html#flow-api-support

^ permalink raw reply	[flat|nested] 69+ messages in thread

* RE: [PATCH V3 02/21] net/softnic: remove flow support
  2022-11-30 11:18     ` Ferruh Yigit
@ 2022-12-01 11:27       ` Dumitrescu, Cristian
  0 siblings, 0 replies; 69+ messages in thread
From: Dumitrescu, Cristian @ 2022-12-01 11:27 UTC (permalink / raw)
  To: Ferruh Yigit, Thomas Monjalon; +Cc: Jangra, Yogesh, dev



> -----Original Message-----
> From: Ferruh Yigit <ferruh.yigit@amd.com>
> Sent: Wednesday, November 30, 2022 11:19 AM
> To: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>
> Cc: Jangra, Yogesh <yogesh.jangra@intel.com>; dev@dpdk.org
> Subject: Re: [PATCH V3 02/21] net/softnic: remove flow support
> 
> On 9/1/2022 3:20 PM, Cristian Dumitrescu wrote:
> > Remove the Ethernet device flow API support.
> >
> > 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      |    9 -
> >  drivers/net/softnic/rte_eth_softnic_cli.c  |   81 -
> >  drivers/net/softnic/rte_eth_softnic_flow.c | 2293 --------------------
> >  4 files changed, 2384 deletions(-)
> >  delete mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c
> 
> Hi Cristian,
> 
> I can still see some flow API reference in the softnic documentation
> [1], is the latest documentation up to date?
> 
> 
> [1]
> https://doc.dpdk.org/guides/nics/softnic.html#flow-api-support

Thanks Ferruh, we will fix the documentation.

^ permalink raw reply	[flat|nested] 69+ messages in thread

end of thread, other threads:[~2022-12-01 11:27 UTC | newest]

Thread overview: 69+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 07/21] net/softnic: replace the legacy pipeline with the SWX pipeline Cristian Dumitrescu
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

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.