From: Ye Xiaolong <xiaolong.ye@intel.com>
To: Ying Wang <ying.a.wang@intel.com>
Cc: qi.z.zhang@intel.com, qiming.yang@intel.com, dev@dpdk.org,
wei.zhao1@intel.com
Subject: Re: [dpdk-dev] [PATCH 2/4] net/ice: rework for generic flow enabling
Date: Wed, 4 Sep 2019 22:44:35 +0800 [thread overview]
Message-ID: <20190904144435.GC54897@intel.com> (raw)
In-Reply-To: <20190903221522.151382-3-ying.a.wang@intel.com>
On 09/04, Ying Wang wrote:
>The patch reworks the generic flow API (rte_flow) implementation.
>It introduces an abstract layer which provides a unified interface
>for low-level filter engine (switch, fdir, hash) to register supported
>patterns and actions and implement flow validate/create/destroy/flush/
>query activities.
>
>The patch also removes the existing switch filter implementation to
>avoid compile error. Switch filter implementation for the new framework
>will be added in the following patch.
>
>Signed-off-by: Ying Wang <ying.a.wang@intel.com>
>---
> drivers/net/ice/ice_ethdev.c | 22 +-
> drivers/net/ice/ice_ethdev.h | 15 +-
> drivers/net/ice/ice_generic_flow.c | 768 +++++++++++++++--------------------
> drivers/net/ice/ice_generic_flow.h | 782 ++++++++----------------------------
> drivers/net/ice/ice_switch_filter.c | 511 -----------------------
> drivers/net/ice/ice_switch_filter.h | 18 -
> 6 files changed, 525 insertions(+), 1591 deletions(-)
Please add update to document and release notes.
>
>diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c
>index 4e0645db1..647aca3ed 100644
>--- a/drivers/net/ice/ice_ethdev.c
>+++ b/drivers/net/ice/ice_ethdev.c
[snip]
>+int
>+ice_flow_init(struct ice_adapter *ad)
>+{
>+ int ret = 0;
>+ struct ice_pf *pf = &ad->pf;
>+ void *temp;
>+ struct ice_flow_engine *engine = NULL;
>+
>+ TAILQ_INIT(&pf->flow_list);
>+ TAILQ_INIT(&pf->rss_parser_list);
>+ TAILQ_INIT(&pf->perm_parser_list);
>+ TAILQ_INIT(&pf->dist_parser_list);
>+
>+ TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
>+ if (engine->init == NULL)
>+ return -EINVAL;
I think ENOTSUP is more preferred here.
>+
>+ ret = engine->init(ad);
>+ if (ret)
>+ return ret;
>+ }
>+ return 0;
>+}
>+
>+void
>+ice_flow_uninit(struct ice_adapter *ad)
>+{
>+ struct ice_pf *pf = &ad->pf;
>+ struct ice_flow_engine *engine;
>+ struct rte_flow *p_flow;
>+ struct ice_flow_parser *p_parser;
>+ void *temp;
>+
>+ TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
>+ if (engine->uninit)
>+ engine->uninit(ad);
>+ }
>+
>+ /* Remove all flows */
>+ while ((p_flow = TAILQ_FIRST(&pf->flow_list))) {
>+ TAILQ_REMOVE(&pf->flow_list, p_flow, node);
>+ if (p_flow->engine->free)
>+ p_flow->engine->free(p_flow);
>+ rte_free(p_flow);
>+ }
>+
>+ /* Cleanup parser list */
>+ while ((p_parser = TAILQ_FIRST(&pf->rss_parser_list)))
>+ TAILQ_REMOVE(&pf->rss_parser_list, p_parser, node);
>+
>+ while ((p_parser = TAILQ_FIRST(&pf->perm_parser_list)))
>+ TAILQ_REMOVE(&pf->perm_parser_list, p_parser, node);
>+
>+ while ((p_parser = TAILQ_FIRST(&pf->dist_parser_list)))
>+ TAILQ_REMOVE(&pf->dist_parser_list, p_parser, node);
>+}
>+
>+int
>+ice_register_parser(struct ice_flow_parser *parser,
>+ struct ice_adapter *ad)
>+{
>+ struct ice_parser_list *list = NULL;
>+ struct ice_pf *pf = &ad->pf;
>+
>+ switch (parser->stage) {
>+ case ICE_FLOW_STAGE_RSS:
>+ list = &pf->rss_parser_list;
>+ break;
>+ case ICE_FLOW_STAGE_PERMISSION:
>+ list = &pf->perm_parser_list;
>+ break;
>+ case ICE_FLOW_STAGE_DISTRIBUTOR:
>+ list = &pf->dist_parser_list;
>+ break;
>+ default:
>+ return -EINVAL;
>+ }
>+
>+ if (ad->devargs.pipeline_mode_support)
>+ TAILQ_INSERT_TAIL(list, parser, node);
>+ else {
>+ if (parser->engine->type == ICE_FLOW_ENGINE_SWITCH
>+ || parser->engine->type == ICE_FLOW_ENGINE_HASH)
>+ TAILQ_INSERT_TAIL(list, parser, node);
>+ else if (parser->engine->type == ICE_FLOW_ENGINE_FDIR)
>+ TAILQ_INSERT_HEAD(list, parser, node);
>+ else
>+ return -EINVAL;
>+ }
>+ return 0;
>+}
>+
>+void
>+ice_unregister_parser(struct ice_flow_parser *parser,
>+ struct ice_adapter *ad)
>+{
>+ struct ice_pf *pf = &ad->pf;
>+ struct ice_parser_list *list;
>+ struct ice_flow_parser *p_parser;
>+ void *temp;
>+
>+ switch (parser->stage) {
>+ case ICE_FLOW_STAGE_RSS:
>+ list = &pf->rss_parser_list;
>+ break;
>+ case ICE_FLOW_STAGE_PERMISSION:
>+ list = &pf->perm_parser_list;
>+ break;
>+ case ICE_FLOW_STAGE_DISTRIBUTOR:
>+ list = &pf->dist_parser_list;
>+ break;
>+ default:
>+ return;
>+ }
>+
>+ TAILQ_FOREACH_SAFE(p_parser, list, node, temp) {
>+ if (p_parser->engine->type == parser->engine->type)
>+ TAILQ_REMOVE(list, p_parser, node);
>+ }
>+
>+}
>+
> static int
>-ice_flow_valid_attr(const struct rte_flow_attr *attr,
>- struct rte_flow_error *error)
>+ice_flow_valid_attr(struct ice_adapter *ad,
>+ const struct rte_flow_attr *attr,
>+ struct rte_flow_error *error)
> {
> /* Must be input direction */
> if (!attr->ingress) {
>@@ -61,15 +212,25 @@ ice_flow_valid_attr(const struct rte_flow_attr *attr,
> attr, "Not support egress.");
> return -rte_errno;
> }
>-
>- /* Not supported */
>- if (attr->priority) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
>- attr, "Not support priority.");
>- return -rte_errno;
>+ /* Check pipeline mode support to set classification stage */
>+ if (ad->devargs.pipeline_mode_support) {
>+ if (0 == attr->priority)
>+ ice_pipeline_stage =
>+ ICE_FLOW_CLASSIFY_STAGE_PERMISSION;
>+ else
>+ ice_pipeline_stage =
>+ ICE_FLOW_CLASSIFY_STAGE_DISTRIBUTOR;
>+ } else {
>+ ice_pipeline_stage =
>+ ICE_FLOW_CLASSIFY_STAGE_DISTRIBUTOR_ONLY;
>+ /* Not supported */
>+ if (attr->priority) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
>+ attr, "Not support priority.");
>+ return -rte_errno;
>+ }
> }
>-
> /* Not supported */
> if (attr->group) {
> rte_flow_error_set(error, EINVAL,
>@@ -102,7 +263,7 @@ ice_find_first_item(const struct rte_flow_item *item, bool is_void)
> /* Skip all VOID items of the pattern */
> static void
> ice_pattern_skip_void_item(struct rte_flow_item *items,
>- const struct rte_flow_item *pattern)
>+ const struct rte_flow_item *pattern)
Unnecessary change here, only indentation changes.
> {
> uint32_t cpy_count = 0;
> const struct rte_flow_item *pb = pattern, *pe = pattern;
>@@ -124,7 +285,6 @@ ice_pattern_skip_void_item(struct rte_flow_item *items,
> items += cpy_count;
>
> if (pe->type == RTE_FLOW_ITEM_TYPE_END) {
>- pb = pe;
seems this is some code cleanup, prefer a separate patch, not a strong opinion though.
> break;
> }
>
>@@ -151,11 +311,15 @@ ice_match_pattern(enum rte_flow_item_type *item_array,
> item->type == RTE_FLOW_ITEM_TYPE_END);
> }
>
>-static uint64_t ice_flow_valid_pattern(const struct rte_flow_item pattern[],
>+struct ice_pattern_match_item *
>+ice_search_pattern_match_item(const struct rte_flow_item pattern[],
>+ struct ice_pattern_match_item *array,
>+ uint32_t array_len,
> struct rte_flow_error *error)
> {
> uint16_t i = 0;
>- uint64_t inset;
>+ struct ice_pattern_match_item *pattern_match_item;
>+ /* need free by each filter */
> struct rte_flow_item *items; /* used for pattern without VOID items */
> uint32_t item_num = 0; /* non-void item number */
>
>@@ -172,451 +336,149 @@ static uint64_t ice_flow_valid_pattern(const struct rte_flow_item pattern[],
> if (!items) {
> rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_ITEM_NUM,
> NULL, "No memory for PMD internal items.");
>- return -ENOMEM;
>+ return NULL;
>+ }
>+ pattern_match_item = rte_zmalloc("ice_pattern_match_item",
>+ sizeof(struct ice_pattern_match_item), 0);
>+ if (!pattern_match_item) {
>+ PMD_DRV_LOG(ERR, "Failed to allocate memory.");
>+ return NULL;
> }
>-
> ice_pattern_skip_void_item(items, pattern);
>
>- for (i = 0; i < RTE_DIM(ice_supported_patterns); i++)
[snip]
>
>+static int
>+ice_flow_validate(struct rte_eth_dev *dev,
>+ const struct rte_flow_attr *attr,
>+ const struct rte_flow_item pattern[],
>+ const struct rte_flow_action actions[],
>+ struct rte_flow_error *error)
>+{
>+ int ret = ICE_ERR_NOT_SUPPORTED;
Unnecessary initialization.
>+ void *meta = NULL;
>+ struct ice_flow_engine *engine = NULL;
>+
>+ ret = ice_flow_validate_filter(dev, attr, pattern, actions,
>+ &engine, &meta, error);
>+ return ret;
>+}
>+
> static struct rte_flow *
> ice_flow_create(struct rte_eth_dev *dev,
>- const struct rte_flow_attr *attr,
>- const struct rte_flow_item pattern[],
>- const struct rte_flow_action actions[],
>- struct rte_flow_error *error)
>+ const struct rte_flow_attr *attr,
>+ const struct rte_flow_item pattern[],
>+ const struct rte_flow_action actions[],
>+ struct rte_flow_error *error)
> {
> struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> struct rte_flow *flow = NULL;
>- int ret;
>+ int ret = 0;
Unnecessary initialization.
>+ struct ice_adapter *ad =
>+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
>+ struct ice_flow_engine *engine = NULL;
>+ void *meta = NULL;
>
> flow = rte_zmalloc("ice_flow", sizeof(struct rte_flow), 0);
> if (!flow) {
>@@ -626,65 +488,105 @@ ice_flow_create(struct rte_eth_dev *dev,
> return flow;
> }
>
>- ret = ice_flow_validate(dev, attr, pattern, actions, error);
>+ ret = ice_flow_validate_filter(dev, attr, pattern, actions,
>+ &engine, &meta, error);
> if (ret < 0)
> goto free_flow;
>
>- ret = ice_create_switch_filter(pf, pattern, actions, flow, error);
>+ if (engine->create == NULL)
>+ goto free_flow;
>+
>+ ret = engine->create(ad, flow, meta, error);
> if (ret)
> goto free_flow;
>
>+ flow->engine = engine;
> TAILQ_INSERT_TAIL(&pf->flow_list, flow, node);
> return flow;
>
> free_flow:
>- rte_flow_error_set(error, -ret,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "Failed to create flow.");
>+ PMD_DRV_LOG(ERR, "Failed to create flow");
> rte_free(flow);
> return NULL;
> }
>
> static int
> ice_flow_destroy(struct rte_eth_dev *dev,
>- struct rte_flow *flow,
>- struct rte_flow_error *error)
>+ struct rte_flow *flow,
>+ struct rte_flow_error *error)
> {
> struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
>+ struct ice_adapter *ad =
>+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
> int ret = 0;
>
>- ret = ice_destroy_switch_filter(pf, flow, error);
>-
>+ if (!flow || !flow->engine->destroy) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_HANDLE,
>+ NULL, "NULL flow or NULL destroy");
>+ return -rte_errno;
>+ }
>+ ret = flow->engine->destroy(ad, flow, error);
> if (!ret) {
> TAILQ_REMOVE(&pf->flow_list, flow, node);
> rte_free(flow);
>- } else {
>- rte_flow_error_set(error, -ret,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "Failed to destroy flow.");
>- }
>+ } else
>+ PMD_DRV_LOG(ERR, "Failed to destroy flow");
>
> return ret;
> }
>
> static int
> ice_flow_flush(struct rte_eth_dev *dev,
>- struct rte_flow_error *error)
>+ struct rte_flow_error *error)
Unnecessary change.
> {
> struct ice_pf *pf = ICE_DEV_PRIVATE_TO_PF(dev->data->dev_private);
>- struct rte_flow *p_flow;
>+ struct rte_flow *p_flow = NULL;
Unnecessary initialization.
> void *temp;
> int ret = 0;
>
> TAILQ_FOREACH_SAFE(p_flow, &pf->flow_list, node, temp) {
> ret = ice_flow_destroy(dev, p_flow, error);
> if (ret) {
>- rte_flow_error_set(error, -ret,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "Failed to flush SW flows.");
>- return -rte_errno;
>+ PMD_DRV_LOG(ERR, "Failed to flush flows");
>+ return -EINVAL;
> }
> }
>
> return ret;
> }
>+
>+static int
>+ice_flow_query_count(struct rte_eth_dev *dev,
>+ struct rte_flow *flow,
>+ const struct rte_flow_action *actions,
>+ void *data,
>+ struct rte_flow_error *error)
>+{
>+ int ret = -EINVAL;
>+ struct ice_adapter *ad =
>+ ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
>+
>+ if (!flow || !flow->engine->query) {
>+ rte_flow_error_set(error, EINVAL,
>+ RTE_FLOW_ERROR_TYPE_HANDLE,
>+ NULL, "NULL flow or NULL query");
>+ return -rte_errno;
>+ }
>+
>+ for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
>+ switch (actions->type) {
>+ case RTE_FLOW_ACTION_TYPE_VOID:
>+ break;
>+ case RTE_FLOW_ACTION_TYPE_COUNT:
>+ ret = flow->engine->query(ad, flow, data, error);
>+ break;
>+ default:
>+ return rte_flow_error_set(error, ENOTSUP,
>+ RTE_FLOW_ERROR_TYPE_ACTION,
>+ actions,
>+ "action not supported");
>+ }
>+ }
>+ return ret;
>+}
[snip]
>+TAILQ_HEAD(ice_engine_list, ice_flow_engine);
>+
>+/* Struct to store flow created. */
>+struct rte_flow {
>+TAILQ_ENTRY(rte_flow) node;
Indentation is needed here.
>+ struct ice_flow_engine *engine;
>+ void *rule;
>+};
>+
>+/* Struct to store parser created. */
>+struct ice_flow_parser {
>+ TAILQ_ENTRY(ice_flow_parser) node;
>+ struct ice_flow_engine *engine;
>+ struct ice_pattern_match_item *array;
>+ uint32_t array_len;
>+ parse_pattern_action_t parse_pattern_action;
>+ enum ice_flow_classification_stage stage;
>+};
>+
>+void ice_register_flow_engine(struct ice_flow_engine *engine);
>+int ice_flow_init(struct ice_adapter *ad);
>+void ice_flow_uninit(struct ice_adapter *ad);
>+int ice_register_parser(struct ice_flow_parser *parser,
>+ struct ice_adapter *ad);
>+void ice_unregister_parser(struct ice_flow_parser *parser,
>+ struct ice_adapter *ad);
>+struct ice_pattern_match_item *
>+ice_search_pattern_match_item(
>+ const struct rte_flow_item pattern[],
>+ struct ice_pattern_match_item *array,
>+ uint32_t array_len,
>+ struct rte_flow_error *error);
>
> #endif
>diff --git a/drivers/net/ice/ice_switch_filter.c b/drivers/net/ice/ice_switch_filter.c
>index b88b4f59a..6b72bf252 100644
>--- a/drivers/net/ice/ice_switch_filter.c
>+++ b/drivers/net/ice/ice_switch_filter.c
>@@ -2,515 +2,4 @@
> * Copyright(c) 2019 Intel Corporation
> */
>
>-#include <sys/queue.h>
>-#include <stdio.h>
>-#include <errno.h>
>-#include <stdint.h>
>-#include <string.h>
>-#include <unistd.h>
>-#include <stdarg.h>
>
>-#include <rte_debug.h>
>-#include <rte_ether.h>
>-#include <rte_ethdev_driver.h>
>-#include <rte_log.h>
>-#include <rte_malloc.h>
>-#include <rte_eth_ctrl.h>
>-#include <rte_tailq.h>
>-#include <rte_flow_driver.h>
>-
>-#include "ice_logs.h"
>-#include "base/ice_type.h"
>-#include "ice_switch_filter.h"
>-
>-static int
>-ice_parse_switch_filter(const struct rte_flow_item pattern[],
>- const struct rte_flow_action actions[],
>- struct rte_flow_error *error,
>- struct ice_adv_lkup_elem *list,
>- uint16_t *lkups_num,
>- enum ice_sw_tunnel_type tun_type)
>-{
>- const struct rte_flow_item *item = pattern;
>- enum rte_flow_item_type item_type;
>- const struct rte_flow_item_eth *eth_spec, *eth_mask;
>- const struct rte_flow_item_ipv4 *ipv4_spec, *ipv4_mask;
>- const struct rte_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
>- const struct rte_flow_item_tcp *tcp_spec, *tcp_mask;
>- const struct rte_flow_item_udp *udp_spec, *udp_mask;
>- const struct rte_flow_item_sctp *sctp_spec, *sctp_mask;
>- const struct rte_flow_item_nvgre *nvgre_spec, *nvgre_mask;
>- const struct rte_flow_item_vxlan *vxlan_spec, *vxlan_mask;
>- uint16_t j, t = 0;
>- uint16_t tunnel_valid = 0;
>-
>- for (item = pattern; item->type !=
>- RTE_FLOW_ITEM_TYPE_END; item++) {
>- item_type = item->type;
>-
>- switch (item_type) {
>- case RTE_FLOW_ITEM_TYPE_ETH:
>- eth_spec = item->spec;
>- eth_mask = item->mask;
>- if (eth_spec && eth_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_MAC_OFOS : ICE_MAC_IL;
>- struct ice_ether_hdr *h;
>- struct ice_ether_hdr *m;
>- uint16_t i = 0;
>- h = &list[t].h_u.eth_hdr;
>- m = &list[t].m_u.eth_hdr;
>- for (j = 0; j < RTE_ETHER_ADDR_LEN; j++) {
>- if (eth_mask->src.addr_bytes[j] ==
>- UINT8_MAX) {
>- h->src_addr[j] =
>- eth_spec->src.addr_bytes[j];
>- m->src_addr[j] =
>- eth_mask->src.addr_bytes[j];
>- i = 1;
>- }
>- if (eth_mask->dst.addr_bytes[j] ==
>- UINT8_MAX) {
>- h->dst_addr[j] =
>- eth_spec->dst.addr_bytes[j];
>- m->dst_addr[j] =
>- eth_mask->dst.addr_bytes[j];
>- i = 1;
>- }
>- }
>- if (i)
>- t++;
>- if (eth_mask->type == UINT16_MAX) {
>- list[t].type = ICE_ETYPE_OL;
>- list[t].h_u.ethertype.ethtype_id =
>- eth_spec->type;
>- list[t].m_u.ethertype.ethtype_id =
>- UINT16_MAX;
>- t++;
>- }
>- } else if (!eth_spec && !eth_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_MAC_OFOS : ICE_MAC_IL;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_IPV4:
>- ipv4_spec = item->spec;
>- ipv4_mask = item->mask;
>- if (ipv4_spec && ipv4_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_IPV4_OFOS : ICE_IPV4_IL;
>- if (ipv4_mask->hdr.src_addr == UINT32_MAX) {
>- list[t].h_u.ipv4_hdr.src_addr =
>- ipv4_spec->hdr.src_addr;
>- list[t].m_u.ipv4_hdr.src_addr =
>- UINT32_MAX;
>- }
>- if (ipv4_mask->hdr.dst_addr == UINT32_MAX) {
>- list[t].h_u.ipv4_hdr.dst_addr =
>- ipv4_spec->hdr.dst_addr;
>- list[t].m_u.ipv4_hdr.dst_addr =
>- UINT32_MAX;
>- }
>- if (ipv4_mask->hdr.time_to_live == UINT8_MAX) {
>- list[t].h_u.ipv4_hdr.time_to_live =
>- ipv4_spec->hdr.time_to_live;
>- list[t].m_u.ipv4_hdr.time_to_live =
>- UINT8_MAX;
>- }
>- if (ipv4_mask->hdr.next_proto_id == UINT8_MAX) {
>- list[t].h_u.ipv4_hdr.protocol =
>- ipv4_spec->hdr.next_proto_id;
>- list[t].m_u.ipv4_hdr.protocol =
>- UINT8_MAX;
>- }
>- if (ipv4_mask->hdr.type_of_service ==
>- UINT8_MAX) {
>- list[t].h_u.ipv4_hdr.tos =
>- ipv4_spec->hdr.type_of_service;
>- list[t].m_u.ipv4_hdr.tos = UINT8_MAX;
>- }
>- t++;
>- } else if (!ipv4_spec && !ipv4_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_IPV4_OFOS : ICE_IPV4_IL;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_IPV6:
>- ipv6_spec = item->spec;
>- ipv6_mask = item->mask;
>- if (ipv6_spec && ipv6_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_IPV6_OFOS : ICE_IPV6_IL;
>- struct ice_ipv6_hdr *f;
>- struct ice_ipv6_hdr *s;
>- f = &list[t].h_u.ipv6_hdr;
>- s = &list[t].m_u.ipv6_hdr;
>- for (j = 0; j < ICE_IPV6_ADDR_LENGTH; j++) {
>- if (ipv6_mask->hdr.src_addr[j] ==
>- UINT8_MAX) {
>- f->src_addr[j] =
>- ipv6_spec->hdr.src_addr[j];
>- s->src_addr[j] =
>- ipv6_mask->hdr.src_addr[j];
>- }
>- if (ipv6_mask->hdr.dst_addr[j] ==
>- UINT8_MAX) {
>- f->dst_addr[j] =
>- ipv6_spec->hdr.dst_addr[j];
>- s->dst_addr[j] =
>- ipv6_mask->hdr.dst_addr[j];
>- }
>- }
>- if (ipv6_mask->hdr.proto == UINT8_MAX) {
>- f->next_hdr =
>- ipv6_spec->hdr.proto;
>- s->next_hdr = UINT8_MAX;
>- }
>- if (ipv6_mask->hdr.hop_limits == UINT8_MAX) {
>- f->hop_limit =
>- ipv6_spec->hdr.hop_limits;
>- s->hop_limit = UINT8_MAX;
>- }
>- t++;
>- } else if (!ipv6_spec && !ipv6_mask) {
>- list[t].type = (tun_type == ICE_NON_TUN) ?
>- ICE_IPV4_OFOS : ICE_IPV4_IL;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_UDP:
>- udp_spec = item->spec;
>- udp_mask = item->mask;
>- if (udp_spec && udp_mask) {
>- if (tun_type == ICE_SW_TUN_VXLAN &&
>- tunnel_valid == 0)
>- list[t].type = ICE_UDP_OF;
>- else
>- list[t].type = ICE_UDP_ILOS;
>- if (udp_mask->hdr.src_port == UINT16_MAX) {
>- list[t].h_u.l4_hdr.src_port =
>- udp_spec->hdr.src_port;
>- list[t].m_u.l4_hdr.src_port =
>- udp_mask->hdr.src_port;
>- }
>- if (udp_mask->hdr.dst_port == UINT16_MAX) {
>- list[t].h_u.l4_hdr.dst_port =
>- udp_spec->hdr.dst_port;
>- list[t].m_u.l4_hdr.dst_port =
>- udp_mask->hdr.dst_port;
>- }
>- t++;
>- } else if (!udp_spec && !udp_mask) {
>- list[t].type = ICE_UDP_ILOS;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_TCP:
>- tcp_spec = item->spec;
>- tcp_mask = item->mask;
>- if (tcp_spec && tcp_mask) {
>- list[t].type = ICE_TCP_IL;
>- if (tcp_mask->hdr.src_port == UINT16_MAX) {
>- list[t].h_u.l4_hdr.src_port =
>- tcp_spec->hdr.src_port;
>- list[t].m_u.l4_hdr.src_port =
>- tcp_mask->hdr.src_port;
>- }
>- if (tcp_mask->hdr.dst_port == UINT16_MAX) {
>- list[t].h_u.l4_hdr.dst_port =
>- tcp_spec->hdr.dst_port;
>- list[t].m_u.l4_hdr.dst_port =
>- tcp_mask->hdr.dst_port;
>- }
>- t++;
>- } else if (!tcp_spec && !tcp_mask) {
>- list[t].type = ICE_TCP_IL;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_SCTP:
>- sctp_spec = item->spec;
>- sctp_mask = item->mask;
>- if (sctp_spec && sctp_mask) {
>- list[t].type = ICE_SCTP_IL;
>- if (sctp_mask->hdr.src_port == UINT16_MAX) {
>- list[t].h_u.sctp_hdr.src_port =
>- sctp_spec->hdr.src_port;
>- list[t].m_u.sctp_hdr.src_port =
>- sctp_mask->hdr.src_port;
>- }
>- if (sctp_mask->hdr.dst_port == UINT16_MAX) {
>- list[t].h_u.sctp_hdr.dst_port =
>- sctp_spec->hdr.dst_port;
>- list[t].m_u.sctp_hdr.dst_port =
>- sctp_mask->hdr.dst_port;
>- }
>- t++;
>- } else if (!sctp_spec && !sctp_mask) {
>- list[t].type = ICE_SCTP_IL;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_VXLAN:
>- vxlan_spec = item->spec;
>- vxlan_mask = item->mask;
>- tunnel_valid = 1;
>- if (vxlan_spec && vxlan_mask) {
>- list[t].type = ICE_VXLAN;
>- if (vxlan_mask->vni[0] == UINT8_MAX &&
>- vxlan_mask->vni[1] == UINT8_MAX &&
>- vxlan_mask->vni[2] == UINT8_MAX) {
>- list[t].h_u.tnl_hdr.vni =
>- (vxlan_spec->vni[2] << 16) |
>- (vxlan_spec->vni[1] << 8) |
>- vxlan_spec->vni[0];
>- list[t].m_u.tnl_hdr.vni =
>- UINT32_MAX;
>- }
>- t++;
>- } else if (!vxlan_spec && !vxlan_mask) {
>- list[t].type = ICE_VXLAN;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_NVGRE:
>- nvgre_spec = item->spec;
>- nvgre_mask = item->mask;
>- tunnel_valid = 1;
>- if (nvgre_spec && nvgre_mask) {
>- list[t].type = ICE_NVGRE;
>- if (nvgre_mask->tni[0] == UINT8_MAX &&
>- nvgre_mask->tni[1] == UINT8_MAX &&
>- nvgre_mask->tni[2] == UINT8_MAX) {
>- list[t].h_u.nvgre_hdr.tni_flow =
>- (nvgre_spec->tni[2] << 16) |
>- (nvgre_spec->tni[1] << 8) |
>- nvgre_spec->tni[0];
>- list[t].m_u.nvgre_hdr.tni_flow =
>- UINT32_MAX;
>- }
>- t++;
>- } else if (!nvgre_spec && !nvgre_mask) {
>- list[t].type = ICE_NVGRE;
>- }
>- break;
>-
>- case RTE_FLOW_ITEM_TYPE_VOID:
>- case RTE_FLOW_ITEM_TYPE_END:
>- break;
>-
>- default:
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_ITEM, actions,
>- "Invalid pattern item.");
>- goto out;
>- }
>- }
>-
>- *lkups_num = t;
>-
>- return 0;
>-out:
>- return -rte_errno;
>-}
>-
>-/* By now ice switch filter action code implement only
>- * supports QUEUE or DROP.
>- */
>-static int
>-ice_parse_switch_action(struct ice_pf *pf,
>- const struct rte_flow_action *actions,
>- struct rte_flow_error *error,
>- struct ice_adv_rule_info *rule_info)
>-{
>- struct ice_vsi *vsi = pf->main_vsi;
>- const struct rte_flow_action_queue *act_q;
>- uint16_t base_queue;
>- const struct rte_flow_action *action;
>- enum rte_flow_action_type action_type;
>-
>- base_queue = pf->base_queue;
>- for (action = actions; action->type !=
>- RTE_FLOW_ACTION_TYPE_END; action++) {
>- action_type = action->type;
>- switch (action_type) {
>- case RTE_FLOW_ACTION_TYPE_QUEUE:
>- act_q = action->conf;
>- rule_info->sw_act.fltr_act =
>- ICE_FWD_TO_Q;
>- rule_info->sw_act.fwd_id.q_id =
>- base_queue + act_q->index;
>- break;
>-
>- case RTE_FLOW_ACTION_TYPE_DROP:
>- rule_info->sw_act.fltr_act =
>- ICE_DROP_PACKET;
>- break;
>-
>- case RTE_FLOW_ACTION_TYPE_VOID:
>- break;
>-
>- default:
>- rte_flow_error_set(error,
>- EINVAL,
>- RTE_FLOW_ERROR_TYPE_ITEM,
>- actions,
>- "Invalid action type");
>- return -rte_errno;
>- }
>- }
>-
>- rule_info->sw_act.vsi_handle = vsi->idx;
>- rule_info->rx = 1;
>- rule_info->sw_act.src = vsi->idx;
>- rule_info->priority = 5;
>-
>- return 0;
>-}
>-
>-static int
>-ice_switch_rule_set(struct ice_pf *pf,
>- struct ice_adv_lkup_elem *list,
>- uint16_t lkups_cnt,
>- struct ice_adv_rule_info *rule_info,
>- struct rte_flow *flow,
>- struct rte_flow_error *error)
>-{
>- struct ice_hw *hw = ICE_PF_TO_HW(pf);
>- int ret;
>- struct ice_rule_query_data rule_added = {0};
>- struct ice_rule_query_data *filter_ptr;
>-
>- if (lkups_cnt > ICE_MAX_CHAIN_WORDS) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_ITEM, NULL,
>- "item number too large for rule");
>- return -rte_errno;
>- }
>- if (!list) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_ITEM, NULL,
>- "lookup list should not be NULL");
>- return -rte_errno;
>- }
>-
>- ret = ice_add_adv_rule(hw, list, lkups_cnt, rule_info, &rule_added);
>-
>- if (!ret) {
>- filter_ptr = rte_zmalloc("ice_switch_filter",
>- sizeof(struct ice_rule_query_data), 0);
>- if (!filter_ptr) {
>- PMD_DRV_LOG(ERR, "failed to allocate memory");
>- return -EINVAL;
>- }
>- flow->rule = filter_ptr;
>- rte_memcpy(filter_ptr,
>- &rule_added,
>- sizeof(struct ice_rule_query_data));
>- }
>-
>- return ret;
>-}
>-
>-int
>-ice_create_switch_filter(struct ice_pf *pf,
>- const struct rte_flow_item pattern[],
>- const struct rte_flow_action actions[],
>- struct rte_flow *flow,
>- struct rte_flow_error *error)
>-{
>- int ret = 0;
>- struct ice_adv_rule_info rule_info = {0};
>- struct ice_adv_lkup_elem *list = NULL;
>- uint16_t lkups_num = 0;
>- const struct rte_flow_item *item = pattern;
>- uint16_t item_num = 0;
>- enum ice_sw_tunnel_type tun_type = ICE_NON_TUN;
>-
>- for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
>- item_num++;
>- if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
>- tun_type = ICE_SW_TUN_VXLAN;
>- if (item->type == RTE_FLOW_ITEM_TYPE_NVGRE)
>- tun_type = ICE_SW_TUN_NVGRE;
>- /* reserve one more memory slot for ETH which may
>- * consume 2 lookup items.
>- */
>- if (item->type == RTE_FLOW_ITEM_TYPE_ETH)
>- item_num++;
>- }
>- rule_info.tun_type = tun_type;
>-
>- list = rte_zmalloc(NULL, item_num * sizeof(*list), 0);
>- if (!list) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "No memory for PMD internal items");
>- return -rte_errno;
>- }
>-
>- ret = ice_parse_switch_filter(pattern, actions, error,
>- list, &lkups_num, tun_type);
>- if (ret)
>- goto error;
>-
>- ret = ice_parse_switch_action(pf, actions, error, &rule_info);
>- if (ret)
>- goto error;
>-
>- ret = ice_switch_rule_set(pf, list, lkups_num, &rule_info, flow, error);
>- if (ret)
>- goto error;
>-
>- rte_free(list);
>- return 0;
>-
>-error:
>- rte_free(list);
>-
>- return -rte_errno;
>-}
>-
>-int
>-ice_destroy_switch_filter(struct ice_pf *pf,
>- struct rte_flow *flow,
>- struct rte_flow_error *error)
>-{
>- struct ice_hw *hw = ICE_PF_TO_HW(pf);
>- int ret;
>- struct ice_rule_query_data *filter_ptr;
>-
>- filter_ptr = (struct ice_rule_query_data *)
>- flow->rule;
>-
>- if (!filter_ptr) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "no such flow"
>- " create by switch filter");
>- return -rte_errno;
>- }
>-
>- ret = ice_rem_adv_rule_by_id(hw, filter_ptr);
>- if (ret) {
>- rte_flow_error_set(error, EINVAL,
>- RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
>- "fail to destroy switch filter rule");
>- return -rte_errno;
>- }
>-
>- rte_free(filter_ptr);
>- return ret;
>-}
>-
>-void
>-ice_free_switch_filter_rule(void *rule)
>-{
>- struct ice_rule_query_data *filter_ptr;
>-
>- filter_ptr = (struct ice_rule_query_data *)rule;
>-
>- rte_free(filter_ptr);
>-}
>diff --git a/drivers/net/ice/ice_switch_filter.h b/drivers/net/ice/ice_switch_filter.h
>index cea47990e..5afcddeaf 100644
>--- a/drivers/net/ice/ice_switch_filter.h
>+++ b/drivers/net/ice/ice_switch_filter.h
>@@ -2,23 +2,5 @@
> * Copyright(c) 2019 Intel Corporation
> */
>
>-#ifndef _ICE_SWITCH_FILTER_H_
>-#define _ICE_SWITCH_FILTER_H_
>
>-#include "base/ice_switch.h"
>-#include "base/ice_type.h"
>-#include "ice_ethdev.h"
>
>-int
>-ice_create_switch_filter(struct ice_pf *pf,
>- const struct rte_flow_item pattern[],
>- const struct rte_flow_action actions[],
>- struct rte_flow *flow,
>- struct rte_flow_error *error);
>-int
>-ice_destroy_switch_filter(struct ice_pf *pf,
>- struct rte_flow *flow,
>- struct rte_flow_error *error);
>-void
>-ice_free_switch_filter_rule(void *rule);
>-#endif /* _ICE_SWITCH_FILTER_H_ */
>--
>2.15.1
>
next prev parent reply other threads:[~2019-09-04 14:46 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-03 22:15 [dpdk-dev] [PATCH 0/4] rework for ice generic flow framework and switch filter Ying Wang
2019-09-03 22:15 ` [dpdk-dev] [PATCH 1/4] net/ice: add devargs to control pipeline mode Ying Wang
2019-09-04 12:34 ` Ye Xiaolong
2019-09-09 3:08 ` Yang, Qiming
2019-09-09 9:17 ` Ye Xiaolong
2019-09-10 7:10 ` Yang, Qiming
2019-09-04 18:29 ` Stillwell Jr, Paul M
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 0/5] rework for ice generic flow framework and switch filter Ying Wang
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 1/5] net/ice: minor code clean Ying Wang
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 0/5] rework for ice generic flow framework and switch filter Ying Wang
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 1/5] net/ice: minor code clean Ying Wang
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 0/5] rework for ice generic flow framework and switch filter Ying Wang
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 1/5] net/ice: minor code clean Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 0/5] rework for ice generic flow framework and switch filter Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 1/5] net/ice: minor code clean Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 2/5] net/ice: add devargs to control pipeline mode Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 3/5] net/ice: rework for generic flow enabling Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 4/5] net/ice: add pattern manifest Ying Wang
2019-10-16 18:33 ` [dpdk-dev] [PATCH v5 5/5] net/ice: rework switch filter Ying Wang
2019-10-17 3:03 ` [dpdk-dev] [PATCH v5 0/5] rework for ice generic flow framework and " Ye Xiaolong
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 2/5] net/ice: add devargs to control pipeline mode Ying Wang
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 3/5] net/ice: rework for generic flow enabling Ying Wang
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 4/5] net/ice: add pattern manifest Ying Wang
2019-10-14 3:42 ` [dpdk-dev] [PATCH v4 5/5] net/ice: rework switch filter Ying Wang
2019-10-16 2:55 ` Ye Xiaolong
2019-10-16 3:03 ` Wang, Ying A
2019-10-17 2:26 ` [dpdk-dev] [PATCH v4 0/5] rework for ice generic flow framework and " Ye Xiaolong
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 2/5] net/ice: add devargs to control pipeline mode Ying Wang
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 3/5] net/ice: rework for generic flow enabling Ying Wang
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 4/5] net/ice: add pattern manifest Ying Wang
2019-09-26 18:55 ` [dpdk-dev] [PATCH v3 5/5] net/ice: rework switch filter Ying Wang
2019-09-30 0:27 ` [dpdk-dev] [PATCH v3 0/5] rework for ice generic flow framework and " Zhang, Qi Z
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 2/5] net/ice: add devargs to control pipeline mode Ying Wang
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 3/5] net/ice: rework for generic flow enabling Ying Wang
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 4/5] net/ice: add pattern manifest Ying Wang
2019-09-16 23:06 ` [dpdk-dev] [PATCH v2 5/5] net/ice: rework switch filter Ying Wang
2019-09-03 22:15 ` [dpdk-dev] [PATCH 2/4] net/ice: rework for generic flow enabling Ying Wang
2019-09-04 14:44 ` Ye Xiaolong [this message]
2019-09-05 12:59 ` Wang, Ying A
2019-09-05 13:26 ` Ye Xiaolong
2019-09-06 16:12 ` Ye Xiaolong
2019-09-09 1:45 ` Wang, Ying A
2019-09-09 9:53 ` Ye Xiaolong
2019-09-09 10:21 ` Wang, Ying A
2019-09-08 15:55 ` Ye Xiaolong
2019-09-09 2:12 ` Wang, Ying A
2019-09-09 9:31 ` Ye Xiaolong
2019-09-03 22:15 ` [dpdk-dev] [PATCH 3/4] net/ice: add pattern manifest Ying Wang
2019-09-03 22:15 ` [dpdk-dev] [PATCH 4/4] net/ice: rework switch filter Ying Wang
2019-09-08 12:04 ` Ye Xiaolong
2019-09-09 3:03 ` Zhao1, Wei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190904144435.GC54897@intel.com \
--to=xiaolong.ye@intel.com \
--cc=dev@dpdk.org \
--cc=qi.z.zhang@intel.com \
--cc=qiming.yang@intel.com \
--cc=wei.zhao1@intel.com \
--cc=ying.a.wang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.