@@ -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__ */
@@ -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;
}
@@ -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