[PATCH v2 15/26] net/hinic3: refactor flow rule parsing
Jiacheng Ye
yejiacheng4 at h-partners.com
Wed Oct 14 17:09:11 CEST 2026
The flow rule parser was based on a fixed hardcoded pattern table that was
hard to extend. Replace it with a simpler protocol-graph classifier, and
add IP-in-IP and Geneve tunnel patterns.
Signed-off-by: Jiacheng Ye <yejiacheng4 at h-partners.com>
---
doc/guides/nics/features/hinic3.ini | 2 +
drivers/net/hinic3/hinic3_fdir.c | 65 ++-
drivers/net/hinic3/hinic3_fdir.h | 14 +-
drivers/net/hinic3/hinic3_flow.c | 594 ++++++++++++++++++++--------
drivers/net/hinic3/hinic3_flow.h | 196 ---------
5 files changed, 478 insertions(+), 393 deletions(-)
delete mode 100644 drivers/net/hinic3/hinic3_flow.h
diff --git a/doc/guides/nics/features/hinic3.ini b/doc/guides/nics/features/hinic3.ini
index 8083dc63d1..14f152a604 100644
--- a/doc/guides/nics/features/hinic3.ini
+++ b/doc/guides/nics/features/hinic3.ini
@@ -43,12 +43,14 @@ ARMv8 = Y
[rte_flow items]
any = Y
eth = P
+geneve = Y
icmp = Y
ipv4 = Y
ipv6 = Y
tcp = Y
udp = Y
vxlan = Y
+vxlan_gpe = Y
[rte_flow actions]
queue = Y
diff --git a/drivers/net/hinic3/hinic3_fdir.c b/drivers/net/hinic3/hinic3_fdir.c
index 71d50a3d22..2b9b25f65a 100644
--- a/drivers/net/hinic3/hinic3_fdir.c
+++ b/drivers/net/hinic3/hinic3_fdir.c
@@ -77,8 +77,6 @@ hinic3_fdir_tcam_ipv4_init(struct hinic3_fdir_filter *rule,
/* Fill type of ip. */
tcam_key->key_mask.ip_type = HINIC3_UINT1_MAX;
tcam_key->key_info.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
- tcam_key->key_mask.vlan_flag = HINIC3_UINT1_MAX;
- tcam_key->key_info.vlan_flag = 0;
/* Fill src IPv4. */
tcam_key->key_mask.sipv4_h =
@@ -101,8 +99,9 @@ hinic3_fdir_tcam_ipv4_init(struct hinic3_fdir_filter *rule,
HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv4.dst_ip);
}
-static void hinic3_fdir_ipv6_tcam_key_init_sip(struct hinic3_fdir_filter *rule,
- struct hinic3_tcam_key *tcam_key)
+static inline void
+hinic3_fdir_ipv6_tcam_key_init_sip(struct hinic3_fdir_filter *rule,
+ struct hinic3_tcam_key *tcam_key)
{
tcam_key->key_mask_ipv6.sipv6_key0 =
HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.src_ip[0]);
@@ -138,8 +137,9 @@ static void hinic3_fdir_ipv6_tcam_key_init_sip(struct hinic3_fdir_filter *rule,
HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.src_ip[0x3]);
}
-static void hinic3_fdir_ipv6_tcam_key_init_dip(struct hinic3_fdir_filter *rule,
- struct hinic3_tcam_key *tcam_key)
+static inline void
+hinic3_fdir_ipv6_tcam_key_init_dip(struct hinic3_fdir_filter *rule,
+ struct hinic3_tcam_key *tcam_key)
{
tcam_key->key_mask_ipv6.dipv6_key0 =
HINIC3_32_UPPER_16_BITS(rule->key_mask.ipv6.dst_ip[0]);
@@ -175,8 +175,9 @@ static void hinic3_fdir_ipv6_tcam_key_init_dip(struct hinic3_fdir_filter *rule,
HINIC3_32_LOWER_16_BITS(rule->key_spec.ipv6.dst_ip[0x3]);
}
-static void hinic3_fdir_ipv6_tcam_key_init(struct hinic3_fdir_filter *rule,
- struct hinic3_tcam_key *tcam_key)
+static void
+hinic3_fdir_ipv6_tcam_key_init(struct hinic3_fdir_filter *rule,
+ struct hinic3_tcam_key *tcam_key)
{
hinic3_fdir_ipv6_tcam_key_init_sip(rule, tcam_key);
hinic3_fdir_ipv6_tcam_key_init_dip(rule, tcam_key);
@@ -240,15 +241,11 @@ hinic3_fdir_tcam_notunnel_init(struct rte_eth_dev *dev,
}
static void
-hinic3_fdir_tcam_vxlan_ipv4_init(struct hinic3_fdir_filter *rule,
+hinic3_fdir_tcam_vxlan_geneve_ipv4_init(struct hinic3_fdir_filter *rule,
struct hinic3_tcam_key *tcam_key)
{
- /* Fill type of ip. */
tcam_key->key_mask.ip_type = HINIC3_UINT1_MAX;
tcam_key->key_info.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
- tcam_key->key_mask.vlan_flag = HINIC3_UINT1_MAX;
- tcam_key->key_info.vlan_flag = 0;
-
/* Fill src ipv4. */
tcam_key->key_mask.sipv4_h =
HINIC3_32_UPPER_16_BITS(rule->key_mask.inner_ipv4.src_ip);
@@ -271,7 +268,7 @@ hinic3_fdir_tcam_vxlan_ipv4_init(struct hinic3_fdir_filter *rule,
}
static void
-hinic3_fdir_tcam_vxlan_ipv6_init(struct hinic3_fdir_filter *rule,
+hinic3_fdir_tcam_vxlan_geneve_ipv6_init(struct hinic3_fdir_filter *rule,
struct hinic3_tcam_key *tcam_key)
{
/* Fill type of ip. */
@@ -359,7 +356,7 @@ hinic3_fdir_tcam_ipv6_vxlan_init(struct rte_eth_dev *dev,
* Pointer to the TCAM key.
*/
static void
-hinic3_fdir_tcam_vxlan_init(struct rte_eth_dev *dev,
+hinic3_fdir_tcam_vxlan_geneve_init(struct rte_eth_dev *dev,
struct hinic3_fdir_filter *rule,
struct hinic3_tcam_key *tcam_key)
{
@@ -416,10 +413,10 @@ hinic3_fdir_tcam_vxlan_init(struct rte_eth_dev *dev,
HINIC3_UINT15_MAX;
if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV4)
- hinic3_fdir_tcam_vxlan_ipv4_init(rule, tcam_key);
+ hinic3_fdir_tcam_vxlan_geneve_ipv4_init(rule, tcam_key);
else if (rule->ip_type == HINIC3_FDIR_IP_TYPE_IPV6)
- hinic3_fdir_tcam_vxlan_ipv6_init(rule, tcam_key);
+ hinic3_fdir_tcam_vxlan_geneve_ipv6_init(rule, tcam_key);
}
static void
@@ -432,7 +429,7 @@ hinic3_fdir_tcam_info_init(struct rte_eth_dev *dev,
if (rule->tunnel_type == HINIC3_FDIR_TUNNEL_MODE_NORMAL)
hinic3_fdir_tcam_notunnel_init(dev, rule, tcam_key);
else
- hinic3_fdir_tcam_vxlan_init(dev, rule, tcam_key);
+ hinic3_fdir_tcam_vxlan_geneve_init(dev, rule, tcam_key);
/* Set the queue index. */
fdir_tcam_rule->data.qid = rule->rq_index;
@@ -841,7 +838,7 @@ hinic3_dynamic_lookup_tcam_filter(struct hinic3_nic_dev *nic_dev,
* capacity of dynamic TCAM blocks.
*/
if (rule_nums >= block_cnt * HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
- if (block_cnt >= (HINIC3_TCAM_DYNAMIC_MAX_FILTERS /
+ if (block_cnt >= (HINIC3_TCAM_DYNAMIC_MAX_FILTERS(nic_dev) /
HINIC3_TCAM_DYNAMIC_BLOCK_SIZE)) {
PMD_DRV_LOG(ERR,
"Dynamic tcam block is full, alloc failed!");
@@ -1001,6 +998,9 @@ hinic3_set_fdir_ethertype_filter(void *hwdev, uint8_t pkt_type, void *filter, ui
PMD_DRV_LOG(ERR,
"set fdir ethertype rule failed, err: %d, status: 0x%x, out size: 0x%x, func_id %d",
err, ethertype_cmd.head.status, out_size, ethertype_cmd.func_id);
+ if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0 && en != 0)
+ hinic3_tcam_index_free(nic_dev, HINIC3_TCAM_GET_INDEX_IN_BLOCK(index),
+ HINIC3_TCAM_GET_DYNAMIC_BLOCK_INDEX(index));
return -EIO;
}
if ((hinic3_get_driver_feature(nic_dev) & NIC_F_HTN_FDIR) != 0) {
@@ -1213,24 +1213,16 @@ hinic3_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
else
hinic3_fdir_tcam_info_htn_init(dev, fdir_filter, &tcam_key, &fdir_tcam_rule);
- /* Search for a filter. */
- tcam_filter =
- hinic3_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key,
- HINIC3_ACTION_ADD, HINIC3_INVALID_INDEX);
- if (tcam_filter != NULL && add) {
- PMD_DRV_LOG(ERR, "Filter exists.");
- return -EEXIST;
- }
- if (tcam_filter == NULL && !add) {
- PMD_DRV_LOG(ERR, "Filter doesn't exist.");
- return -ENOENT;
- }
-
- /*
- * If the value of Add is true, the system performs the adding
- * operation.
- */
if (add) {
+ /* Search for a filter. */
+ tcam_filter =
+ hinic3_tcam_filter_lookup(&tcam_info->tcam_list, &tcam_key,
+ HINIC3_ACTION_ADD, HINIC3_INVALID_INDEX);
+ if (tcam_filter != NULL) {
+ PMD_DRV_LOG(ERR, "Filter exists.");
+ return -EEXIST;
+ }
+
ret = hinic3_add_tcam_filter(dev, &tcam_key, &fdir_tcam_rule);
if (ret)
goto cfg_tcam_filter_err;
@@ -1594,6 +1586,7 @@ hinic3_flow_add_del_ethertype_filter(struct rte_eth_dev *dev,
/* Get dev private info. */
struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
int ret;
+
/* Add or remove an Ethernet type filter rule. */
ret = hinic3_flow_add_del_ethertype_filter_rule(dev, ethertype_filter, add);
diff --git a/drivers/net/hinic3/hinic3_fdir.h b/drivers/net/hinic3/hinic3_fdir.h
index 277d89d4fd..997587554d 100644
--- a/drivers/net/hinic3/hinic3_fdir.h
+++ b/drivers/net/hinic3/hinic3_fdir.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2025 Huawei Technologies Co., Ltd
+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd
*/
#ifndef _HINIC3_FDIR_H_
@@ -8,8 +8,13 @@
#define HINIC3_FLOW_MAX_PATTERN_NUM 16
#define HINIC3_TCAM_DYNAMIC_BLOCK_SIZE 16
+#define HINIC3_TCAM_DYNAMIC_MAX_FILTERS(nic_dev) \
+ (HINIC3_IS_SP230_NIC(nic_dev) \
+ ? HINIC3_TCAM_DYNAMIC_MAX_FILTERS_HTN \
+ : HINIC3_TCAM_DYNAMIC_MAX_FILTERS_STN)
-#define HINIC3_TCAM_DYNAMIC_MAX_FILTERS 1024
+#define HINIC3_TCAM_DYNAMIC_MAX_FILTERS_STN 2048
+#define HINIC3_TCAM_DYNAMIC_MAX_FILTERS_HTN 1024
#define HINIC3_PKT_TCAM_DYNAMIC_INDEX_START(block_index) \
(HINIC3_TCAM_DYNAMIC_BLOCK_SIZE * (block_index))
@@ -96,6 +101,7 @@ enum hinic3_fdir_tunnel_mode {
HINIC3_FDIR_TUNNEL_MODE_GENEVE = 5,
HINIC3_FDIR_TUNNEL_MODE_NSH = 6,
HINIC3_FDIR_TUNNEL_MODE_IPIP = 7,
+ HINIC3_FDIR_TUNNEL_MODE_MAX = 8,
};
enum hinic3_fdir_ip_type {
@@ -186,7 +192,7 @@ struct hinic3_tcam_key_mem_htn {
uint32_t rsvd0 : 16;
uint32_t ip_proto : 8;
uint32_t tunnel_type : 3;
- uint32_t function_id_h: 5;
+ uint32_t function_id_h : 5;
uint32_t function_id_l : 5;
uint32_t ip_type : 2;
@@ -250,7 +256,7 @@ struct hinic3_tcam_key_mem_htn {
uint32_t rsvd8 : 16;
uint32_t sport : 16;
- uint32_t dipv4_l :16;
+ uint32_t dipv4_l : 16;
uint32_t rsvd9 : 16;
uint32_t dport : 16;
diff --git a/drivers/net/hinic3/hinic3_flow.c b/drivers/net/hinic3/hinic3_flow.c
index 1f686d4675..b2da5c6347 100644
--- a/drivers/net/hinic3/hinic3_flow.c
+++ b/drivers/net/hinic3/hinic3_flow.c
@@ -8,7 +8,6 @@
#include "base/hinic3_hwdev.h"
#include "base/hinic3_nic_cfg.h"
#include "hinic3_ethdev.h"
-#include "hinic3_flow.h"
#define HINIC3_UINT8_MAX 0xff
@@ -19,12 +18,6 @@ typedef int (*hinic3_parse_filter_t)(struct rte_eth_dev *dev,
struct rte_flow_error *error,
struct hinic3_filter_t *filter);
-/* Indicate valid filter mode . */
-struct hinic3_valid_pattern {
- enum rte_flow_item_type *items;
- hinic3_parse_filter_t parse_filter;
-};
-
static int hinic3_flow_parse_fdir_filter(struct rte_eth_dev *dev,
const struct rte_flow_attr *attr,
const struct rte_flow_item pattern[],
@@ -39,65 +32,12 @@ static int hinic3_flow_parse_ethertype_filter(struct rte_eth_dev *dev,
struct rte_flow_error *error,
struct hinic3_filter_t *filter);
-static int hinic3_flow_parse_fdir_vxlan_filter(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,
- struct hinic3_filter_t *filter);
-
-/*
- * Define a supported pattern array, including the matching patterns of
- * various network protocols and corresponding parsing functions.
- */
-static const struct hinic3_valid_pattern hinic3_supported_patterns[] = {
- /* Support ethertype. */
- {pattern_ethertype, hinic3_flow_parse_ethertype_filter},
- /* Support ipv4 but not tunnel, and any field can be masked. */
- {pattern_ipv4, hinic3_flow_parse_fdir_filter},
- {pattern_ipv4_any, hinic3_flow_parse_fdir_filter},
- /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
- {pattern_ipv4_udp, hinic3_flow_parse_fdir_filter},
- {pattern_ipv4_tcp, hinic3_flow_parse_fdir_filter},
- /* Support ipv4 + icmp not tunnel, and any field can be masked. */
- {pattern_ipv4_icmp, hinic3_flow_parse_fdir_filter},
-
- /* Support ipv4 + l4 but not tunnel, and any field can be masked. */
- {pattern_ethertype_udp, hinic3_flow_parse_fdir_filter},
- {pattern_ethertype_tcp, hinic3_flow_parse_fdir_filter},
-
- /* Support ipv4 + vxlan + any, and any field can be masked. */
- {pattern_ipv4_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
- /* Support ipv4 + vxlan + ipv4, and any field can be masked. */
- {pattern_ipv4_vxlan_ipv4, hinic3_flow_parse_fdir_vxlan_filter},
- /* Support ipv4 + vxlan + ipv4 + l4, and any field can be masked. */
- {pattern_ipv4_vxlan_ipv4_tcp, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv4_vxlan_ipv4_udp, hinic3_flow_parse_fdir_vxlan_filter},
- /* Support ipv4 + vxlan + ipv6, and any field can be masked. */
- {pattern_ipv4_vxlan_ipv6, hinic3_flow_parse_fdir_vxlan_filter},
- /* Support ipv4 + vxlan + ipv6 + l4, and any field can be masked. */
- {pattern_ipv4_vxlan_ipv6_tcp, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv4_vxlan_ipv6_udp, hinic3_flow_parse_fdir_vxlan_filter},
- /* Support ipv4 + vxlan + l4, and any field can be masked. */
- {pattern_ipv4_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv4_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv4_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
-
- /* Support ipv6 but not tunnel, and any field can be masked. */
- {pattern_ipv6, hinic3_flow_parse_fdir_filter},
- /* Support ipv6 + l4 but not tunnel, and any field can be masked. */
- {pattern_ipv6_udp, hinic3_flow_parse_fdir_filter},
- {pattern_ipv6_tcp, hinic3_flow_parse_fdir_filter},
-
- /* Support ipv6 + vxlan + any, and any field can be masked. */
- {pattern_ipv6_vxlan, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv6_vxlan_any, hinic3_flow_parse_fdir_vxlan_filter},
-
- /* Support ipv6 + vxlan + l4, and any field can be masked. */
- {pattern_ipv6_vxlan_tcp, hinic3_flow_parse_fdir_vxlan_filter},
- {pattern_ipv6_vxlan_udp, hinic3_flow_parse_fdir_vxlan_filter},
-
-};
+static int hinic3_flow_parse_fdir_vxlan_geneve_filter(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,
+ struct hinic3_filter_t *filter);
static inline void
net_addr_to_host(uint32_t *dst, const uint32_t *src, size_t len)
@@ -107,30 +47,243 @@ net_addr_to_host(uint32_t *dst, const uint32_t *src, size_t len)
dst[i] = rte_be_to_cpu_32(src[i]);
}
-static bool
-hinic3_match_pattern(enum rte_flow_item_type *item_array,
- const struct rte_flow_item *pattern)
-{
- const struct rte_flow_item *item = pattern;
+/* IPINIP and GPE are split out due to chip support differences. */
+enum hinic3_flow_filter_kind {
+ HINIC3_FLOW_KIND_ETHERTYPE, /* [ETH]. */
+ HINIC3_FLOW_KIND_NON_TUNNEL, /* single L3/L4 or ethertype L4. */
+ HINIC3_FLOW_KIND_VXLAN_GENEVE, /* vxlan/geneve. */
+ HINIC3_FLOW_KIND_GPE, /* vxlan-gpe. */
+ HINIC3_FLOW_KIND_IPINIP, /* ip-in-ip. */
+ HINIC3_FLOW_KIND_INVALID,
+};
+
+/*
+ * The pattern is parsed as a small protocol graph. Every supported pattern
+ * starts with ETH and then follows one of the supported encapsulation paths
+ * (plain L3/L4, tunneled, or ip-in-ip). VOID items are transparent.
+ */
- /* skip the first void item. */
+/* Peek at the next non-VOID item type. */
+static enum rte_flow_item_type
+hinic3_flow_next(const struct rte_flow_item *item)
+{
while (item->type == RTE_FLOW_ITEM_TYPE_VOID)
item++;
- /* Find no void item. */
- while (((*item_array == item->type) &&
- (*item_array != RTE_FLOW_ITEM_TYPE_END)) ||
- (item->type == RTE_FLOW_ITEM_TYPE_VOID)) {
- if (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
- item++;
- } else {
- item_array++;
- item++;
+ return item->type;
+}
+
+/* Consume the next non-VOID item when it matches @p type. */
+static bool
+hinic3_flow_take(const struct rte_flow_item **item,
+ enum rte_flow_item_type type)
+{
+ while ((*item)->type == RTE_FLOW_ITEM_TYPE_VOID)
+ (*item)++;
+
+ if ((*item)->type != type)
+ return false;
+
+ (*item)++;
+ return true;
+}
+
+/* Return true when only the END item remains. */
+static bool
+hinic3_flow_at_end(const struct rte_flow_item *item)
+{
+ return hinic3_flow_next(item) == RTE_FLOW_ITEM_TYPE_END;
+}
+
+/* Finish a branch, which is valid only when END is reached. */
+static enum hinic3_flow_filter_kind
+hinic3_flow_finish(const struct rte_flow_item *item,
+ enum hinic3_flow_filter_kind kind)
+{
+ return hinic3_flow_at_end(item) ? kind : HINIC3_FLOW_KIND_INVALID;
+}
+
+/* Classify an inner L3 (IPv4/IPv6) with an optional L4, returning @p kind. */
+static enum hinic3_flow_filter_kind
+hinic3_flow_classify_inner(const struct rte_flow_item **item,
+ enum hinic3_flow_filter_kind kind,
+ enum rte_flow_item_type outer_ip)
+{
+ enum rte_flow_item_type next = hinic3_flow_next(*item);
+
+ if (next != RTE_FLOW_ITEM_TYPE_IPV4 &&
+ next != RTE_FLOW_ITEM_TYPE_IPV6)
+ return HINIC3_FLOW_KIND_INVALID;
+
+ /*
+ * An outer IPv6 plus any inner L3 does not fit in the TCAM, so only
+ * an IPv4 outer (or no outer at all) may carry an inner L3.
+ */
+ if (outer_ip == RTE_FLOW_ITEM_TYPE_IPV6)
+ return HINIC3_FLOW_KIND_INVALID;
+
+ hinic3_flow_take(item, next);
+
+ switch (hinic3_flow_next(*item)) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return kind;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ hinic3_flow_take(item, hinic3_flow_next(*item));
+ return hinic3_flow_finish(*item, kind);
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
+ }
+}
+
+/* Consume a tunnel header and classify the payload that follows it. */
+static enum hinic3_flow_filter_kind
+hinic3_flow_classify_tunnel(const struct rte_flow_item **item,
+ enum rte_flow_item_type tunnel_type,
+ enum rte_flow_item_type outer_ip)
+{
+ enum hinic3_flow_filter_kind kind =
+ tunnel_type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE ?
+ HINIC3_FLOW_KIND_GPE : HINIC3_FLOW_KIND_VXLAN_GENEVE;
+ enum rte_flow_item_type next;
+
+ if (!hinic3_flow_take(item, tunnel_type))
+ return HINIC3_FLOW_KIND_INVALID;
+
+ next = hinic3_flow_next(*item);
+
+ /* A bare tunnel with nothing after the header is valid. */
+ if (next == RTE_FLOW_ITEM_TYPE_END)
+ return kind;
+
+ /* GPE: an optional inner ETH (which may be terminal), then an L3(+L4). */
+ if (tunnel_type == RTE_FLOW_ITEM_TYPE_VXLAN_GPE) {
+ if (next == RTE_FLOW_ITEM_TYPE_ETH) {
+ hinic3_flow_take(item, RTE_FLOW_ITEM_TYPE_ETH);
+ if (hinic3_flow_at_end(*item))
+ return kind;
+ }
+ return hinic3_flow_classify_inner(item, kind, outer_ip);
+ }
+
+ /* vxlan/geneve: a bare L4/ANY, or an inner L3(+L4). */
+ switch (next) {
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ case RTE_FLOW_ITEM_TYPE_ANY:
+ hinic3_flow_take(item, next);
+ return hinic3_flow_finish(*item, kind);
+ case RTE_FLOW_ITEM_TYPE_ETH:
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ if (next == RTE_FLOW_ITEM_TYPE_ETH) {
+ hinic3_flow_take(item, RTE_FLOW_ITEM_TYPE_ETH);
+ break;
+ }
+ /* Geneve accepts a bare inner L3; vxlan requires the inner ETH. */
+ if (tunnel_type != RTE_FLOW_ITEM_TYPE_GENEVE)
+ return HINIC3_FLOW_KIND_INVALID;
+ break;
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
+ }
+
+ return hinic3_flow_classify_inner(item, kind, outer_ip);
+}
+
+/* Classify the payload that follows the outer L3. */
+static enum hinic3_flow_filter_kind
+hinic3_flow_classify_ip(const struct rte_flow_item **item,
+ enum rte_flow_item_type ip_type)
+{
+ enum rte_flow_item_type next = hinic3_flow_next(*item);
+
+ switch (next) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return HINIC3_FLOW_KIND_NON_TUNNEL;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ hinic3_flow_take(item, RTE_FLOW_ITEM_TYPE_TCP);
+ return hinic3_flow_finish(*item, HINIC3_FLOW_KIND_NON_TUNNEL);
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ hinic3_flow_take(item, RTE_FLOW_ITEM_TYPE_UDP);
+ next = hinic3_flow_next(*item);
+ switch (next) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return HINIC3_FLOW_KIND_NON_TUNNEL;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ return hinic3_flow_classify_tunnel(item, next, ip_type);
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
+ }
+ case RTE_FLOW_ITEM_TYPE_ICMP:
+ case RTE_FLOW_ITEM_TYPE_ANY:
+ /* ICMP and ANY are valid only right after an IPv4 outer. */
+ if (ip_type != RTE_FLOW_ITEM_TYPE_IPV4)
+ return HINIC3_FLOW_KIND_INVALID;
+ hinic3_flow_take(item, next);
+ return hinic3_flow_finish(*item, HINIC3_FLOW_KIND_NON_TUNNEL);
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ /* Ip-in-ip: a second L3 with an optional L4 (or ANY). */
+ hinic3_flow_take(item, next);
+ switch (hinic3_flow_next(*item)) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return HINIC3_FLOW_KIND_IPINIP;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ case RTE_FLOW_ITEM_TYPE_ANY:
+ hinic3_flow_take(item, hinic3_flow_next(*item));
+ return hinic3_flow_finish(*item, HINIC3_FLOW_KIND_IPINIP);
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
}
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
}
+}
- return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
- item->type == RTE_FLOW_ITEM_TYPE_END);
+/* Classify a pattern into one of the supported filter kinds. */
+static enum hinic3_flow_filter_kind
+hinic3_flow_classify(const struct rte_flow_item *pattern)
+{
+ const struct rte_flow_item *item = pattern;
+ enum rte_flow_item_type next;
+
+ if (!hinic3_flow_take(&item, RTE_FLOW_ITEM_TYPE_ETH))
+ return HINIC3_FLOW_KIND_INVALID;
+
+ switch (hinic3_flow_next(item)) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return HINIC3_FLOW_KIND_ETHERTYPE;
+ case RTE_FLOW_ITEM_TYPE_TCP:
+ hinic3_flow_take(&item, RTE_FLOW_ITEM_TYPE_TCP);
+ return hinic3_flow_finish(item, HINIC3_FLOW_KIND_NON_TUNNEL);
+ case RTE_FLOW_ITEM_TYPE_UDP:
+ hinic3_flow_take(&item, RTE_FLOW_ITEM_TYPE_UDP);
+ next = hinic3_flow_next(item);
+ switch (next) {
+ case RTE_FLOW_ITEM_TYPE_END:
+ return HINIC3_FLOW_KIND_NON_TUNNEL;
+ case RTE_FLOW_ITEM_TYPE_VXLAN:
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ /* No outer IP: pass END so classify_inner allows it. */
+ return hinic3_flow_classify_tunnel(&item, next,
+ RTE_FLOW_ITEM_TYPE_END);
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
+ }
+ case RTE_FLOW_ITEM_TYPE_IPV4:
+ hinic3_flow_take(&item, RTE_FLOW_ITEM_TYPE_IPV4);
+ return hinic3_flow_classify_ip(&item, RTE_FLOW_ITEM_TYPE_IPV4);
+ case RTE_FLOW_ITEM_TYPE_IPV6:
+ hinic3_flow_take(&item, RTE_FLOW_ITEM_TYPE_IPV6);
+ return hinic3_flow_classify_ip(&item, RTE_FLOW_ITEM_TYPE_IPV6);
+ default:
+ return HINIC3_FLOW_KIND_INVALID;
+ }
}
/**
@@ -142,20 +295,27 @@ hinic3_match_pattern(enum rte_flow_item_type *item_array,
* Matched resolution filter. If no resolution filter is found, return NULL.
*/
static hinic3_parse_filter_t
-hinic3_find_parse_filter_func(const struct rte_flow_item *pattern)
+hinic3_find_parse_filter_func(struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern)
{
- hinic3_parse_filter_t parse_filter = NULL;
- uint8_t i;
- /* Traverse all supported patterns. */
- for (i = 0; i < RTE_DIM(hinic3_supported_patterns); i++) {
- if (hinic3_match_pattern(hinic3_supported_patterns[i].items, pattern)) {
- parse_filter =
- hinic3_supported_patterns[i].parse_filter;
- break;
- }
- }
+ struct hinic3_nic_dev *nic_dev = HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
- return parse_filter;
+ switch (hinic3_flow_classify(pattern)) {
+ case HINIC3_FLOW_KIND_ETHERTYPE:
+ return hinic3_flow_parse_ethertype_filter;
+ case HINIC3_FLOW_KIND_NON_TUNNEL:
+ return hinic3_flow_parse_fdir_filter;
+ case HINIC3_FLOW_KIND_VXLAN_GENEVE:
+ return hinic3_flow_parse_fdir_vxlan_geneve_filter;
+ case HINIC3_FLOW_KIND_GPE:
+ return HINIC3_IS_SP620_NIC(nic_dev) ?
+ hinic3_flow_parse_fdir_vxlan_geneve_filter : NULL;
+ case HINIC3_FLOW_KIND_IPINIP:
+ return HINIC3_IS_SP620_NIC(nic_dev) ? NULL :
+ hinic3_flow_parse_fdir_vxlan_geneve_filter;
+ default:
+ return NULL;
+ }
}
/**
@@ -182,12 +342,36 @@ hinic3_flow_parse_action(struct rte_eth_dev *dev,
const struct rte_flow_action_queue *act_q;
const struct rte_flow_action *act = actions;
- /* skip the first void item. */
- while (act->type == RTE_FLOW_ACTION_TYPE_VOID)
- act++;
+ /* Only one non-VOID action before END is supported. */
+ const struct rte_flow_action *last_act = NULL;
+ for (act = actions; act->type != RTE_FLOW_ACTION_TYPE_END; act++) {
+ if (act->type == RTE_FLOW_ACTION_TYPE_VOID)
+ continue;
+ if (last_act != NULL) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, act,
+ "Multiple actions not supported.");
+ return -rte_errno;
+ }
+ last_act = act;
+ }
+ if (last_act == NULL) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, actions,
+ "No valid action.");
+ return -rte_errno;
+ }
+
+ act = last_act;
switch (act->type) {
case RTE_FLOW_ACTION_TYPE_QUEUE:
+ if (act->conf == NULL) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ act, "Invalid action queue config.");
+ return -rte_errno;
+ }
act_q = (const struct rte_flow_action_queue *)act->conf;
filter->fdir_filter.rq_index = act_q->index;
if (filter->fdir_filter.rq_index >= dev->data->nb_rx_queues) {
@@ -230,6 +414,14 @@ hinic3_flow_fdir_ipv4(const struct rte_flow_item *flow_item,
mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
+
+ filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
+ filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
+
+ /* When both L3 mask and spec are empty, return 0, then proceed to evaluate L4. */
+ if (!mask_ipv4 && !spec_ipv4)
+ return 0;
+
if (!mask_ipv4 || !spec_ipv4) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
@@ -251,9 +443,6 @@ hinic3_flow_fdir_ipv4(const struct rte_flow_item *flow_item,
return -rte_errno;
}
- /* Set the filter information. */
- filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
- filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
filter->fdir_filter.key_mask.ipv4.src_ip =
rte_be_to_cpu_32(mask_ipv4->hdr.src_addr);
filter->fdir_filter.key_spec.ipv4.src_ip =
@@ -277,6 +466,14 @@ hinic3_flow_fdir_ipv6(const struct rte_flow_item *flow_item,
mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
+
+ filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
+ filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
+
+ /* When both L3 mask and spec are empty, return 0, then proceed to evaluate L4. */
+ if (!mask_ipv6 && !spec_ipv6)
+ return 0;
+
if (!mask_ipv6 || !spec_ipv6) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
@@ -293,9 +490,6 @@ hinic3_flow_fdir_ipv6(const struct rte_flow_item *flow_item,
return -rte_errno;
}
- /* Set the filter information. */
- filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
- filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
net_addr_to_host(filter->fdir_filter.key_mask.ipv6.src_ip,
(const uint32_t *)mask_ipv6->hdr.src_addr.a, 4);
net_addr_to_host(filter->fdir_filter.key_spec.ipv6.src_ip,
@@ -639,6 +833,12 @@ hinic3_flow_parse_ethertype_pattern(__rte_unused struct rte_eth_dev *dev,
case RTE_ETHER_TYPE_LLDP:
break;
+ case RTE_ETHER_TYPE_CNM:
+ break;
+
+ case RTE_ETHER_TYPE_ECP:
+ break;
+
default:
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
@@ -686,14 +886,15 @@ static int
hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
struct hinic3_filter_t *filter,
const struct rte_flow_item *flow_item,
- enum hinic3_fdir_tunnel_mode tunnel_mode)
+ enum hinic3_fdir_tunnel_mode *tunnel_mode)
{
const struct rte_flow_item_ipv4 *spec_ipv4, *mask_ipv4;
mask_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->mask;
spec_ipv4 = (const struct rte_flow_item_ipv4 *)flow_item->spec;
- if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
+ if (*tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_MAX) {
filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
+ *tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
if (!mask_ipv4 && !spec_ipv4)
return 0;
@@ -702,7 +903,7 @@ hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Invalid fdir filter, vxlan outer ipv4 mask or spec");
+ "Invalid fdir filter, vxlan/geneve outer ipv4 mask or spec");
return -rte_errno;
}
@@ -718,7 +919,7 @@ hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
mask_ipv4->hdr.next_proto_id ||
mask_ipv4->hdr.hdr_checksum) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
- "Not supported by fdir filter, vxlan outer ipv4 only support src ip, dst ip");
+ "Not supported by fdir filter, vxlan/geneve outer ipv4 only support src ip,dst ip");
return -rte_errno;
}
@@ -733,6 +934,10 @@ hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
rte_be_to_cpu_32(spec_ipv4->hdr.dst_addr);
} else {
filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV4;
+ if (*tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
+ *tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_IPIP;
+ filter->fdir_filter.tunnel_type = *tunnel_mode;
+ }
if (!mask_ipv4 && !spec_ipv4)
return 0;
@@ -741,7 +946,7 @@ hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Invalid fdir filter, vxlan inner ipv4 mask or spec");
+ "Invalid fdir filter, vxlan/geneve inner ipv4 mask or spec");
return -rte_errno;
}
@@ -758,7 +963,7 @@ hinic3_flow_fdir_tunnel_ipv4(struct rte_flow_error *error,
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Not supported by fdir filter, vxlan inner ipv4 only support src ip, dst ip, proto");
+ "Not supported by fdir filter, vxlan/geneve inner ipv4 only support src ip,dst ip, proto");
return -rte_errno;
}
@@ -783,15 +988,16 @@ static int
hinic3_flow_fdir_tunnel_ipv6(struct rte_flow_error *error,
struct hinic3_filter_t *filter,
const struct rte_flow_item *flow_item,
- enum hinic3_fdir_tunnel_mode tunnel_mode)
+ enum hinic3_fdir_tunnel_mode *tunnel_mode)
{
const struct rte_flow_item_ipv6 *spec_ipv6, *mask_ipv6;
mask_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->mask;
spec_ipv6 = (const struct rte_flow_item_ipv6 *)flow_item->spec;
- if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
+ if (*tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_MAX) {
filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
+ *tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_NORMAL;
if (!mask_ipv6 && !spec_ipv6)
return 0;
@@ -822,7 +1028,10 @@ hinic3_flow_fdir_tunnel_ipv6(struct rte_flow_error *error,
(const uint32_t *)spec_ipv6->hdr.dst_addr.a, 4);
} else {
filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
-
+ if (*tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
+ *tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_IPIP;
+ filter->fdir_filter.tunnel_type = *tunnel_mode;
+ }
if (!mask_ipv6 && !spec_ipv6)
return 0;
@@ -869,7 +1078,7 @@ hinic3_flow_fdir_tunnel_tcp(struct rte_flow_error *error,
if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Not supported by fdir filter, vxlan only support inner tcp");
+ "Not supported by fdir filter, vxlan/geneve only support inner tcp");
return -rte_errno;
}
@@ -894,7 +1103,7 @@ hinic3_flow_fdir_tunnel_tcp(struct rte_flow_error *error,
mask_tcp->hdr.tcp_urp) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Not supported by fdir filter, vxlan inner tcp only support src port,dst port");
+ "Not supported by fdir filter, vxlan/geneve inner tcp only support src port,dst port");
return -rte_errno;
}
@@ -921,7 +1130,8 @@ hinic3_flow_fdir_tunnel_udp(struct rte_flow_error *error,
mask_udp = (const struct rte_flow_item_udp *)flow_item->mask;
spec_udp = (const struct rte_flow_item_udp *)flow_item->spec;
- if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
+ if (tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_MAX ||
+ tunnel_mode == HINIC3_FDIR_TUNNEL_MODE_NORMAL) {
/*
* UDP is used to describe protocol,
* spec and mask should be NULL.
@@ -942,7 +1152,7 @@ hinic3_flow_fdir_tunnel_udp(struct rte_flow_error *error,
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Invalid fdir filter vxlan inner udp mask or spec");
+ "Invalid fdir filter vxlan/geneve inner udp mask or spec");
return -rte_errno;
}
@@ -960,57 +1170,114 @@ hinic3_flow_fdir_tunnel_udp(struct rte_flow_error *error,
return 0;
}
+static inline enum hinic3_fdir_tunnel_mode
+hinic3_flow_tunnel_mode(enum rte_flow_item_type type)
+{
+ switch (type) {
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ return HINIC3_FDIR_TUNNEL_MODE_GENEVE;
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ return HINIC3_FDIR_TUNNEL_MODE_GPE;
+ default:
+ return HINIC3_FDIR_TUNNEL_MODE_VXLAN;
+ }
+}
+
static int
-hinic3_flow_fdir_vxlan(struct rte_flow_error *error,
- struct hinic3_filter_t *filter,
- const struct rte_flow_item *flow_item)
+hinic3_flow_fdir_vxlan_geneve(struct rte_flow_error *error,
+ struct hinic3_filter_t *filter,
+ enum hinic3_fdir_tunnel_mode tunnel_mode,
+ const struct rte_flow_item *flow_item)
{
- const struct rte_flow_item_vxlan *spec_vxlan, *mask_vxlan;
+ const uint8_t *vni;
+ const uint8_t *vni_mask;
uint32_t vxlan_vni_id = 0;
uint32_t vxlan_vni_id_mask = 0;
- spec_vxlan = (const struct rte_flow_item_vxlan *)flow_item->spec;
- mask_vxlan = (const struct rte_flow_item_vxlan *)flow_item->mask;
-
- filter->fdir_filter.tunnel_type = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
+ filter->fdir_filter.tunnel_type = tunnel_mode;
- if (!spec_vxlan && !mask_vxlan) {
+ if (!flow_item->spec && !flow_item->mask)
return 0;
- } else if (filter->fdir_filter.outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV6) {
+
+ if (filter->fdir_filter.outer_ip_type == HINIC3_FDIR_IP_TYPE_IPV6) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Invalid fdir filter vxlan mask or spec, ipv6 vxlan, don't support vni");
+ "Invalid fdir filter vxlan/geneve mask or spec, ipv6 vxlan/geneve, don't support vni");
return -rte_errno;
}
- if (!spec_vxlan || !mask_vxlan) {
+ if (!flow_item->spec || !flow_item->mask) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
flow_item,
- "Invalid fdir filter vxlan mask or spec");
+ "Invalid fdir filter vxlan/geneve mask or spec");
return -rte_errno;
}
- memcpy(((uint8_t *)&vxlan_vni_id + 1), spec_vxlan->vni, 3);
+ switch (tunnel_mode) {
+ case HINIC3_FDIR_TUNNEL_MODE_GENEVE: {
+ const struct rte_flow_item_geneve *spec =
+ (const struct rte_flow_item_geneve *)flow_item->spec;
+ const struct rte_flow_item_geneve *mask =
+ (const struct rte_flow_item_geneve *)flow_item->mask;
+
+ /* Only VNI is matched; option length and protocol are not. */
+ if (mask->ver_opt_len_o_c_rsvd0 || mask->protocol)
+ goto unsupported;
+ vni = spec->vni;
+ vni_mask = mask->vni;
+ break;
+ }
+ case HINIC3_FDIR_TUNNEL_MODE_GPE: {
+ const struct rte_flow_item_vxlan_gpe *spec =
+ (const struct rte_flow_item_vxlan_gpe *)flow_item->spec;
+ const struct rte_flow_item_vxlan_gpe *mask =
+ (const struct rte_flow_item_vxlan_gpe *)flow_item->mask;
+
+ /* Only VNI is matched; protocol is not. */
+ if (mask->protocol)
+ goto unsupported;
+ vni = spec->vni;
+ vni_mask = mask->vni;
+ break;
+ }
+ default:
+ vni = ((const struct rte_flow_item_vxlan *)flow_item->spec)->vni;
+ vni_mask =
+ ((const struct rte_flow_item_vxlan *)flow_item->mask)->vni;
+ break;
+ }
+
+ memcpy(((uint8_t *)&vxlan_vni_id + 1), vni, 3);
filter->fdir_filter.key_spec.tunnel.tunnel_id =
rte_be_to_cpu_32(vxlan_vni_id);
- memcpy(((uint8_t *)&vxlan_vni_id_mask + 1), mask_vxlan->vni, 3);
+ memcpy(((uint8_t *)&vxlan_vni_id_mask + 1), vni_mask, 3);
filter->fdir_filter.key_mask.tunnel.tunnel_id =
rte_be_to_cpu_32(vxlan_vni_id_mask);
return 0;
+
+unsupported:
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, flow_item,
+ "Not supported by fdir filter, only vni is supported");
+ return -rte_errno;
}
static int
-hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
- const struct rte_flow_item *pattern,
- struct rte_flow_error *error,
- struct hinic3_filter_t *filter)
+hinic3_flow_parse_fdir_vxlan_geneve_pattern(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_item *pattern,
+ struct rte_flow_error *error,
+ struct hinic3_filter_t *filter)
{
const struct rte_flow_item *flow_item = pattern;
- enum hinic3_fdir_tunnel_mode tunnel_mode =
- HINIC3_FDIR_TUNNEL_MODE_NORMAL;
+ enum hinic3_fdir_tunnel_mode tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_MAX;
enum rte_flow_item_type type;
int err;
+ if (pattern == NULL) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Invalid pattern");
+ return -rte_errno;
+ }
+
/* Inner and outer ip type, set it to any by default */
filter->fdir_filter.ip_type = HINIC3_FDIR_IP_TYPE_ANY;
filter->fdir_filter.outer_ip_type = HINIC3_FDIR_IP_TYPE_ANY;
@@ -1038,14 +1305,14 @@ hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
case RTE_FLOW_ITEM_TYPE_IPV4:
err = hinic3_flow_fdir_tunnel_ipv4(error,
- filter, flow_item, tunnel_mode);
+ filter, flow_item, &tunnel_mode);
if (err)
return -rte_errno;
break;
case RTE_FLOW_ITEM_TYPE_IPV6:
err = hinic3_flow_fdir_tunnel_ipv6(error,
- filter, flow_item, tunnel_mode);
+ filter, flow_item, &tunnel_mode);
if (err)
return -rte_errno;
break;
@@ -1065,10 +1332,12 @@ hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
break;
case RTE_FLOW_ITEM_TYPE_VXLAN:
- err = hinic3_flow_fdir_vxlan(error, filter, flow_item);
+ case RTE_FLOW_ITEM_TYPE_GENEVE:
+ case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
+ tunnel_mode = hinic3_flow_tunnel_mode(type);
+ err = hinic3_flow_fdir_vxlan_geneve(error, filter, tunnel_mode, flow_item);
if (err)
return -rte_errno;
- tunnel_mode = HINIC3_FDIR_TUNNEL_MODE_VXLAN;
break;
default:
@@ -1099,16 +1368,16 @@ hinic3_flow_parse_fdir_vxlan_pattern(__rte_unused struct rte_eth_dev *dev,
* 0 on success, non-zero on failure.
*/
static int
-hinic3_flow_parse_fdir_vxlan_filter(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,
- struct hinic3_filter_t *filter)
+hinic3_flow_parse_fdir_vxlan_geneve_filter(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,
+ struct hinic3_filter_t *filter)
{
int ret;
- ret = hinic3_flow_parse_fdir_vxlan_pattern(dev, pattern, error, filter);
+ ret = hinic3_flow_parse_fdir_vxlan_geneve_pattern(dev, pattern, error, filter);
if (ret)
return ret;
@@ -1153,11 +1422,25 @@ hinic3_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
hinic3_parse_filter_t parse_filter;
uint32_t pattern_num = 0;
int ret = 0;
- /* Check whether the parameter is valid. */
- if (!pattern || !actions || !attr) {
+
+ if (!pattern) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+ NULL, "Pattern is NULL.");
+ return -rte_errno;
+ }
+
+ if (!actions) {
rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
- "NULL param.");
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "Actions is NULL.");
+ return -rte_errno;
+ }
+
+ if (!attr) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ATTR,
+ NULL, "Attr is NULL.");
return -rte_errno;
}
@@ -1174,7 +1457,7 @@ hinic3_flow_parse(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
* The corresponding filter is returned. If the filter is not found,
* NULL is returned.
*/
- parse_filter = hinic3_find_parse_filter_func(pattern);
+ parse_filter = hinic3_find_parse_filter_func(dev, pattern);
if (!parse_filter) {
rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
pattern, "Unsupported pattern");
@@ -1303,9 +1586,7 @@ hinic3_flow_create(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
NULL, "Unsupported filter type.");
goto free_flow;
}
-
return flow;
-
free_flow:
rte_free(flow);
rte_free(filter_rules);
@@ -1467,7 +1748,6 @@ hinic3_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error)
return ret;
}
-/* Structure for managing flow table operations. */
const struct rte_flow_ops hinic3_flow_ops = {
.validate = hinic3_flow_validate,
.create = hinic3_flow_create,
diff --git a/drivers/net/hinic3/hinic3_flow.h b/drivers/net/hinic3/hinic3_flow.h
deleted file mode 100644
index c4b38e44e7..0000000000
--- a/drivers/net/hinic3/hinic3_flow.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2025 Huawei Technologies Co., Ltd
- */
-
-#ifndef _HINIC3_FLOW_H_
-#define _HINIC3_FLOW_H_
-
-#include <rte_flow.h>
-
-/* Indicate the type of the IPv4 ICPM matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_icmp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_ICMP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 any protocol matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_any[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_ANY,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the Ether matching pattern. */
-static enum rte_flow_item_type pattern_ethertype[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the TCP matching pattern. */
-static enum rte_flow_item_type pattern_ethertype_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the UDP matching pattern. */
-static enum rte_flow_item_type pattern_ethertype_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan any protocol matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_any[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ANY, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_TCP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv4 matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv4 TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_TCP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv4 UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv4_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv6 matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv6 TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_TCP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 vxlan IPv6 UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_vxlan_ipv6_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 matching pattern. */
-static enum rte_flow_item_type pattern_ipv4[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv4 TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv4_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 matching pattern. */
-static enum rte_flow_item_type pattern_ipv6[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_vxlan[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 VXLAN any protocol matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_vxlan_any[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_ANY, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 VXLAN TCP matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_vxlan_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_TCP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-/* Indicate the type of the IPv6 VXLAN UDP matching pattern. */
-static enum rte_flow_item_type pattern_ipv6_vxlan_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH, RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_VXLAN,
- RTE_FLOW_ITEM_TYPE_UDP, RTE_FLOW_ITEM_TYPE_END,
-};
-
-#endif /**< _HINIC3_FLOW_H_ */
--
2.33.0
More information about the dev
mailing list