From c352e315a8aec2f3a9200b9073b072e945daead1 Mon Sep 17 00:00:00 2001 From: jiangheng12 Date: Thu, 9 Mar 2023 21:58:14 +0800 Subject: [PATCH] sync patches to enable hinic flow director --- ...1-net-hinic-add-flow-director-filter.patch | 1816 +++++++++++++++++ ...TCAM-filter-switch-for-flow-director.patch | 150 ++ ...-memory-allocations-in-flow-creation.patch | 57 + ...filters-on-memory-allocation-failure.patch | 79 + ...t-0005-net-hinic-fix-TCAM-filter-set.patch | 40 + dpdk.spec | 10 +- 6 files changed, 2151 insertions(+), 1 deletion(-) create mode 100644 backport-0001-net-hinic-add-flow-director-filter.patch create mode 100644 backport-0002-net-hinic-add-TCAM-filter-switch-for-flow-director.patch create mode 100644 backport-0003-net-hinic-check-memory-allocations-in-flow-creation.patch create mode 100644 backport-0004-net-hinic-fix-filters-on-memory-allocation-failure.patch create mode 100644 backport-0005-net-hinic-fix-TCAM-filter-set.patch diff --git a/backport-0001-net-hinic-add-flow-director-filter.patch b/backport-0001-net-hinic-add-flow-director-filter.patch new file mode 100644 index 0000000..a285817 --- /dev/null +++ b/backport-0001-net-hinic-add-flow-director-filter.patch @@ -0,0 +1,1816 @@ +From 1fe89aa37f368722c882a4bdd2f8a427761255a5 Mon Sep 17 00:00:00 2001 +From: Xiaoyun Wang +Date: Tue, 17 Mar 2020 23:01:15 +0800 +Subject: [PATCH] net/hinic: add flow director filter + +The patch supports filter type of inner VXLAN or non vxlan dport, +and use TCAM method to config these rules. + +Signed-off-by: Xiaoyun Wang +--- + drivers/net/hinic/base/hinic_pmd_cmd.h | 6 + + drivers/net/hinic/base/hinic_pmd_niccfg.c | 184 ++++- + drivers/net/hinic/base/hinic_pmd_niccfg.h | 81 ++ + drivers/net/hinic/hinic_pmd_ethdev.c | 6 +- + drivers/net/hinic/hinic_pmd_ethdev.h | 110 ++- + drivers/net/hinic/hinic_pmd_flow.c | 961 +++++++++++++++++++--- + 6 files changed, 1199 insertions(+), 149 deletions(-) + +diff --git a/drivers/net/hinic/base/hinic_pmd_cmd.h b/drivers/net/hinic/base/hinic_pmd_cmd.h +index c025851521..09918a76fa 100644 +--- a/drivers/net/hinic/base/hinic_pmd_cmd.h ++++ b/drivers/net/hinic/base/hinic_pmd_cmd.h +@@ -115,6 +115,12 @@ enum hinic_port_cmd { + + HINIC_PORT_CMD_GET_PORT_INFO = 0xaa, + ++ HINIC_PORT_CMD_UP_TC_ADD_FLOW = 0xaf, ++ HINIC_PORT_CMD_UP_TC_DEL_FLOW = 0xb0, ++ HINIC_PORT_CMD_UP_TC_GET_FLOW = 0xb1, ++ HINIC_PORT_CMD_UP_TC_FLUSH_TCAM = 0xb2, ++ HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK = 0xb3, ++ + HINIC_PORT_CMD_SET_IPSU_MAC = 0xcb, + HINIC_PORT_CMD_GET_IPSU_MAC = 0xcc, + +diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c +index 2dc431e288..0bbcd36322 100644 +--- a/drivers/net/hinic/base/hinic_pmd_niccfg.c ++++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c +@@ -19,22 +19,6 @@ + buf_out, out_size, 0) + + +-#define TCAM_SET 0x1 +-#define TCAM_CLEAR 0x2 +- +-struct hinic_port_qfilter_info { +- struct hinic_mgmt_msg_head mgmt_msg_head; +- +- u16 func_id; +- u8 normal_type_enable; +- u8 filter_type_enable; +- u8 filter_enable; +- u8 filter_type; +- u8 qid; +- u8 fdir_flag; +- u32 key; +-}; +- + /** + * hinic_init_function_table - Initialize function table. + * +@@ -1901,7 +1885,7 @@ int hinic_set_fdir_tcam(void *hwdev, u16 type_mask, + &port_tcam_cmd, sizeof(port_tcam_cmd), + &port_tcam_cmd, &out_size); + if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) { +- PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x\n", ++ PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x", + err, port_tcam_cmd.mgmt_msg_head.status, out_size); + return -EFAULT; + } +@@ -1938,10 +1922,174 @@ int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask) + &port_tcam_cmd, sizeof(port_tcam_cmd), + &port_tcam_cmd, &out_size); + if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) { +- PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x\n", ++ PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x", + err, port_tcam_cmd.mgmt_msg_head.status, out_size); + return -EFAULT; + } + + return 0; + } ++ ++int hinic_add_tcam_rule(void *hwdev, struct tag_tcam_cfg_rule *tcam_rule) ++{ ++ u16 out_size = sizeof(struct tag_fdir_add_rule_cmd); ++ struct tag_fdir_add_rule_cmd tcam_cmd; ++ int err; ++ ++ if (!hwdev) { ++ PMD_DRV_LOG(ERR, "Hwdev is NULL"); ++ return -EINVAL; ++ } ++ ++ if (tcam_rule->index >= HINIC_MAX_TCAM_RULES_NUM) { ++ PMD_DRV_LOG(ERR, "Tcam rules num to add is invalid"); ++ return -EFAULT; ++ } ++ ++ memset(&tcam_cmd, 0, sizeof(struct tag_fdir_add_rule_cmd)); ++ tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; ++ memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule, ++ sizeof(struct tag_tcam_cfg_rule)); ++ ++ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ADD_FLOW, ++ &tcam_cmd, sizeof(tcam_cmd), ++ &tcam_cmd, &out_size); ++ if (err || tcam_cmd.mgmt_msg_head.status || !out_size) { ++ PMD_DRV_LOG(ERR, ++ "Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x", ++ err, tcam_cmd.mgmt_msg_head.status, out_size); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++int hinic_del_tcam_rule(void *hwdev, u32 index) ++{ ++ u16 out_size = sizeof(struct tag_fdir_del_rule_cmd); ++ struct tag_fdir_del_rule_cmd tcam_cmd; ++ int err; ++ ++ if (!hwdev) { ++ PMD_DRV_LOG(ERR, "Hwdev is NULL"); ++ return -EINVAL; ++ } ++ ++ if (index >= HINIC_MAX_TCAM_RULES_NUM) { ++ PMD_DRV_LOG(ERR, "Tcam rules num to del is invalid"); ++ return -EFAULT; ++ } ++ ++ memset(&tcam_cmd, 0, sizeof(struct tag_fdir_del_rule_cmd)); ++ tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; ++ tcam_cmd.index_start = index; ++ tcam_cmd.index_num = 1; ++ ++ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_DEL_FLOW, ++ &tcam_cmd, sizeof(tcam_cmd), ++ &tcam_cmd, &out_size); ++ if (err || tcam_cmd.mgmt_msg_head.status || !out_size) { ++ PMD_DRV_LOG(ERR, ++ "Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x", ++ err, tcam_cmd.mgmt_msg_head.status, out_size); ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static int hinic_mgmt_tcam_block(void *hwdev, u8 alloc_en, ++ u8 block_type, u16 *index) ++{ ++ struct hinic_cmd_ctrl_tcam_block tcam_block_info; ++ u16 out_size = sizeof(struct hinic_cmd_ctrl_tcam_block); ++ struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev; ++ int err; ++ ++ if (!hwdev) { ++ PMD_DRV_LOG(ERR, "Hwdev is NULL"); ++ return -EINVAL; ++ } ++ ++ memset(&tcam_block_info, 0, sizeof(struct hinic_cmd_ctrl_tcam_block)); ++ tcam_block_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; ++ tcam_block_info.func_id = hinic_global_func_id(hwdev); ++ tcam_block_info.alloc_en = alloc_en; ++ tcam_block_info.tcam_type = block_type; ++ tcam_block_info.tcam_block_index = *index; ++ ++ err = l2nic_msg_to_mgmt_sync(hwdev, ++ HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, ++ &tcam_block_info, sizeof(tcam_block_info), ++ &tcam_block_info, &out_size); ++ if (tcam_block_info.mgmt_msg_head.status == ++ HINIC_MGMT_CMD_UNSUPPORTED) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(INFO, "Firmware/uP doesn't support alloc or del tcam block"); ++ return err; ++ } else if ((err == HINIC_MBOX_VF_CMD_ERROR) && ++ (HINIC_IS_VF(nic_hwdev))) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(INFO, "VF doesn't support alloc and del tcam block."); ++ return err; ++ } else if (err || (!out_size) || tcam_block_info.mgmt_msg_head.status) { ++ PMD_DRV_LOG(ERR, ++ "Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x", ++ err, tcam_block_info.mgmt_msg_head.status, out_size); ++ return -EFAULT; ++ } ++ ++ if (alloc_en) ++ *index = tcam_block_info.tcam_block_index; ++ ++ return 0; ++} ++ ++int hinic_alloc_tcam_block(void *hwdev, u8 block_type, u16 *index) ++{ ++ return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_ENABLE, ++ block_type, index); ++} ++ ++int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index) ++{ ++ return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_DISABLE, ++ block_type, index); ++} ++ ++int hinic_flush_tcam_rule(void *hwdev) ++{ ++ struct hinic_cmd_flush_tcam_rules tcam_flush; ++ u16 out_size = sizeof(struct hinic_cmd_flush_tcam_rules); ++ struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev; ++ int err; ++ ++ if (!hwdev) { ++ PMD_DRV_LOG(ERR, "Hwdev is NULL"); ++ return -EINVAL; ++ } ++ ++ memset(&tcam_flush, 0, sizeof(struct hinic_cmd_flush_tcam_rules)); ++ tcam_flush.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; ++ tcam_flush.func_id = hinic_global_func_id(hwdev); ++ ++ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, ++ &tcam_flush, sizeof(struct hinic_cmd_flush_tcam_rules), ++ &tcam_flush, &out_size); ++ if (tcam_flush.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(INFO, "Firmware/uP doesn't support flush tcam fdir"); ++ } else if ((err == HINIC_MBOX_VF_CMD_ERROR) && ++ (HINIC_IS_VF(nic_hwdev))) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(INFO, "VF doesn't support flush tcam fdir"); ++ } else if (err || (!out_size) || tcam_flush.mgmt_msg_head.status) { ++ PMD_DRV_LOG(ERR, ++ "Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x", ++ err, tcam_flush.mgmt_msg_head.status, out_size); ++ err = -EFAULT; ++ } ++ ++ return err; ++} ++ +diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.h b/drivers/net/hinic/base/hinic_pmd_niccfg.h +index b9e037ec2d..be6b320b31 100644 +--- a/drivers/net/hinic/base/hinic_pmd_niccfg.h ++++ b/drivers/net/hinic/base/hinic_pmd_niccfg.h +@@ -750,6 +750,77 @@ struct hinic_fdir_tcam_info { + struct tag_pa_action filter_action; + }; + ++#define TCAM_SET 0x1 ++#define TCAM_CLEAR 0x2 ++ ++struct hinic_port_qfilter_info { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ ++ u16 func_id; ++ u8 normal_type_enable; ++ u8 filter_type_enable; ++ u8 filter_enable; ++ u8 filter_type; ++ u8 qid; ++ u8 fdir_flag; ++ u32 key; ++}; ++ ++#define HINIC_MAX_TCAM_RULES_NUM (10240) ++#define HINIC_TCAM_BLOCK_ENABLE 1 ++#define HINIC_TCAM_BLOCK_DISABLE 0 ++ ++struct tag_tcam_result { ++ u32 qid; ++ u32 rsvd; ++}; ++ ++#define TCAM_FLOW_KEY_SIZE 24 ++ ++struct tag_tcam_key_x_y { ++ u8 x[TCAM_FLOW_KEY_SIZE]; ++ u8 y[TCAM_FLOW_KEY_SIZE]; ++}; ++ ++struct tag_tcam_cfg_rule { ++ u32 index; ++ struct tag_tcam_result data; ++ struct tag_tcam_key_x_y key; ++}; ++ ++struct tag_fdir_add_rule_cmd { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ struct tag_tcam_cfg_rule rule; ++}; ++ ++struct tag_fdir_del_rule_cmd { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ ++ u32 index_start; ++ u32 index_num; ++}; ++ ++struct hinic_cmd_flush_tcam_rules { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ ++ u16 func_id; ++ u16 rsvd; ++}; ++ ++struct hinic_cmd_ctrl_tcam_block { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ ++ u16 func_id; ++ u8 alloc_en; /* 0: free tcam block, 1: alloc tcam block */ ++ /* ++ * 0: alloc 1k size tcam block, ++ * 1: alloc 128 size tcam block, others rsvd ++ */ ++ u8 tcam_type; ++ u16 tcam_block_index; ++ u16 rsvd; ++}; ++ + int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id); + + int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id); +@@ -858,4 +929,14 @@ int hinic_set_fdir_tcam(void *hwdev, u16 type_mask, + + int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask); + ++int hinic_add_tcam_rule(void *hwdev, struct tag_tcam_cfg_rule *tcam_rule); ++ ++int hinic_del_tcam_rule(void *hwdev, u32 index); ++ ++int hinic_alloc_tcam_block(void *hwdev, u8 block_type, u16 *index); ++ ++int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index); ++ ++int hinic_flush_tcam_rule(void *hwdev); ++ + #endif /* _HINIC_PMD_NICCFG_H_ */ +diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c +index 37aa042db2..9e90056f92 100644 +--- a/drivers/net/hinic/hinic_pmd_ethdev.c ++++ b/drivers/net/hinic/hinic_pmd_ethdev.c +@@ -1222,7 +1222,7 @@ static void hinic_dev_stop(struct rte_eth_dev *dev) + /* clean root context */ + hinic_free_qp_ctxts(nic_dev->hwdev); + +- hinic_free_fdir_filter(nic_dev); ++ hinic_destroy_fdir_filter(dev); + + /* free mbuf */ + hinic_free_all_rx_mbuf(dev); +@@ -2946,6 +2946,7 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) + struct rte_ether_addr *eth_addr; + struct hinic_nic_dev *nic_dev; + struct hinic_filter_info *filter_info; ++ struct hinic_tcam_info *tcam_info; + u32 mac_size; + int rc; + +@@ -3035,9 +3036,12 @@ static int hinic_func_init(struct rte_eth_dev *eth_dev) + + /* initialize filter info */ + filter_info = &nic_dev->filter; ++ tcam_info = &nic_dev->tcam; + memset(filter_info, 0, sizeof(struct hinic_filter_info)); ++ memset(tcam_info, 0, sizeof(struct hinic_tcam_info)); + /* initialize 5tuple filter list */ + TAILQ_INIT(&filter_info->fivetuple_list); ++ TAILQ_INIT(&tcam_info->tcam_list); + TAILQ_INIT(&nic_dev->filter_ntuple_list); + TAILQ_INIT(&nic_dev->filter_ethertype_list); + TAILQ_INIT(&nic_dev->filter_fdir_rule_list); +diff --git a/drivers/net/hinic/hinic_pmd_ethdev.h b/drivers/net/hinic/hinic_pmd_ethdev.h +index 3e3f3b3607..d67e2161c1 100644 +--- a/drivers/net/hinic/hinic_pmd_ethdev.h ++++ b/drivers/net/hinic/hinic_pmd_ethdev.h +@@ -95,20 +95,113 @@ struct hinic_hw_fdir_mask { + uint32_t dst_ipv4_mask; + uint16_t src_port_mask; + uint16_t dst_port_mask; ++ uint16_t proto_mask; ++ uint16_t tunnel_flag; ++ uint16_t tunnel_inner_src_port_mask; ++ uint16_t tunnel_inner_dst_port_mask; + }; + + /* Flow Director attribute */ + struct hinic_atr_input { +- u32 dst_ip; +- u32 src_ip; +- u16 src_port; +- u16 dst_port; ++ uint32_t dst_ip; ++ uint32_t src_ip; ++ uint16_t src_port; ++ uint16_t dst_port; ++ uint16_t proto; ++ uint16_t tunnel_flag; ++ uint16_t tunnel_inner_src_port; ++ uint16_t tunnel_inner_dst_port; ++}; ++ ++enum hinic_fdir_mode { ++ HINIC_FDIR_MODE_NORMAL = 0, ++ HINIC_FDIR_MODE_TCAM = 1, ++}; ++ ++#define HINIC_PF_MAX_TCAM_FILTERS 1024 ++#define HINIC_VF_MAX_TCAM_FILTERS 128 ++#define HINIC_SUPPORT_PF_MAX_NUM 4 ++#define HINIC_TOTAL_PF_MAX_NUM 16 ++#define HINIC_SUPPORT_VF_MAX_NUM 32 ++#define HINIC_TCAM_BLOCK_TYPE_PF 0 /* 1024 tcam index of a block */ ++#define HINIC_TCAM_BLOCK_TYPE_VF 1 /* 128 tcam index of a block */ ++ ++#define HINIC_PKT_VF_TCAM_INDEX_START(block_index) \ ++ (HINIC_PF_MAX_TCAM_FILTERS * HINIC_SUPPORT_PF_MAX_NUM + \ ++ HINIC_VF_MAX_TCAM_FILTERS * (block_index)) ++ ++TAILQ_HEAD(hinic_tcam_filter_list, hinic_tcam_filter); ++ ++struct hinic_tcam_info { ++ struct hinic_tcam_filter_list tcam_list; ++ u8 tcam_index_array[HINIC_PF_MAX_TCAM_FILTERS]; ++ u16 tcam_block_index; ++ u16 tcam_rule_nums; ++}; ++ ++struct tag_tcam_key_mem { ++#if (RTE_BYTE_ORDER == RTE_BIG_ENDIAN) ++ ++ u32 rsvd0:16; ++ u32 function_id:16; ++ ++ u32 protocol:8; ++ /* ++ * tunnel packet, mask must be 0xff, spec value is 1; ++ * normal packet, mask must be 0, spec value is 0; ++ * if tunnal packet, ucode use ++ * sip/dip/protocol/src_port/dst_dport from inner packet ++ */ ++ u32 tunnel_flag:8; ++ u32 sip_h:16; ++ ++ u32 sip_l:16; ++ u32 dip_h:16; ++ ++ u32 dip_l:16; ++ u32 src_port:16; ++ ++ u32 dst_port:16; ++ /* ++ * tunnel packet and normal packet, ++ * ext_dip mask must be 0xffffffff ++ */ ++ u32 ext_dip_h:16; ++ u32 ext_dip_l:16; ++ u32 rsvd2:16; ++#else ++ u32 function_id:16; ++ u32 rsvd0:16; ++ ++ u32 sip_h:16; ++ u32 tunnel_flag:8; ++ u32 protocol:8; ++ ++ u32 dip_h:16; ++ u32 sip_l:16; ++ ++ u32 src_port:16; ++ u32 dip_l:16; ++ ++ u32 ext_dip_h:16; ++ u32 dst_port:16; ++ ++ u32 rsvd2:16; ++ u32 ext_dip_l:16; ++#endif ++}; ++ ++struct tag_tcam_key { ++ struct tag_tcam_key_mem key_info; ++ struct tag_tcam_key_mem key_mask; + }; + + struct hinic_fdir_rule { + struct hinic_hw_fdir_mask mask; + struct hinic_atr_input hinic_fdir; /* key of fdir filter */ + uint8_t queue; /* queue assigned when matched */ ++ enum hinic_fdir_mode mode; /* fdir type */ ++ u16 tcam_index; + }; + + /* ntuple filter list structure */ +@@ -129,6 +222,13 @@ struct hinic_fdir_rule_ele { + struct hinic_fdir_rule filter_info; + }; + ++struct hinic_tcam_filter { ++ TAILQ_ENTRY(hinic_tcam_filter) entries; ++ uint16_t index; /* tcam index */ ++ struct tag_tcam_key tcam_key; ++ uint16_t queue; /* rx queue assigned to */ ++}; ++ + struct rte_flow { + enum rte_filter_type filter_type; + void *rule; +@@ -181,6 +281,7 @@ struct hinic_nic_dev { + u32 rx_csum_en; + + struct hinic_filter_info filter; ++ struct hinic_tcam_info tcam; + struct hinic_ntuple_filter_list filter_ntuple_list; + struct hinic_ethertype_filter_list filter_ethertype_list; + struct hinic_fdir_rule_filter_list filter_fdir_rule_list; +@@ -189,4 +290,5 @@ struct hinic_nic_dev { + + void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev); + ++void hinic_destroy_fdir_filter(struct rte_eth_dev *dev); + #endif /* _HINIC_PMD_ETHDEV_H_ */ +diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c +index 49c9d8768c..c1f86eff05 100644 +--- a/drivers/net/hinic/hinic_pmd_flow.c ++++ b/drivers/net/hinic/hinic_pmd_flow.c +@@ -46,7 +46,12 @@ + #define PA_IP_PROTOCOL_TYPE_SCTP 5 + #define PA_IP_PROTOCOL_TYPE_VRRP 112 + +-#define IP_HEADER_PROTOCOL_TYPE_TCP 6 ++#define IP_HEADER_PROTOCOL_TYPE_TCP 6 ++#define IP_HEADER_PROTOCOL_TYPE_UDP 17 ++#define IP_HEADER_PROTOCOL_TYPE_ICMP 1 ++ ++#define FDIR_TCAM_NORMAL_PACKET 0 ++#define FDIR_TCAM_TUNNEL_PACKET 1 + + #define HINIC_MIN_N_TUPLE_PRIO 1 + #define HINIC_MAX_N_TUPLE_PRIO 7 +@@ -82,6 +87,10 @@ + #define HINIC_DEV_PRIVATE_TO_FILTER_INFO(nic_dev) \ + (&((struct hinic_nic_dev *)nic_dev)->filter) + ++#define HINIC_DEV_PRIVATE_TO_TCAM_INFO(nic_dev) \ ++ (&((struct hinic_nic_dev *)nic_dev)->tcam) ++ ++ + enum hinic_atr_flow_type { + HINIC_ATR_FLOW_TYPE_IPV4_DIP = 0x1, + HINIC_ATR_FLOW_TYPE_IPV4_SIP = 0x2, +@@ -270,8 +279,7 @@ hinic_parse_ethertype_aciton(const struct rte_flow_action *actions, + * other members in mask and spec should set to 0x00. + * item->last should be NULL. + */ +-static int +-cons_parse_ethertype_filter(const struct rte_flow_attr *attr, ++static int cons_parse_ethertype_filter(const struct rte_flow_attr *attr, + const struct rte_flow_item *pattern, + const struct rte_flow_action *actions, + struct rte_eth_ethertype_filter *filter, +@@ -341,8 +349,7 @@ cons_parse_ethertype_filter(const struct rte_flow_attr *attr, + return 0; + } + +-static int +-hinic_parse_ethertype_filter(struct rte_eth_dev *dev, ++static int hinic_parse_ethertype_filter(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], +@@ -728,8 +735,7 @@ static int hinic_check_ntuple_item_ele(const struct rte_flow_item *item, + * Because the pattern is used to describe the packets, + * normally the packets should use network order. + */ +-static int +-cons_parse_ntuple_filter(const struct rte_flow_attr *attr, ++static int cons_parse_ntuple_filter(const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], + struct rte_eth_ntuple_filter *filter, +@@ -752,8 +758,7 @@ cons_parse_ntuple_filter(const struct rte_flow_attr *attr, + return 0; + } + +-static int +-hinic_parse_ntuple_filter(struct rte_eth_dev *dev, ++static int hinic_parse_ntuple_filter(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], +@@ -891,6 +896,7 @@ static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item, + + rule->mask.dst_ipv4_mask = ipv4_mask->hdr.dst_addr; + rule->mask.src_ipv4_mask = ipv4_mask->hdr.src_addr; ++ rule->mode = HINIC_FDIR_MODE_NORMAL; + + if (item->spec) { + ipv4_spec = +@@ -906,6 +912,8 @@ static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item, + item = next_no_void_pattern(pattern, item); + if (item->type != RTE_FLOW_ITEM_TYPE_TCP && + item->type != RTE_FLOW_ITEM_TYPE_UDP && ++ item->type != RTE_FLOW_ITEM_TYPE_ICMP && ++ item->type != RTE_FLOW_ITEM_TYPE_ANY && + item->type != RTE_FLOW_ITEM_TYPE_END) { + memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, +@@ -920,6 +928,239 @@ static int hinic_normal_item_check_ip(const struct rte_flow_item **in_out_item, + } + + static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, ++ __rte_unused const struct rte_flow_item pattern[], ++ __rte_unused struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = *in_out_item; ++ ++ if (item->type != RTE_FLOW_ITEM_TYPE_END) { ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by normal fdir filter,not support l4"); ++ return -rte_errno; ++ } ++ ++ return 0; ++} ++ ++ ++static int hinic_normal_item_check_end(const struct rte_flow_item *item, ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ /* Check if the next not void item is END */ ++ if (item->type != RTE_FLOW_ITEM_TYPE_END) { ++ memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter,support end"); ++ return -rte_errno; ++ } ++ ++ return 0; ++} ++ ++static int hinic_check_normal_item_ele(const struct rte_flow_item *item, ++ const struct rte_flow_item pattern[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ if (hinic_normal_item_check_ether(&item, pattern, error) || ++ hinic_normal_item_check_ip(&item, pattern, rule, error) || ++ hinic_normal_item_check_l4(&item, pattern, rule, error) || ++ hinic_normal_item_check_end(item, rule, error)) ++ return -rte_errno; ++ ++ return 0; ++} ++ ++static int ++hinic_tcam_normal_item_check_l4(const struct rte_flow_item **in_out_item, ++ const struct rte_flow_item pattern[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = *in_out_item; ++ const struct rte_flow_item_tcp *tcp_spec; ++ const struct rte_flow_item_tcp *tcp_mask; ++ const struct rte_flow_item_udp *udp_spec; ++ const struct rte_flow_item_udp *udp_mask; ++ ++ if (item->type == RTE_FLOW_ITEM_TYPE_ICMP) { ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.proto_mask = UINT16_MAX; ++ rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_ICMP; ++ } else if (item->type == RTE_FLOW_ITEM_TYPE_ANY) { ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ } else if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { ++ if (!item->mask) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support src, dst ports"); ++ return -rte_errno; ++ } ++ ++ tcp_mask = (const struct rte_flow_item_tcp *)item->mask; ++ ++ /* ++ * Only support src & dst ports, tcp flags, ++ * others should be masked. ++ */ ++ if (tcp_mask->hdr.sent_seq || ++ tcp_mask->hdr.recv_ack || ++ tcp_mask->hdr.data_off || ++ tcp_mask->hdr.rx_win || ++ tcp_mask->hdr.cksum || ++ tcp_mask->hdr.tcp_urp) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir normal tcam filter"); ++ return -rte_errno; ++ } ++ ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.proto_mask = UINT16_MAX; ++ rule->mask.dst_port_mask = tcp_mask->hdr.dst_port; ++ rule->mask.src_port_mask = tcp_mask->hdr.src_port; ++ ++ rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_TCP; ++ if (item->spec) { ++ tcp_spec = (const struct rte_flow_item_tcp *)item->spec; ++ rule->hinic_fdir.dst_port = tcp_spec->hdr.dst_port; ++ rule->hinic_fdir.src_port = tcp_spec->hdr.src_port; ++ } ++ } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { ++ /* ++ * Only care about src & dst ports, ++ * others should be masked. ++ */ ++ if (!item->mask) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support src, dst ports"); ++ return -rte_errno; ++ } ++ ++ udp_mask = (const struct rte_flow_item_udp *)item->mask; ++ if (udp_mask->hdr.dgram_len || ++ udp_mask->hdr.dgram_cksum) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support udp"); ++ return -rte_errno; ++ } ++ ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.proto_mask = UINT16_MAX; ++ rule->mask.src_port_mask = udp_mask->hdr.src_port; ++ rule->mask.dst_port_mask = udp_mask->hdr.dst_port; ++ ++ rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_UDP; ++ if (item->spec) { ++ udp_spec = (const struct rte_flow_item_udp *)item->spec; ++ rule->hinic_fdir.src_port = udp_spec->hdr.src_port; ++ rule->hinic_fdir.dst_port = udp_spec->hdr.dst_port; ++ } ++ } else { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter tcam normal, l4 only support icmp, tcp"); ++ return -rte_errno; ++ } ++ ++ item = next_no_void_pattern(pattern, item); ++ if (item->type != RTE_FLOW_ITEM_TYPE_END) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter tcam normal, support end"); ++ return -rte_errno; ++ } ++ ++ /* get next no void item */ ++ *in_out_item = item; ++ ++ return 0; ++} ++ ++static int hinic_check_tcam_normal_item_ele(const struct rte_flow_item *item, ++ const struct rte_flow_item pattern[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ if (hinic_normal_item_check_ether(&item, pattern, error) || ++ hinic_normal_item_check_ip(&item, pattern, rule, error) || ++ hinic_tcam_normal_item_check_l4(&item, pattern, rule, error) || ++ hinic_normal_item_check_end(item, rule, error)) ++ return -rte_errno; ++ ++ return 0; ++} ++ ++static int hinic_tunnel_item_check_l4(const struct rte_flow_item **in_out_item, ++ const struct rte_flow_item pattern[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = *in_out_item; ++ ++ if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { ++ item = next_no_void_pattern(pattern, item); ++ if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support vxlan"); ++ return -rte_errno; ++ } ++ ++ *in_out_item = item; ++ } else { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter tcam tunnel, outer l4 only support udp"); ++ return -rte_errno; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic_tunnel_item_check_vxlan(const struct rte_flow_item **in_out_item, ++ const struct rte_flow_item pattern[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = *in_out_item; ++ ++ ++ if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN) { ++ item = next_no_void_pattern(pattern, item); ++ if (item->type != RTE_FLOW_ITEM_TYPE_TCP && ++ item->type != RTE_FLOW_ITEM_TYPE_UDP && ++ item->type != RTE_FLOW_ITEM_TYPE_ANY) { ++ (void)memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ rte_flow_error_set(error, EINVAL, ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support tcp/udp"); ++ return -rte_errno; ++ } ++ ++ *in_out_item = item; ++ } ++ ++ return 0; ++} ++ ++static int ++hinic_tunnel_inner_item_check_l4(const struct rte_flow_item **in_out_item, + const struct rte_flow_item pattern[], + struct hinic_fdir_rule *rule, + struct rte_flow_error *error) +@@ -933,13 +1174,14 @@ static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, + if (item->type != RTE_FLOW_ITEM_TYPE_END) { + /* Not supported last point for range */ + if (item->last) { ++ memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + item, "Not supported last point for range"); + return -rte_errno; + } + +- /* Get TCP/UDP info */ ++ /* get the TCP/UDP info */ + if (item->type == RTE_FLOW_ITEM_TYPE_TCP) { + /* + * Only care about src & dst ports, +@@ -948,8 +1190,8 @@ static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, + if (!item->mask) { + memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, +- RTE_FLOW_ERROR_TYPE_ITEM, item, +- "Not supported by fdir filter,support src,dst ports"); ++ RTE_FLOW_ERROR_TYPE_ITEM, ++ item, "Not supported by fdir filter, support src, dst ports"); + return -rte_errno; + } + +@@ -961,26 +1203,31 @@ static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, + tcp_mask->hdr.rx_win || + tcp_mask->hdr.cksum || + tcp_mask->hdr.tcp_urp) { +- memset(rule, 0, sizeof(struct hinic_fdir_rule)); ++ (void)memset(rule, 0, ++ sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, +- item, "Not supported by fdir filter,support tcp"); ++ item, "Not supported by fdir filter, support tcp"); + return -rte_errno; + } + +- rule->mask.src_port_mask = tcp_mask->hdr.src_port; +- rule->mask.dst_port_mask = tcp_mask->hdr.dst_port; ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.tunnel_flag = UINT16_MAX; ++ rule->mask.tunnel_inner_src_port_mask = ++ tcp_mask->hdr.src_port; ++ rule->mask.tunnel_inner_dst_port_mask = ++ tcp_mask->hdr.dst_port; ++ rule->mask.proto_mask = UINT16_MAX; + ++ rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_TCP; + if (item->spec) { + tcp_spec = +- (const struct rte_flow_item_tcp *) +- item->spec; +- rule->hinic_fdir.src_port = +- tcp_spec->hdr.src_port; +- rule->hinic_fdir.dst_port = +- tcp_spec->hdr.dst_port; ++ (const struct rte_flow_item_tcp *)item->spec; ++ rule->hinic_fdir.tunnel_inner_src_port = ++ tcp_spec->hdr.src_port; ++ rule->hinic_fdir.tunnel_inner_dst_port = ++ tcp_spec->hdr.dst_port; + } +- + } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { + /* + * Only care about src & dst ports, +@@ -990,7 +1237,7 @@ static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, + memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, +- item, "Not supported by fdir filter,support src,dst ports"); ++ item, "Not supported by fdir filter, support src, dst ports"); + return -rte_errno; + } + +@@ -1000,60 +1247,55 @@ static int hinic_normal_item_check_l4(const struct rte_flow_item **in_out_item, + memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, +- item, "Not supported by fdir filter,support udp"); ++ item, "Not supported by fdir filter, support udp"); + return -rte_errno; + } +- rule->mask.src_port_mask = udp_mask->hdr.src_port; +- rule->mask.dst_port_mask = udp_mask->hdr.dst_port; + ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.tunnel_flag = UINT16_MAX; ++ rule->mask.tunnel_inner_src_port_mask = ++ udp_mask->hdr.src_port; ++ rule->mask.tunnel_inner_dst_port_mask = ++ udp_mask->hdr.dst_port; ++ rule->mask.proto_mask = UINT16_MAX; ++ ++ rule->hinic_fdir.proto = IP_HEADER_PROTOCOL_TYPE_UDP; + if (item->spec) { + udp_spec = +- (const struct rte_flow_item_udp *) +- item->spec; +- rule->hinic_fdir.src_port = +- udp_spec->hdr.src_port; +- rule->hinic_fdir.dst_port = +- udp_spec->hdr.dst_port; ++ (const struct rte_flow_item_udp *)item->spec; ++ rule->hinic_fdir.tunnel_inner_src_port = ++ udp_spec->hdr.src_port; ++ rule->hinic_fdir.tunnel_inner_dst_port = ++ udp_spec->hdr.dst_port; + } ++ } else if (item->type == RTE_FLOW_ITEM_TYPE_ANY) { ++ rule->mode = HINIC_FDIR_MODE_TCAM; ++ rule->mask.tunnel_flag = UINT16_MAX; + } else { + memset(rule, 0, sizeof(struct hinic_fdir_rule)); + rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, +- item, "Not supported by fdir filter,support tcp/udp"); ++ item, "Not supported by fdir filter, support tcp/udp"); + return -rte_errno; + } + +- /* Get next no void item */ ++ /* get next no void item */ + *in_out_item = next_no_void_pattern(pattern, item); + } + + return 0; + } + +-static int hinic_normal_item_check_end(const struct rte_flow_item *item, +- struct hinic_fdir_rule *rule, +- struct rte_flow_error *error) +-{ +- /* Check if the next not void item is END */ +- if (item->type != RTE_FLOW_ITEM_TYPE_END) { +- memset(rule, 0, sizeof(struct hinic_fdir_rule)); +- rte_flow_error_set(error, EINVAL, +- RTE_FLOW_ERROR_TYPE_ITEM, +- item, "Not supported by fdir filter,support end"); +- return -rte_errno; +- } +- +- return 0; +-} +- +-static int hinic_check_normal_item_ele(const struct rte_flow_item *item, ++static int hinic_check_tcam_tunnel_item_ele(const struct rte_flow_item *item, + const struct rte_flow_item pattern[], + struct hinic_fdir_rule *rule, + struct rte_flow_error *error) + { + if (hinic_normal_item_check_ether(&item, pattern, error) || + hinic_normal_item_check_ip(&item, pattern, rule, error) || +- hinic_normal_item_check_l4(&item, pattern, rule, error) || ++ hinic_tunnel_item_check_l4(&item, pattern, rule, error) || ++ hinic_tunnel_item_check_vxlan(&item, pattern, rule, error) || ++ hinic_tunnel_inner_item_check_l4(&item, pattern, rule, error) || + hinic_normal_item_check_end(item, rule, error)) + return -rte_errno; + +@@ -1172,8 +1414,107 @@ hinic_parse_fdir_filter_normal(const struct rte_flow_attr *attr, + return 0; + } + ++/** ++ * Parse the rule to see if it is a IP or MAC VLAN flow director rule. ++ * And get the flow director filter info BTW. ++ * UDP/TCP/SCTP PATTERN: ++ * The first not void item can be ETH or IPV4 or IPV6 ++ * The second not void item must be IPV4 or IPV6 if the first one is ETH. ++ * The next not void item can be ANY/TCP/UDP ++ * ACTION: ++ * The first not void action should be QUEUE. ++ * The second not void optional action should be MARK, ++ * mark_id is a uint32_t number. ++ * The next not void action should be END. ++ * UDP/TCP pattern example: ++ * ITEM Spec Mask ++ * ETH NULL NULL ++ * IPV4 src_addr 1.2.3.6 0xFFFFFFFF ++ * dst_addr 1.2.3.5 0xFFFFFFFF ++ * UDP/TCP src_port 80 0xFFFF ++ * dst_port 80 0xFFFF ++ * END ++ * Other members in mask and spec should set to 0x00. ++ * Item->last should be NULL. ++ */ ++static int ++hinic_parse_fdir_filter_tcam_normal(const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = NULL; ++ ++ if (hinic_check_filter_arg(attr, pattern, actions, error)) ++ return -rte_errno; ++ ++ if (hinic_check_tcam_normal_item_ele(item, pattern, rule, error)) ++ return -rte_errno; ++ ++ if (hinic_check_normal_attr_ele(attr, rule, error)) ++ return -rte_errno; ++ ++ if (hinic_check_normal_act_ele(item, actions, rule, error)) ++ return -rte_errno; ++ ++ return 0; ++} ++ ++/** ++ * Parse the rule to see if it is a IP or MAC VLAN flow director rule. ++ * And get the flow director filter info BTW. ++ * UDP/TCP/SCTP PATTERN: ++ * The first not void item can be ETH or IPV4 or IPV6 ++ * The second not void item must be IPV4 or IPV6 if the first one is ETH. ++ * The next not void item must be UDP ++ * The next not void item must be VXLAN(optional) ++ * The first not void item can be ETH or IPV4 or IPV6 ++ * The next not void item could be ANY or UDP or TCP(optional) ++ * The next not void item must be END. ++ * ACTION: ++ * The first not void action should be QUEUE. ++ * The second not void optional action should be MARK, ++ * mark_id is a uint32_t number. ++ * The next not void action should be END. ++ * UDP/TCP pattern example: ++ * ITEM Spec Mask ++ * ETH NULL NULL ++ * IPV4 src_addr 1.2.3.6 0xFFFFFFFF ++ * dst_addr 1.2.3.5 0xFFFFFFFF ++ * UDP NULL NULL ++ * VXLAN NULL NULL ++ * UDP/TCP src_port 80 0xFFFF ++ * dst_port 80 0xFFFF ++ * END ++ * Other members in mask and spec should set to 0x00. ++ * Item->last should be NULL. ++ */ + static int +-hinic_parse_fdir_filter(struct rte_eth_dev *dev, ++hinic_parse_fdir_filter_tacm_tunnel(const struct rte_flow_attr *attr, ++ const struct rte_flow_item pattern[], ++ const struct rte_flow_action actions[], ++ struct hinic_fdir_rule *rule, ++ struct rte_flow_error *error) ++{ ++ const struct rte_flow_item *item = NULL; ++ ++ if (hinic_check_filter_arg(attr, pattern, actions, error)) ++ return -rte_errno; ++ ++ if (hinic_check_tcam_tunnel_item_ele(item, pattern, rule, error)) ++ return -rte_errno; ++ ++ if (hinic_check_normal_attr_ele(attr, rule, error)) ++ return -rte_errno; ++ ++ if (hinic_check_normal_act_ele(item, actions, rule, error)) ++ return -rte_errno; ++ ++ return 0; ++} ++ ++static int hinic_parse_fdir_filter(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[], +@@ -1182,11 +1523,22 @@ hinic_parse_fdir_filter(struct rte_eth_dev *dev, + { + int ret; + +- ret = hinic_parse_fdir_filter_normal(attr, pattern, +- actions, rule, error); ++ ret = hinic_parse_fdir_filter_normal(attr, pattern, actions, ++ rule, error); ++ if (!ret) ++ goto step_next; ++ ++ ret = hinic_parse_fdir_filter_tcam_normal(attr, pattern, actions, ++ rule, error); ++ if (!ret) ++ goto step_next; ++ ++ ret = hinic_parse_fdir_filter_tacm_tunnel(attr, pattern, actions, ++ rule, error); + if (ret) + return ret; + ++step_next: + if (rule->queue >= dev->data->nb_rx_queues) + return -ENOTSUP; + +@@ -1229,18 +1581,17 @@ static int hinic_flow_validate(struct rte_eth_dev *dev, + return ret; + } + +-static inline int +-ntuple_ip_filter(struct rte_eth_ntuple_filter *filter, +- struct hinic_5tuple_filter_info *filter_info) ++static inline int ntuple_ip_filter(struct rte_eth_ntuple_filter *filter, ++ struct hinic_5tuple_filter_info *hinic_filter_info) + { + switch (filter->dst_ip_mask) { + case UINT32_MAX: +- filter_info->dst_ip_mask = 0; +- filter_info->dst_ip = filter->dst_ip; ++ hinic_filter_info->dst_ip_mask = 0; ++ hinic_filter_info->dst_ip = filter->dst_ip; + break; + case 0: +- filter_info->dst_ip_mask = 1; +- filter_info->dst_ip = 0; ++ hinic_filter_info->dst_ip_mask = 1; ++ hinic_filter_info->dst_ip = 0; + break; + default: + PMD_DRV_LOG(ERR, "Invalid dst_ip mask."); +@@ -1249,12 +1600,12 @@ ntuple_ip_filter(struct rte_eth_ntuple_filter *filter, + + switch (filter->src_ip_mask) { + case UINT32_MAX: +- filter_info->src_ip_mask = 0; +- filter_info->src_ip = filter->src_ip; ++ hinic_filter_info->src_ip_mask = 0; ++ hinic_filter_info->src_ip = filter->src_ip; + break; + case 0: +- filter_info->src_ip_mask = 1; +- filter_info->src_ip = 0; ++ hinic_filter_info->src_ip_mask = 1; ++ hinic_filter_info->src_ip = 0; + break; + default: + PMD_DRV_LOG(ERR, "Invalid src_ip mask."); +@@ -1263,18 +1614,17 @@ ntuple_ip_filter(struct rte_eth_ntuple_filter *filter, + return 0; + } + +-static inline int +-ntuple_port_filter(struct rte_eth_ntuple_filter *filter, +- struct hinic_5tuple_filter_info *filter_info) ++static inline int ntuple_port_filter(struct rte_eth_ntuple_filter *filter, ++ struct hinic_5tuple_filter_info *hinic_filter_info) + { + switch (filter->dst_port_mask) { + case UINT16_MAX: +- filter_info->dst_port_mask = 0; +- filter_info->dst_port = filter->dst_port; ++ hinic_filter_info->dst_port_mask = 0; ++ hinic_filter_info->dst_port = filter->dst_port; + break; + case 0: +- filter_info->dst_port_mask = 1; +- filter_info->dst_port = 0; ++ hinic_filter_info->dst_port_mask = 1; ++ hinic_filter_info->dst_port = 0; + break; + default: + PMD_DRV_LOG(ERR, "Invalid dst_port mask."); +@@ -1283,12 +1633,12 @@ ntuple_port_filter(struct rte_eth_ntuple_filter *filter, + + switch (filter->src_port_mask) { + case UINT16_MAX: +- filter_info->src_port_mask = 0; +- filter_info->src_port = filter->src_port; ++ hinic_filter_info->src_port_mask = 0; ++ hinic_filter_info->src_port = filter->src_port; + break; + case 0: +- filter_info->src_port_mask = 1; +- filter_info->src_port = 0; ++ hinic_filter_info->src_port_mask = 1; ++ hinic_filter_info->src_port = 0; + break; + default: + PMD_DRV_LOG(ERR, "Invalid src_port mask."); +@@ -1298,18 +1648,17 @@ ntuple_port_filter(struct rte_eth_ntuple_filter *filter, + return 0; + } + +-static inline int +-ntuple_proto_filter(struct rte_eth_ntuple_filter *filter, +- struct hinic_5tuple_filter_info *filter_info) ++static inline int ntuple_proto_filter(struct rte_eth_ntuple_filter *filter, ++ struct hinic_5tuple_filter_info *hinic_filter_info) + { + switch (filter->proto_mask) { + case UINT8_MAX: +- filter_info->proto_mask = 0; +- filter_info->proto = filter->proto; ++ hinic_filter_info->proto_mask = 0; ++ hinic_filter_info->proto = filter->proto; + break; + case 0: +- filter_info->proto_mask = 1; +- filter_info->proto = 0; ++ hinic_filter_info->proto_mask = 1; ++ hinic_filter_info->proto = 0; + break; + default: + PMD_DRV_LOG(ERR, "Invalid protocol mask."); +@@ -1319,8 +1668,7 @@ ntuple_proto_filter(struct rte_eth_ntuple_filter *filter, + return 0; + } + +-static inline int +-ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, ++static inline int ntuple_filter_to_5tuple(struct rte_eth_ntuple_filter *filter, + struct hinic_5tuple_filter_info *filter_info) + { + if (filter->queue >= HINIC_MAX_RX_QUEUE_NUM || +@@ -1468,30 +1816,20 @@ static int hinic_set_vrrp_tcam(struct hinic_nic_dev *nic_dev) + */ + void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev) + { +- struct hinic_filter_info *filter_info = +- HINIC_DEV_PRIVATE_TO_FILTER_INFO(nic_dev); ++ (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); + +- if (filter_info->type_mask & +- (1 << HINIC_PKT_TYPE_FIND_ID(PKT_BGPD_DPORT_TYPE))) +- hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_DPORT); ++ (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_DPORT); + +- if (filter_info->type_mask & +- (1 << HINIC_PKT_TYPE_FIND_ID(PKT_BGPD_SPORT_TYPE))) +- hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT); ++ (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT); + +- if (filter_info->type_mask & +- (1 << HINIC_PKT_TYPE_FIND_ID(PKT_VRRP_TYPE))) +- hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_VRRP); ++ (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_VRRP); + +- if (filter_info->type_mask & +- (1 << HINIC_PKT_TYPE_FIND_ID(PKT_LACP_TYPE))) +- hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_LACP); ++ (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_LACP); + +- hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); ++ (void)hinic_flush_tcam_rule(nic_dev->hwdev); + } + +-static int +-hinic_filter_info_init(struct hinic_5tuple_filter *filter, ++static int hinic_filter_info_init(struct hinic_5tuple_filter *filter, + struct hinic_filter_info *filter_info) + { + switch (filter->filter_info.proto) { +@@ -1544,10 +1882,8 @@ hinic_filter_info_init(struct hinic_5tuple_filter *filter, + return 0; + } + +-static int +-hinic_lookup_new_filter(struct hinic_5tuple_filter *filter, +- struct hinic_filter_info *filter_info, +- int *index) ++static int hinic_lookup_new_filter(struct hinic_5tuple_filter *filter, ++ struct hinic_filter_info *filter_info, int *index) + { + int type_id; + +@@ -1586,9 +1922,8 @@ hinic_lookup_new_filter(struct hinic_5tuple_filter *filter, + * - On success, zero. + * - On failure, a negative value. + */ +-static int +-hinic_add_5tuple_filter(struct rte_eth_dev *dev, +- struct hinic_5tuple_filter *filter) ++static int hinic_add_5tuple_filter(struct rte_eth_dev *dev, ++ struct hinic_5tuple_filter *filter) + { + struct hinic_filter_info *filter_info = + HINIC_DEV_PRIVATE_TO_FILTER_INFO(dev->data->dev_private); +@@ -1676,8 +2011,7 @@ hinic_add_5tuple_filter(struct rte_eth_dev *dev, + * @param filter + * The pointer of the filter will be removed. + */ +-static void +-hinic_remove_5tuple_filter(struct rte_eth_dev *dev, ++static void hinic_remove_5tuple_filter(struct rte_eth_dev *dev, + struct hinic_5tuple_filter *filter) + { + struct hinic_filter_info *filter_info = +@@ -1929,7 +2263,6 @@ hinic_add_del_ethertype_filter(struct rte_eth_dev *dev, + default: + break; + } +- + } else { + ethertype_filter.pkt_proto = filter->ether_type; + i = hinic_ethertype_filter_lookup(filter_info, +@@ -1972,9 +2305,8 @@ hinic_add_del_ethertype_filter(struct rte_eth_dev *dev, + return 0; + } + +-static int +-hinic_fdir_info_init(struct hinic_fdir_rule *rule, +- struct hinic_fdir_info *fdir_info) ++static int hinic_fdir_info_init(struct hinic_fdir_rule *rule, ++ struct hinic_fdir_info *fdir_info) + { + switch (rule->mask.src_ipv4_mask) { + case UINT32_MAX: +@@ -2014,10 +2346,8 @@ hinic_fdir_info_init(struct hinic_fdir_rule *rule, + return 0; + } + +-static inline int +-hinic_add_del_fdir_filter(struct rte_eth_dev *dev, +- struct hinic_fdir_rule *rule, +- bool add) ++static inline int hinic_add_del_fdir_filter(struct rte_eth_dev *dev, ++ struct hinic_fdir_rule *rule, bool add) + { + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); + struct hinic_fdir_info fdir_info; +@@ -2062,6 +2392,352 @@ hinic_add_del_fdir_filter(struct rte_eth_dev *dev, + return 0; + } + ++static void tcam_translate_key_y(u8 *key_y, u8 *src_input, u8 *mask, u8 len) ++{ ++ u8 idx; ++ ++ for (idx = 0; idx < len; idx++) ++ key_y[idx] = src_input[idx] & mask[idx]; ++} ++ ++static void tcam_translate_key_x(u8 *key_x, u8 *key_y, u8 *mask, u8 len) ++{ ++ u8 idx; ++ ++ for (idx = 0; idx < len; idx++) ++ key_x[idx] = key_y[idx] ^ mask[idx]; ++} ++ ++static void tcam_key_calculate(struct tag_tcam_key *tcam_key, ++ struct tag_tcam_cfg_rule *fdir_tcam_rule) ++{ ++ tcam_translate_key_y(fdir_tcam_rule->key.y, ++ (u8 *)(&tcam_key->key_info), ++ (u8 *)(&tcam_key->key_mask), ++ TCAM_FLOW_KEY_SIZE); ++ tcam_translate_key_x(fdir_tcam_rule->key.x, ++ fdir_tcam_rule->key.y, ++ (u8 *)(&tcam_key->key_mask), ++ TCAM_FLOW_KEY_SIZE); ++} ++ ++static int hinic_fdir_tcam_info_init(struct rte_eth_dev *dev, ++ struct hinic_fdir_rule *rule, ++ struct tag_tcam_key *tcam_key, ++ struct tag_tcam_cfg_rule *fdir_tcam_rule) ++{ ++ struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); ++ ++ switch (rule->mask.dst_ipv4_mask) { ++ case UINT32_MAX: ++ tcam_key->key_info.ext_dip_h = ++ (rule->hinic_fdir.dst_ip >> 16) & 0xffffU; ++ tcam_key->key_info.ext_dip_l = ++ rule->hinic_fdir.dst_ip & 0xffffU; ++ tcam_key->key_mask.ext_dip_h = ++ (rule->mask.dst_ipv4_mask >> 16) & 0xffffU; ++ tcam_key->key_mask.ext_dip_l = ++ rule->mask.dst_ipv4_mask & 0xffffU; ++ break; ++ ++ case 0: ++ break; ++ ++ default: ++ PMD_DRV_LOG(ERR, "invalid src_ip mask."); ++ return -EINVAL; ++ } ++ ++ if (rule->mask.dst_port_mask > 0) { ++ tcam_key->key_info.dst_port = rule->hinic_fdir.dst_port; ++ tcam_key->key_mask.dst_port = rule->mask.dst_port_mask; ++ } ++ ++ if (rule->mask.src_port_mask > 0) { ++ tcam_key->key_info.src_port = rule->hinic_fdir.src_port; ++ tcam_key->key_mask.src_port = rule->mask.src_port_mask; ++ } ++ ++ switch (rule->mask.tunnel_flag) { ++ case UINT16_MAX: ++ tcam_key->key_info.tunnel_flag = FDIR_TCAM_TUNNEL_PACKET; ++ tcam_key->key_mask.tunnel_flag = UINT8_MAX; ++ break; ++ ++ case 0: ++ tcam_key->key_info.tunnel_flag = FDIR_TCAM_NORMAL_PACKET; ++ tcam_key->key_mask.tunnel_flag = 0; ++ break; ++ ++ default: ++ PMD_DRV_LOG(ERR, "invalid tunnel flag mask."); ++ return -EINVAL; ++ } ++ ++ if (rule->mask.tunnel_inner_dst_port_mask > 0) { ++ tcam_key->key_info.dst_port = ++ rule->hinic_fdir.tunnel_inner_dst_port; ++ tcam_key->key_mask.dst_port = ++ rule->mask.tunnel_inner_dst_port_mask; ++ } ++ ++ if (rule->mask.tunnel_inner_src_port_mask > 0) { ++ tcam_key->key_info.src_port = ++ rule->hinic_fdir.tunnel_inner_src_port; ++ tcam_key->key_mask.src_port = ++ rule->mask.tunnel_inner_src_port_mask; ++ } ++ ++ switch (rule->mask.proto_mask) { ++ case UINT16_MAX: ++ tcam_key->key_info.protocol = rule->hinic_fdir.proto; ++ tcam_key->key_mask.protocol = UINT8_MAX; ++ break; ++ ++ case 0: ++ break; ++ ++ default: ++ PMD_DRV_LOG(ERR, "invalid tunnel flag mask."); ++ return -EINVAL; ++ } ++ ++ tcam_key->key_mask.function_id = UINT16_MAX; ++ ++ tcam_key->key_info.function_id = hinic_global_func_id(nic_dev->hwdev); ++ ++ fdir_tcam_rule->data.qid = rule->queue; ++ ++ tcam_key_calculate(tcam_key, fdir_tcam_rule); ++ ++ return 0; ++} ++ ++static inline struct hinic_tcam_filter * ++hinic_tcam_filter_lookup(struct hinic_tcam_filter_list *filter_list, ++ struct tag_tcam_key *key) ++{ ++ struct hinic_tcam_filter *it; ++ ++ TAILQ_FOREACH(it, filter_list, entries) { ++ if (memcmp(key, &it->tcam_key, ++ sizeof(struct tag_tcam_key)) == 0) { ++ return it; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int hinic_lookup_new_tcam_filter(struct rte_eth_dev *dev, ++ struct hinic_tcam_info *tcam_info, ++ struct hinic_tcam_filter *tcam_filter, ++ u16 *tcam_index) ++{ ++ int index; ++ int max_index; ++ struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); ++ ++ if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) ++ max_index = HINIC_VF_MAX_TCAM_FILTERS; ++ else ++ max_index = HINIC_PF_MAX_TCAM_FILTERS; ++ ++ for (index = 0; index < max_index; index++) { ++ if (tcam_info->tcam_index_array[index] == 0) ++ break; ++ } ++ ++ if (index == max_index) { ++ PMD_DRV_LOG(ERR, "function 0x%x tcam filters only support %d filter rules", ++ hinic_global_func_id(nic_dev->hwdev), max_index); ++ return -EINVAL; ++ } ++ ++ tcam_filter->index = index; ++ *tcam_index = index; ++ ++ return 0; ++} ++ ++static int hinic_add_tcam_filter(struct rte_eth_dev *dev, ++ struct hinic_tcam_filter *tcam_filter, ++ struct tag_tcam_cfg_rule *fdir_tcam_rule) ++{ ++ struct hinic_tcam_info *tcam_info = ++ HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); ++ struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); ++ u16 index = 0; ++ u16 tcam_block_index = 0; ++ int rc; ++ ++ if (hinic_lookup_new_tcam_filter(dev, tcam_info, tcam_filter, &index)) ++ return -EINVAL; ++ ++ if (tcam_info->tcam_rule_nums == 0) { ++ if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { ++ rc = hinic_alloc_tcam_block(nic_dev->hwdev, ++ HINIC_TCAM_BLOCK_TYPE_VF, &tcam_block_index); ++ if (rc != 0) { ++ PMD_DRV_LOG(ERR, "VF fdir filter tcam alloc block failed!"); ++ return -EFAULT; ++ } ++ } else { ++ rc = hinic_alloc_tcam_block(nic_dev->hwdev, ++ HINIC_TCAM_BLOCK_TYPE_PF, &tcam_block_index); ++ if (rc != 0) { ++ PMD_DRV_LOG(ERR, "PF fdir filter tcam alloc block failed!"); ++ return -EFAULT; ++ } ++ } ++ ++ tcam_info->tcam_block_index = tcam_block_index; ++ } else { ++ tcam_block_index = tcam_info->tcam_block_index; ++ } ++ ++ if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { ++ fdir_tcam_rule->index = ++ HINIC_PKT_VF_TCAM_INDEX_START(tcam_block_index) + index; ++ } else { ++ fdir_tcam_rule->index = ++ tcam_block_index * HINIC_PF_MAX_TCAM_FILTERS + index; ++ } ++ ++ rc = hinic_add_tcam_rule(nic_dev->hwdev, fdir_tcam_rule); ++ if (rc != 0) { ++ PMD_DRV_LOG(ERR, "Fdir_tcam_rule add failed!"); ++ return -EFAULT; ++ } ++ ++ PMD_DRV_LOG(INFO, "Add fdir_tcam_rule function_id: 0x%x," ++ "tcam_block_id: %d, index: %d, queue: %d, tcam_rule_nums: %d succeed", ++ hinic_global_func_id(nic_dev->hwdev), tcam_block_index, ++ fdir_tcam_rule->index, fdir_tcam_rule->data.qid, ++ tcam_info->tcam_rule_nums + 1); ++ ++ if (tcam_info->tcam_rule_nums == 0) { ++ rc = hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, true); ++ if (rc < 0) { ++ (void)hinic_del_tcam_rule(nic_dev->hwdev, ++ fdir_tcam_rule->index); ++ return rc; ++ } ++ } ++ ++ TAILQ_INSERT_TAIL(&tcam_info->tcam_list, tcam_filter, entries); ++ ++ tcam_info->tcam_index_array[index] = 1; ++ tcam_info->tcam_rule_nums++; ++ ++ return 0; ++} ++ ++static int hinic_del_tcam_filter(struct rte_eth_dev *dev, ++ struct hinic_tcam_filter *tcam_filter) ++{ ++ struct hinic_tcam_info *tcam_info = ++ HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); ++ struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); ++ u32 index = 0; ++ u16 tcam_block_index = tcam_info->tcam_block_index; ++ int rc; ++ u8 block_type = 0; ++ ++ if (hinic_func_type(nic_dev->hwdev) == TYPE_VF) { ++ index = HINIC_PKT_VF_TCAM_INDEX_START(tcam_block_index) + ++ tcam_filter->index; ++ block_type = HINIC_TCAM_BLOCK_TYPE_VF; ++ } else { ++ index = tcam_block_index * HINIC_PF_MAX_TCAM_FILTERS + ++ tcam_filter->index; ++ block_type = HINIC_TCAM_BLOCK_TYPE_PF; ++ } ++ ++ rc = hinic_del_tcam_rule(nic_dev->hwdev, index); ++ if (rc != 0) { ++ PMD_DRV_LOG(ERR, "fdir_tcam_rule del failed!"); ++ return -EFAULT; ++ } ++ ++ PMD_DRV_LOG(INFO, "Del fdir_tcam_rule function_id: 0x%x, " ++ "tcam_block_id: %d, index: %d, tcam_rule_nums: %d succeed", ++ hinic_global_func_id(nic_dev->hwdev), tcam_block_index, index, ++ tcam_info->tcam_rule_nums - 1); ++ ++ TAILQ_REMOVE(&tcam_info->tcam_list, tcam_filter, entries); ++ ++ tcam_info->tcam_index_array[tcam_filter->index] = 0; ++ ++ rte_free(tcam_filter); ++ ++ tcam_info->tcam_rule_nums--; ++ ++ if (tcam_info->tcam_rule_nums == 0) { ++ (void)hinic_free_tcam_block(nic_dev->hwdev, block_type, ++ &tcam_block_index); ++ } ++ ++ return 0; ++} ++ ++static int hinic_add_del_tcam_fdir_filter(struct rte_eth_dev *dev, ++ struct hinic_fdir_rule *rule, bool add) ++{ ++ struct hinic_tcam_info *tcam_info = ++ HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); ++ struct hinic_tcam_filter *tcam_filter; ++ struct tag_tcam_cfg_rule fdir_tcam_rule; ++ struct tag_tcam_key tcam_key; ++ int ret; ++ ++ memset(&fdir_tcam_rule, 0, sizeof(struct tag_tcam_cfg_rule)); ++ memset((void *)&tcam_key, 0, sizeof(struct tag_tcam_key)); ++ ++ ret = hinic_fdir_tcam_info_init(dev, rule, &tcam_key, &fdir_tcam_rule); ++ if (ret) { ++ PMD_DRV_LOG(ERR, "Init hiovs fdir info failed!"); ++ return ret; ++ } ++ ++ tcam_filter = hinic_tcam_filter_lookup(&tcam_info->tcam_list, ++ &tcam_key); ++ 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 (add) { ++ tcam_filter = rte_zmalloc("hiovs_5tuple_filter", ++ sizeof(struct hinic_tcam_filter), 0); ++ if (tcam_filter == NULL) ++ return -ENOMEM; ++ (void)rte_memcpy(&tcam_filter->tcam_key, ++ &tcam_key, sizeof(struct tag_tcam_key)); ++ tcam_filter->queue = fdir_tcam_rule.data.qid; ++ ++ ret = hinic_add_tcam_filter(dev, tcam_filter, &fdir_tcam_rule); ++ if (ret < 0) { ++ rte_free(tcam_filter); ++ return ret; ++ } ++ ++ rule->tcam_index = fdir_tcam_rule.index; ++ ++ } else { ++ PMD_DRV_LOG(ERR, "Begin to hiovs_del_tcam_filter"); ++ ret = hinic_del_tcam_filter(dev, tcam_filter); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ + /** + * Create or destroy a flow rule. + * Theorically one rule can match more than one filters. +@@ -2158,7 +2834,16 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + ret = hinic_parse_fdir_filter(dev, attr, pattern, + actions, &fdir_rule, error); + if (!ret) { +- ret = hinic_add_del_fdir_filter(dev, &fdir_rule, TRUE); ++ if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) { ++ ret = hinic_add_del_fdir_filter(dev, ++ &fdir_rule, TRUE); ++ } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) { ++ ret = hinic_add_del_tcam_fdir_filter(dev, ++ &fdir_rule, TRUE); ++ } else { ++ PMD_DRV_LOG(INFO, "flow fdir rule create failed, rule mode wrong"); ++ goto out; ++ } + if (!ret) { + fdir_rule_ptr = rte_zmalloc("hinic_fdir_rule", + sizeof(struct hinic_fdir_rule_ele), 0); +@@ -2187,9 +2872,8 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + } + + /* Destroy a flow rule on hinic. */ +-static int hinic_flow_destroy(struct rte_eth_dev *dev, +- struct rte_flow *flow, +- struct rte_flow_error *error) ++static int hinic_flow_destroy(struct rte_eth_dev *dev, struct rte_flow *flow, ++ struct rte_flow_error *error) + { + int ret; + struct rte_flow *pmd_flow = flow; +@@ -2235,7 +2919,15 @@ static int hinic_flow_destroy(struct rte_eth_dev *dev, + rte_memcpy(&fdir_rule, + &fdir_rule_ptr->filter_info, + sizeof(struct hinic_fdir_rule)); +- ret = hinic_add_del_fdir_filter(dev, &fdir_rule, FALSE); ++ if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) { ++ ret = hinic_add_del_fdir_filter(dev, &fdir_rule, FALSE); ++ } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) { ++ ret = hinic_add_del_tcam_fdir_filter(dev, &fdir_rule, ++ FALSE); ++ } else { ++ PMD_DRV_LOG(ERR, "FDIR Filter type is wrong!"); ++ ret = -EINVAL; ++ } + if (!ret) { + TAILQ_REMOVE(&nic_dev->filter_fdir_rule_list, + fdir_rule_ptr, entries); +@@ -2318,8 +3010,16 @@ static void hinic_clear_all_ethertype_filter(struct rte_eth_dev *dev) + static void hinic_clear_all_fdir_filter(struct rte_eth_dev *dev) + { + struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev); ++ struct hinic_tcam_info *tcam_info = ++ HINIC_DEV_PRIVATE_TO_TCAM_INFO(dev->data->dev_private); ++ struct hinic_tcam_filter *tcam_filter_ptr; ++ ++ while ((tcam_filter_ptr = TAILQ_FIRST(&tcam_info->tcam_list))) ++ (void)hinic_del_tcam_filter(dev, tcam_filter_ptr); + + (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); ++ ++ (void)hinic_flush_tcam_rule(nic_dev->hwdev); + } + + static void hinic_filterlist_flush(struct rte_eth_dev *dev) +@@ -2377,9 +3077,18 @@ static int hinic_flow_flush(struct rte_eth_dev *dev, + return 0; + } + ++void hinic_destroy_fdir_filter(struct rte_eth_dev *dev) ++{ ++ hinic_clear_all_ntuple_filter(dev); ++ hinic_clear_all_ethertype_filter(dev); ++ hinic_clear_all_fdir_filter(dev); ++ hinic_filterlist_flush(dev); ++} ++ + const struct rte_flow_ops hinic_flow_ops = { + .validate = hinic_flow_validate, + .create = hinic_flow_create, + .destroy = hinic_flow_destroy, + .flush = hinic_flow_flush, + }; ++ +-- +2.23.0 + diff --git a/backport-0002-net-hinic-add-TCAM-filter-switch-for-flow-director.patch b/backport-0002-net-hinic-add-TCAM-filter-switch-for-flow-director.patch new file mode 100644 index 0000000..7bb8fcb --- /dev/null +++ b/backport-0002-net-hinic-add-TCAM-filter-switch-for-flow-director.patch @@ -0,0 +1,150 @@ +From 0023e525a52cd5c9463332c5f5b9e95a4c07d938 Mon Sep 17 00:00:00 2001 +From: Xiaoyun Wang +Date: Sat, 27 Jun 2020 11:55:47 +0800 +Subject: [PATCH] net/hinic: add TCAM filter switch for flow director + +When the filter rule needs to use the TCAM method, driver +enables the TCAM filter switch, otherwise disables it, which +can improve the performance of microcode in FDIR scenarios that +does not use TCAM method. + +Fixes: 1fe89aa37f36 ("net/hinic: add flow director filter") +Cc: stable@dpdk.org + +Signed-off-by: Xiaoyun Wang +--- + drivers/net/hinic/base/hinic_pmd_cmd.h | 1 + + drivers/net/hinic/base/hinic_pmd_niccfg.c | 41 +++++++++++++++++++++++ + drivers/net/hinic/base/hinic_pmd_niccfg.h | 11 ++++++ + drivers/net/hinic/hinic_pmd_flow.c | 13 +++++++ + 4 files changed, 66 insertions(+) + +diff --git a/drivers/net/hinic/base/hinic_pmd_cmd.h b/drivers/net/hinic/base/hinic_pmd_cmd.h +index 09918a76fa..9ecb712334 100644 +--- a/drivers/net/hinic/base/hinic_pmd_cmd.h ++++ b/drivers/net/hinic/base/hinic_pmd_cmd.h +@@ -120,6 +120,7 @@ enum hinic_port_cmd { + HINIC_PORT_CMD_UP_TC_GET_FLOW = 0xb1, + HINIC_PORT_CMD_UP_TC_FLUSH_TCAM = 0xb2, + HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK = 0xb3, ++ HINIC_PORT_CMD_UP_TC_ENABLE = 0xb4, + + HINIC_PORT_CMD_SET_IPSU_MAC = 0xcb, + HINIC_PORT_CMD_GET_IPSU_MAC = 0xcc, +diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c +index e894503d73..67f6bc4070 100644 +--- a/drivers/net/hinic/base/hinic_pmd_niccfg.c ++++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c +@@ -2114,3 +2114,44 @@ int hinic_flush_tcam_rule(void *hwdev) + return err; + } + ++int hinic_set_fdir_tcam_rule_filter(void *hwdev, bool enable) ++{ ++ struct hinic_port_tcam_info port_tcam_cmd; ++ u16 out_size = sizeof(port_tcam_cmd); ++ int err; ++ ++ if (!hwdev) ++ return -EINVAL; ++ ++ memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); ++ port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; ++ port_tcam_cmd.func_id = hinic_global_func_id(hwdev); ++ port_tcam_cmd.tcam_enable = (u8)enable; ++ ++ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ENABLE, ++ &port_tcam_cmd, sizeof(port_tcam_cmd), ++ &port_tcam_cmd, &out_size); ++ if ((port_tcam_cmd.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED && ++ port_tcam_cmd.mgmt_msg_head.status) || err || !out_size) { ++ if (err == HINIC_MBOX_VF_CMD_ERROR && ++ HINIC_IS_VF((struct hinic_hwdev *)hwdev)) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(WARNING, "VF doesn't support setting fdir tcam filter"); ++ return err; ++ } ++ PMD_DRV_LOG(ERR, "Set fdir tcam filter failed, err: %d, " ++ "status: 0x%x, out size: 0x%x, enable: 0x%x", ++ err, port_tcam_cmd.mgmt_msg_head.status, out_size, ++ enable); ++ return -EFAULT; ++ } ++ ++ if (port_tcam_cmd.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) { ++ err = HINIC_MGMT_CMD_UNSUPPORTED; ++ PMD_DRV_LOG(WARNING, "Fw doesn't support setting fdir tcam filter"); ++ } ++ ++ return err; ++} ++ ++ +diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.h b/drivers/net/hinic/base/hinic_pmd_niccfg.h +index 846b5973ec..73b16b4d69 100644 +--- a/drivers/net/hinic/base/hinic_pmd_niccfg.h ++++ b/drivers/net/hinic/base/hinic_pmd_niccfg.h +@@ -766,6 +766,15 @@ struct hinic_port_qfilter_info { + u32 key; + }; + ++struct hinic_port_tcam_info { ++ struct hinic_mgmt_msg_head mgmt_msg_head; ++ ++ u16 func_id; ++ u8 tcam_enable; ++ u8 rsvd1; ++ u32 rsvd2; ++}; ++ + #define HINIC_MAX_TCAM_RULES_NUM (10240) + #define HINIC_TCAM_BLOCK_ENABLE 1 + #define HINIC_TCAM_BLOCK_DISABLE 0 +@@ -941,4 +950,6 @@ int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index); + + int hinic_flush_tcam_rule(void *hwdev); + ++int hinic_set_fdir_tcam_rule_filter(void *hwdev, bool enable); ++ + #endif /* _HINIC_PMD_NICCFG_H_ */ +diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c +index cc0744da2d..a7bad570bb 100644 +--- a/drivers/net/hinic/hinic_pmd_flow.c ++++ b/drivers/net/hinic/hinic_pmd_flow.c +@@ -1900,6 +1900,8 @@ void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev) + { + (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); + ++ (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); ++ + (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_DPORT); + + (void)hinic_clear_fdir_tcam(nic_dev->hwdev, TCAM_PKT_BGP_SPORT); +@@ -2801,6 +2803,15 @@ static int hinic_add_tcam_filter(struct rte_eth_dev *dev, + fdir_tcam_rule->index); + return rc; + } ++ ++ rc = hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true); ++ if (rc && rc != HINIC_MGMT_CMD_UNSUPPORTED) { ++ (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, ++ false); ++ (void)hinic_del_tcam_rule(nic_dev->hwdev, ++ fdir_tcam_rule->index); ++ return rc; ++ } + } + + TAILQ_INSERT_TAIL(&tcam_info->tcam_list, tcam_filter, entries); +@@ -3197,6 +3208,8 @@ static void hinic_clear_all_fdir_filter(struct rte_eth_dev *dev) + + (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, false); + ++ (void)hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, false); ++ + (void)hinic_flush_tcam_rule(nic_dev->hwdev); + } + +-- +2.23.0 + diff --git a/backport-0003-net-hinic-check-memory-allocations-in-flow-creation.patch b/backport-0003-net-hinic-check-memory-allocations-in-flow-creation.patch new file mode 100644 index 0000000..700902d --- /dev/null +++ b/backport-0003-net-hinic-check-memory-allocations-in-flow-creation.patch @@ -0,0 +1,57 @@ +From d7964ce192e79507d3b32b4a02e6293a40eb4708 Mon Sep 17 00:00:00 2001 +From: Yunjian Wang +Date: Tue, 28 Jul 2020 20:34:46 +0800 +Subject: [PATCH] net/hinic: check memory allocations in flow creation + +The function rte_zmalloc() could return NULL, the return +value need to be checked. + +Fixes: f4ca3fd54c4d ("net/hinic: create and destroy flow director filter") +Cc: stable@dpdk.org + +Signed-off-by: Yunjian Wang +Reviewed-by: Ferruh Yigit +--- + drivers/net/hinic/hinic_pmd_flow.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c +index a7bad570bb..503a32fff0 100644 +--- a/drivers/net/hinic/hinic_pmd_flow.c ++++ b/drivers/net/hinic/hinic_pmd_flow.c +@@ -2977,6 +2977,10 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + if (!ret) { + ntuple_filter_ptr = rte_zmalloc("hinic_ntuple_filter", + sizeof(struct hinic_ntuple_filter_ele), 0); ++ if (ntuple_filter_ptr == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate ntuple_filter_ptr"); ++ goto out; ++ } + rte_memcpy(&ntuple_filter_ptr->filter_info, + &ntuple_filter, + sizeof(struct rte_eth_ntuple_filter)); +@@ -3003,6 +3007,10 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + ethertype_filter_ptr = + rte_zmalloc("hinic_ethertype_filter", + sizeof(struct hinic_ethertype_filter_ele), 0); ++ if (ethertype_filter_ptr == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate ethertype_filter_ptr"); ++ goto out; ++ } + rte_memcpy(ðertype_filter_ptr->filter_info, + ðertype_filter, + sizeof(struct rte_eth_ethertype_filter)); +@@ -3036,6 +3044,10 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + if (!ret) { + fdir_rule_ptr = rte_zmalloc("hinic_fdir_rule", + sizeof(struct hinic_fdir_rule_ele), 0); ++ if (fdir_rule_ptr == NULL) { ++ PMD_DRV_LOG(ERR, "Failed to allocate fdir_rule_ptr"); ++ goto out; ++ } + rte_memcpy(&fdir_rule_ptr->filter_info, &fdir_rule, + sizeof(struct hinic_fdir_rule)); + TAILQ_INSERT_TAIL(&nic_dev->filter_fdir_rule_list, +-- +2.23.0 + diff --git a/backport-0004-net-hinic-fix-filters-on-memory-allocation-failure.patch b/backport-0004-net-hinic-fix-filters-on-memory-allocation-failure.patch new file mode 100644 index 0000000..74f005f --- /dev/null +++ b/backport-0004-net-hinic-fix-filters-on-memory-allocation-failure.patch @@ -0,0 +1,79 @@ +From 0c87a15f5f1ccb9eefb6231aea9d095686f2def4 Mon Sep 17 00:00:00 2001 +From: Xiaoyun Wang +Date: Mon, 14 Sep 2020 22:31:42 +0800 +Subject: [PATCH] net/hinic: fix filters on memory allocation failure + +If rte_zmalloc failed, pmd driver should also delete the ntuple +filter or ethertype filter or normal and tcam filter that already +added before. + +Fixes: d7964ce192e7 ("net/hinic: check memory allocations in flow creation") +Cc: stable@dpdk.org + +Signed-off-by: Xiaoyun Wang +--- + drivers/net/hinic/hinic_pmd_flow.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c +index 70fd4450c2..9888a8793b 100644 +--- a/drivers/net/hinic/hinic_pmd_flow.c ++++ b/drivers/net/hinic/hinic_pmd_flow.c +@@ -694,6 +694,7 @@ static int hinic_ntuple_item_check_end(const struct rte_flow_item *item, + item, "Not supported by ntuple filter"); + return -rte_errno; + } ++ + return 0; + } + +@@ -2981,6 +2982,8 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + sizeof(struct hinic_ntuple_filter_ele), 0); + if (ntuple_filter_ptr == NULL) { + PMD_DRV_LOG(ERR, "Failed to allocate ntuple_filter_ptr"); ++ (void)hinic_add_del_ntuple_filter(dev, ++ &ntuple_filter, FALSE); + goto out; + } + rte_memcpy(&ntuple_filter_ptr->filter_info, +@@ -3011,6 +3014,8 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + sizeof(struct hinic_ethertype_filter_ele), 0); + if (ethertype_filter_ptr == NULL) { + PMD_DRV_LOG(ERR, "Failed to allocate ethertype_filter_ptr"); ++ (void)hinic_add_del_ethertype_filter(dev, ++ ðertype_filter, FALSE); + goto out; + } + rte_memcpy(ðertype_filter_ptr->filter_info, +@@ -3034,11 +3039,10 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + actions, &fdir_rule, error); + if (!ret) { + if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) { +- ret = hinic_add_del_fdir_filter(dev, +- &fdir_rule, TRUE); ++ ret = hinic_add_del_fdir_filter(dev, &fdir_rule, TRUE); + } else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) { +- ret = hinic_add_del_tcam_fdir_filter(dev, +- &fdir_rule, TRUE); ++ ret = hinic_add_del_tcam_fdir_filter(dev, &fdir_rule, ++ TRUE); + } else { + PMD_DRV_LOG(INFO, "flow fdir rule create failed, rule mode wrong"); + goto out; +@@ -3048,6 +3052,13 @@ static struct rte_flow *hinic_flow_create(struct rte_eth_dev *dev, + sizeof(struct hinic_fdir_rule_ele), 0); + if (fdir_rule_ptr == NULL) { + PMD_DRV_LOG(ERR, "Failed to allocate fdir_rule_ptr"); ++ if (fdir_rule.mode == HINIC_FDIR_MODE_NORMAL) ++ hinic_add_del_fdir_filter(dev, ++ &fdir_rule, FALSE); ++ else if (fdir_rule.mode == HINIC_FDIR_MODE_TCAM) ++ hinic_add_del_tcam_fdir_filter(dev, ++ &fdir_rule, FALSE); ++ + goto out; + } + rte_memcpy(&fdir_rule_ptr->filter_info, &fdir_rule, +-- +2.23.0 + diff --git a/backport-0005-net-hinic-fix-TCAM-filter-set.patch b/backport-0005-net-hinic-fix-TCAM-filter-set.patch new file mode 100644 index 0000000..d251652 --- /dev/null +++ b/backport-0005-net-hinic-fix-TCAM-filter-set.patch @@ -0,0 +1,40 @@ +From 19cc028345f3c2318fad89db34eec276a0af4dd2 Mon Sep 17 00:00:00 2001 +From: Xiaoyun Wang +Date: Mon, 14 Sep 2020 22:31:43 +0800 +Subject: [PATCH] net/hinic: fix TCAM filter set + +hinic supports two methods: linear table and tcam table, +if tcam filter enables failed but linear table is ok, +which also needs to enable filter, so for this scene, +driver should not close fdir switch. + +Fixes: f4ca3fd54c4d ("net/hinic: create and destroy flow director filter") +Cc: stable@dpdk.org + +Signed-off-by: Xiaoyun Wang +--- + drivers/net/hinic/hinic_pmd_flow.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hinic/hinic_pmd_flow.c b/drivers/net/hinic/hinic_pmd_flow.c +index 9888a8793b..d71a42afbd 100644 +--- a/drivers/net/hinic/hinic_pmd_flow.c ++++ b/drivers/net/hinic/hinic_pmd_flow.c +@@ -2809,8 +2809,12 @@ static int hinic_add_tcam_filter(struct rte_eth_dev *dev, + + rc = hinic_set_fdir_tcam_rule_filter(nic_dev->hwdev, true); + if (rc && rc != HINIC_MGMT_CMD_UNSUPPORTED) { +- (void)hinic_set_fdir_filter(nic_dev->hwdev, 0, 0, 0, +- false); ++ /* ++ * hinic supports two methods: linear table and tcam ++ * table, if tcam filter enables failed but linear table ++ * is ok, which also needs to enable filter, so for this ++ * scene, driver should not close fdir switch. ++ */ + (void)hinic_del_tcam_rule(nic_dev->hwdev, + fdir_tcam_rule->index); + return rc; +-- +2.23.0 + diff --git a/dpdk.spec b/dpdk.spec index 8dfd5ac..be72e72 100644 --- a/dpdk.spec +++ b/dpdk.spec @@ -1,6 +1,6 @@ Name: dpdk Version: 19.11 -Release: 25 +Release: 26 Packager: packaging@6wind.com URL: http://dpdk.org %global source_version 19.11 @@ -54,6 +54,11 @@ Patch6005: backport-gro-trim-tail-padding-bytes.patch Patch6006: backport-gro-check-payload-length-after-trim.patch Patch6007: backport-net-hinic-fix-crash-in-secondary-process.patch Patch6008: fix-virtio-hardthrough-scenes-device-init-bug.patch +Patch6009: backport-0001-net-hinic-add-flow-director-filter.patch +Patch6010: backport-0002-net-hinic-add-TCAM-filter-switch-for-flow-director.patch +Patch6011: backport-0003-net-hinic-check-memory-allocations-in-flow-creation.patch +Patch6012: backport-0004-net-hinic-fix-filters-on-memory-allocation-failure.patch +Patch6013: backport-0005-net-hinic-fix-TCAM-filter-set.patch Summary: Data Plane Development Kit core Group: System Environment/Libraries @@ -223,6 +228,9 @@ strip -g $RPM_BUILD_ROOT/lib/modules/${namer}/extra/dpdk/rte_kni.ko /usr/sbin/depmod %changelog +* Thu Mar 09 2023 jiangheng - 19.11-26 +- sync patches to enable hinic flow director + * Sat Dec 3 2022 wangzongchao - 19.11-25 - fix the virtio hardthrough scenes device init bug -- Gitee