All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] add flow API support to softnic
@ 2018-09-06 16:26 Reshma Pattan
  2018-09-06 16:26 ` [PATCH 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
                   ` (30 more replies)
  0 siblings, 31 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev

This patch series adds the flow API support
for the softnic.

This patch set also introduce a new cli command
to provide mapping of flow group and direction
to softnic pipeline and table.

Reshma Pattan (15):
  net/softnic: add infrastructure for flow API
  net/softnic: rte flow attr mapping to pipeline
  net/softnic: add new cli for flow attribute map
  net/softnic: various data type changes
  net/softnic: add free table and find out port functions
  net/softnic: add function to get eth device from softnic
  net/softnic: flow API validate support
  net/softnic: validate and map flow rule with acl table match
  net/softnic: parse flow protocol for acl table match
  net/softnic: validate and map flow with hash table match
  net/softnic: validate and map flow action with table action
  net/softnic: add flow create API
  net/softnic: add flow destroy API
  net/softnic: add flow query API
  net/softnic: add parsing for raw flow item

 drivers/net/softnic/Makefile                    |    1 +
 drivers/net/softnic/meson.build                 |    1 +
 drivers/net/softnic/rte_eth_softnic.c           |   16 +
 drivers/net/softnic/rte_eth_softnic_cli.c       |  115 +-
 drivers/net/softnic/rte_eth_softnic_flow.c      | 1809 +++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h |   98 +-
 drivers/net/softnic/rte_eth_softnic_pipeline.c  |   61 +-
 7 files changed, 2071 insertions(+), 30 deletions(-)
 create mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

-- 
2.14.4

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

* [PATCH 01/15] net/softnic: add infrastructure for flow API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 02/15] net/softnic: rte flow attr mapping to pipeline Reshma Pattan
                   ` (29 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Add rte_flow infra structure for flow api support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index a25eb874c..882cfd191 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -20,6 +20,7 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_tm_driver.h>
+#include <rte_flow_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "conn.h"
@@ -43,6 +44,13 @@ struct pmd_params {
 	} tm;
 };
 
+/**
+ * Ethdev Flow API
+ */
+struct rte_flow;
+
+TAILQ_HEAD(flow_list, rte_flow);
+
 /**
  * MEMPOOL
  */
@@ -762,6 +770,15 @@ struct softnic_table_rule_action {
 	struct rte_table_action_time_params time;
 };
 
+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,
-- 
2.14.4

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

* [PATCH 02/15] net/softnic: rte flow attr mapping to pipeline
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
  2018-09-06 16:26 ` [PATCH 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added mapping support from rte flow attributes
to softnic pipeline and table.

So added flow attribute map set and get functions
definition to new file rte_eth_sofnic_flow.c.

Added pmd flow internals with ingress and egress
flow attribute maps.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/Makefile                    |  1 +
 drivers/net/softnic/meson.build                 |  1 +
 drivers/net/softnic/rte_eth_softnic_flow.c      | 46 +++++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h | 31 +++++++++++++++++
 4 files changed, 79 insertions(+)
 create mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile
index ea9b65f4e..12515b10d 100644
--- a/drivers/net/softnic/Makefile
+++ b/drivers/net/softnic/Makefile
@@ -33,6 +33,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_thread.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_cli.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += parser.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += conn.c
 
diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index ff9822747..56e5e2b21 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -13,6 +13,7 @@ sources = files('rte_eth_softnic_tm.c',
 	'rte_eth_softnic_pipeline.c',
 	'rte_eth_softnic_thread.c',
 	'rte_eth_softnic_cli.c',
+	'rte_eth_softnic_flow.c',
 	'parser.c',
 	'conn.c')
 deps += ['pipeline', 'port', 'table', 'sched']
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
new file mode 100644
index 000000000..843db7590
--- /dev/null
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include "rte_eth_softnic_internals.h"
+#include "rte_eth_softnic.h"
+
+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];
+	strcpy(map->pipeline_name, 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];
+}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 882cfd191..d1996c469 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -51,6 +51,21 @@ 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];
+};
+
 /**
  * MEMPOOL
  */
@@ -497,6 +512,7 @@ struct pmd_internals {
 		struct tm_internals tm; /**< Traffic Management */
 	} soft;
 
+	struct flow_internals flow;
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
@@ -510,6 +526,21 @@ struct pmd_internals {
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
 };
 
+/**
+ * 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);
+
 /**
  * MEMPOOL
  */
-- 
2.14.4

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

* [PATCH 03/15] net/softnic: add new cli for flow attribute map
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
  2018-09-06 16:26 ` [PATCH 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
  2018-09-06 16:26 ` [PATCH 02/15] net/softnic: rte flow attr mapping to pipeline Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 04/15] net/softnic: various data type changes Reshma Pattan
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added new cli by which user can specify to softnic
which rte flow group and direction has to mapped to
which pipeline and table.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 81 +++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 0c7448cc4..8f5f82555 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4797,6 +4797,81 @@ 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)
 {
@@ -5089,6 +5164,12 @@ 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]);
 }
 
-- 
2.14.4

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

* [PATCH 04/15] net/softnic: various data type changes
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (2 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 05/15] net/softnic: add free table and find out port functions Reshma Pattan
                   ` (26 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Change dev_name, action_profile_name and key_mask
from char* type to arary type of structures
softnic_port_in_params, softnic_port_out_params
and softnic_table_hash_params.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c       | 34 +++++++++++--------------
 drivers/net/softnic/rte_eth_softnic_internals.h | 18 ++++++-------
 drivers/net/softnic/rte_eth_softnic_pipeline.c  |  4 +--
 3 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 8f5f82555..dc8ccdc73 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1697,6 +1697,8 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 	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;
@@ -1735,7 +1737,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_RXQ;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
@@ -1758,7 +1760,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_SWQ;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tmgr") == 0) {
@@ -1770,7 +1772,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_TMGR;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tap") == 0) {
@@ -1782,7 +1784,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_TAP;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		if (strcmp(tokens[t0 + 2], "mempool") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
@@ -1814,8 +1816,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_SOURCE;
 
-		p.dev_name = NULL;
-
 		if (strcmp(tokens[t0 + 1], "mempool") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
 				"mempool");
@@ -1851,7 +1851,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		return;
 	}
 
-	p.action_profile_name = NULL;
 	if (n_tokens > t0 &&
 		(strcmp(tokens[t0], "action") == 0)) {
 		if (n_tokens < t0 + 2) {
@@ -1859,7 +1858,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 			return;
 		}
 
-		p.action_profile_name = tokens[t0 + 1];
+		strcpy(p.action_profile_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	}
@@ -1945,7 +1944,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TXQ;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 
 		if (strcmp(tokens[8], "txq") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
@@ -1966,7 +1965,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "tmgr") == 0) {
 		if (n_tokens != 8) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1976,7 +1975,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TMGR;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "tap") == 0) {
 		if (n_tokens != 8) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1986,7 +1985,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TAP;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "sink") == 0) {
 		if ((n_tokens != 7) && (n_tokens != 11)) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1996,8 +1995,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SINK;
 
-		p.dev_name = NULL;
-
 		if (n_tokens == 7) {
 			p.sink.file_name = NULL;
 			p.sink.max_n_pkts = 0;
@@ -2064,12 +2061,13 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 	char *out,
 	size_t out_size)
 {
-	uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
 	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;
@@ -2203,12 +2201,11 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 		}
 
 		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			key_mask, &key_mask_size) != 0) ||
+			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;
 		}
-		p.match.hash.key_mask = key_mask;
 
 		if (strcmp(tokens[t0 + 6], "offset") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
@@ -2295,7 +2292,6 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 		return;
 	}
 
-	p.action_profile_name = NULL;
 	if (n_tokens > t0 &&
 		(strcmp(tokens[t0], "action") == 0)) {
 		if (n_tokens < t0 + 2) {
@@ -2303,7 +2299,7 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 			return;
 		}
 
-		p.action_profile_name = tokens[t0 + 1];
+		strcpy(p.action_profile_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d1996c469..f40215dfe 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -308,7 +308,7 @@ enum softnic_port_in_type {
 struct softnic_port_in_params {
 	/* Read */
 	enum softnic_port_in_type type;
-	const char *dev_name;
+	char dev_name[NAME_SIZE];
 	union {
 		struct {
 			uint16_t queue_id;
@@ -328,7 +328,7 @@ struct softnic_port_in_params {
 	uint32_t burst_size;
 
 	/* Action */
-	const char *action_profile_name;
+	char action_profile_name[NAME_SIZE];
 };
 
 enum softnic_port_out_type {
@@ -341,7 +341,7 @@ enum softnic_port_out_type {
 
 struct softnic_port_out_params {
 	enum softnic_port_out_type type;
-	const char *dev_name;
+	char dev_name[NAME_SIZE];
 	union {
 		struct {
 			uint16_t queue_id;
@@ -376,11 +376,15 @@ struct softnic_table_array_params {
 	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;
+	uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
 	uint32_t n_buckets;
 	int extendable_bucket;
 };
@@ -402,7 +406,7 @@ struct softnic_table_params {
 	} match;
 
 	/* Action */
-	const char *action_profile_name;
+	char action_profile_name[NAME_SIZE];
 };
 
 struct softnic_port_in {
@@ -757,10 +761,6 @@ struct softnic_table_rule_match_array {
 	uint32_t pos;
 };
 
-#ifndef TABLE_RULE_MATCH_SIZE_MAX
-#define TABLE_RULE_MATCH_SIZE_MAX                          256
-#endif
-
 struct softnic_table_rule_match_hash {
 	uint8_t key[TABLE_RULE_MATCH_SIZE_MAX];
 };
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 45136a4a2..dacf7bc9a 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -213,7 +213,7 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		return -1;
 
 	ap = NULL;
-	if (params->action_profile_name) {
+	if (strlen(params->action_profile_name)) {
 		ap = softnic_port_in_action_profile_find(softnic,
 			params->action_profile_name);
 		if (ap == NULL)
@@ -730,7 +730,7 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 		return -1;
 
 	ap = NULL;
-	if (params->action_profile_name) {
+	if (strlen(params->action_profile_name)) {
 		ap = softnic_table_action_profile_find(softnic,
 			params->action_profile_name);
 		if (ap == NULL)
-- 
2.14.4

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

* [PATCH 05/15] net/softnic: add free table and find out port functions
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (3 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 04/15] net/softnic: various data type changes Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
                   ` (25 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added utility function to freeup the
pipeline tables.

Added utility functions to find the pipeline
output port.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 13 ++++++
 drivers/net/softnic/rte_eth_softnic_pipeline.c  | 57 +++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index f40215dfe..9c587bc7d 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -415,10 +415,15 @@ struct softnic_port_in {
 	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 flow_list flows;
 };
 
 struct pipeline {
@@ -426,7 +431,9 @@ struct pipeline {
 	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;
@@ -725,6 +732,12 @@ 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,
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index dacf7bc9a..d1084ea36 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -43,17 +43,41 @@ softnic_pipeline_init(struct pmd_internals *p)
 	return 0;
 }
 
+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);
+	}
+}
+
 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);
@@ -160,6 +184,7 @@ softnic_pipeline_create(struct pmd_internals *softnic,
 	/* 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;
@@ -401,6 +426,7 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 	} pp_nodrop;
 
 	struct pipeline *pipeline;
+	struct softnic_port_out *port_out;
 	uint32_t port_id;
 	int status;
 
@@ -542,6 +568,8 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		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;
@@ -960,7 +988,36 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 	memcpy(&table->params, params, sizeof(*params));
 	table->ap = ap;
 	table->a = action;
+	TAILQ_INIT(&table->flows);
 	pipeline->n_tables++;
 
 	return 0;
 }
+
+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;
+		}
+
+	return -1;
+}
-- 
2.14.4

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

* [PATCH 06/15] net/softnic: add function to get eth device from softnic
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (4 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 05/15] net/softnic: add free table and find out port functions Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 07/15] net/softnic: flow API validate support Reshma Pattan
                   ` (24 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Add utility function to get the rte_eth_dev from
a given softnic.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 9c587bc7d..1857ec50d 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -18,6 +18,7 @@
 #include <rte_table_action.h>
 #include <rte_pipeline.h>
 
+#include <rte_ethdev_core.h>
 #include <rte_ethdev_driver.h>
 #include <rte_tm_driver.h>
 #include <rte_flow_driver.h>
@@ -537,6 +538,22 @@ struct pmd_internals {
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
 };
 
+static inline struct rte_eth_dev *
+ETHDEV(struct pmd_internals *softnic)
+{
+	uint16_t port_id;
+	int status;
+
+	if (softnic == NULL)
+		return NULL;
+
+	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+	if (status)
+		return NULL;
+
+	return &rte_eth_devices[port_id];
+}
+
 /**
  * Ethdev Flow API
  */
-- 
2.14.4

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

* [PATCH 07/15] net/softnic: flow API validate support
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (5 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
                   ` (23 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Start adding flow api operations.

Started with flow validate api support by adding
below basic infrastructure.

flow_pipeline_table_get()
pmd_flow_validate()

Additional flow validate changes will be
added in next patches.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic.c           |  16 ++++
 drivers/net/softnic/rte_eth_softnic_flow.c      | 112 ++++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h |   2 +
 3 files changed, 130 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 30fb3952a..ae2a4385b 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -205,6 +205,21 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
+static int
+pmd_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
+		enum rte_filter_type filter_type,
+		enum rte_filter_op filter_op,
+		void *arg)
+{
+	if (filter_type == RTE_ETH_FILTER_GENERIC &&
+			filter_op == RTE_ETH_FILTER_GET) {
+		*(const void **)arg = &pmd_flow_ops;
+		return 0;
+	}
+
+	return -ENOTSUP;
+}
+
 static int
 pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -222,6 +237,7 @@ 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,
+	.filter_ctrl = pmd_filter_ctrl,
 	.tm_ops_get = pmd_tm_ops_get,
 };
 
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 843db7590..f37890333 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -44,3 +44,115 @@ flow_attr_map_get(struct pmd_internals *softnic,
 	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;
+}
+
+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 pmd_internals *softnic = dev->data->dev_private;
+	struct pipeline *pipeline;
+	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");
+
+	return 0;
+}
+
+const struct rte_flow_ops pmd_flow_ops = {
+	.validate = pmd_flow_validate,
+};
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 1857ec50d..a1a2e1558 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -569,6 +569,8 @@ flow_attr_map_get(struct pmd_internals *softnic,
 		uint32_t group_id,
 		int ingress);
 
+extern const struct rte_flow_ops pmd_flow_ops;
+
 /**
  * MEMPOOL
  */
-- 
2.14.4

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

* [PATCH 08/15] net/softnic: validate and map flow rule with acl table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (6 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 07/15] net/softnic: flow API validate support Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 09/15] net/softnic: parse flow protocol for " Reshma Pattan
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Support for validating and mapping rte flow rule with
ACL table match is added.

As part of this support below utility functions
been added
flow_rule_match_get()
flow_rule_match_acl_get()
flow_item_skip_disabled_protos()
flow_item_proto_preprocess()
flow_item_is_proto()
flow_item_raw_preprocess()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 386 +++++++++++++++++++++++++++++
 1 file changed, 386 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index f37890333..022d41775 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -95,6 +95,375 @@ flow_pipeline_table_get(struct pmd_internals *softnic,
 	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_flow_item_eth);
+		return 1; /* TRUE */
+
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		*mask = &rte_flow_item_vlan_mask;
+		*size = sizeof(struct rte_flow_item_vlan);
+		return 1;
+
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		*mask = &rte_flow_item_ipv4_mask;
+		*size = sizeof(struct rte_flow_item_ipv4);
+		return 1;
+
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		*mask = &rte_flow_item_ipv6_mask;
+		*size = sizeof(struct rte_flow_item_ipv6);
+		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_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");
+
+	/* 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 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;
+
+	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) {
+	default:
+		return rte_flow_error_set(error,
+			ENOTSUP,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			item,
+			"ACL: IP protocol required");
+	} /* switch */
+}
+
+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 */
+	default:
+		return rte_flow_error_set(error,
+			ENOTSUP,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Unsupported pipeline table match type");
+	}
+}
+
 static int
 pmd_flow_validate(struct rte_eth_dev *dev,
 		const struct rte_flow_attr *attr,
@@ -102,8 +471,11 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 		const struct rte_flow_action action[],
 		struct rte_flow_error *error)
 {
+	struct softnic_table_rule_match rule_match;
+
 	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;
@@ -150,6 +522,20 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 				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;
+
 	return 0;
 }
 
-- 
2.14.4

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

* [PATCH 09/15] net/softnic: parse flow protocol for acl table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (7 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added flow protocol parsing for IPV4/IPV6 and
TCP/UDP/SCTP for ACL table rule match.

Added below helper functions for doing the same.
port_mask_to_range()
ipv6_mask_to_depth()
ipv4_mask_to_depth()
mask_to_depth()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 344 ++++++++++++++++++++++++++++-
 1 file changed, 342 insertions(+), 2 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 022d41775..d6d9893b5 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1,10 +1,13 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
+ * Copyright(c) 2018 Intel Corporation
  */
 
 #include "rte_eth_softnic_internals.h"
 #include "rte_eth_softnic.h"
 
+#define rte_ntohs rte_be_to_cpu_16
+#define rte_ntohl rte_be_to_cpu_32
+
 int
 flow_attr_map_set(struct pmd_internals *softnic,
 		uint32_t group_id,
@@ -397,6 +400,113 @@ flow_item_skip_disabled_protos(const struct rte_flow_item **item,
 	((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,
@@ -409,6 +519,7 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 	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;
@@ -427,6 +538,80 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 		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,
@@ -434,9 +619,164 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 			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 */
+
+	return 0;
 }
 
-static int
+	static int
 flow_rule_match_get(struct pmd_internals *softnic,
 		struct pipeline *pipeline,
 		struct softnic_table *table,
-- 
2.14.4

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

* [PATCH 10/15] net/softnic: validate and map flow with hash table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (8 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 09/15] net/softnic: parse flow protocol for " Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Support for validating and mapping flow rule with HASH
table match is added.

As part of this, below helper functions are added.
flow_rule_match_hash_get()
hash_key_mask_is_same()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 201 ++++++++++++++++++++++++++++-
 1 file changed, 200 insertions(+), 1 deletion(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index d6d9893b5..788397c1d 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -776,7 +776,195 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 	return 0;
 }
 
-	static int
+/***
+ * 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*
+ * respectivelly. 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,
@@ -794,7 +982,18 @@ flow_rule_match_get(struct pmd_internals *softnic,
 			item,
 			rule_match,
 			error);
+
 		/* FALLTHROUGH */
+
+	case TABLE_HASH:
+		return flow_rule_match_hash_get(softnic,
+			pipeline,
+			table,
+			attr,
+			item,
+			rule_match,
+			error);
+
 	default:
 		return rte_flow_error_set(error,
 			ENOTSUP,
-- 
2.14.4

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

* [PATCH 11/15] net/softnic: validate and map flow action with table action
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (9 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:26 ` [PATCH 12/15] net/softnic: add flow create API Reshma Pattan
                   ` (19 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added validation and mapping of flow rule action
with table action profile.

Added flow_rule_action_get() to do the same.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 350 +++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 788397c1d..351d34524 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -994,6 +994,8 @@ flow_rule_match_get(struct pmd_internals *softnic,
 			rule_match,
 			error);
 
+		/* FALLTHROUGH */
+
 	default:
 		return rte_flow_error_set(error,
 			ENOTSUP,
@@ -1003,6 +1005,341 @@ flow_rule_match_get(struct pmd_internals *softnic,
 	}
 }
 
+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 __rte_unused)
+{
+	struct softnic_table_action_profile *profile;
+	struct softnic_table_action_profile_params *params;
+	int n_jump_queue_rss_drop = 0;
+	int n_count = 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");
+
+			sprintf(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");
+
+				sprintf(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 (conf->shared)
+				return rte_flow_error_set(error,
+					ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+					conf,
+					"COUNT: Shared counters not supported");
+
+			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 */
+
+		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,
@@ -1011,6 +1348,7 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 		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;
@@ -1075,6 +1413,18 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 	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;
 }
 
-- 
2.14.4

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

* [PATCH 12/15] net/softnic: add flow create API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (10 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
@ 2018-09-06 16:26 ` Reshma Pattan
  2018-09-06 16:27 ` [PATCH 13/15] net/softnic: add flow destroy API Reshma Pattan
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:26 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

pmd_flow_create API is added to support
rte flow create.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 174 +++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 351d34524..034bca047 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1,13 +1,39 @@
 /* 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_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,
@@ -1428,6 +1454,154 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 	return 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;
+	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;
+
+	/* Flow add to list. */
+	if (new_flow)
+		TAILQ_INSERT_TAIL(&table->flows, flow, node);
+
+	return flow;
+}
+
 const struct rte_flow_ops pmd_flow_ops = {
 	.validate = pmd_flow_validate,
+	.create = pmd_flow_create,
 };
-- 
2.14.4

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

* [PATCH 13/15] net/softnic: add flow destroy API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (11 preceding siblings ...)
  2018-09-06 16:26 ` [PATCH 12/15] net/softnic: add flow create API Reshma Pattan
@ 2018-09-06 16:27 ` Reshma Pattan
  2018-09-06 16:27 ` [PATCH 14/15] net/softnic: add flow query API Reshma Pattan
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:27 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

pmd_flow_destroy() API is added to destroy the
created flow.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 034bca047..3f8531139 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1601,7 +1601,46 @@ pmd_flow_create(struct rte_eth_dev *dev,
 	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");
+
+	/* Flow delete. */
+	TAILQ_REMOVE(&table->flows, flow, node);
+	free(flow);
+
+	return 0;
+}
+
 const struct rte_flow_ops pmd_flow_ops = {
 	.validate = pmd_flow_validate,
 	.create = pmd_flow_create,
+	.destroy = pmd_flow_destroy,
 };
-- 
2.14.4

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

* [PATCH 14/15] net/softnic: add flow query API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (12 preceding siblings ...)
  2018-09-06 16:27 ` [PATCH 13/15] net/softnic: add flow destroy API Reshma Pattan
@ 2018-09-06 16:27 ` Reshma Pattan
  2018-09-06 16:27 ` [PATCH 15/15] net/softnic: add parsing for raw flow item Reshma Pattan
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:27 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added pmd_flow_query() API, for flow query
support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 3f8531139..da235ff7f 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1639,8 +1639,63 @@ pmd_flow_destroy(struct rte_eth_dev *dev,
 	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 = NULL,
+	.query = pmd_flow_query,
+	.isolate = NULL,
 };
-- 
2.14.4

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

* [PATCH 15/15] net/softnic: add parsing for raw flow item
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (13 preceding siblings ...)
  2018-09-06 16:27 ` [PATCH 14/15] net/softnic: add flow query API Reshma Pattan
@ 2018-09-06 16:27 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 00/15] add flow API support to softnic Reshma Pattan
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-06 16:27 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added support for parsing raw flow item.
flow_item_raw_preprocess() is added for the same.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 108 +++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index da235ff7f..656200445 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -297,6 +297,106 @@ flow_item_is_proto(enum rte_flow_item_type type,
 	}
 }
 
+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,
@@ -317,6 +417,14 @@ flow_item_proto_preprocess(const struct rte_flow_item *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. */
-- 
2.14.4

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

* [PATCH v2 00/15] add flow API support to softnic
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (14 preceding siblings ...)
  2018-09-06 16:27 ` [PATCH 15/15] net/softnic: add parsing for raw flow item Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-28 10:36   ` Dumitrescu, Cristian
  2018-09-11 14:20 ` [PATCH v2 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
                   ` (14 subsequent siblings)
  30 siblings, 1 reply; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev

This patch series adds the flow API support
for the softnic.

This patch set also introduce a new cli command
to provide mapping of flow group and direction
to softnic pipeline and table.

v2: added missing code to patch #9/10
reworded commit titles.

Reshma Pattan (15):
  net/softnic: add infrastructure for flow API
  net/softnic: map flow attributes to pipeline table
  net/softnic: add new cli for flow attribute map
  net/softnic: replace some pointers with arrays
  net/softnic: add free table and find out port functions
  net/softnic: add function to get eth device from softnic
  net/softnic: implement flow validate API
  net/softnic: validate and map flow rule with acl table match
  net/softnic: parse flow protocol for acl table match
  net/softnic: validate and map flow with hash table match
  net/softnic: validate and map flow action with table action
  net/softnic: add flow create API
  net/softnic: add flow destroy API
  net/softnic: add flow query API
  net/softnic: add parsing for raw flow item

 drivers/net/softnic/Makefile                    |    1 +
 drivers/net/softnic/meson.build                 |    1 +
 drivers/net/softnic/rte_eth_softnic.c           |   16 +
 drivers/net/softnic/rte_eth_softnic_cli.c       |  115 +-
 drivers/net/softnic/rte_eth_softnic_flow.c      | 1824 +++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h |   98 +-
 drivers/net/softnic/rte_eth_softnic_pipeline.c  |   61 +-
 7 files changed, 2086 insertions(+), 30 deletions(-)
 create mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

-- 
2.14.4

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

* [PATCH v2 01/15] net/softnic: add infrastructure for flow API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (15 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 00/15] add flow API support to softnic Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 02/15] net/softnic: map flow attributes to pipeline table Reshma Pattan
                   ` (13 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Add rte_flow infra structure for flow api support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index a25eb874c..882cfd191 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -20,6 +20,7 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_tm_driver.h>
+#include <rte_flow_driver.h>
 
 #include "rte_eth_softnic.h"
 #include "conn.h"
@@ -43,6 +44,13 @@ struct pmd_params {
 	} tm;
 };
 
+/**
+ * Ethdev Flow API
+ */
+struct rte_flow;
+
+TAILQ_HEAD(flow_list, rte_flow);
+
 /**
  * MEMPOOL
  */
@@ -762,6 +770,15 @@ struct softnic_table_rule_action {
 	struct rte_table_action_time_params time;
 };
 
+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,
-- 
2.14.4

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

* [PATCH v2 02/15] net/softnic: map flow attributes to pipeline table
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (16 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added mapping support from rte flow attributes
to softnic pipeline and table.

So added flow attribute map set and get functions
definition to new file rte_eth_sofnic_flow.c.

Added pmd flow internals with ingress and egress
flow attribute maps.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/Makefile                    |  1 +
 drivers/net/softnic/meson.build                 |  1 +
 drivers/net/softnic/rte_eth_softnic_flow.c      | 46 +++++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h | 31 +++++++++++++++++
 4 files changed, 79 insertions(+)
 create mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c

diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile
index ea9b65f4e..12515b10d 100644
--- a/drivers/net/softnic/Makefile
+++ b/drivers/net/softnic/Makefile
@@ -33,6 +33,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_action.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_pipeline.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_thread.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_cli.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_flow.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += parser.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += conn.c
 
diff --git a/drivers/net/softnic/meson.build b/drivers/net/softnic/meson.build
index ff9822747..56e5e2b21 100644
--- a/drivers/net/softnic/meson.build
+++ b/drivers/net/softnic/meson.build
@@ -13,6 +13,7 @@ sources = files('rte_eth_softnic_tm.c',
 	'rte_eth_softnic_pipeline.c',
 	'rte_eth_softnic_thread.c',
 	'rte_eth_softnic_cli.c',
+	'rte_eth_softnic_flow.c',
 	'parser.c',
 	'conn.c')
 deps += ['pipeline', 'port', 'table', 'sched']
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
new file mode 100644
index 000000000..843db7590
--- /dev/null
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation
+ */
+
+#include "rte_eth_softnic_internals.h"
+#include "rte_eth_softnic.h"
+
+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];
+	strcpy(map->pipeline_name, 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];
+}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 882cfd191..d1996c469 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -51,6 +51,21 @@ 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];
+};
+
 /**
  * MEMPOOL
  */
@@ -497,6 +512,7 @@ struct pmd_internals {
 		struct tm_internals tm; /**< Traffic Management */
 	} soft;
 
+	struct flow_internals flow;
 	struct softnic_conn *conn;
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
@@ -510,6 +526,21 @@ struct pmd_internals {
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
 };
 
+/**
+ * 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);
+
 /**
  * MEMPOOL
  */
-- 
2.14.4

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

* [PATCH v2 03/15] net/softnic: add new cli for flow attribute map
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (17 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 02/15] net/softnic: map flow attributes to pipeline table Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 04/15] net/softnic: replace some pointers with arrays Reshma Pattan
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added new cli by which user can specify to softnic
which rte flow group and direction has to mapped to
which pipeline and table.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c | 81 +++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 0c7448cc4..8f5f82555 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -4797,6 +4797,81 @@ 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)
 {
@@ -5089,6 +5164,12 @@ 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]);
 }
 
-- 
2.14.4

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

* [PATCH v2 04/15] net/softnic: replace some pointers with arrays
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (18 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 05/15] net/softnic: add free table and find out port functions Reshma Pattan
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Change dev_name, action_profile_name and key_mask
from char* type to arary type of structures
softnic_port_in_params, softnic_port_out_params
and softnic_table_hash_params.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_cli.c       | 34 +++++++++++--------------
 drivers/net/softnic/rte_eth_softnic_internals.h | 18 ++++++-------
 drivers/net/softnic/rte_eth_softnic_pipeline.c  |  4 +--
 3 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_cli.c b/drivers/net/softnic/rte_eth_softnic_cli.c
index 8f5f82555..dc8ccdc73 100644
--- a/drivers/net/softnic/rte_eth_softnic_cli.c
+++ b/drivers/net/softnic/rte_eth_softnic_cli.c
@@ -1697,6 +1697,8 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 	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;
@@ -1735,7 +1737,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_RXQ;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		if (strcmp(tokens[t0 + 2], "rxq") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
@@ -1758,7 +1760,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_SWQ;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tmgr") == 0) {
@@ -1770,7 +1772,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_TMGR;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	} else if (strcmp(tokens[t0], "tap") == 0) {
@@ -1782,7 +1784,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_TAP;
 
-		p.dev_name = tokens[t0 + 1];
+		strcpy(p.dev_name, tokens[t0 + 1]);
 
 		if (strcmp(tokens[t0 + 2], "mempool") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
@@ -1814,8 +1816,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 
 		p.type = PORT_IN_SOURCE;
 
-		p.dev_name = NULL;
-
 		if (strcmp(tokens[t0 + 1], "mempool") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
 				"mempool");
@@ -1851,7 +1851,6 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 		return;
 	}
 
-	p.action_profile_name = NULL;
 	if (n_tokens > t0 &&
 		(strcmp(tokens[t0], "action") == 0)) {
 		if (n_tokens < t0 + 2) {
@@ -1859,7 +1858,7 @@ cmd_pipeline_port_in(struct pmd_internals *softnic,
 			return;
 		}
 
-		p.action_profile_name = tokens[t0 + 1];
+		strcpy(p.action_profile_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	}
@@ -1945,7 +1944,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TXQ;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 
 		if (strcmp(tokens[8], "txq") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
@@ -1966,7 +1965,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SWQ;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "tmgr") == 0) {
 		if (n_tokens != 8) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1976,7 +1975,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TMGR;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "tap") == 0) {
 		if (n_tokens != 8) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1986,7 +1985,7 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_TAP;
 
-		p.dev_name = tokens[7];
+		strcpy(p.dev_name, tokens[7]);
 	} else if (strcmp(tokens[6], "sink") == 0) {
 		if ((n_tokens != 7) && (n_tokens != 11)) {
 			snprintf(out, out_size, MSG_ARG_MISMATCH,
@@ -1996,8 +1995,6 @@ cmd_pipeline_port_out(struct pmd_internals *softnic,
 
 		p.type = PORT_OUT_SINK;
 
-		p.dev_name = NULL;
-
 		if (n_tokens == 7) {
 			p.sink.file_name = NULL;
 			p.sink.max_n_pkts = 0;
@@ -2064,12 +2061,13 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 	char *out,
 	size_t out_size)
 {
-	uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
 	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;
@@ -2203,12 +2201,11 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 		}
 
 		if ((softnic_parse_hex_string(tokens[t0 + 5],
-			key_mask, &key_mask_size) != 0) ||
+			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;
 		}
-		p.match.hash.key_mask = key_mask;
 
 		if (strcmp(tokens[t0 + 6], "offset") != 0) {
 			snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
@@ -2295,7 +2292,6 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 		return;
 	}
 
-	p.action_profile_name = NULL;
 	if (n_tokens > t0 &&
 		(strcmp(tokens[t0], "action") == 0)) {
 		if (n_tokens < t0 + 2) {
@@ -2303,7 +2299,7 @@ cmd_pipeline_table(struct pmd_internals *softnic,
 			return;
 		}
 
-		p.action_profile_name = tokens[t0 + 1];
+		strcpy(p.action_profile_name, tokens[t0 + 1]);
 
 		t0 += 2;
 	}
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index d1996c469..f40215dfe 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -308,7 +308,7 @@ enum softnic_port_in_type {
 struct softnic_port_in_params {
 	/* Read */
 	enum softnic_port_in_type type;
-	const char *dev_name;
+	char dev_name[NAME_SIZE];
 	union {
 		struct {
 			uint16_t queue_id;
@@ -328,7 +328,7 @@ struct softnic_port_in_params {
 	uint32_t burst_size;
 
 	/* Action */
-	const char *action_profile_name;
+	char action_profile_name[NAME_SIZE];
 };
 
 enum softnic_port_out_type {
@@ -341,7 +341,7 @@ enum softnic_port_out_type {
 
 struct softnic_port_out_params {
 	enum softnic_port_out_type type;
-	const char *dev_name;
+	char dev_name[NAME_SIZE];
 	union {
 		struct {
 			uint16_t queue_id;
@@ -376,11 +376,15 @@ struct softnic_table_array_params {
 	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;
+	uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
 	uint32_t n_buckets;
 	int extendable_bucket;
 };
@@ -402,7 +406,7 @@ struct softnic_table_params {
 	} match;
 
 	/* Action */
-	const char *action_profile_name;
+	char action_profile_name[NAME_SIZE];
 };
 
 struct softnic_port_in {
@@ -757,10 +761,6 @@ struct softnic_table_rule_match_array {
 	uint32_t pos;
 };
 
-#ifndef TABLE_RULE_MATCH_SIZE_MAX
-#define TABLE_RULE_MATCH_SIZE_MAX                          256
-#endif
-
 struct softnic_table_rule_match_hash {
 	uint8_t key[TABLE_RULE_MATCH_SIZE_MAX];
 };
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index 45136a4a2..dacf7bc9a 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -213,7 +213,7 @@ softnic_pipeline_port_in_create(struct pmd_internals *softnic,
 		return -1;
 
 	ap = NULL;
-	if (params->action_profile_name) {
+	if (strlen(params->action_profile_name)) {
 		ap = softnic_port_in_action_profile_find(softnic,
 			params->action_profile_name);
 		if (ap == NULL)
@@ -730,7 +730,7 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 		return -1;
 
 	ap = NULL;
-	if (params->action_profile_name) {
+	if (strlen(params->action_profile_name)) {
 		ap = softnic_table_action_profile_find(softnic,
 			params->action_profile_name);
 		if (ap == NULL)
-- 
2.14.4

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

* [PATCH v2 05/15] net/softnic: add free table and find out port functions
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (19 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 04/15] net/softnic: replace some pointers with arrays Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added utility function to freeup the
pipeline tables.

Added utility functions to find the pipeline
output port.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 13 ++++++
 drivers/net/softnic/rte_eth_softnic_pipeline.c  | 57 +++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index f40215dfe..9c587bc7d 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -415,10 +415,15 @@ struct softnic_port_in {
 	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 flow_list flows;
 };
 
 struct pipeline {
@@ -426,7 +431,9 @@ struct pipeline {
 	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;
@@ -725,6 +732,12 @@ 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,
diff --git a/drivers/net/softnic/rte_eth_softnic_pipeline.c b/drivers/net/softnic/rte_eth_softnic_pipeline.c
index dacf7bc9a..d1084ea36 100644
--- a/drivers/net/softnic/rte_eth_softnic_pipeline.c
+++ b/drivers/net/softnic/rte_eth_softnic_pipeline.c
@@ -43,17 +43,41 @@ softnic_pipeline_init(struct pmd_internals *p)
 	return 0;
 }
 
+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);
+	}
+}
+
 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);
@@ -160,6 +184,7 @@ softnic_pipeline_create(struct pmd_internals *softnic,
 	/* 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;
@@ -401,6 +426,7 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 	} pp_nodrop;
 
 	struct pipeline *pipeline;
+	struct softnic_port_out *port_out;
 	uint32_t port_id;
 	int status;
 
@@ -542,6 +568,8 @@ softnic_pipeline_port_out_create(struct pmd_internals *softnic,
 		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;
@@ -960,7 +988,36 @@ softnic_pipeline_table_create(struct pmd_internals *softnic,
 	memcpy(&table->params, params, sizeof(*params));
 	table->ap = ap;
 	table->a = action;
+	TAILQ_INIT(&table->flows);
 	pipeline->n_tables++;
 
 	return 0;
 }
+
+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;
+		}
+
+	return -1;
+}
-- 
2.14.4

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

* [PATCH v2 06/15] net/softnic: add function to get eth device from softnic
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (20 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 05/15] net/softnic: add free table and find out port functions Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 07/15] net/softnic: implement flow validate API Reshma Pattan
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Add utility function to get the rte_eth_dev from
a given softnic.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_internals.h | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 9c587bc7d..1857ec50d 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -18,6 +18,7 @@
 #include <rte_table_action.h>
 #include <rte_pipeline.h>
 
+#include <rte_ethdev_core.h>
 #include <rte_ethdev_driver.h>
 #include <rte_tm_driver.h>
 #include <rte_flow_driver.h>
@@ -537,6 +538,22 @@ struct pmd_internals {
 	struct softnic_thread_data thread_data[RTE_MAX_LCORE];
 };
 
+static inline struct rte_eth_dev *
+ETHDEV(struct pmd_internals *softnic)
+{
+	uint16_t port_id;
+	int status;
+
+	if (softnic == NULL)
+		return NULL;
+
+	status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+	if (status)
+		return NULL;
+
+	return &rte_eth_devices[port_id];
+}
+
 /**
  * Ethdev Flow API
  */
-- 
2.14.4

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

* [PATCH v2 07/15] net/softnic: implement flow validate API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (21 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Start adding flow api operations.

Started with flow validate api support by adding
below basic infrastructure.

flow_pipeline_table_get()
pmd_flow_validate()

Additional flow validate changes will be
added in next patches.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic.c           |  16 ++++
 drivers/net/softnic/rte_eth_softnic_flow.c      | 112 ++++++++++++++++++++++++
 drivers/net/softnic/rte_eth_softnic_internals.h |   2 +
 3 files changed, 130 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index 30fb3952a..ae2a4385b 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -205,6 +205,21 @@ pmd_link_update(struct rte_eth_dev *dev __rte_unused,
 	return 0;
 }
 
+static int
+pmd_filter_ctrl(struct rte_eth_dev *dev __rte_unused,
+		enum rte_filter_type filter_type,
+		enum rte_filter_op filter_op,
+		void *arg)
+{
+	if (filter_type == RTE_ETH_FILTER_GENERIC &&
+			filter_op == RTE_ETH_FILTER_GET) {
+		*(const void **)arg = &pmd_flow_ops;
+		return 0;
+	}
+
+	return -ENOTSUP;
+}
+
 static int
 pmd_tm_ops_get(struct rte_eth_dev *dev __rte_unused, void *arg)
 {
@@ -222,6 +237,7 @@ 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,
+	.filter_ctrl = pmd_filter_ctrl,
 	.tm_ops_get = pmd_tm_ops_get,
 };
 
diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 843db7590..f37890333 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -44,3 +44,115 @@ flow_attr_map_get(struct pmd_internals *softnic,
 	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;
+}
+
+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 pmd_internals *softnic = dev->data->dev_private;
+	struct pipeline *pipeline;
+	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");
+
+	return 0;
+}
+
+const struct rte_flow_ops pmd_flow_ops = {
+	.validate = pmd_flow_validate,
+};
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index 1857ec50d..a1a2e1558 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -569,6 +569,8 @@ flow_attr_map_get(struct pmd_internals *softnic,
 		uint32_t group_id,
 		int ingress);
 
+extern const struct rte_flow_ops pmd_flow_ops;
+
 /**
  * MEMPOOL
  */
-- 
2.14.4

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

* [PATCH v2 08/15] net/softnic: validate and map flow rule with acl table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (22 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 07/15] net/softnic: implement flow validate API Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 09/15] net/softnic: parse flow protocol for " Reshma Pattan
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Support for validating and mapping rte flow rule with
ACL table match is added.

As part of this support below utility functions
been added
flow_rule_match_get()
flow_rule_match_acl_get()
flow_item_skip_disabled_protos()
flow_item_proto_preprocess()
flow_item_is_proto()
flow_item_raw_preprocess()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 386 +++++++++++++++++++++++++++++
 1 file changed, 386 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index f37890333..022d41775 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -95,6 +95,375 @@ flow_pipeline_table_get(struct pmd_internals *softnic,
 	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_flow_item_eth);
+		return 1; /* TRUE */
+
+	case RTE_FLOW_ITEM_TYPE_VLAN:
+		*mask = &rte_flow_item_vlan_mask;
+		*size = sizeof(struct rte_flow_item_vlan);
+		return 1;
+
+	case RTE_FLOW_ITEM_TYPE_IPV4:
+		*mask = &rte_flow_item_ipv4_mask;
+		*size = sizeof(struct rte_flow_item_ipv4);
+		return 1;
+
+	case RTE_FLOW_ITEM_TYPE_IPV6:
+		*mask = &rte_flow_item_ipv6_mask;
+		*size = sizeof(struct rte_flow_item_ipv6);
+		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_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");
+
+	/* 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 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;
+
+	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) {
+	default:
+		return rte_flow_error_set(error,
+			ENOTSUP,
+			RTE_FLOW_ERROR_TYPE_ITEM,
+			item,
+			"ACL: IP protocol required");
+	} /* switch */
+}
+
+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 */
+	default:
+		return rte_flow_error_set(error,
+			ENOTSUP,
+			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+			NULL,
+			"Unsupported pipeline table match type");
+	}
+}
+
 static int
 pmd_flow_validate(struct rte_eth_dev *dev,
 		const struct rte_flow_attr *attr,
@@ -102,8 +471,11 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 		const struct rte_flow_action action[],
 		struct rte_flow_error *error)
 {
+	struct softnic_table_rule_match rule_match;
+
 	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;
@@ -150,6 +522,20 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 				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;
+
 	return 0;
 }
 
-- 
2.14.4

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

* [PATCH v2 09/15] net/softnic: parse flow protocol for acl table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (23 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
                   ` (5 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added flow protocol parsing for IPV4/IPV6 and
TCP/UDP/SCTP for ACL table rule match.

Added below helper functions for doing the same.
port_mask_to_range()
ipv6_mask_to_depth()
ipv4_mask_to_depth()
mask_to_depth()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 359 ++++++++++++++++++++++++++++-
 1 file changed, 357 insertions(+), 2 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 022d41775..94af66391 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1,10 +1,13 @@
 /* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2017 Intel Corporation
+ * Copyright(c) 2018 Intel Corporation
  */
 
 #include "rte_eth_softnic_internals.h"
 #include "rte_eth_softnic.h"
 
+#define rte_ntohs rte_be_to_cpu_16
+#define rte_ntohl rte_be_to_cpu_32
+
 int
 flow_attr_map_set(struct pmd_internals *softnic,
 		uint32_t group_id,
@@ -397,6 +400,113 @@ flow_item_skip_disabled_protos(const struct rte_flow_item **item,
 	((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,
@@ -409,6 +519,7 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 	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;
@@ -427,6 +538,80 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 		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,
@@ -434,9 +619,179 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 			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;
 }
 
-static int
+	static int
 flow_rule_match_get(struct pmd_internals *softnic,
 		struct pipeline *pipeline,
 		struct softnic_table *table,
-- 
2.14.4

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

* [PATCH v2 10/15] net/softnic: validate and map flow with hash table match
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (24 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 09/15] net/softnic: parse flow protocol for " Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
                   ` (4 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Support for validating and mapping flow rule with HASH
table match is added.

As part of this, below helper functions are added.
flow_rule_match_hash_get()
hash_key_mask_is_same()

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 201 ++++++++++++++++++++++++++++-
 1 file changed, 200 insertions(+), 1 deletion(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 94af66391..dc3dd493b 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -791,7 +791,195 @@ flow_rule_match_acl_get(struct pmd_internals *softnic __rte_unused,
 	return 0;
 }
 
-	static int
+/***
+ * 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*
+ * respectivelly. 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,
@@ -809,7 +997,18 @@ flow_rule_match_get(struct pmd_internals *softnic,
 			item,
 			rule_match,
 			error);
+
 		/* FALLTHROUGH */
+
+	case TABLE_HASH:
+		return flow_rule_match_hash_get(softnic,
+			pipeline,
+			table,
+			attr,
+			item,
+			rule_match,
+			error);
+
 	default:
 		return rte_flow_error_set(error,
 			ENOTSUP,
-- 
2.14.4

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

* [PATCH v2 11/15] net/softnic: validate and map flow action with table action
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (25 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 12/15] net/softnic: add flow create API Reshma Pattan
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added validation and mapping of flow rule action
with table action profile.

Added flow_rule_action_get() to do the same.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 350 +++++++++++++++++++++++++++++
 1 file changed, 350 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index dc3dd493b..16f1e4730 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1009,6 +1009,8 @@ flow_rule_match_get(struct pmd_internals *softnic,
 			rule_match,
 			error);
 
+		/* FALLTHROUGH */
+
 	default:
 		return rte_flow_error_set(error,
 			ENOTSUP,
@@ -1018,6 +1020,341 @@ flow_rule_match_get(struct pmd_internals *softnic,
 	}
 }
 
+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 __rte_unused)
+{
+	struct softnic_table_action_profile *profile;
+	struct softnic_table_action_profile_params *params;
+	int n_jump_queue_rss_drop = 0;
+	int n_count = 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");
+
+			sprintf(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");
+
+				sprintf(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 (conf->shared)
+				return rte_flow_error_set(error,
+					ENOTSUP,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF,
+					conf,
+					"COUNT: Shared counters not supported");
+
+			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 */
+
+		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,
@@ -1026,6 +1363,7 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 		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;
@@ -1090,6 +1428,18 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 	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;
 }
 
-- 
2.14.4

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

* [PATCH v2 12/15] net/softnic: add flow create API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (26 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 13/15] net/softnic: add flow destroy API Reshma Pattan
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

pmd_flow_create API is added to support
rte flow create.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 174 +++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 16f1e4730..d3c94965b 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1,13 +1,39 @@
 /* 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_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,
@@ -1443,6 +1469,154 @@ pmd_flow_validate(struct rte_eth_dev *dev,
 	return 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;
+	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;
+
+	/* Flow add to list. */
+	if (new_flow)
+		TAILQ_INSERT_TAIL(&table->flows, flow, node);
+
+	return flow;
+}
+
 const struct rte_flow_ops pmd_flow_ops = {
 	.validate = pmd_flow_validate,
+	.create = pmd_flow_create,
 };
-- 
2.14.4

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

* [PATCH v2 13/15] net/softnic: add flow destroy API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (27 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 12/15] net/softnic: add flow create API Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 14/15] net/softnic: add flow query API Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 15/15] net/softnic: add parsing for raw flow item Reshma Pattan
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

pmd_flow_destroy() API is added to destroy the
created flow.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 39 ++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index d3c94965b..90387b30b 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1616,7 +1616,46 @@ pmd_flow_create(struct rte_eth_dev *dev,
 	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");
+
+	/* Flow delete. */
+	TAILQ_REMOVE(&table->flows, flow, node);
+	free(flow);
+
+	return 0;
+}
+
 const struct rte_flow_ops pmd_flow_ops = {
 	.validate = pmd_flow_validate,
 	.create = pmd_flow_create,
+	.destroy = pmd_flow_destroy,
 };
-- 
2.14.4

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

* [PATCH v2 14/15] net/softnic: add flow query API
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (28 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 13/15] net/softnic: add flow destroy API Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  2018-09-11 14:20 ` [PATCH v2 15/15] net/softnic: add parsing for raw flow item Reshma Pattan
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added pmd_flow_query() API, for flow query
support.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index 90387b30b..bdf1d4091 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -1654,8 +1654,63 @@ pmd_flow_destroy(struct rte_eth_dev *dev,
 	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 = NULL,
+	.query = pmd_flow_query,
+	.isolate = NULL,
 };
-- 
2.14.4

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

* [PATCH v2 15/15] net/softnic: add parsing for raw flow item
  2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
                   ` (29 preceding siblings ...)
  2018-09-11 14:20 ` [PATCH v2 14/15] net/softnic: add flow query API Reshma Pattan
@ 2018-09-11 14:20 ` Reshma Pattan
  30 siblings, 0 replies; 33+ messages in thread
From: Reshma Pattan @ 2018-09-11 14:20 UTC (permalink / raw)
  To: dev; +Cc: Cristian Dumitrescu, Reshma Pattan

Added support for parsing raw flow item.
flow_item_raw_preprocess() is added for the same.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
Signed-off-by: Reshma Pattan <reshma.pattan@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_flow.c | 108 +++++++++++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/drivers/net/softnic/rte_eth_softnic_flow.c b/drivers/net/softnic/rte_eth_softnic_flow.c
index bdf1d4091..fc7a0b02a 100644
--- a/drivers/net/softnic/rte_eth_softnic_flow.c
+++ b/drivers/net/softnic/rte_eth_softnic_flow.c
@@ -297,6 +297,106 @@ flow_item_is_proto(enum rte_flow_item_type type,
 	}
 }
 
+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,
@@ -317,6 +417,14 @@ flow_item_proto_preprocess(const struct rte_flow_item *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. */
-- 
2.14.4

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

* Re: [PATCH v2 00/15] add flow API support to softnic
  2018-09-11 14:20 ` [PATCH v2 00/15] add flow API support to softnic Reshma Pattan
@ 2018-09-28 10:36   ` Dumitrescu, Cristian
  0 siblings, 0 replies; 33+ messages in thread
From: Dumitrescu, Cristian @ 2018-09-28 10:36 UTC (permalink / raw)
  To: Pattan, Reshma, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Reshma Pattan
> Sent: Tuesday, September 11, 2018 3:21 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v2 00/15] add flow API support to softnic
> 
> This patch series adds the flow API support
> for the softnic.
> 
> This patch set also introduce a new cli command
> to provide mapping of flow group and direction
> to softnic pipeline and table.
> 
> v2: added missing code to patch #9/10
> reworded commit titles.
> 
> Reshma Pattan (15):
>   net/softnic: add infrastructure for flow API
>   net/softnic: map flow attributes to pipeline table
>   net/softnic: add new cli for flow attribute map
>   net/softnic: replace some pointers with arrays
>   net/softnic: add free table and find out port functions
>   net/softnic: add function to get eth device from softnic
>   net/softnic: implement flow validate API
>   net/softnic: validate and map flow rule with acl table match
>   net/softnic: parse flow protocol for acl table match
>   net/softnic: validate and map flow with hash table match
>   net/softnic: validate and map flow action with table action
>   net/softnic: add flow create API
>   net/softnic: add flow destroy API
>   net/softnic: add flow query API
>   net/softnic: add parsing for raw flow item
> 
>  drivers/net/softnic/Makefile                    |    1 +
>  drivers/net/softnic/meson.build                 |    1 +
>  drivers/net/softnic/rte_eth_softnic.c           |   16 +
>  drivers/net/softnic/rte_eth_softnic_cli.c       |  115 +-
>  drivers/net/softnic/rte_eth_softnic_flow.c      | 1824
> +++++++++++++++++++++++
>  drivers/net/softnic/rte_eth_softnic_internals.h |   98 +-
>  drivers/net/softnic/rte_eth_softnic_pipeline.c  |   61 +-
>  7 files changed, 2086 insertions(+), 30 deletions(-)
>  create mode 100644 drivers/net/softnic/rte_eth_softnic_flow.c
> 
> --
> 2.14.4

Series applied to next-pipeline tree, thanks!

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

end of thread, other threads:[~2018-09-28 10:36 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-06 16:26 [PATCH 00/15] add flow API support to softnic Reshma Pattan
2018-09-06 16:26 ` [PATCH 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
2018-09-06 16:26 ` [PATCH 02/15] net/softnic: rte flow attr mapping to pipeline Reshma Pattan
2018-09-06 16:26 ` [PATCH 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
2018-09-06 16:26 ` [PATCH 04/15] net/softnic: various data type changes Reshma Pattan
2018-09-06 16:26 ` [PATCH 05/15] net/softnic: add free table and find out port functions Reshma Pattan
2018-09-06 16:26 ` [PATCH 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
2018-09-06 16:26 ` [PATCH 07/15] net/softnic: flow API validate support Reshma Pattan
2018-09-06 16:26 ` [PATCH 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
2018-09-06 16:26 ` [PATCH 09/15] net/softnic: parse flow protocol for " Reshma Pattan
2018-09-06 16:26 ` [PATCH 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
2018-09-06 16:26 ` [PATCH 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
2018-09-06 16:26 ` [PATCH 12/15] net/softnic: add flow create API Reshma Pattan
2018-09-06 16:27 ` [PATCH 13/15] net/softnic: add flow destroy API Reshma Pattan
2018-09-06 16:27 ` [PATCH 14/15] net/softnic: add flow query API Reshma Pattan
2018-09-06 16:27 ` [PATCH 15/15] net/softnic: add parsing for raw flow item Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 00/15] add flow API support to softnic Reshma Pattan
2018-09-28 10:36   ` Dumitrescu, Cristian
2018-09-11 14:20 ` [PATCH v2 01/15] net/softnic: add infrastructure for flow API Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 02/15] net/softnic: map flow attributes to pipeline table Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 03/15] net/softnic: add new cli for flow attribute map Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 04/15] net/softnic: replace some pointers with arrays Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 05/15] net/softnic: add free table and find out port functions Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 06/15] net/softnic: add function to get eth device from softnic Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 07/15] net/softnic: implement flow validate API Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 08/15] net/softnic: validate and map flow rule with acl table match Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 09/15] net/softnic: parse flow protocol for " Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 10/15] net/softnic: validate and map flow with hash " Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 11/15] net/softnic: validate and map flow action with table action Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 12/15] net/softnic: add flow create API Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 13/15] net/softnic: add flow destroy API Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 14/15] net/softnic: add flow query API Reshma Pattan
2018-09-11 14:20 ` [PATCH v2 15/15] net/softnic: add parsing for raw flow item Reshma Pattan

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.