DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control
@ 2020-03-17 15:01 Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 1/7] net/hinic: fix LRO problems Xiaoyun wang
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

This patch fixes LRO and hotupdate firmware problems,
optimize doorbell area initialization without const macro
definition, Optimize log files, support pause flow control
and inner vxlan or non vxlan dport filter type.

--
v1->v2:
  - Fix LRO problems
  - Fix hotupdate firmware problem
  - Optimize doorbell area initialization 
  - Remove 40GE Mezz card id
  - Add Fdir filter type
  - Optimize log files
  - Support pause flow control

v1:
  - Allocate IO memory with socketid

Xiaoyun wang (7):
  net/hinic: fix LRO problems
  net/hinic/base: fix hotupdate firmware problem
  net/hinic/base: optimize doorbell area initialization
  net/hinic: remove 40GE Mezz card id
  net/hinic: Add Fdir filter type
  net/hinic/base: Optimize log files
  net/hinic/base: Support Pause flow control

 drivers/net/hinic/base/hinic_pmd_cmd.h    |   6 +
 drivers/net/hinic/base/hinic_pmd_cmdq.c   |   4 +
 drivers/net/hinic/base/hinic_pmd_cmdq.h   |   1 +
 drivers/net/hinic/base/hinic_pmd_hwif.c   |  23 +-
 drivers/net/hinic/base/hinic_pmd_hwif.h   |   1 +
 drivers/net/hinic/base/hinic_pmd_mbox.c   |   3 +-
 drivers/net/hinic/base/hinic_pmd_mgmt.c   |   9 +-
 drivers/net/hinic/base/hinic_pmd_niccfg.c | 233 +++++++-
 drivers/net/hinic/base/hinic_pmd_niccfg.h |  83 +++
 drivers/net/hinic/base/hinic_pmd_nicio.c  |  26 +-
 drivers/net/hinic/hinic_pmd_ethdev.c      | 145 +++--
 drivers/net/hinic/hinic_pmd_ethdev.h      | 113 +++-
 drivers/net/hinic/hinic_pmd_flow.c        | 961 ++++++++++++++++++++++++++----
 drivers/net/hinic/hinic_pmd_rx.c          |  42 +-
 drivers/net/hinic/hinic_pmd_tx.c          |   1 +
 15 files changed, 1433 insertions(+), 218 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 1/7] net/hinic: fix LRO problems
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 2/7] net/hinic/base: fix hotupdate firmware problem Xiaoyun wang
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

Pmd driver should change the max_lro_pkt_size parameter into lro_wqe_num
that used for hardware, and when packets are coalesced by hardware,
PKT_RX_LRO flag should be set in the RX mbuf.

Fixes: 9d4878ef0897 ("net/hinic: support LRO offload")
Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/hinic_pmd_ethdev.c | 17 ++-------------
 drivers/net/hinic/hinic_pmd_rx.c     | 42 +++++++++++++++++++++++++++++++++++-
 2 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c
index 8493f6e..b81ecd0 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -736,6 +736,7 @@ static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa)
 	info->max_mac_addrs  = HINIC_MAX_UC_MAC_ADDRS;
 	info->min_mtu = HINIC_MIN_MTU_SIZE;
 	info->max_mtu = HINIC_MAX_MTU_SIZE;
+	info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE;
 
 	hinic_get_speed_capa(dev, &info->speed_capa);
 	info->rx_queue_offload_capa = 0;
@@ -811,12 +812,10 @@ static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl)
 	return 0;
 }
 
-
 static int hinic_rxtx_configure(struct rte_eth_dev *dev)
 {
-	int err;
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
-	bool lro_en;
+	int err;
 
 	/* rx configure, if rss enable, need to init default configuration */
 	err = hinic_rx_configure(dev);
@@ -833,18 +832,6 @@ static int hinic_rxtx_configure(struct rte_eth_dev *dev)
 		goto set_rx_mode_fail;
 	}
 
-	/* config lro */
-	lro_en = dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_TCP_LRO ?
-			true : false;
-
-	err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en,
-				HINIC_LRO_WQE_NUM_DEFAULT);
-	if (err) {
-		PMD_DRV_LOG(ERR, "%s lro failed, err: %d",
-			lro_en ? "Enable" : "Disable", err);
-		goto set_rx_mode_fail;
-	}
-
 	return HINIC_OK;
 
 set_rx_mode_fail:
diff --git a/drivers/net/hinic/hinic_pmd_rx.c b/drivers/net/hinic/hinic_pmd_rx.c
index f1b873a..224337d 100644
--- a/drivers/net/hinic/hinic_pmd_rx.c
+++ b/drivers/net/hinic/hinic_pmd_rx.c
@@ -656,6 +656,10 @@ int hinic_rx_configure(struct rte_eth_dev *dev)
 	struct rte_eth_rss_conf rss_conf =
 		dev->data->dev_conf.rx_adv_conf.rss_conf;
 	int err;
+	bool lro_en;
+	int max_lro_size;
+	int lro_wqe_num;
+	int buf_size;
 
 	if (nic_dev->flags & ETH_MQ_RX_RSS_FLAG) {
 		if (rss_conf.rss_hf == 0) {
@@ -681,15 +685,42 @@ int hinic_rx_configure(struct rte_eth_dev *dev)
 	if (err)
 		goto rx_csum_ofl_err;
 
+	/* config lro */
+	lro_en = dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_TCP_LRO ?
+			true : false;
+	max_lro_size = dev->data->dev_conf.rxmode.max_lro_pkt_size;
+	buf_size = nic_dev->hwdev->nic_io->rq_buf_size;
+	lro_wqe_num = max_lro_size / buf_size ? (max_lro_size / buf_size) : 1;
+
+	err = hinic_set_rx_lro(nic_dev->hwdev, lro_en, lro_en, lro_wqe_num);
+	if (err) {
+		PMD_DRV_LOG(ERR, "%s %s lro failed, err: %d, max_lro_size: %d",
+				dev->data->name, lro_en ? "Enable" : "Disable",
+				err, max_lro_size);
+		goto set_rx_lro_err;
+	}
+
 	return 0;
 
+set_rx_lro_err:
 rx_csum_ofl_err:
 rss_config_err:
+
 	hinic_destroy_num_qps(nic_dev);
 
 	return HINIC_ERROR;
 }
 
+static void hinic_rx_remove_lro(struct hinic_nic_dev *nic_dev)
+{
+	int err;
+
+	err = hinic_set_rx_lro(nic_dev->hwdev, false, false, 0);
+	if (err)
+		PMD_DRV_LOG(ERR, "%s disable LRO failed",
+			    nic_dev->proc_dev_name);
+}
+
 void hinic_rx_remove_configure(struct rte_eth_dev *dev)
 {
 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
@@ -698,6 +729,8 @@ void hinic_rx_remove_configure(struct rte_eth_dev *dev)
 		hinic_rss_deinit(nic_dev);
 		hinic_destroy_num_qps(nic_dev);
 	}
+
+	hinic_rx_remove_lro(nic_dev);
 }
 
 void hinic_free_all_rx_mbufs(struct hinic_rxq *rxq)
@@ -956,7 +989,7 @@ u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
 	volatile struct hinic_rq_cqe *rx_cqe;
 	u16 rx_buf_len, pkts = 0;
 	u16 sw_ci, ci_mask, wqebb_cnt = 0;
-	u32 pkt_len, status, vlan_len;
+	u32 pkt_len, status, vlan_len, lro_num;
 	u64 rx_bytes = 0;
 	struct hinic_rq_cqe cqe;
 	u32 offload_type, rss_hash;
@@ -1024,6 +1057,13 @@ u16 hinic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, u16 nb_pkts)
 		rxm->ol_flags |= hinic_rx_rss_hash(offload_type, rss_hash,
 						   &rxm->hash.rss);
 
+		/* lro offload */
+		lro_num = HINIC_GET_RX_NUM_LRO(cqe.status);
+		if (unlikely(lro_num != 0)) {
+			rxm->ol_flags |= PKT_RX_LRO;
+			rxm->tso_segsz = pkt_len / lro_num;
+		}
+
 		/* 6. clear done bit */
 		rx_cqe->status = 0;
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 2/7] net/hinic/base: fix hotupdate firmware problem
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 1/7] net/hinic: fix LRO problems Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 3/7] net/hinic/base: optimize doorbell area initialization Xiaoyun wang
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

When repeatedly hotupdate firmware and start/stop port at the same time,
port start may be failed when cmdq reinit failed at the fw active phase,
so if deteted status of cmdq is fail, then reinit the cmdq when port start.

Fixes: d9ce1917941c ("net/hinic/base: add hardware operation")
Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/base/hinic_pmd_cmdq.c  | 4 ++++
 drivers/net/hinic/base/hinic_pmd_cmdq.h  | 1 +
 drivers/net/hinic/base/hinic_pmd_nicio.c | 9 +++++++++
 3 files changed, 14 insertions(+)

diff --git a/drivers/net/hinic/base/hinic_pmd_cmdq.c b/drivers/net/hinic/base/hinic_pmd_cmdq.c
index d73e2bf..685498e 100644
--- a/drivers/net/hinic/base/hinic_pmd_cmdq.c
+++ b/drivers/net/hinic/base/hinic_pmd_cmdq.c
@@ -7,6 +7,7 @@
 #include "hinic_pmd_hwif.h"
 #include "hinic_pmd_wq.h"
 #include "hinic_pmd_mgmt.h"
+#include "hinic_pmd_mbox.h"
 #include "hinic_pmd_cmdq.h"
 
 #define CMDQ_CMD_TIMEOUT				5000 /* millisecond */
@@ -439,11 +440,14 @@ static int hinic_set_cmdq_ctxts(struct hinic_hwdev *hwdev)
 					     cmdq_ctxt, in_size, NULL,
 					     NULL, 0);
 		if (err) {
+			if (err == HINIC_MBOX_PF_BUSY_ACTIVE_FW)
+				cmdqs->status |= HINIC_CMDQ_SET_FAIL;
 			PMD_DRV_LOG(ERR, "Set cmdq ctxt failed");
 			return -EFAULT;
 		}
 	}
 
+	cmdqs->status &= ~HINIC_CMDQ_SET_FAIL;
 	cmdqs->status |= HINIC_CMDQ_ENABLE;
 
 	return 0;
diff --git a/drivers/net/hinic/base/hinic_pmd_cmdq.h b/drivers/net/hinic/base/hinic_pmd_cmdq.h
index da939e1..4ce0a4c 100644
--- a/drivers/net/hinic/base/hinic_pmd_cmdq.h
+++ b/drivers/net/hinic/base/hinic_pmd_cmdq.h
@@ -170,6 +170,7 @@ struct hinic_cmdq_ctxt {
 
 enum hinic_cmdq_status {
 	HINIC_CMDQ_ENABLE = BIT(0),
+	HINIC_CMDQ_SET_FAIL = BIT(1)
 };
 
 enum hinic_cmdq_cmd_type {
diff --git a/drivers/net/hinic/base/hinic_pmd_nicio.c b/drivers/net/hinic/base/hinic_pmd_nicio.c
index 59e39ed..31a13fb 100644
--- a/drivers/net/hinic/base/hinic_pmd_nicio.c
+++ b/drivers/net/hinic/base/hinic_pmd_nicio.c
@@ -533,6 +533,15 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 		return err;
 	}
 
+	if (hwdev->cmdqs->status & HINIC_CMDQ_SET_FAIL) {
+		err = hinic_reinit_cmdq_ctxts(hwdev);
+		if (err) {
+			PMD_DRV_LOG(ERR, "Reinit cmdq context failed, rc: %d\n",
+				err);
+			return err;
+		}
+	}
+
 	err = init_qp_ctxts(nic_io);
 	if (err) {
 		PMD_DRV_LOG(ERR, "Init QP ctxts failed, rc: %d", err);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 3/7] net/hinic/base: optimize doorbell area initialization
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 1/7] net/hinic: fix LRO problems Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 2/7] net/hinic/base: fix hotupdate firmware problem Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 4/7] net/hinic: remove 40GE Mezz card id Xiaoyun wang
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

The maximum doorbell area is inited from hardware param, and not uses
const macro param.

Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/base/hinic_pmd_hwif.c | 23 +++++++++++++++++------
 drivers/net/hinic/base/hinic_pmd_hwif.h |  1 +
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/net/hinic/base/hinic_pmd_hwif.c b/drivers/net/hinic/base/hinic_pmd_hwif.c
index 8a01fbc..0fced5b 100644
--- a/drivers/net/hinic/base/hinic_pmd_hwif.c
+++ b/drivers/net/hinic/base/hinic_pmd_hwif.c
@@ -183,17 +183,19 @@ static void set_ppf(struct hinic_hwif *hwif)
 		attr->func_type = TYPE_PPF;
 }
 
-static void init_db_area_idx(struct hinic_free_db_area *free_db_area)
+static void init_db_area_idx(struct hinic_hwif *hwif)
 {
+	struct hinic_free_db_area *free_db_area = &hwif->free_db_area;
+	u32 db_max_areas = hwif->db_max_areas;
 	u32 i;
 
-	for (i = 0; i < HINIC_DB_MAX_AREAS; i++)
+	for (i = 0; i < db_max_areas; i++)
 		free_db_area->db_idx[i] = i;
 
 	free_db_area->alloc_pos = 0;
 	free_db_area->return_pos = 0;
 
-	free_db_area->num_free = HINIC_DB_MAX_AREAS;
+	free_db_area->num_free = db_max_areas;
 
 	spin_lock_init(&free_db_area->idx_lock);
 }
@@ -214,7 +216,7 @@ static int get_db_idx(struct hinic_hwif *hwif, u32 *idx)
 	free_db_area->num_free--;
 
 	pos = free_db_area->alloc_pos++;
-	pos &= HINIC_DB_MAX_AREAS - 1;
+	pos &= (hwif->db_max_areas - 1);
 
 	pg_idx = free_db_area->db_idx[pos];
 
@@ -235,7 +237,7 @@ static void free_db_idx(struct hinic_hwif *hwif, u32 idx)
 	spin_lock(&free_db_area->idx_lock);
 
 	pos = free_db_area->return_pos++;
-	pos &= HINIC_DB_MAX_AREAS - 1;
+	pos &= (hwif->db_max_areas - 1);
 
 	free_db_area->db_idx[pos] = idx;
 
@@ -391,8 +393,13 @@ static int hinic_init_hwif(struct hinic_hwdev *hwdev, void *cfg_reg_base,
 		    void *db_base, __rte_unused void *dwqe_mapping)
 {
 	struct hinic_hwif *hwif;
+	struct rte_pci_device *pci_dev;
+	u64 db_bar_len;
 	int err;
 
+	pci_dev = (struct rte_pci_device *)(hwdev->pcidev_hdl);
+	db_bar_len = pci_dev->mem_resource[HINIC_DB_MEM_BAR].len;
+
 	hwif = hwdev->hwif;
 
 	hwif->cfg_regs_base = (u8 __iomem *)cfg_reg_base;
@@ -400,7 +407,11 @@ static int hinic_init_hwif(struct hinic_hwdev *hwdev, void *cfg_reg_base,
 
 	hwif->db_base_phy = db_base_phy;
 	hwif->db_base = (u8 __iomem *)db_base;
-	init_db_area_idx(&hwif->free_db_area);
+	hwif->db_max_areas = db_bar_len / HINIC_DB_PAGE_SIZE;
+	if (hwif->db_max_areas > HINIC_DB_MAX_AREAS)
+		hwif->db_max_areas = HINIC_DB_MAX_AREAS;
+
+	init_db_area_idx(hwif);
 
 	get_hwif_attr(hwif);
 
diff --git a/drivers/net/hinic/base/hinic_pmd_hwif.h b/drivers/net/hinic/base/hinic_pmd_hwif.h
index 6752587..de99507 100644
--- a/drivers/net/hinic/base/hinic_pmd_hwif.h
+++ b/drivers/net/hinic/base/hinic_pmd_hwif.h
@@ -73,6 +73,7 @@ struct hinic_hwif {
 	u8 __iomem			*intr_regs_base;
 	u64				db_base_phy;
 	u8 __iomem			*db_base;
+	u64				db_max_areas;
 	struct hinic_free_db_area	free_db_area;
 	struct hinic_func_attr		attr;
 };
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 4/7] net/hinic: remove 40GE Mezz card id
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
                   ` (2 preceding siblings ...)
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 3/7] net/hinic/base: optimize doorbell area initialization Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 5/7] net/hinic: Add Fdir filter type Xiaoyun wang
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

The 40GE Mezz card is not support, so remove it from the pmd driver.

Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/hinic_pmd_ethdev.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c
index b81ecd0..37aa042 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -36,7 +36,6 @@
 
 /* Mezz card for Blade Server */
 #define HINIC_DEV_ID_MEZZ_25GE		0x0210
-#define HINIC_DEV_ID_MEZZ_40GE		0x020D
 #define HINIC_DEV_ID_MEZZ_100GE		0x0205
 
 /* 2*25G and 2*100G card */
@@ -3122,7 +3121,6 @@ static int hinic_dev_uninit(struct rte_eth_dev *dev)
 static struct rte_pci_id pci_id_hinic_map[] = {
 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_PRD) },
 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_25GE) },
-	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_40GE) },
 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_100GE) },
 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF) },
 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF_HV) },
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 5/7] net/hinic: Add Fdir filter type
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
                   ` (3 preceding siblings ...)
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 4/7] net/hinic: remove 40GE Mezz card id Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 6/7] net/hinic/base: Optimize log files Xiaoyun wang
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

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 <cloud.wangxiaoyun@huawei.com>
---
 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 c025851..09918a7 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 2dc431e..9c273ad 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 does'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 does'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 does'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 b9e037e..be6b320 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 37aa042..9e90056 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 3e3f3b3..910a57b 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 protocal: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 protocal: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 49c9d87..7f8f330 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 @@ static int hinic_check_ethertype_first_item(const struct rte_flow_item *item,
  * 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 @@ static int hinic_check_ethertype_first_item(const struct rte_flow_item *item,
 	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 @@ static int hinic_check_ntuple_item_ele(const struct rte_flow_item *item,
 	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 @@ static int hinic_check_normal_act_ele(const struct rte_flow_item *item,
 	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 @@ static int hinic_check_normal_act_ele(const struct rte_flow_item *item,
 {
 	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 @@ static int hinic_flow_validate(struct rte_eth_dev *dev,
 
 	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 @@ static int hinic_flow_validate(struct rte_eth_dev *dev,
 	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 @@ static int hinic_flow_validate(struct rte_eth_dev *dev,
 
 	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 @@ static int hinic_flow_validate(struct rte_eth_dev *dev,
 	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 @@ static int hinic_flow_validate(struct rte_eth_dev *dev,
 	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 @@ void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev)
 	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 @@ void hinic_free_fdir_filter(struct hinic_nic_dev *nic_dev)
  *    - 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 @@ void hinic_free_fdir_filter(struct hinic_nic_dev *nic_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 @@ static int hinic_add_del_ntuple_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 @@ static int hinic_add_del_ntuple_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 @@ static int hinic_add_del_ntuple_filter(struct rte_eth_dev *dev,
 	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 @@ static int hinic_add_del_ntuple_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.protocal = rule->hinic_fdir.proto;
+		tcam_key->key_mask.protocal = 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 faied!");
+				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 faied!");
+				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 faied!");
+		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 succed",
+		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 faied!");
+		return -EFAULT;
+	}
+
+	PMD_DRV_LOG(INFO, "Del fdir_tcam_rule function_id: 0x%x, "
+		"tcam_block_id: %d, index: %d, tcam_rule_nums: %d succed",
+		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,
 };
+
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 6/7] net/hinic/base: Optimize log files
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
                   ` (4 preceding siblings ...)
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 5/7] net/hinic: Add Fdir filter type Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 7/7] net/hinic/base: Support Pause flow control Xiaoyun wang
  2020-03-20 10:05 ` [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Ferruh Yigit
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

The patch optimizes log files without "\n".

Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/base/hinic_pmd_mbox.c   |  3 +--
 drivers/net/hinic/base/hinic_pmd_mgmt.c   |  9 ++++-----
 drivers/net/hinic/base/hinic_pmd_niccfg.c | 20 +++++++++-----------
 drivers/net/hinic/base/hinic_pmd_nicio.c  | 19 ++++++++-----------
 drivers/net/hinic/hinic_pmd_ethdev.c      | 31 +++++++++++++++----------------
 5 files changed, 37 insertions(+), 45 deletions(-)

diff --git a/drivers/net/hinic/base/hinic_pmd_mbox.c b/drivers/net/hinic/base/hinic_pmd_mbox.c
index 935d60b..bf83fbd 100644
--- a/drivers/net/hinic/base/hinic_pmd_mbox.c
+++ b/drivers/net/hinic/base/hinic_pmd_mbox.c
@@ -191,8 +191,7 @@ static int recv_vf_mbox_handler(struct hinic_mbox_func_to_func *func_to_func,
 						buf_out, out_size);
 		break;
 	default:
-		PMD_DRV_LOG(ERR, "No handler, mod = %d",
-				recv_mbox->mod);
+		PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_mbox->mod);
 		rc = HINIC_MBOX_VF_CMD_ERROR;
 		break;
 	}
diff --git a/drivers/net/hinic/base/hinic_pmd_mgmt.c b/drivers/net/hinic/base/hinic_pmd_mgmt.c
index eee50a8..addc9d2 100644
--- a/drivers/net/hinic/base/hinic_pmd_mgmt.c
+++ b/drivers/net/hinic/base/hinic_pmd_mgmt.c
@@ -449,7 +449,7 @@ static void hinic_pf_to_mgmt_free(struct hinic_hwdev *hwdev)
 			       recv_msg->msg_len);
 			*out_size = recv_msg->msg_len;
 		} else {
-			PMD_DRV_LOG(ERR, "Mgmt rsp's msg len:%u overflow.",
+			PMD_DRV_LOG(ERR, "Mgmt rsp's msg len: %u overflow.",
 				recv_msg->msg_len);
 			err = -ERANGE;
 		}
@@ -577,7 +577,7 @@ static void hinic_mgmt_recv_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
 						buf_out, &out_size);
 		break;
 	default:
-		PMD_DRV_LOG(ERR, "No handler, mod = %d", recv_msg->mod);
+		PMD_DRV_LOG(ERR, "No handler, mod: %d", recv_msg->mod);
 		break;
 	}
 
@@ -617,7 +617,7 @@ static int recv_mgmt_msg_handler(struct hinic_msg_pf_to_mgmt *pf_to_mgmt,
 
 	if (!check_mgmt_seq_id_and_seg_len(recv_msg, seq_id, seq_len)) {
 		PMD_DRV_LOG(ERR,
-			"Mgmt msg sequence and segment check fail, "
+			"Mgmt msg sequence and segment check failed, "
 			"func id: 0x%x, front id: 0x%x, current id: 0x%x, seg len: 0x%x",
 			hinic_global_func_id(pf_to_mgmt->hwdev),
 			recv_msg->sed_id, seq_id, seq_len);
@@ -741,8 +741,7 @@ int hinic_aeq_poll_msg(struct hinic_eq *eq, u32 timeout, void *param)
 
 		event = EQ_ELEM_DESC_GET(aeqe_desc, TYPE);
 		if (EQ_ELEM_DESC_GET(aeqe_desc, SRC)) {
-			PMD_DRV_LOG(ERR, "AEQ sw event not support %d",
-				event);
+			PMD_DRV_LOG(ERR, "AEQ sw event not support %d", event);
 			return -ENODEV;
 
 		} else {
diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c
index 9c273ad..a724211 100644
--- a/drivers/net/hinic/base/hinic_pmd_niccfg.c
+++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c
@@ -276,7 +276,7 @@ int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
 	int err;
 
 	if (!hwdev || !old_mac || !new_mac) {
-		PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL\n");
+		PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL");
 		return -EINVAL;
 	}
 
@@ -293,12 +293,12 @@ int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
 	if (err || !out_size ||
 	    (mac_info.mgmt_msg_head.status &&
 	     mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
-		PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",
+		PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x",
 			    err, mac_info.mgmt_msg_head.status, out_size);
 		return -EINVAL;
 	}
 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
-		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation.\n");
+		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation");
 		return HINIC_PF_SET_VF_ALREADY;
 	}
 
@@ -385,7 +385,7 @@ int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
 				     &out_size);
 	if (err || !out_size || vlan_info.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR,
-			"Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n",
+			"Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x",
 			add ? "add" : "remove", err,
 			vlan_info.mgmt_msg_head.status, out_size);
 		return -EINVAL;
@@ -431,7 +431,7 @@ int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
 		err = HINIC_MGMT_CMD_UNSUPPORTED;
 	} else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR,
-			"Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x\n",
+			"Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x",
 			vlan_filter_ctrl, err,
 			vlan_filter.mgmt_msg_head.status, out_size);
 		err = -EINVAL;
@@ -473,7 +473,7 @@ int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
 					&vlan_cfg, &out_size);
 	if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
 		PMD_DRV_LOG(ERR,
-			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
+			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x",
 			err, vlan_cfg.mgmt_msg_head.status, out_size);
 		return -EINVAL;
 	}
@@ -687,8 +687,7 @@ int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
 		pg_bw_t += *(pg_bw + i);
 
 		if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
-			PMD_DRV_LOG(ERR,
-				"Invalid up %d mapping tc: %d", i,
+			PMD_DRV_LOG(ERR, "Invalid up %d mapping tc: %d", i,
 				*(up_tc + i));
 			return -EINVAL;
 		}
@@ -1400,7 +1399,7 @@ int hinic_set_anti_attack(void *hwdev, bool enable)
 				     &rate, sizeof(rate), &rate,
 				     &out_size);
 	if (err || !out_size || rate.mgmt_msg_head.status) {
-		PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
+		PMD_DRV_LOG(ERR, "Can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
 			(enable ? "enable" : "disable"), err,
 			rate.mgmt_msg_head.status, out_size);
 		return -EINVAL;
@@ -1502,8 +1501,7 @@ int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
 				     sizeof(fast_recycled_mode),
 				     &fast_recycled_mode, &out_size, 0);
 	if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
-		PMD_DRV_LOG(ERR,
-			"Failed to set recycle mode, ret = %d",
+		PMD_DRV_LOG(ERR, "Failed to set recycle mode, ret: %d",
 			fast_recycled_mode.mgmt_msg_head.status);
 		return -EFAULT;
 	}
diff --git a/drivers/net/hinic/base/hinic_pmd_nicio.c b/drivers/net/hinic/base/hinic_pmd_nicio.c
index 31a13fb..fd34b03 100644
--- a/drivers/net/hinic/base/hinic_pmd_nicio.c
+++ b/drivers/net/hinic/base/hinic_pmd_nicio.c
@@ -312,7 +312,8 @@ static int init_sq_ctxts(struct hinic_nic_io *nic_io)
 					     HINIC_UCODE_CMD_MDY_QUEUE_CONTEXT,
 					     cmd_buf, &out_param, 0);
 		if (err || out_param != 0) {
-			PMD_DRV_LOG(ERR, "Failed to set SQ ctxts, err:%d", err);
+			PMD_DRV_LOG(ERR, "Failed to set SQ ctxts, err: %d",
+				err);
 			err = -EFAULT;
 			break;
 		}
@@ -536,7 +537,7 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 	if (hwdev->cmdqs->status & HINIC_CMDQ_SET_FAIL) {
 		err = hinic_reinit_cmdq_ctxts(hwdev);
 		if (err) {
-			PMD_DRV_LOG(ERR, "Reinit cmdq context failed, rc: %d\n",
+			PMD_DRV_LOG(ERR, "Reinit cmdq context failed, rc: %d",
 				err);
 			return err;
 		}
@@ -551,8 +552,7 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 	/* clean LRO/TSO context space */
 	err = clean_qp_offload_ctxt(nic_io);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Clean qp offload ctxts failed, rc: %d",
-			err);
+		PMD_DRV_LOG(ERR, "Clean qp offload ctxts failed, rc: %d", err);
 		return err;
 	}
 
@@ -561,16 +561,14 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 	/* update rx buf size to function table */
 	err = hinic_set_rx_vhd_mode(hwdev, 0, rx_buf_sz);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Set rx vhd mode failed, rc: %d",
-			err);
+		PMD_DRV_LOG(ERR, "Set rx vhd mode failed, rc: %d", err);
 		return err;
 	}
 
 	err = hinic_set_root_ctxt(hwdev, nic_io->rq_depth,
 				  nic_io->sq_depth, rx_buf_sz);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Set root context failed, rc: %d",
-			err);
+		PMD_DRV_LOG(ERR, "Set root context failed, rc: %d", err);
 		return err;
 	}
 
@@ -585,8 +583,7 @@ int hinic_init_qp_ctxts(struct hinic_hwdev *hwdev)
 		sq_attr.dma_attr_off = 0;
 		err = hinic_set_ci_table(hwdev, q_id, &sq_attr);
 		if (err) {
-			PMD_DRV_LOG(ERR, "Set ci table failed, rc: %d",
-				err);
+			PMD_DRV_LOG(ERR, "Set ci table failed, rc: %d", err);
 			goto set_cons_idx_table_err;
 		}
 	}
@@ -744,7 +741,7 @@ static int hinic_alloc_nicio(struct hinic_hwdev *hwdev)
 
 	max_qps = hinic_func_max_qnum(hwdev);
 	if ((max_qps & (max_qps - 1))) {
-		PMD_DRV_LOG(ERR, "wrong number of max_qps: %d",
+		PMD_DRV_LOG(ERR, "Wrong number of max_qps: %d",
 			max_qps);
 		return -EINVAL;
 	}
diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c
index 9e90056..22e3efa 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -347,7 +347,7 @@ static int hinic_dev_configure(struct rte_eth_dev *dev)
 	err = hinic_vlan_offload_set(dev,
 				ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed\n");
+		PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed");
 		(void)hinic_config_mq_mode(dev, FALSE);
 		return err;
 	}
@@ -785,7 +785,7 @@ static int hinic_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
 
 	err = hinic_get_mgmt_version(nic_dev->hwdev, fw_ver);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Failed to get fw version\n");
+		PMD_DRV_LOG(ERR, "Failed to get fw version");
 		return -EINVAL;
 	}
 
@@ -1198,7 +1198,7 @@ static void hinic_dev_stop(struct rte_eth_dev *dev)
 	/* just stop phy port and vport */
 	rc = hinic_set_port_enable(nic_dev->hwdev, false);
 	if (rc)
-		PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name:%s, port_id:%d",
+		PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name: %s, port_id: %d",
 			  rc, name, port_id);
 
 	rc = hinic_set_vport_enable(nic_dev->hwdev, false);
@@ -1861,7 +1861,7 @@ static int hinic_rss_hash_update(struct rte_eth_dev *dev,
 	}
 
 	if (rss_conf->rss_key_len > HINIC_RSS_KEY_SIZE) {
-		PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len:%d",
+		PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len: %d",
 			    rss_conf->rss_key_len);
 		return HINIC_ERROR;
 	}
@@ -1982,7 +1982,7 @@ static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev,
 		return HINIC_OK;
 
 	if (reta_size != NIC_RSS_INDIR_SIZE) {
-		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size:%d", reta_size);
+		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
 		return HINIC_ERROR;
 	}
 
@@ -2000,7 +2000,7 @@ static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev,
 
 	for (i = 0 ; i < reta_size; i++) {
 		if (indirtbl[i] >= nic_dev->num_rq) {
-			PMD_DRV_LOG(ERR, "Invalid reta entry, index:%d, num_rq:%d",
+			PMD_DRV_LOG(ERR, "Invalid reta entry, index: %d, num_rq: %d",
 				    i, nic_dev->num_rq);
 			goto disable_rss;
 		}
@@ -2047,13 +2047,13 @@ static int hinic_rss_indirtbl_query(struct rte_eth_dev *dev,
 	u16 i = 0;
 
 	if (reta_size != NIC_RSS_INDIR_SIZE) {
-		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size:%d", reta_size);
+		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
 		return HINIC_ERROR;
 	}
 
 	err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
 	if (err) {
-		PMD_DRV_LOG(ERR, "Get rss indirect table failed, error:%d",
+		PMD_DRV_LOG(ERR, "Get rss indirect table failed, error: %d",
 			    err);
 		return err;
 	}
@@ -2272,7 +2272,7 @@ static int hinic_set_mac_addr(struct rte_eth_dev *dev,
 
 	rte_ether_addr_copy(addr, &nic_dev->default_addr);
 
-	PMD_DRV_LOG(INFO, "Set new mac address %02x:%02x:%02x:%02x:%02x:%02x\n",
+	PMD_DRV_LOG(INFO, "Set new mac address %02x:%02x:%02x:%02x:%02x:%02x",
 		    addr->addr_bytes[0], addr->addr_bytes[1],
 		    addr->addr_bytes[2], addr->addr_bytes[3],
 		    addr->addr_bytes[4], addr->addr_bytes[5]);
@@ -2286,7 +2286,7 @@ static int hinic_set_mac_addr(struct rte_eth_dev *dev,
  * @param dev
  *   Pointer to Ethernet device structure.
  * @param index
- *   MAC address index.
+ *   MAC address index, should less than 128.
  */
 static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
 {
@@ -2315,16 +2315,15 @@ static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
  * @param dev
  *   Pointer to Ethernet device structure.
  * @param mac_addr
- *   MAC address to register.
+ *   Pointer to MAC address
  * @param index
- *   MAC address index.
+ *   MAC address index, should less than 128.
  * @param vmdq
- *   VMDq pool index to associate address with (ignored).
+ *   VMDq pool index(not used).
  *
  * @return
- *   0 on success, a negative errno value otherwise and rte_errno is set.
+ *   0 on success, negative error value otherwise.
  */
-
 static int hinic_mac_addr_add(struct rte_eth_dev *dev,
 			      struct rte_ether_addr *mac_addr, uint32_t index,
 			      __rte_unused uint32_t vmdq)
@@ -2335,7 +2334,7 @@ static int hinic_mac_addr_add(struct rte_eth_dev *dev,
 	int ret;
 
 	if (index >= HINIC_MAX_UC_MAC_ADDRS) {
-		PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range,", index);
+		PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range", index);
 		return -EINVAL;
 	}
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [dpdk-dev] [PATCH v2 7/7] net/hinic/base: Support Pause flow control
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
                   ` (5 preceding siblings ...)
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 6/7] net/hinic/base: Optimize log files Xiaoyun wang
@ 2020-03-17 15:01 ` Xiaoyun wang
  2020-03-20 10:05 ` [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Ferruh Yigit
  7 siblings, 0 replies; 9+ messages in thread
From: Xiaoyun wang @ 2020-03-17 15:01 UTC (permalink / raw)
  To: dev
  Cc: ferruh.yigit, bluca, luoxianjun, luoxingyu, zhouguoyang,
	xuanziyang2, shahar.belkar, yin.yinshi, Xiaoyun wang

The patch supports pause flow control, including getting or
setting rx_pasue, tx_pause and auto_neg, auto_neg is just
for Electric port type.

Signed-off-by: Xiaoyun wang <cloud.wangxiaoyun@huawei.com>
---
 drivers/net/hinic/base/hinic_pmd_niccfg.c | 29 ++++++++++
 drivers/net/hinic/base/hinic_pmd_niccfg.h |  2 +
 drivers/net/hinic/hinic_pmd_ethdev.c      | 89 ++++++++++++++++++++++++++++++-
 drivers/net/hinic/hinic_pmd_ethdev.h      |  3 ++
 drivers/net/hinic/hinic_pmd_tx.c          |  1 +
 5 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.c b/drivers/net/hinic/base/hinic_pmd_niccfg.c
index a724211..ceb1319 100644
--- a/drivers/net/hinic/base/hinic_pmd_niccfg.c
+++ b/drivers/net/hinic/base/hinic_pmd_niccfg.c
@@ -668,6 +668,35 @@ int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
 	return 0;
 }
 
+int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
+{
+	struct hinic_pause_config pause_info;
+	u16 out_size = sizeof(pause_info);
+	int err;
+
+	if (!hwdev || !nic_pause)
+		return -EINVAL;
+
+	memset(&pause_info, 0, sizeof(pause_info));
+	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
+	pause_info.func_id = hinic_global_func_id(hwdev);
+
+	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
+				     &pause_info, sizeof(pause_info),
+				     &pause_info, &out_size);
+	if (err || !out_size || pause_info.mgmt_msg_head.status) {
+		PMD_DRV_LOG(ERR, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",
+			err, pause_info.mgmt_msg_head.status, out_size);
+		return -EINVAL;
+	}
+
+	nic_pause->auto_neg = pause_info.auto_neg;
+	nic_pause->rx_pause = pause_info.rx_pause;
+	nic_pause->tx_pause = pause_info.tx_pause;
+
+	return 0;
+}
+
 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
 		      u8 *pgid, u8 *up_bw, u8 *prio)
 {
diff --git a/drivers/net/hinic/base/hinic_pmd_niccfg.h b/drivers/net/hinic/base/hinic_pmd_niccfg.h
index be6b320..846b597 100644
--- a/drivers/net/hinic/base/hinic_pmd_niccfg.h
+++ b/drivers/net/hinic/base/hinic_pmd_niccfg.h
@@ -850,6 +850,8 @@ int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
 
 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause);
 
+int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause);
+
 int hinic_reset_port_link_cfg(void *hwdev);
 
 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw, u8 *pgid, u8 *up_bw,
diff --git a/drivers/net/hinic/hinic_pmd_ethdev.c b/drivers/net/hinic/hinic_pmd_ethdev.c
index 22e3efa..23724a0 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.c
+++ b/drivers/net/hinic/hinic_pmd_ethdev.c
@@ -1833,6 +1833,81 @@ static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev)
 	return rc;
 }
 
+static int hinic_flow_ctrl_get(struct rte_eth_dev *dev,
+			struct rte_eth_fc_conf *fc_conf)
+{
+	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct nic_pause_config nic_pause;
+	int err;
+
+	memset(&nic_pause, 0, sizeof(nic_pause));
+
+	err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause);
+	if (err)
+		return err;
+
+	if (nic_dev->pause_set || !nic_pause.auto_neg) {
+		nic_pause.rx_pause = nic_dev->nic_pause.rx_pause;
+		nic_pause.tx_pause = nic_dev->nic_pause.tx_pause;
+	}
+
+	fc_conf->autoneg = nic_pause.auto_neg;
+
+	if (nic_pause.tx_pause && nic_pause.rx_pause)
+		fc_conf->mode = RTE_FC_FULL;
+	else if (nic_pause.tx_pause)
+		fc_conf->mode = RTE_FC_TX_PAUSE;
+	else if (nic_pause.rx_pause)
+		fc_conf->mode = RTE_FC_RX_PAUSE;
+	else
+		fc_conf->mode = RTE_FC_NONE;
+
+	PMD_DRV_LOG(INFO, "Get pause options, tx: %s, rx: %s, auto: %s\n",
+		nic_pause.tx_pause ? "on" : "off",
+		nic_pause.rx_pause ? "on" : "off",
+		nic_pause.auto_neg ? "on" : "off");
+
+	return 0;
+}
+
+static int hinic_flow_ctrl_set(struct rte_eth_dev *dev,
+			struct rte_eth_fc_conf *fc_conf)
+{
+	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
+	struct nic_pause_config nic_pause;
+	int err;
+
+	nic_pause.auto_neg = fc_conf->autoneg;
+
+	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
+		(fc_conf->mode & RTE_FC_TX_PAUSE))
+		nic_pause.tx_pause = true;
+	else
+		nic_pause.tx_pause = false;
+
+	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
+		(fc_conf->mode & RTE_FC_RX_PAUSE))
+		nic_pause.rx_pause = true;
+	else
+		nic_pause.rx_pause = false;
+
+	err = hinic_set_pause_config(nic_dev->hwdev, nic_pause);
+	if (err)
+		return err;
+
+	nic_dev->pause_set = true;
+	nic_dev->nic_pause.auto_neg = nic_pause.auto_neg;
+	nic_dev->nic_pause.rx_pause = nic_pause.rx_pause;
+	nic_dev->nic_pause.tx_pause = nic_pause.tx_pause;
+
+	PMD_DRV_LOG(INFO, "Get pause options, tx: %s, rx: %s, auto: %s\n",
+		nic_pause.tx_pause ? "on" : "off",
+		nic_pause.rx_pause ? "on" : "off",
+		nic_pause.auto_neg ? "on" : "off");
+
+	return 0;
+}
+
 /**
  * DPDK callback to update the RSS hash key and RSS hash type.
  *
@@ -2453,12 +2528,22 @@ static int hinic_dev_filter_ctrl(struct rte_eth_dev *dev,
 static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev)
 {
 	struct nic_pause_config pause_config = {0};
+	int err;
 
 	pause_config.auto_neg = 0;
 	pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
 	pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
 
-	return hinic_set_pause_config(nic_dev->hwdev, pause_config);
+	err = hinic_set_pause_config(nic_dev->hwdev, pause_config);
+	if (err)
+		return err;
+
+	nic_dev->pause_set = true;
+	nic_dev->nic_pause.auto_neg = pause_config.auto_neg;
+	nic_dev->nic_pause.rx_pause = pause_config.rx_pause;
+	nic_dev->nic_pause.tx_pause = pause_config.tx_pause;
+
+	return 0;
 }
 
 static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev)
@@ -2886,6 +2971,8 @@ static void hinic_dev_close(struct rte_eth_dev *dev)
 	.allmulticast_disable          = hinic_dev_allmulticast_disable,
 	.promiscuous_enable            = hinic_dev_promiscuous_enable,
 	.promiscuous_disable           = hinic_dev_promiscuous_disable,
+	.flow_ctrl_get                 = hinic_flow_ctrl_get,
+	.flow_ctrl_set                 = hinic_flow_ctrl_set,
 	.rss_hash_update               = hinic_rss_hash_update,
 	.rss_hash_conf_get             = hinic_rss_conf_get,
 	.reta_update                   = hinic_rss_indirtbl_update,
diff --git a/drivers/net/hinic/hinic_pmd_ethdev.h b/drivers/net/hinic/hinic_pmd_ethdev.h
index 910a57b..c23d3cf 100644
--- a/drivers/net/hinic/hinic_pmd_ethdev.h
+++ b/drivers/net/hinic/hinic_pmd_ethdev.h
@@ -263,6 +263,9 @@ struct hinic_nic_dev {
 	u8 num_rss;
 	u8 rx_queue_list[HINIC_MAX_RX_QUEUES];
 
+	bool pause_set;
+	struct nic_pause_config nic_pause;
+
 	u32 vfta[HINIC_VFTA_SIZE];	/* VLAN bitmap */
 
 	struct rte_ether_addr default_addr;
diff --git a/drivers/net/hinic/hinic_pmd_tx.c b/drivers/net/hinic/hinic_pmd_tx.c
index 64ec2c1..f24e3e4 100644
--- a/drivers/net/hinic/hinic_pmd_tx.c
+++ b/drivers/net/hinic/hinic_pmd_tx.c
@@ -16,6 +16,7 @@
 #include "base/hinic_pmd_hwif.h"
 #include "base/hinic_pmd_wq.h"
 #include "base/hinic_pmd_nicio.h"
+#include "base/hinic_pmd_niccfg.h"
 #include "hinic_pmd_ethdev.h"
 #include "hinic_pmd_tx.h"
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control
  2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
                   ` (6 preceding siblings ...)
  2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 7/7] net/hinic/base: Support Pause flow control Xiaoyun wang
@ 2020-03-20 10:05 ` Ferruh Yigit
  7 siblings, 0 replies; 9+ messages in thread
From: Ferruh Yigit @ 2020-03-20 10:05 UTC (permalink / raw)
  To: Xiaoyun wang, dev
  Cc: bluca, luoxianjun, luoxingyu, zhouguoyang, xuanziyang2,
	shahar.belkar, yin.yinshi

On 3/17/2020 3:01 PM, Xiaoyun wang wrote:
> This patch fixes LRO and hotupdate firmware problems,
> optimize doorbell area initialization without const macro
> definition, Optimize log files, support pause flow control
> and inner vxlan or non vxlan dport filter type.
> 
> --
> v1->v2:
>   - Fix LRO problems
>   - Fix hotupdate firmware problem
>   - Optimize doorbell area initialization 
>   - Remove 40GE Mezz card id
>   - Add Fdir filter type
>   - Optimize log files
>   - Support pause flow control
> 
> v1:
>   - Allocate IO memory with socketid
> 
> Xiaoyun wang (7):
>   net/hinic: fix LRO problems
>   net/hinic/base: fix hotupdate firmware problem
>   net/hinic/base: optimize doorbell area initialization
>   net/hinic: remove 40GE Mezz card id
>   net/hinic: Add Fdir filter type
>   net/hinic/base: Optimize log files
>   net/hinic/base: Support Pause flow control
> 

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2020-03-20 10:05 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-17 15:01 [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 1/7] net/hinic: fix LRO problems Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 2/7] net/hinic/base: fix hotupdate firmware problem Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 3/7] net/hinic/base: optimize doorbell area initialization Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 4/7] net/hinic: remove 40GE Mezz card id Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 5/7] net/hinic: Add Fdir filter type Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 6/7] net/hinic/base: Optimize log files Xiaoyun wang
2020-03-17 15:01 ` [dpdk-dev] [PATCH v2 7/7] net/hinic/base: Support Pause flow control Xiaoyun wang
2020-03-20 10:05 ` [dpdk-dev] [PATCH v2 0/7] Fix LRO issue and support Flow Control Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).