Add high level API with describes base create/destroy implementation Signed-off-by: Serhii Iliushyk <sil-...@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(-)
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 -- 2.45.0