[v5,03/80] net/ntnic: add minimal create/destroy flow operations

Message ID 20241030213940.3470062-4-sil-plv@napatech.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series Provide flow filter and statistics support |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Serhii Iliushyk Oct. 30, 2024, 9:38 p.m. UTC
Add high-level API flow create/destroy implementation

Signed-off-by: Serhii Iliushyk <sil-plv@napatech.com>
---
v2
* Change cast to void with __rte_unused
---
 drivers/net/ntnic/include/create_elements.h   |  51 ++++
 drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 227 +++++++++++++++++-
 drivers/net/ntnic/ntutil/nt_util.h            |   3 +
 3 files changed, 274 insertions(+), 7 deletions(-)
  

Patch

diff --git a/drivers/net/ntnic/include/create_elements.h b/drivers/net/ntnic/include/create_elements.h
index 802e6dcbe1..179542d2b2 100644
--- a/drivers/net/ntnic/include/create_elements.h
+++ b/drivers/net/ntnic/include/create_elements.h
@@ -6,8 +6,59 @@ 
 #ifndef __CREATE_ELEMENTS_H__
 #define __CREATE_ELEMENTS_H__
 
+#include "stdint.h"
 
 #include "stream_binary_flow_api.h"
 #include <rte_flow.h>
 
+#define MAX_ELEMENTS 64
+#define MAX_ACTIONS 32
+
+struct cnv_match_s {
+	struct rte_flow_item rte_flow_item[MAX_ELEMENTS];
+};
+
+struct cnv_attr_s {
+	struct cnv_match_s match;
+	struct rte_flow_attr attr;
+	uint16_t forced_vlan_vid;
+	uint16_t caller_id;
+};
+
+struct cnv_action_s {
+	struct rte_flow_action flow_actions[MAX_ACTIONS];
+	struct rte_flow_action_queue queue;
+};
+
+/*
+ * Only needed because it eases the use of statistics through NTAPI
+ * for faster integration into NTAPI version of driver
+ * Therefore, this is only a good idea when running on a temporary NTAPI
+ * The query() functionality must go to flow engine, when moved to Open Source driver
+ */
+
+struct rte_flow {
+	void *flw_hdl;
+	int used;
+
+	uint32_t flow_stat_id;
+
+	uint16_t caller_id;
+};
+
+enum nt_rte_flow_item_type {
+	NT_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
+	NT_RTE_FLOW_ITEM_TYPE_TUNNEL,
+};
+
+extern rte_spinlock_t flow_lock;
+int convert_error(struct rte_flow_error *error, struct rte_flow_error *rte_flow_error);
+int create_attr(struct cnv_attr_s *attribute, const struct rte_flow_attr *attr);
+int create_match_elements(struct cnv_match_s *match, const struct rte_flow_item items[],
+	int max_elem);
+int create_action_elements_inline(struct cnv_action_s *action,
+	const struct rte_flow_action actions[],
+	int max_elem,
+	uint32_t queue_offset);
+
 #endif	/* __CREATE_ELEMENTS_H__ */
diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
index 445139abc9..74cf360da0 100644
--- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
+++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c
@@ -4,24 +4,237 @@ 
  */
 
 #include <rte_flow_driver.h>
+#include "nt_util.h"
+#include "create_elements.h"
 #include "ntnic_mod_reg.h"
+#include "ntos_system.h"
+
+#define MAX_RTE_FLOWS 8192
+
+#define NT_MAX_COLOR_FLOW_STATS 0x400
+
+rte_spinlock_t flow_lock = RTE_SPINLOCK_INITIALIZER;
+static struct rte_flow nt_flows[MAX_RTE_FLOWS];
+
+int convert_error(struct rte_flow_error *error, struct rte_flow_error *rte_flow_error)
+{
+	if (error) {
+		error->cause = NULL;
+		error->message = rte_flow_error->message;
+
+		if (rte_flow_error->type == RTE_FLOW_ERROR_TYPE_NONE ||
+			rte_flow_error->type == RTE_FLOW_ERROR_TYPE_NONE)
+			error->type = RTE_FLOW_ERROR_TYPE_NONE;
+
+		else
+			error->type = RTE_FLOW_ERROR_TYPE_UNSPECIFIED;
+	}
+
+	return 0;
+}
+
+int create_attr(struct cnv_attr_s *attribute, const struct rte_flow_attr *attr)
+{
+	memset(&attribute->attr, 0x0, sizeof(struct rte_flow_attr));
+
+	if (attr) {
+		attribute->attr.group = attr->group;
+		attribute->attr.priority = attr->priority;
+	}
+
+	return 0;
+}
+
+int create_match_elements(struct cnv_match_s *match, const struct rte_flow_item items[],
+	int max_elem)
+{
+	int eidx = 0;
+	int iter_idx = 0;
+	int type = -1;
+
+	if (!items) {
+		NT_LOG(ERR, FILTER, "ERROR no items to iterate!");
+		return -1;
+	}
+
+	do {
+		type = items[iter_idx].type;
+
+		if (type < 0) {
+			if ((int)items[iter_idx].type == NT_RTE_FLOW_ITEM_TYPE_TUNNEL) {
+				type = NT_RTE_FLOW_ITEM_TYPE_TUNNEL;
+
+			} else {
+				NT_LOG(ERR, FILTER, "ERROR unknown item type received!");
+				return -1;
+			}
+		}
+
+		if (type >= 0) {
+			if (items[iter_idx].last) {
+				/* Ranges are not supported yet */
+				NT_LOG(ERR, FILTER, "ERROR ITEM-RANGE SETUP - NOT SUPPORTED!");
+				return -1;
+			}
+
+			if (eidx == max_elem) {
+				NT_LOG(ERR, FILTER, "ERROR TOO MANY ELEMENTS ENCOUNTERED!");
+				return -1;
+			}
+
+			match->rte_flow_item[eidx].type = type;
+			match->rte_flow_item[eidx].spec = items[iter_idx].spec;
+			match->rte_flow_item[eidx].mask = items[iter_idx].mask;
+
+			eidx++;
+			iter_idx++;
+		}
+
+	} while (type >= 0 && type != RTE_FLOW_ITEM_TYPE_END);
+
+	return (type >= 0) ? 0 : -1;
+}
+
+int create_action_elements_inline(struct cnv_action_s *action __rte_unused,
+	const struct rte_flow_action actions[] __rte_unused,
+	int max_elem __rte_unused,
+	uint32_t queue_offset __rte_unused)
+{
+	int type = -1;
+
+	return (type >= 0) ? 0 : -1;
+}
+
+static inline uint16_t get_caller_id(uint16_t port)
+{
+	return MAX_VDPA_PORTS + port + 1;
+}
+
+static int convert_flow(struct rte_eth_dev *eth_dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item items[],
+	const struct rte_flow_action actions[],
+	struct cnv_attr_s *attribute,
+	struct cnv_match_s *match,
+	struct cnv_action_s *action,
+	struct rte_flow_error *error)
+{
+	struct pmd_internals *internals = (struct pmd_internals *)eth_dev->data->dev_private;
+	struct fpga_info_s *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
+
+	static struct rte_flow_error flow_error = {
+		.type = RTE_FLOW_ERROR_TYPE_NONE, .message = "none" };
+	uint32_t queue_offset = 0;
+
+	/* Set initial error */
+	convert_error(error, &flow_error);
+
+	if (!internals) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Missing eth_dev");
+		return -1;
+	}
+
+	if (internals->type == PORT_TYPE_OVERRIDE && internals->vpq_nb_vq > 0) {
+		/*
+		 * The queues coming from the main PMD will always start from 0
+		 * When the port is a the VF/vDPA port the queues must be changed
+		 * to match the queues allocated for VF/vDPA.
+		 */
+		queue_offset = internals->vpq[0].id;
+	}
+
+	if (create_attr(attribute, attr) != 0) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR, NULL, "Error in attr");
+		return -1;
+	}
+
+	if (create_match_elements(match, items, MAX_ELEMENTS) != 0) {
+		rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+			"Error in items");
+		return -1;
+	}
+
+	if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE) {
+		if (create_action_elements_inline(action, actions,
+			MAX_ACTIONS, queue_offset) != 0) {
+			rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+				"Error in actions");
+			return -1;
+		}
+
+	} else {
+		rte_flow_error_set(error, EPERM, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+			"Unsupported adapter profile");
+		return -1;
+	}
+
+	return 0;
+}
 
 static int
-eth_flow_destroy(struct rte_eth_dev *eth_dev __rte_unused, struct rte_flow *flow __rte_unused,
-	struct rte_flow_error *error __rte_unused)
+eth_flow_destroy(struct rte_eth_dev *eth_dev __rte_unused, struct rte_flow *flow,
+	struct rte_flow_error *error)
 {
+	static struct rte_flow_error flow_error = {
+		.type = RTE_FLOW_ERROR_TYPE_NONE, .message = "none" };
 	int res = 0;
+	/* Set initial error */
+	convert_error(error, &flow_error);
+
+	if (!flow)
+		return 0;
 
 	return res;
 }
 
-static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev __rte_unused,
-	const struct rte_flow_attr *attr __rte_unused,
-	const struct rte_flow_item items[] __rte_unused,
-	const struct rte_flow_action actions[] __rte_unused,
-	struct rte_flow_error *error __rte_unused)
+static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev,
+	const struct rte_flow_attr *attr,
+	const struct rte_flow_item items[],
+	const struct rte_flow_action actions[],
+	struct rte_flow_error *error)
 {
+	struct pmd_internals *internals = (struct pmd_internals *)eth_dev->data->dev_private;
+
+	struct fpga_info_s *fpga_info = &internals->p_drv->ntdrv.adapter_info.fpga_info;
+
+	struct cnv_attr_s attribute = { 0 };
+	struct cnv_match_s match = { 0 };
+	struct cnv_action_s action = { 0 };
+
+	static struct rte_flow_error flow_error = {
+		.type = RTE_FLOW_ERROR_TYPE_NONE, .message = "none" };
+	uint32_t flow_stat_id = 0;
+
+	if (convert_flow(eth_dev, attr, items, actions, &attribute, &match, &action, error) < 0)
+		return NULL;
+
+	/* Main application caller_id is port_id shifted above VF ports */
+	attribute.caller_id = get_caller_id(eth_dev->data->port_id);
+
+	if (fpga_info->profile == FPGA_INFO_PROFILE_INLINE && attribute.attr.group > 0) {
+		convert_error(error, &flow_error);
+		return (struct rte_flow *)NULL;
+	}
+
 	struct rte_flow *flow = NULL;
+	rte_spinlock_lock(&flow_lock);
+	int i;
+
+	for (i = 0; i < MAX_RTE_FLOWS; i++) {
+		if (!nt_flows[i].used) {
+			nt_flows[i].flow_stat_id = flow_stat_id;
+
+			if (nt_flows[i].flow_stat_id < NT_MAX_COLOR_FLOW_STATS) {
+				nt_flows[i].used = 1;
+				flow = &nt_flows[i];
+			}
+
+			break;
+		}
+	}
+
+	rte_spinlock_unlock(&flow_lock);
 
 	return flow;
 }
diff --git a/drivers/net/ntnic/ntutil/nt_util.h b/drivers/net/ntnic/ntutil/nt_util.h
index 64947f5fbf..71ecd6c68c 100644
--- a/drivers/net/ntnic/ntutil/nt_util.h
+++ b/drivers/net/ntnic/ntutil/nt_util.h
@@ -9,6 +9,9 @@ 
 #include <stdint.h>
 #include "nt4ga_link.h"
 
+/* Total max VDPA ports */
+#define MAX_VDPA_PORTS 128UL
+
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(arr) RTE_DIM(arr)
 #endif