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 <[email protected]>
---
 drivers/net/hinic3/base/hinic3_nic_cfg.h |   2 +-
 drivers/net/hinic3/hinic3_ethdev.h       |  12 +
 drivers/net/hinic3/hinic3_fdir.c         | 158 ++++--
 drivers/net/hinic3/hinic3_fdir.h         |  19 +-
 drivers/net/hinic3/hinic3_flow.c         | 581 +++++++++++++++++------
 drivers/net/hinic3/hinic3_flow.h         | 196 --------
 6 files changed, 573 insertions(+), 395 deletions(-)
 delete mode 100644 drivers/net/hinic3/hinic3_flow.h

diff --git a/drivers/net/hinic3/base/hinic3_nic_cfg.h 
b/drivers/net/hinic3/base/hinic3_nic_cfg.h
index ecd410785f..ef139b25b9 100644
--- a/drivers/net/hinic3/base/hinic3_nic_cfg.h
+++ b/drivers/net/hinic3/base/hinic3_nic_cfg.h
@@ -938,7 +938,7 @@ struct hinic3_set_fdir_ethertype_rule {
        uint8_t pkt_type_en;
        uint8_t pkt_type;
        uint8_t qid;
-       uint8_t rsvd2;
+       uint8_t flags;
 };
 
 struct hinic3_cmd_set_rq_flush {
diff --git a/drivers/net/hinic3/hinic3_ethdev.h 
b/drivers/net/hinic3/hinic3_ethdev.h
index b38853f556..34c74f95d9 100644
--- a/drivers/net/hinic3/hinic3_ethdev.h
+++ b/drivers/net/hinic3/hinic3_ethdev.h
@@ -107,6 +107,13 @@ enum nic_feature_cap {
 TAILQ_HEAD(hinic3_ethertype_filter_list, rte_flow);
 TAILQ_HEAD(hinic3_fdir_rule_filter_list, rte_flow);
 
+enum nic_type {
+       NIC_SP620 = 0,
+       NIC_SP560 = 1,
+       NIC_SP230 = 2,
+       NIC_UNKNOWN = 3,
+};
+
 struct hinic3_nic_dev {
        struct hinic3_hwdev *hwdev; /**< Hardware device. */
        struct hinic3_txq **txqs;
@@ -156,12 +163,17 @@ struct hinic3_nic_dev {
        struct hinic3_nic_rx_ops *rx_ops;
        struct hinic3_nic_tx_ops *tx_ops;
        uint32_t fec_mode;  /**< Current FEC mode for ethdev. */
+       enum nic_type nic_type; /**< NIC type. */
 
 };
 
 #define SELECT_OTHER_COS_ID(cos_id) ((cos_id) ^ 4)
 #define ODD_NUMBER_QUEUE_ID(q_id) ((q_id) & 1)
 
+#define HINIC3_IS_SP620_NIC(nic_dev) ((nic_dev)->nic_type == NIC_SP620)
+#define HINIC3_IS_SP560_NIC(nic_dev) ((nic_dev)->nic_type == NIC_SP560)
+#define HINIC3_IS_SP230_NIC(nic_dev) ((nic_dev)->nic_type == NIC_SP230)
+
 extern const struct rte_flow_ops hinic3_flow_ops;
 
 /**
diff --git a/drivers/net/hinic3/hinic3_fdir.c b/drivers/net/hinic3/hinic3_fdir.c
index 71d50a3d22..baa86c0c81 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);
@@ -189,8 +190,6 @@ hinic3_fdir_tcam_ipv6_init(struct hinic3_fdir_filter *rule,
        /* Fill type of ip. */
        tcam_key->key_mask_ipv6.ip_type = HINIC3_UINT1_MAX;
        tcam_key->key_info_ipv6.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
-       tcam_key->key_mask_ipv6.vlan_flag = HINIC3_UINT1_MAX;
-       tcam_key->key_info_ipv6.vlan_flag = 0;
 
        hinic3_fdir_ipv6_tcam_key_init(rule, tcam_key);
 }
@@ -240,15 +239,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,14 +266,12 @@ 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. */
        tcam_key->key_mask_vxlan_ipv6.ip_type = HINIC3_UINT1_MAX;
        tcam_key->key_info_vxlan_ipv6.ip_type = HINIC3_FDIR_IP_TYPE_IPV6;
-       tcam_key->key_mask_vxlan_ipv6.vlan_flag = HINIC3_UINT1_MAX;
-       tcam_key->key_info_vxlan_ipv6.vlan_flag = 0;
 
        /* Use inner dst ipv6 to fill the dst ipv6 of tcam_key. */
        tcam_key->key_mask_vxlan_ipv6.dipv6_key0 =
@@ -359,7 +352,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 +409,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 +425,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;
@@ -693,6 +686,16 @@ hinic3_fdir_tcam_info_htn_init(struct rte_eth_dev *dev,
        tcam_key_calculate(tcam_key, fdir_tcam_rule);
 }
 
+static void hinic3_fdir_tcam_key_get(struct rte_eth_dev *dev,
+                                    struct hinic3_fdir_filter *rule,
+                                    struct hinic3_tcam_key *tcam_key)
+{
+       if (rule->tunnel_type == HINIC3_FDIR_TUNNEL_MODE_NORMAL)
+               hinic3_fdir_tcam_notunnel_init(dev, rule, tcam_key);
+       else
+               hinic3_fdir_tcam_vxlan_geneve_init(dev, rule, tcam_key);
+}
+
 /**
  * Find filter in given ethertype filter list.
  *
@@ -841,7 +844,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!");
@@ -992,6 +995,10 @@ hinic3_set_fdir_ethertype_filter(void *hwdev, uint8_t 
pkt_type, void *filter, ui
        ethertype_cmd.pkt_type_en = en;
        ethertype_cmd.index = index;
        ethertype_cmd.qid = (uint8_t)ethertype_filter->queue;
+       if (en == 0)
+               ethertype_cmd.flags = 0;
+       else
+               ethertype_cmd.flags = (uint8_t)ethertype_filter->flags;
 
        err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_L2NIC,
                                     HINIC3_NIC_CMD_SET_FDIR_STATUS,
@@ -1001,6 +1008,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 +1223,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 +1596,11 @@ 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;
+
+       if (!ethertype_filter) {
+               PMD_DRV_LOG(ERR, "ethertype_filter is NULL");
+               return -EINVAL;
+       }
        /* Add or remove an Ethernet type filter rule. */
        ret = hinic3_flow_add_del_ethertype_filter_rule(dev, ethertype_filter, 
add);
 
@@ -1641,3 +1648,74 @@ hinic3_flow_add_del_ethertype_filter(struct rte_eth_dev 
*dev,
        hinic3_flow_add_del_ethertype_filter_rule(dev, ethertype_filter, !add);
        return ret;
 }
+
+int
+hinic3_flow_query_fdir_filter(struct rte_eth_dev *dev, struct 
hinic3_fdir_filter *fdir_filter,
+                             __rte_unused uint64_t *hits, __rte_unused 
uint64_t *bytes_count)
+{
+       struct hinic3_tcam_info   *tcam_info =
+               HINIC3_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private);
+       struct hinic3_nic_dev     *nic_dev   = 
HINIC3_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+       struct hinic3_tcam_filter *tcam_filter;
+       struct hinic3_tcam_key     tcam_key;
+
+       memset((void *)&tcam_key, 0, sizeof(struct hinic3_tcam_key));
+       hinic3_fdir_tcam_key_get(dev, fdir_filter, &tcam_key);
+       tcam_filter = hinic3_tcam_filter_lookup(&tcam_info->tcam_list, 
&tcam_key,
+                                               HINIC3_ACTION_NOT_ADD, 
fdir_filter->tcam_index);
+       if (tcam_filter == NULL) {
+               PMD_DRV_LOG(ERR, "Filter doesn't exist.");
+               return -EINVAL;
+       }
+
+       if (fdir_filter->ip_type == HINIC3_FDIR_IP_TYPE_IPV4) {
+               PMD_DRV_LOG(INFO, "fdir ipv4 flow get:");
+               PMD_DRV_LOG(INFO, "glb index:%d", fdir_filter->tcam_index);
+               PMD_DRV_LOG(INFO, "ether_type mask: 0x%x", 
fdir_filter->key_mask.ether_type);
+               PMD_DRV_LOG(INFO, "ether_type spec: 0x%x", 
fdir_filter->key_spec.ether_type);
+               PMD_DRV_LOG(INFO, "protocol mask: 0x%x", 
fdir_filter->key_mask.ipv4.proto);
+               PMD_DRV_LOG(INFO, "protocol spec: 0x%x", 
fdir_filter->key_spec.ipv4.proto);
+               PMD_DRV_LOG(INFO, "src_ip mask: 0x%x", 
fdir_filter->key_mask.ipv4.src_ip);
+               PMD_DRV_LOG(INFO, "src_ip spec: 0x%x", 
fdir_filter->key_spec.ipv4.src_ip);
+               PMD_DRV_LOG(INFO, "dst_ip mask: 0x%x", 
fdir_filter->key_mask.ipv4.dst_ip);
+               PMD_DRV_LOG(INFO, "dst_ip spec: 0x%x", 
fdir_filter->key_spec.ipv4.dst_ip);
+               PMD_DRV_LOG(INFO, "src_port mask: 0x%x", 
fdir_filter->key_mask.src_port);
+               PMD_DRV_LOG(INFO, "src_port spec: 0x%x", 
fdir_filter->key_spec.src_port);
+               PMD_DRV_LOG(INFO, "dst_port mask: 0x%x", 
fdir_filter->key_mask.dst_port);
+               PMD_DRV_LOG(INFO, "dst_port spec: 0x%x", 
fdir_filter->key_spec.dst_port);
+               PMD_DRV_LOG(INFO, "rule_nums: 0x%x", nic_dev->tcam_rule_nums);
+               PMD_DRV_LOG(INFO, "mark_id: 0x%x", fdir_filter->rq_index);
+       } else {
+               PMD_DRV_LOG(INFO, "fdir ipv6 flow get:");
+               PMD_DRV_LOG(INFO, "glb index:%d", fdir_filter->tcam_index);
+               PMD_DRV_LOG(INFO, "protocol mask: 0x%x", 
fdir_filter->key_mask.ipv6.proto);
+               PMD_DRV_LOG(INFO, "protocol spec: 0x%x", 
fdir_filter->key_spec.ipv6.proto);
+               PMD_DRV_LOG(INFO, "src_ip mask: 0x%08x:%08x:%08x:%08x",
+                           fdir_filter->key_mask.ipv6.src_ip[0],
+                           fdir_filter->key_mask.ipv6.src_ip[1],
+                           fdir_filter->key_mask.ipv6.src_ip[2],
+                           fdir_filter->key_mask.ipv6.src_ip[3]);
+               PMD_DRV_LOG(INFO, "src_ip spec: 0x%08x:%08x:%08x:%08x",
+                           fdir_filter->key_spec.ipv6.src_ip[0],
+                           fdir_filter->key_spec.ipv6.src_ip[1],
+                           fdir_filter->key_spec.ipv6.src_ip[2],
+                           fdir_filter->key_spec.ipv6.src_ip[3]);
+               PMD_DRV_LOG(INFO, "dst_ip mask: 0x%08x:%08x:%08x:%08x",
+                           fdir_filter->key_mask.ipv6.dst_ip[0],
+                           fdir_filter->key_mask.ipv6.dst_ip[1],
+                           fdir_filter->key_mask.ipv6.dst_ip[2],
+                           fdir_filter->key_mask.ipv6.dst_ip[3]);
+               PMD_DRV_LOG(INFO, "dst_ip spec: 0x%08x:%08x:%08x:%08x",
+                           fdir_filter->key_spec.ipv6.dst_ip[0],
+                           fdir_filter->key_spec.ipv6.dst_ip[1],
+                           fdir_filter->key_spec.ipv6.dst_ip[2],
+                           fdir_filter->key_spec.ipv6.dst_ip[3]);
+               PMD_DRV_LOG(INFO, "src_port mask: 0x%x", 
fdir_filter->key_mask.src_port);
+               PMD_DRV_LOG(INFO, "src_port spec: 0x%x", 
fdir_filter->key_spec.src_port);
+               PMD_DRV_LOG(INFO, "dst_port mask: 0x%x", 
fdir_filter->key_mask.dst_port);
+               PMD_DRV_LOG(INFO, "dst_port spec: 0x%x", 
fdir_filter->key_spec.dst_port);
+               PMD_DRV_LOG(INFO, "rule_nums: 0x%x", nic_dev->tcam_rule_nums);
+               PMD_DRV_LOG(INFO, "mark_id: 0x%x", fdir_filter->rq_index);
+       }
+       return 0;
+}
diff --git a/drivers/net/hinic3/hinic3_fdir.h b/drivers/net/hinic3/hinic3_fdir.h
index 277d89d4fd..73600788fe 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))
@@ -22,6 +27,8 @@
 
 #define HINIC3_TCAM_INVALID_INDEX 0xFFFF
 
+#define HINIC3_RSS_QUEUE_BUF 128
+
 enum hinic3_ether_type {
        HINIC3_PKT_TYPE_ARP = 1,
        HINIC3_PKT_TYPE_ARP_REQ,
@@ -71,6 +78,7 @@ struct hinic3_fdir_filter {
 struct hinic3_ethertype_filter {
        int tcam_index[HINIC3_PKT_TYPE_BUTT];
        uint16_t ether_type;    /**< Ether type to match */
+       uint16_t flags;
        uint16_t queue;         /**< Queue assigned to when match*/
 };
 
@@ -96,6 +104,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 +195,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 +259,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;
@@ -668,6 +677,8 @@ int hinic3_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 int hinic3_flow_add_del_ethertype_filter(struct rte_eth_dev *dev,
                                         struct hinic3_ethertype_filter 
*ethertype_filter,
                                         bool add);
+int hinic3_flow_query_fdir_filter(struct rte_eth_dev *dev, struct 
hinic3_fdir_filter *fdir_filter,
+                                 __rte_unused uint64_t *hits, __rte_unused 
uint64_t *bytes_count);
 void hinic3_free_fdir_filter(struct rte_eth_dev *dev);
 int hinic3_enable_rxq_fdir_filter(struct rte_eth_dev *dev, uint32_t queue_id,
                                  uint32_t able);
diff --git a/drivers/net/hinic3/hinic3_flow.c b/drivers/net/hinic3/hinic3_flow.c
index 5c255619e3..e88787452d 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,
+};
 
-       /* skip the first void item. */
+/*
+ * 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.
+ */
+
+/* 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);
        }
 
-       return (*item_array == RTE_FLOW_ITEM_TYPE_END &&
-               item->type == RTE_FLOW_ITEM_TYPE_END);
+       /* 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;
+       }
+}
+
+/* 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,28 @@ 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) ?
+               hinic3_flow_parse_fdir_filter :
+               hinic3_flow_parse_fdir_vxlan_geneve_filter;
+       default:
+               return NULL;
+       }
 }
 
 /**
@@ -182,12 +343,29 @@ 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++;
+       /* Find the last non-VOID action before END */
+       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)
+                       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 +408,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 +437,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 +460,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 +484,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 +827,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 +880,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 +897,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 +913,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 +928,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 +940,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 +957,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 +982,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 +1022,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 +1072,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 +1097,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 +1124,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 +1146,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,53 +1164,74 @@ 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;
        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) {
                return 0;
        } else 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) {
                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);
-       filter->fdir_filter.key_mask.tunnel.tunnel_id =
-               rte_be_to_cpu_32(vxlan_vni_id);
+       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);
+       filter->fdir_filter.key_mask.tunnel.tunnel_id = 
rte_be_to_cpu_32(vxlan_vni_id_mask);
        return 0;
 }
 
 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;
@@ -1034,14 +1259,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;
@@ -1061,10 +1286,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:
@@ -1095,16 +1322,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;
 
@@ -1149,11 +1376,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_ACTION,
+                                  NULL, "Actions is NULL.");
+               return -rte_errno;
+       }
+
+       if (!attr) {
                rte_flow_error_set(error, EINVAL,
-                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
-                                  "NULL param.");
+                                  RTE_FLOW_ERROR_TYPE_ATTR,
+                                  NULL, "Attr is NULL.");
                return -rte_errno;
        }
 
@@ -1170,7 +1411,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");
@@ -1299,9 +1540,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);
@@ -1332,10 +1571,6 @@ hinic3_flow_destroy(struct rte_eth_dev *dev, struct 
rte_flow *flow,
                        &rules->ethertype_filter, false);
                if (!ret)
                        TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, 
node);
-
-               flow->rule = rules;
-               flow->filter_type = rules->filter_type;
-               TAILQ_REMOVE(&nic_dev->filter_ethertype_list, flow, node);
                break;
 
        case RTE_ETH_FILTER_FDIR:
@@ -1467,10 +1702,48 @@ hinic3_flow_flush(struct rte_eth_dev *dev, struct 
rte_flow_error *error)
        return ret;
 }
 
-/* Structure for managing flow table operations. */
+static int
+hinic3_flow_query(struct rte_eth_dev *dev, struct rte_flow *flow,
+                 __rte_unused const struct rte_flow_action *actions,
+                 void *data, struct rte_flow_error *error)
+{
+       int ret = -EINVAL;
+       enum rte_filter_type filter_type;
+       struct hinic3_filter_t *filter_rules = NULL;
+       struct rte_flow_query_count *flow_count = NULL;
+
+       if (!flow || !data) {
+               PMD_DRV_LOG(ERR, "Invalid flow parameter!");
+               return -EPERM;
+       }
+
+       flow_count = (struct rte_flow_query_count *)data;
+       filter_type = flow->filter_type;
+       switch (filter_type) {
+       case RTE_ETH_FILTER_ETHERTYPE:
+               PMD_DRV_LOG(ERR, "Ethertype type %d, current not to process", 
filter_type);
+               break;
+       case RTE_ETH_FILTER_FDIR:
+               filter_rules = (struct hinic3_filter_t *)flow->rule;
+               ret = hinic3_flow_query_fdir_filter(dev, 
&filter_rules->fdir_filter,
+                       &flow_count->hits, &flow_count->bytes);
+               break;
+       default:
+               PMD_DRV_LOG(ERR, "Filter type %d not support to query", 
filter_type);
+               ret = -EINVAL;
+               break;
+       }
+
+       if (ret)
+               rte_flow_error_set(error, -ret, RTE_FLOW_ERROR_TYPE_HANDLE, 
NULL, "Failed to query flow.");
+
+       return ret;
+}
+
 const struct rte_flow_ops hinic3_flow_ops = {
        .validate = hinic3_flow_validate,
        .create = hinic3_flow_create,
        .destroy = hinic3_flow_destroy,
        .flush = hinic3_flow_flush,
+       .query = hinic3_flow_query,
 };
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


Reply via email to