[dpdk-dev] [PATCH] net/i40e: fix statistics

2019-01-23 Thread chenmin . sun
From: Chenmin Sun 

1. Fix the lldp stop condition check - for firmware
versions 6.01(for X710)/3.33(for X722) or later we need stop the lldp
2. Doucment known issue for tx bytes decreasing due to link status chage

Fixes: 044846f071cc ("net/i40e: stop LLDP before setting local LLDP MIB")
Cc: sta...@dpdk.org
Cc: qi.z.zh...@intel.com

Signed-off-by: Chenmin Sun 
---
 doc/guides/nics/i40e.rst   |  7 +++
 drivers/net/i40e/i40e_ethdev.c | 38 +++---
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 6aceb53ea..d9ec07e12 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -698,3 +698,10 @@ See :numref:`figure_intel_perf_test_setup` for the 
performance test setup.
* Start creating a stream on packet generator.
 
* Set the Ethernet II type to 0x0800.
+
+Tx bytes affected by the link status change
+~~~
+
+For firmware versions prior to 6.01 for X710 series and 3.33 for X722 series, 
the tx_bytes statsistics data is affected by
+the link down event. Each time the link status changes to down, the tx_bytes 
decreases 110 bytes.
+
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index a6b97e164..181efbac0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1493,9 +1493,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
goto err_setup_pf_switch;
}
 
-   /* reset all stats of the device, including pf and main vsi */
-   i40e_dev_stats_reset(dev);
-
vsi = pf->main_vsi;
 
/* Disable double vlan by default */
@@ -1590,6 +1587,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
memset(&pf->rss_info, 0,
sizeof(struct i40e_rte_flow_rss_conf));
 
+   /* reset all stats of the device, including pf and main vsi */
+   i40e_dev_stats_reset(dev);
+
return 0;
 
 err_init_fdir_filter_list:
@@ -3454,12 +3454,38 @@ i40e_fw_version_get(struct rte_eth_dev *dev, char 
*fw_version, size_t fw_size)
 ver, build, patch);
 
ret += 1; /* add the size of '\0' */
+
if (fw_size < (u32)ret)
return ret;
else
return 0;
 }
 
+/*
+ * When using NVM 6.01(for X710 XL710 XXV710)/3.33(for X722) or later,
+ * the Rx data path does not hang if the FW LLDP is stopped.
+ * return true if lldp need to stop
+ * return false if we cannot disable the LLDP to avoid Rx data path blocking.
+ */
+static bool
+i40e_need_stop_lldp(struct rte_eth_dev *dev)
+{
+   double nvm_ver;
+   char ver_str[64] = {0};
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   i40e_fw_version_get(dev, ver_str, 64);
+   nvm_ver = atof(ver_str);
+   if ((hw->mac.type == I40E_MAC_X722 ||
+hw->mac.type == I40E_MAC_X722_VF) &&
+((uint32_t)(nvm_ver * 1000) >= (uint32_t)(3.33 * 1000)))
+   return true;
+   else if ((uint32_t)(nvm_ver * 1000) >= (uint32_t)(6.01 * 1000))
+   return true;
+
+   return false;
+}
+
 static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -11425,11 +11451,7 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool 
sw_dcb)
 * LLDP MIB change event.
 */
if (sw_dcb == TRUE) {
-   /* When using NVM 6.01 or later, the RX data path does
-* not hang if the FW LLDP is stopped.
-*/
-   if (((hw->nvm.version >> 12) & 0xf) >= 6 &&
-   ((hw->nvm.version >> 4) & 0xff) >= 1) {
+   if (i40e_need_stop_lldp(dev)) {
ret = i40e_aq_stop_lldp(hw, TRUE, NULL);
if (ret != I40E_SUCCESS)
PMD_INIT_LOG(DEBUG, "Failed to stop lldp");
-- 
2.17.1



[dpdk-dev] [PATCH v2] net/i40e: fix statistics

2019-01-24 Thread chenmin . sun
From: Chenmin Sun 

1. Fix the lldp stop condition check - for firmware
versions 6.01(for X710)/3.33(for X722) or later we need stop the lldp
2. Doucment known issue for tx bytes decreasing due to link status chage
3. Deferred stats reset in dev_init to avoid some noise be counted.

Fixes: 044846f071cc ("net/i40e: stop LLDP before setting local LLDP MIB")
Cc: sta...@dpdk.org
Cc: qi.z.zh...@intel.com

Signed-off-by: Chenmin Sun 
---
 doc/guides/nics/i40e.rst   |  7 +++
 drivers/net/i40e/i40e_ethdev.c | 38 +++---
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/doc/guides/nics/i40e.rst b/doc/guides/nics/i40e.rst
index 6aceb53ea..d9ec07e12 100644
--- a/doc/guides/nics/i40e.rst
+++ b/doc/guides/nics/i40e.rst
@@ -698,3 +698,10 @@ See :numref:`figure_intel_perf_test_setup` for the 
performance test setup.
* Start creating a stream on packet generator.
 
* Set the Ethernet II type to 0x0800.
+
+Tx bytes affected by the link status change
+~~~
+
+For firmware versions prior to 6.01 for X710 series and 3.33 for X722 series, 
the tx_bytes statsistics data is affected by
+the link down event. Each time the link status changes to down, the tx_bytes 
decreases 110 bytes.
+
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index a6b97e164..181efbac0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1493,9 +1493,6 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
goto err_setup_pf_switch;
}
 
-   /* reset all stats of the device, including pf and main vsi */
-   i40e_dev_stats_reset(dev);
-
vsi = pf->main_vsi;
 
/* Disable double vlan by default */
@@ -1590,6 +1587,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
memset(&pf->rss_info, 0,
sizeof(struct i40e_rte_flow_rss_conf));
 
+   /* reset all stats of the device, including pf and main vsi */
+   i40e_dev_stats_reset(dev);
+
return 0;
 
 err_init_fdir_filter_list:
@@ -3454,12 +3454,38 @@ i40e_fw_version_get(struct rte_eth_dev *dev, char 
*fw_version, size_t fw_size)
 ver, build, patch);
 
ret += 1; /* add the size of '\0' */
+
if (fw_size < (u32)ret)
return ret;
else
return 0;
 }
 
+/*
+ * When using NVM 6.01(for X710 XL710 XXV710)/3.33(for X722) or later,
+ * the Rx data path does not hang if the FW LLDP is stopped.
+ * return true if lldp need to stop
+ * return false if we cannot disable the LLDP to avoid Rx data path blocking.
+ */
+static bool
+i40e_need_stop_lldp(struct rte_eth_dev *dev)
+{
+   double nvm_ver;
+   char ver_str[64] = {0};
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+   i40e_fw_version_get(dev, ver_str, 64);
+   nvm_ver = atof(ver_str);
+   if ((hw->mac.type == I40E_MAC_X722 ||
+hw->mac.type == I40E_MAC_X722_VF) &&
+((uint32_t)(nvm_ver * 1000) >= (uint32_t)(3.33 * 1000)))
+   return true;
+   else if ((uint32_t)(nvm_ver * 1000) >= (uint32_t)(6.01 * 1000))
+   return true;
+
+   return false;
+}
+
 static void
 i40e_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
@@ -11425,11 +11451,7 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool 
sw_dcb)
 * LLDP MIB change event.
 */
if (sw_dcb == TRUE) {
-   /* When using NVM 6.01 or later, the RX data path does
-* not hang if the FW LLDP is stopped.
-*/
-   if (((hw->nvm.version >> 12) & 0xf) >= 6 &&
-   ((hw->nvm.version >> 4) & 0xff) >= 1) {
+   if (i40e_need_stop_lldp(dev)) {
ret = i40e_aq_stop_lldp(hw, TRUE, NULL);
if (ret != I40E_SUCCESS)
PMD_INIT_LOG(DEBUG, "Failed to stop lldp");
-- 
2.17.1



[dpdk-dev] [PATCH] net/ice: fixed speed capability error issue

2019-03-28 Thread chenmin . sun
From: Chenmin Sun 

Device speed capability should be specified based on different phy types
instead of a fixed value, this patch fix the issue.

Fixes: 690175ee51bf ("net/ice: support getting device information")
Cc: wenzhuo...@intel.com

Signed-off-by: Chenmin Sun 
---
 drivers/net/ice/ice_ethdev.c | 17 +++
 drivers/net/ice/ice_ethdev.h | 40 
 2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ice/ice_ethdev.c b/drivers/net/ice/ice_ethdev.c
index c468962e2..f29fb4e3a 100644
--- a/drivers/net/ice/ice_ethdev.c
+++ b/drivers/net/ice/ice_ethdev.c
@@ -1820,6 +1820,8 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
struct ice_hw *hw = ICE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ice_vsi *vsi = pf->main_vsi;
struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
+   u64 phy_type_low;
+   u64 phy_type_high;
 
dev_info->min_rx_bufsize = ICE_BUF_SIZE_MIN;
dev_info->max_rx_pktlen = ICE_FRAME_SIZE_MAX;
@@ -1899,10 +1901,17 @@ ice_dev_info_get(struct rte_eth_dev *dev, struct 
rte_eth_dev_info *dev_info)
   ETH_LINK_SPEED_5G |
   ETH_LINK_SPEED_10G |
   ETH_LINK_SPEED_20G |
-  ETH_LINK_SPEED_25G |
-  ETH_LINK_SPEED_40G |
-  ETH_LINK_SPEED_50G |
-  ETH_LINK_SPEED_100G;
+  ETH_LINK_SPEED_25G;
+
+   phy_type_low = hw->port_info->phy.phy_type_low;
+   phy_type_high = hw->port_info->phy.phy_type_high;
+
+   if (ICE_PHY_TYPE_SUPPORT_50G(phy_type_low))
+   dev_info->speed_capa |= ETH_LINK_SPEED_50G;
+
+   if (ICE_PHY_TYPE_SUPPORT_100G_LOW(phy_type_low) ||
+   ICE_PHY_TYPE_SUPPORT_100G_HIGH(phy_type_high))
+   dev_info->speed_capa |= ETH_LINK_SPEED_100G;
 
dev_info->nb_rx_queues = dev->data->nb_rx_queues;
dev_info->nb_tx_queues = dev->data->nb_tx_queues;
diff --git a/drivers/net/ice/ice_ethdev.h b/drivers/net/ice/ice_ethdev.h
index 151a09e52..630ee00b2 100644
--- a/drivers/net/ice/ice_ethdev.h
+++ b/drivers/net/ice/ice_ethdev.h
@@ -317,4 +317,44 @@ ice_align_floor(int n)
return 0;
return 1 << (sizeof(n) * CHAR_BIT - 1 - __builtin_clz(n));
 }
+
+#define ICE_PHY_TYPE_SUPPORT_50G(phy_type) \
+   (((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_CR2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_SR2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_LR2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_KR2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_LAUI2_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_LAUI2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_AUI2_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_AUI2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_CP) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_SR) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_FR) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_LR) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50GBASE_KR_PAM4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_AUI1_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_50G_AUI1))
+
+#define ICE_PHY_TYPE_SUPPORT_100G_LOW(phy_type) \
+   (((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_CR4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_SR4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_LR4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_KR4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100G_CAUI4_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100G_CAUI4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100G_AUI4_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100G_AUI4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_CR_PAM4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_KR_PAM4) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_CP2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_SR2) || \
+   ((phy_type) & ICE_PHY_TYPE_LOW_100GBASE_DR))
+
+#define ICE_PHY_TYPE_SUPPORT_100G_HIGH(phy_type) \
+   (((phy_type) & ICE_PHY_TYPE_HIGH_100GBASE_KR2_PAM4) || \
+   ((phy_type) & ICE_PHY_TYPE_HIGH_100G_CAUI2_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_HIGH_100G_CAUI2) || \
+   ((phy_type) & ICE_PHY_TYPE_HIGH_100G_AUI2_AOC_ACC) || \
+   ((phy_type) & ICE_PHY_TYPE_HIGH_100G_AUI2))
+
 #endif /* _ICE_ETHDEV_H_ */
-- 
2.17.1



[dpdk-dev] [FDIO] dpdk: add devargs support

2019-12-13 Thread chenmin . sun
From: Chenmin Sun 

Type: feature

This patch adds the devargs support for dpdk device
The devargs are used as hardware-specific init args for dpdk devices
please refer to the nic guides under
$(DPDK_DIR)/doc/guides/nics/$(NIC_DRIVER).rst

Signed-off-by: Chenmin Sun 
Change-Id: Id380d04720090bb66afe5ce09d664e5e248b8eb9
---
 src/plugins/dpdk/device/dpdk.h   |  2 ++
 src/plugins/dpdk/device/format.c |  3 +++
 src/plugins/dpdk/device/init.c   | 36 +---
 src/vpp/conf/startup.conf|  5 +
 4 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h
index d58d2daa7..ab28ac06a 100644
--- a/src/plugins/dpdk/device/dpdk.h
+++ b/src/plugins/dpdk/device/dpdk.h
@@ -336,6 +336,8 @@ typedef struct
   u32 hqos_enabled;
   dpdk_device_config_hqos_t hqos;
   u8 tso;
+  u8 *devargs;
+
 #define DPDK_DEVICE_TSO_DEFAULT 0
 #define DPDK_DEVICE_TSO_OFF 1
 #define DPDK_DEVICE_TSO_ON  2
diff --git a/src/plugins/dpdk/device/format.c b/src/plugins/dpdk/device/format.c
index 292c083fc..20493eb77 100644
--- a/src/plugins/dpdk/device/format.c
+++ b/src/plugins/dpdk/device/format.c
@@ -564,6 +564,9 @@ format_dpdk_device (u8 * s, va_list * args)
  format_white_space, indent + 2, format_dpdk_link_status, xd);
   s = format (s, "%Uflags: %U\n",
  format_white_space, indent + 2, format_dpdk_device_flags, xd);
+  if (di.device->devargs && di.device->devargs->args)
+s = format (s, "%UDevargs: %s\n",
+   format_white_space, indent + 2, di.device->devargs->args);
   s = format (s, "%Urx: queues %d (max %d), desc %d "
  "(min %d max %d align %d)\n",
  format_white_space, indent + 2, xd->rx_q_used, di.max_rx_queues,
diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c
index 5a6262c30..d0125e939 100644
--- a/src/plugins/dpdk/device/init.c
+++ b/src/plugins/dpdk/device/init.c
@@ -1118,6 +1118,8 @@ dpdk_device_config (dpdk_config_main_t * conf, 
vlib_pci_addr_t pci_addr,
{
  devconf->tso = DPDK_DEVICE_TSO_OFF;
}
+  else if (unformat (input, "devargs %s", &devconf->devargs))
+   ;
   else
{
  error = clib_error_return (0, "unknown input `%U'",
@@ -1428,21 +1430,31 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input)
/* copy tso config from default device */
_(tso)
 
+   /* copy tso config from default device */
+   _(devargs)
+
 /* add DPDK EAL whitelist/blacklist entry */
 if (num_whitelisted > 0 && devconf->is_blacklisted == 0)
-  {
-   tmp = format (0, "-w%c", 0);
-   vec_add1 (conf->eal_init_args, tmp);
-   tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
-   vec_add1 (conf->eal_init_args, tmp);
-  }
+{
+ tmp = format (0, "-w%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ if (devconf->devargs)
+ {
+   tmp = format (0, "%U,%s", format_vlib_pci_addr, &devconf->pci_addr, 
devconf->devargs, 0);
+ }
+ else
+ {
+   tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 
0);
+ }
+ vec_add1 (conf->eal_init_args, tmp);
+}
 else if (num_whitelisted == 0 && devconf->is_blacklisted != 0)
-  {
-   tmp = format (0, "-b%c", 0);
-   vec_add1 (conf->eal_init_args, tmp);
-   tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
-   vec_add1 (conf->eal_init_args, tmp);
-  }
+{
+ tmp = format (0, "-b%c", 0);
+ vec_add1 (conf->eal_init_args, tmp);
+ tmp = format (0, "%U%c", format_vlib_pci_addr, &devconf->pci_addr, 0);
+ vec_add1 (conf->eal_init_args, tmp);
+}
   }));
   /* *INDENT-ON* */
 
diff --git a/src/vpp/conf/startup.conf b/src/vpp/conf/startup.conf
index 3d83a1336..b0d0c8664 100644
--- a/src/vpp/conf/startup.conf
+++ b/src/vpp/conf/startup.conf
@@ -105,6 +105,11 @@ cpu {
## Default is off
## To enable TSO, 'enable-tcp-udp-checksum' must be set
# tso on
+
+   ## Devargs
+## device specific init args
+## Default is NULL
+   # devargs safe-mode-support=1,pipeline-mode-support=1
# }
 
## Whitelist specific interface by specifying PCI address
-- 
2.17.1



[dpdk-dev] [DPDK] net/ice: add outer IPv4 matching for GTPU flow

2020-01-20 Thread chenmin . sun
From: Chenmin Sun 

This patch adds the capability of matching the outer IPv4
headers for GTPU flows

Fixes: efc16c621415 ("net/ice: support flow director GTPU tunnel")

Signed-off-by: Chenmin Sun 
---
 drivers/net/ice/base/ice_fdir.c   | 4 
 drivers/net/ice/ice_fdir_filter.c | 3 ++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ice/base/ice_fdir.c b/drivers/net/ice/base/ice_fdir.c
index 87fa0afba..2d61dbfd1 100644
--- a/drivers/net/ice/base/ice_fdir.c
+++ b/drivers/net/ice/base/ice_fdir.c
@@ -804,6 +804,10 @@ ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct 
ice_fdir_fltr *input,
case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_TCP:
case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_ICMP:
case ICE_FLTR_PTYPE_NONF_IPV4_GTPU_IPV4_OTHER:
+   ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
+   input->ip.v4.src_ip);
+   ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
+   input->ip.v4.dst_ip);
ice_pkt_insert_u32(loc, ICE_IPV4_GTPU_TEID_OFFSET,
   input->gtpu_data.teid);
ice_pkt_insert_u6_qfi(loc, ICE_IPV4_GTPU_QFI_OFFSET,
diff --git a/drivers/net/ice/ice_fdir_filter.c 
b/drivers/net/ice/ice_fdir_filter.c
index f356581d1..5aaa7abcf 100644
--- a/drivers/net/ice/ice_fdir_filter.c
+++ b/drivers/net/ice/ice_fdir_filter.c
@@ -68,9 +68,10 @@
ICE_INSET_TUN_SCTP_SRC_PORT | ICE_INSET_TUN_SCTP_DST_PORT)
 
 #define ICE_FDIR_INSET_GTPU (\
-   ICE_INSET_GTPU_TEID)
+   ICE_INSET_IPV4_SRC | ICE_INSET_IPV4_DST | ICE_INSET_GTPU_TEID)
 
 #define ICE_FDIR_INSET_GTPU_EH (\
+   ICE_INSET_IPV4_SRC | ICE_INSET_IPV4_DST | \
ICE_INSET_GTPU_TEID | ICE_INSET_GTPU_QFI)
 
 static struct ice_pattern_match_item ice_fdir_pattern_os[] = {
-- 
2.17.1



[dpdk-dev] [PATCH V2] net/i40e: i40e FDIR update rate optimization

2020-07-08 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking
whether the fdir rule being inserted into the guaranteed space
or shared space.
For the flows that are inserted to the guaranteed space, we assume
that the insertion will always succeed as the hardware only reports
the "no enough space left" error. In this case, the software can
directly return success and no need to retrieve the result from
the hardware. See the fdir programming status descriptor format in
the datasheet for more details.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---

v2:
* Refine commit message and code comments.
* Refine code style.
* Fixed several memory free bugs.
* Replace the bin_serch() with rte_bsf64()
---
 drivers/net/i40e/i40e_ethdev.c  | 136 ++-
 drivers/net/i40e/i40e_ethdev.h  |  63 ---
 drivers/net/i40e/i40e_fdir.c| 190 +---
 drivers/net/i40e/i40e_flow.c| 167 ++--
 drivers/net/i40e/i40e_rxtx.c|  15 ++-
 drivers/net/i40e/rte_pmd_i40e.c |   2 +-
 6 files changed, 455 insertions(+), 118 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 3bc312c11..099f4c5e3 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,17 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   void *mem = NULL;
+   uint32_t i = 0;
+   uint32_t bmp_size;
+   uint32_t alloc = 0;
+   uint32_t best = 0;
+   uint32_t pfqf_fdalloc = 0;
+   uint32_t glqf_ctl_reg = 0;
+   struct rte_bitmap *bmp = NULL;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1077,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
return -EINVAL;
}
+
fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
  sizeof(struct i40e_fdir_filter *) *
  I40E_MAX_FDIR_FILTER_NUM,
@@ -1077,8 +1088,100 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
ret = -ENOMEM;
goto err_fdir_hash_map_alloc;
}
+
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct i40e_fdir_filter) *
+   I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   if (!fdir_info->fdir_filter_array) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir filter 
array!");
+   ret = -ENOMEM;
+   goto err_fdir_filter_array_alloc;
+   }
+
+   pfqf_fdalloc = i40e_read_rx_ctl(hw, I40E_PFQF_FDALLOC);
+   alloc = ((pfqf_fdalloc & I40E_PFQF_FDALLOC_FDALLOC_MASK) >>
+   I40E_PFQF_FDALLOC_FDALLOC_SHIFT);
+   best = ((pfqf_fdalloc & I40E_PFQF_FDALLOC_FDBEST_MASK) >>
+   I40E_PFQF_FDALLOC_FDBEST_SHIFT);
+
+   glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   } else {
+   if (glqf_ctl_reg | I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
+   }
+
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+   PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.",
+   alloc * 32, best * 32);
+
+   fdir_info->fdir_space_size = (alloc + best) * 32;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_available_space = alloc * 32;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_available_space;
+
+   fdir_info->fdir_flow_bitmap.fdir_flo

[dpdk-dev] [PATCH] net/i40e: i40e FDIR update rate optimization

2020-06-12 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking the
fdir rule will be inserted into guaranteed space or shared space.
For the flows that are inserted to the guaranteed space, it returns success
directly without retrieving the result for NIC.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``Support multiple driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c  |  96 -
 drivers/net/i40e/i40e_ethdev.h  |  57 +++---
 drivers/net/i40e/i40e_fdir.c| 182 +---
 drivers/net/i40e/i40e_flow.c| 181 +--
 drivers/net/i40e/i40e_rxtx.c|  15 ++-
 drivers/net/i40e/rte_pmd_i40e.c |   2 +-
 6 files changed, 417 insertions(+), 116 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 970a31cb2..d368c534f 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1057,8 +1058,14 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   void *mem = NULL;
+   uint32_t bmp_size, i = 0;
+   struct rte_bitmap *bmp = NULL;
+   uint32_t alloc = 0, best = 0, pfqf_fdalloc = 0;
+   uint32_t GLQF_ctl_reg = 0;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1087,12 +1094,84 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR,
 "Failed to allocate memory for fdir hash map!");
ret = -ENOMEM;
-   goto err_fdir_hash_map_alloc;
+   goto err_fdir_mem_alloc;
+   }
+
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct 
i40e_fdir_filter) *
+   
I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   pfqf_fdalloc = i40e_read_rx_ctl(hw, I40E_PFQF_FDALLOC);
+   alloc = ((pfqf_fdalloc & I40E_PFQF_FDALLOC_FDALLOC_MASK) >> 
I40E_PFQF_FDALLOC_FDALLOC_SHIFT);
+   best = ((pfqf_fdalloc & I40E_PFQF_FDALLOC_FDBEST_MASK) >> 
I40E_PFQF_FDALLOC_FDBEST_SHIFT);
+
+   GLQF_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   GLQF_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   } else {
+   if (GLQF_ctl_reg | I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
}
+
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, GLQF_ctl_reg);
+   PMD_DRV_LOG(INFO, "FDIR guarantee %u, best %u.",
+   alloc * 32, best * 32);
+
+   fdir_info->fdir_space_size = (alloc + best) * 32;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_available_space = alloc * 32;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_available_space;
+
+   fdir_info->fdir_flow_bitmap.fdir_flow =
+   rte_zmalloc("i40e_fdir_flows",
+   sizeof(struct i40e_fdir_flows) *
+   fdir_info->fdir_space_size,
+   0);
+
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   fdir_info->fdir_flow_bitmap.fdir_flow[i].idx = i;
+
+   bmp_size =
+   rte_bitmap_get_memory_footprint(fdir_info->fdir_space_size);
+
+   mem = rte_zmalloc("gurantee_fdir_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+   if (mem == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir!");
+   ret = -ENOMEM;
+   goto err_fdir_mem_alloc;
+   }
+
+   bmp = rte_bitmap_init(fdir_info->fdir_space_size, mem, bmp_size);
+   if (bmp == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to a

[dpdk-dev] [PATCH V3 0/2] i40e FDIR update rate optimization

2020-07-13 Thread chenmin . sun
From: Chenmin Sun 

i40e FDIR update rate optimization

[PATCH v3 1/2] net/i40e: introduce new data structures
[PATCH v3 2/2] net/i40e: i40e FDIR update rate optimization

v3:
* Split the patch into two
* Renamed some data structures and added some descriptions
---
v2:
* Refine commit message and code comments.
* Refine code style.
* Fixed several memory free bugs.
* Replace the bin_serch() with rte_bsf64()

Chenmin Sun (2):
  net/i40e: i40e FDIR update rate optimization data structures
  net/i40e: i40e FDIR update rate optimization

 drivers/net/i40e/i40e_ethdev.c  | 128 -
 drivers/net/i40e/i40e_ethdev.h  |  76 ++---
 drivers/net/i40e/i40e_fdir.c| 191 +---
 drivers/net/i40e/i40e_flow.c| 167 ++--
 drivers/net/i40e/i40e_rxtx.c|  15 ++-
 drivers/net/i40e/rte_pmd_i40e.c |   2 +-
 6 files changed, 460 insertions(+), 119 deletions(-)

-- 
2.17.1



[dpdk-dev] [PATCH V3 2/2] net/i40e: i40e FDIR update rate optimization

2020-07-13 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking
whether the fdir rule being inserted into the guaranteed space
or shared space.
For the flows that are inserted to the guaranteed space, we assume
that the insertion will always succeed as the hardware only reports
the "no enough space left" error. In this case, the software can
directly return success and no need to retrieve the result from
the hardware. See the fdir programming status descriptor format in
the datasheet for more details.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c  | 128 -
 drivers/net/i40e/i40e_ethdev.h  |   6 +-
 drivers/net/i40e/i40e_fdir.c| 191 +---
 drivers/net/i40e/i40e_flow.c| 167 ++--
 drivers/net/i40e/i40e_rxtx.c|  15 ++-
 drivers/net/i40e/rte_pmd_i40e.c |   2 +-
 6 files changed, 400 insertions(+), 109 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..040b5b200 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,16 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
+   uint32_t best = hw->func_caps.fd_filters_best_effort;
+   uint32_t glqf_ctl_reg = 0;
+   struct rte_bitmap *bmp = NULL;
+   uint32_t bmp_size;
+   void *mem = NULL;
+   uint32_t i = 0;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1076,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
return -EINVAL;
}
+
fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
  sizeof(struct i40e_fdir_filter *) *
  I40E_MAX_FDIR_FILTER_NUM,
@@ -1077,8 +1087,93 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
ret = -ENOMEM;
goto err_fdir_hash_map_alloc;
}
+
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct i40e_fdir_filter) *
+   I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   if (!fdir_info->fdir_filter_array) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir filter 
array!");
+   ret = -ENOMEM;
+   goto err_fdir_filter_array_alloc;
+   }
+
+   glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   } else {
+   if (glqf_ctl_reg | I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
+   }
+
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+   PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
+
+   fdir_info->fdir_space_size = alloc + best;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_available_space = alloc;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_available_space;
+
+   fdir_info->fdir_flow_pool.pool =
+   rte_zmalloc("i40e_fdir_entry",
+   sizeof(struct i40e_fdir_entry) *
+   fdir_info->fdir_space_size,
+   0);
+
+   if (!fdir_info->fdir_flow_pool.pool) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for bitmap flow!");
+   ret = -ENOMEM;
+   goto err_fdir_bitmap_flow_alloc;
+   }
+
+   for (i = 

[dpdk-dev] [PATCH V3 1/2] net/i40e: i40e FDIR update rate optimization data structures

2020-07-13 Thread chenmin . sun
From: Chenmin Sun 

This patch introduces the new data structures for i40e fdir
update rate optimization.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.h | 72 --
 1 file changed, 61 insertions(+), 11 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..8baa67233 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -264,6 +264,15 @@ enum i40e_flxpld_layer_idx {
 #define I40E_DEFAULT_DCB_APP_NUM1
 #define I40E_DEFAULT_DCB_APP_PRIO   3
 
+/*
+ * Struct to store flow created.
+ */
+struct rte_flow {
+   TAILQ_ENTRY(rte_flow) node;
+   enum rte_filter_type filter_type;
+   void *rule;
+};
+
 /**
  * The overhead from MTU to max frame size.
  * Considering QinQ packet, the VLAN tag needs to be counted twice.
@@ -674,17 +683,37 @@ struct i40e_fdir_filter {
struct i40e_fdir_filter_conf fdir;
 };
 
+/* fdir memory pool entry */
+struct i40e_fdir_entry {
+   struct rte_flow flow;
+   uint32_t idx;
+};
+
+/* pre-allocated fdir memory pool */
+struct i40e_fdir_flow_pool {
+   /* a bitmap to manage the fdir pool */
+   struct rte_bitmap *b;
+   /* the size the pool is pf->fdir->fdir_space_size */
+   struct i40e_fdir_entry *pool;
+};
+
+#define FLOW_TO_FLOW_BITMAP(f) \
+   container_of((f), struct i40e_fdir_entry, flow)
+
 TAILQ_HEAD(i40e_fdir_filter_list, i40e_fdir_filter);
 /*
  *  A structure used to define fields of a FDIR related info.
  */
 struct i40e_fdir_info {
+#define PRG_PKT_CNT128
+
struct i40e_vsi *fdir_vsi; /* pointer to fdir VSI structure */
uint16_t match_counter_index;  /* Statistic counter index used for 
fdir*/
struct i40e_tx_queue *txq;
struct i40e_rx_queue *rxq;
void *prg_pkt; /* memory for fdir program packet */
uint64_t dma_addr; /* physic address of packet memory*/
+
/* input set bits for each pctype */
uint64_t input_set[I40E_FILTER_PCTYPE_MAX];
/*
@@ -697,6 +726,36 @@ struct i40e_fdir_info {
struct i40e_fdir_filter_list fdir_list;
struct i40e_fdir_filter **hash_map;
struct rte_hash *hash_table;
+   /* An array to store the inserted rules input */
+   struct i40e_fdir_filter *fdir_filter_array;
+
+   /*
+* Priority ordering at filter invalidation(destroying a flow) between
+* "best effort" space and "guaranteed" space.
+*
+* 0 = At filter invalidation, the hardware first tries to increment the
+* "best effort" space. The "guaranteed" space is incremented only when
+* the global "best effort" space is at it max value or the "best 
effort"
+* space of the PF is at its max value.
+* 1 = At filter invalidation, the hardware first tries to increment its
+* "guaranteed" space. The "best effort" space is incremented only when
+* it is already at its max value.
+*/
+   uint32_t fdir_invalprio;
+   /* the total size of the fdir, this number is the sum of the guaranteed 
+
+* shared space
+*/
+   uint32_t fdir_space_size;
+   /* the actual number of the fdir rules in hardware, initialized as 0 */
+   uint32_t fdir_actual_cnt;
+   /* the guaranteed space of the fdir */
+   uint32_t fdir_guarantee_free_space;
+   /* the available guaranteed space, initialized as the
+* fdir_guarantee_free_space and dynamically maintained
+*/
+   uint32_t fdir_guarantee_available_space;
+   /* the pre-allocated pool of the rte_flow */
+   struct i40e_fdir_flow_pool fdir_flow_pool;
 
/* Mark if flex pit and mask is set */
bool flex_pit_flag[I40E_MAX_FLXPLD_LAYER];
@@ -894,15 +953,6 @@ struct i40e_mirror_rule {
 
 TAILQ_HEAD(i40e_mirror_rule_list, i40e_mirror_rule);
 
-/*
- * Struct to store flow created.
- */
-struct rte_flow {
-   TAILQ_ENTRY(rte_flow) node;
-   enum rte_filter_type filter_type;
-   void *rule;
-};
-
 TAILQ_HEAD(i40e_flow_list, rte_flow);
 
 /* Struct to store Traffic Manager shaper profile. */
@@ -1335,8 +1385,8 @@ int i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
 const struct rte_eth_fdir_filter *filter,
 bool add);
 int i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct i40e_fdir_filter_conf *filter,
- bool add);
+ const struct i40e_fdir_filter_conf *filter,
+ bool add);
 int i40e_dev_tunnel_filter_set(struct i40e_pf *pf,
   struct rte_eth_tunnel_filter_conf *tunnel_filter,
   uint8_t add);
-- 
2.17.1



[dpdk-dev] [PATCH V4 0/4] i40e FDIR update rate optimization

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

[PATCH v4 1/4] net/i40e: introducing the fdir guaranteed/shared space tracking
[PATCH v4 2/4] net/i40e: FDIR flow memory management optimization
[PATCH v4 2/4] net/i40e: move the i40e_get_outer_vlan to where it real needed
[PATCH v4 2/4] net/i40e: FDIR update rate optimization

v4:
* Split the patch to 4
* New two functions for fdir mempool get/put.
* Rewrite function i40e_find_available_buffer().
* Move the fdir space tracking logic to i40e_flow_add_del_fdir_filter().
v3:
* Split the patch into two.
* Renamed some data structures and added some descriptions.
v2:
* Refine commit message and code comments.
* Refine code style.
* Fixed several memory free bugs.
* Replace the bin_serch() with rte_bsf64()

Chenmin Sun (4):
  net/i40e: introducing the fdir space tracking
  net/i40e: FDIR flow memory management optimization
  net/i40e: move the i40e_get_outer_vlan to where it real needed
  net/i40e: FDIR update rate optimization

 drivers/net/i40e/i40e_ethdev.c | 135 +++-
 drivers/net/i40e/i40e_ethdev.h |  85 --
 drivers/net/i40e/i40e_fdir.c   | 284 ++---
 drivers/net/i40e/i40e_flow.c   | 108 +
 drivers/net/i40e/i40e_rxtx.c   |   7 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 6 files changed, 509 insertions(+), 113 deletions(-)

-- 
2.17.1



[dpdk-dev] [PATCH V4 3/4] net/i40e: move the i40e_get_outer_vlan to where it real needed

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch moves the fetching the device tpid to where it really needs,
rather than fetching it every time when entered the functions.
This is because this operation costs too many cycles and it is used only
when matching the ethernet header.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_flow.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8c36f29b9..9a8bca46f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2047,9 +2047,6 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
const struct rte_flow_item_eth *eth_spec;
const struct rte_flow_item_eth *eth_mask;
enum rte_flow_item_type item_type;
-   uint16_t outer_tpid;
-
-   outer_tpid = i40e_get_outer_vlan(dev);
 
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2109,7 +2106,7 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
filter->ether_type == RTE_ETHER_TYPE_LLDP ||
-   filter->ether_type == outer_tpid) {
+   filter->ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
   RTE_FLOW_ERROR_TYPE_ITEM,
   item,
@@ -2611,7 +2608,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
uint16_t flex_size;
bool cfg_flex_pit = true;
bool cfg_flex_msk = true;
-   uint16_t outer_tpid;
uint16_t ether_type;
uint32_t vtc_flow_cpu;
bool outer_ip = true;
@@ -2620,7 +2616,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
memset(off_arr, 0, sizeof(off_arr));
memset(len_arr, 0, sizeof(len_arr));
memset(flex_mask, 0, I40E_FDIR_MAX_FLEX_LEN);
-   outer_tpid = i40e_get_outer_vlan(dev);
filter->input.flow_ext.customized_pctype = false;
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2688,7 +2683,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
if (next_type == RTE_FLOW_ITEM_TYPE_VLAN ||
ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
@@ -2732,7 +2727,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
if (ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
-- 
2.17.1



[dpdk-dev] [PATCH V4 1/4] net/i40e: introducing the fdir space tracking

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch introduces a fdir flow management for guaranteed/shared
space tracking.
The fdir space is reported by the
i40e_hw_capabilities.fd_filters_guaranteed and fd_filters_best_effort.
The fdir space is managed by hardware and now is tracking in software.
The management algorithm is controlled by the GLQF_CTL.INVALPRIO.
Detailed implementation please check in the datasheet and the
description of struct i40e_fdir_info.fdir_invalprio.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c | 41 ++
 drivers/net/i40e/i40e_ethdev.h | 28 +--
 drivers/net/i40e/i40e_fdir.c   | 16 +
 drivers/net/i40e/i40e_flow.c   |  5 +
 drivers/net/i40e/i40e_rxtx.c   |  1 +
 5 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..dca84a1f1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,11 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
+   uint32_t best = hw->func_caps.fd_filters_best_effort;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1071,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
return -EINVAL;
}
+
fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
  sizeof(struct i40e_fdir_filter *) *
  I40E_MAX_FDIR_FILTER_NUM,
@@ -1077,6 +1082,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
ret = -ENOMEM;
goto err_fdir_hash_map_alloc;
}
+
+   fdir_info->fdir_space_size = alloc + best;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_total_space = alloc;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_total_space;
+
+   PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
+
return 0;
 
 err_fdir_hash_map_alloc:
@@ -1101,6 +1115,30 @@ i40e_init_customized_info(struct i40e_pf *pf)
pf->esp_support = false;
 }
 
+static void
+i40e_init_filter_invalidation(struct i40e_pf *pf)
+{
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+   struct i40e_fdir_info *fdir_info = &pf->fdir;
+   uint32_t glqf_ctl_reg = 0;
+
+   glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+   } else {
+   if (glqf_ctl_reg & I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
+   }
+}
+
 void
 i40e_init_queue_region_conf(struct rte_eth_dev *dev)
 {
@@ -1654,6 +1692,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
/* Initialize customized information */
i40e_init_customized_info(pf);
 
+   /* Initialize the filter invalidation configuration */
+   i40e_init_filter_invalidation(pf);
+
ret = i40e_init_ethtype_filter_list(dev);
if (ret < 0)
goto err_init_ethtype_filter_list;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..eb505c799 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -698,6 +698,30 @@ struct i40e_fdir_info {
struct i40e_fdir_filter **hash_map;
struct rte_hash *hash_table;
 
+   /*
+* Priority ordering at filter invalidation(destroying a flow) between
+* "best effort" space and "guaranteed" sp

[dpdk-dev] [PATCH V4 2/4] net/i40e: FDIR flow memory management optimization

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch allocated some memory pool for flow management to avoid
calling rte_zmalloc/rte_free every time.
This patch also improves the hash table operation. When adding/removing
a flow, the software will directly add/delete it from the hash table.
If any error occurs, it then roll back the operation it just done.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c |  94 +++--
 drivers/net/i40e/i40e_ethdev.h |  43 +---
 drivers/net/i40e/i40e_fdir.c   | 121 -
 drivers/net/i40e/i40e_flow.c   |  92 ++---
 4 files changed, 280 insertions(+), 70 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index dca84a1f1..690164320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1051,6 +1051,10 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
char fdir_hash_name[RTE_HASH_NAMESIZE];
uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
uint32_t best = hw->func_caps.fd_filters_best_effort;
+   struct rte_bitmap *bmp = NULL;
+   uint32_t bmp_size;
+   void *mem = NULL;
+   uint32_t i = 0;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1083,6 +1087,18 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
goto err_fdir_hash_map_alloc;
}
 
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct i40e_fdir_filter) *
+   I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   if (!fdir_info->fdir_filter_array) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir filter 
array!");
+   ret = -ENOMEM;
+   goto err_fdir_filter_array_alloc;
+   }
+
fdir_info->fdir_space_size = alloc + best;
fdir_info->fdir_actual_cnt = 0;
fdir_info->fdir_guarantee_total_space = alloc;
@@ -1091,8 +1107,53 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 
PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
 
+   fdir_info->fdir_flow_pool.pool =
+   rte_zmalloc("i40e_fdir_entry",
+   sizeof(struct i40e_fdir_entry) *
+   fdir_info->fdir_space_size,
+   0);
+
+   if (!fdir_info->fdir_flow_pool.pool) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for bitmap flow!");
+   ret = -ENOMEM;
+   goto err_fdir_bitmap_flow_alloc;
+   }
+
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   fdir_info->fdir_flow_pool.pool[i].idx = i;
+
+   bmp_size =
+   rte_bitmap_get_memory_footprint(fdir_info->fdir_space_size);
+   mem = rte_zmalloc("fdir_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+   if (mem == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_mem_alloc;
+   }
+   bmp = rte_bitmap_init(fdir_info->fdir_space_size, mem, bmp_size);
+   if (bmp == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to initialization fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_bmp_alloc;
+   }
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   rte_bitmap_set(bmp, i);
+
+   fdir_info->fdir_flow_pool.bitmap = bmp;
+
return 0;
 
+err_fdir_bmp_alloc:
+   rte_free(mem);
+err_fdir_mem_alloc:
+   rte_free(fdir_info->fdir_flow_pool.pool);
+err_fdir_bitmap_flow_alloc:
+   rte_free(fdir_info->fdir_filter_array);
+err_fdir_filter_array_alloc:
+   rte_free(fdir_info->hash_map);
 err_fdir_hash_map_alloc:
rte_hash_free(fdir_info->hash_table);
 
@@ -1790,16 +1851,30 @@ i40e_rm_fdir_filter_list(struct i40e_pf *pf)
struct i40e_fdir_info *fdir_info;
 
fdir_info = &pf->fdir;
-   /* Remove all flow director rules and hash */
+
+   /* Remove all flow director rules */
+   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list)))
+   TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+}
+
+static void
+i40e_fdir_memory_cleanup(struct i40e_pf *pf)
+{
+   struct i40e_fdir_info *fdir_info;
+
+   fdir_info = &pf->fdir;
+
+   /* flow director memory cleanup */
if (fdir_info->hash_map)
rte_free(fdir_info->hash_map);
if (fdir_info->hash_table)
rte_hash_free(fdir_info->hash_table);
-
-   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))

[dpdk-dev] [PATCH V4 4/4] net/i40e: FDIR update rate optimization

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking
whether the fdir rule being inserted into the guaranteed space
or shared space.
For the flows that are inserted to the guaranteed space, we assume
that the insertion will always succeed as the hardware only report
the "no enough space left" error. In this case, the software can
directly return success and no need to retrieve the result from
the hardware. When destroying a flow, we also assume the operation
will succeed as the software has checked the flow is indeed in
the hardware.
See the fdir programming status descriptor format in the datasheet
for more details.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.h |  14 ++-
 drivers/net/i40e/i40e_fdir.c   | 151 ++---
 drivers/net/i40e/i40e_rxtx.c   |   6 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 4 files changed, 139 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f4f34dad3..96b42b376 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -264,6 +264,8 @@ enum i40e_flxpld_layer_idx {
 #define I40E_DEFAULT_DCB_APP_NUM1
 #define I40E_DEFAULT_DCB_APP_PRIO   3
 
+#define I40E_FDIR_PRG_PKT_CNT   128
+
 /*
  * Struct to store flow created.
  */
@@ -705,12 +707,20 @@ TAILQ_HEAD(i40e_fdir_filter_list, i40e_fdir_filter);
  *  A structure used to define fields of a FDIR related info.
  */
 struct i40e_fdir_info {
+#define I40E_FDIR_PRG_PKT_CNT   128
+
struct i40e_vsi *fdir_vsi; /* pointer to fdir VSI structure */
uint16_t match_counter_index;  /* Statistic counter index used for 
fdir*/
struct i40e_tx_queue *txq;
struct i40e_rx_queue *rxq;
-   void *prg_pkt; /* memory for fdir program packet */
-   uint64_t dma_addr; /* physic address of packet memory*/
+   void *prg_pkt[I40E_FDIR_PRG_PKT_CNT]; /* memory for fdir program 
packet */
+   uint64_t dma_addr[I40E_FDIR_PRG_PKT_CNT]; /* physic address of packet 
memory*/
+   /*
+* txq available buffer counter, indicates how many available buffers
+* for fdir programming, initialized as I40E_FDIR_PRG_PKT_CNT
+*/
+   int txq_available_buf_count;
+
/* input set bits for each pctype */
uint64_t input_set[I40E_FILTER_PCTYPE_MAX];
/*
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index fb778202f..c2647224e 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -100,7 +100,7 @@ static int
 i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
  enum i40e_filter_pctype pctype,
  const struct i40e_fdir_filter_conf *filter,
- bool add);
+ bool add, bool wait_status);
 
 static int
 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
@@ -164,6 +164,7 @@ i40e_fdir_setup(struct i40e_pf *pf)
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz = NULL;
struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
+   uint16_t i;
 
if ((pf->flags & I40E_FLAG_FDIR) == 0) {
PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
@@ -235,15 +236,21 @@ i40e_fdir_setup(struct i40e_pf *pf)
eth_dev->device->driver->name,
I40E_FDIR_MZ_NAME,
eth_dev->data->port_id);
-   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
+   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN *
+   I40E_FDIR_PRG_PKT_CNT, SOCKET_ID_ANY);
if (!mz) {
PMD_DRV_LOG(ERR, "Cannot init memzone for "
 "flow director program packet.");
err = I40E_ERR_NO_MEMORY;
goto fail_mem;
}
-   pf->fdir.prg_pkt = mz->addr;
-   pf->fdir.dma_addr = mz->iova;
+
+   for (i = 0; i < I40E_FDIR_PRG_PKT_CNT; i++) {
+   pf->fdir.prg_pkt[i] = (uint8_t *)mz->addr +
+   I40E_FDIR_PKT_LEN * i;
+   pf->fdir.dma_addr[i] = mz->iova +
+   I40E_FDIR_PKT_LEN * i;
+   }
 
pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
pf->fdir.fdir_actual_cnt = 0;
@@ -1687,7 +1694,7 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
 {
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
-   unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
+   unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt[0];
enum i40e_filter_pctype pctype;
int ret = 0;
 

[dpdk-dev] [PATCH] net/i40e: fix fdir cannot receive rx writeback issue

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch fixes the fdir connot receive rx writeback packet issue,
by setting the fdir_vsi->nb_used_qps to 1.
Besides this, to make sure fdir programming works fine when the port
is stopped, move the fdir interrupt configure from start/stop to
setup/teardown.

Fixes: cfd662d22e ("net/i40e: fix interrupt throttling setting in PF")

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c | 15 ++-
 drivers/net/i40e/i40e_ethdev.h |  2 ++
 drivers/net/i40e/i40e_fdir.c   | 11 +++
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..8933a39f2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2068,7 +2068,7 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t 
itr_idx)
}
 }
 
-static void
+void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2095,7 +2095,7 @@ i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
I40E_WRITE_FLUSH(hw);
 }
 
-static void
+void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2317,13 +2317,6 @@ i40e_dev_start(struct rte_eth_dev *dev)
i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
}
 
-   /* enable FDIR MSIX interrupt */
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi,
- I40E_ITR_INDEX_NONE);
-   i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi);
-   }
-
/* Enable all queues which have been configured */
for (nb_rxq = 0; nb_rxq < dev->data->nb_rx_queues; nb_rxq++) {
ret = i40e_dev_rx_queue_start(dev, nb_rxq);
@@ -2459,10 +2452,6 @@ i40e_dev_stop(struct rte_eth_dev *dev)
i40e_vsi_queues_unbind_intr(pf->vmdq[i].vsi);
}
 
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_unbind_intr(pf->fdir.fdir_vsi);
-   i40e_vsi_disable_queues_intr(pf->fdir.fdir_vsi);
-   }
/* Clear all queues and release memory */
i40e_dev_clear_queues(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..886c98b15 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1268,6 +1268,7 @@ void i40e_pf_enable_irq0(struct i40e_hw *hw);
 int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx);
 void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi);
+void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi);
 int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
   struct i40e_vsi_vlan_pvid_info *info);
 int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
@@ -1277,6 +1278,7 @@ uint64_t i40e_parse_hena(const struct i40e_adapter 
*adapter, uint64_t flags);
 enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);
 enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);
 int i40e_fdir_setup(struct i40e_pf *pf);
+void i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi);
 const struct rte_memzone *i40e_memzone_reserve(const char *name,
uint32_t len,
int socket_id);
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 71eb31fb8..60eeccc1a 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -228,6 +228,11 @@ i40e_fdir_setup(struct i40e_pf *pf)
goto fail_mem;
}
 
+   /* enable FDIR MSIX interrupt */
+   vsi->nb_used_qps = 1;
+   i40e_vsi_queues_bind_intr(vsi, I40E_ITR_INDEX_NONE);
+   i40e_vsi_enable_queues_intr(vsi);
+
/* reserve memory for the fdir programming packet */
snprintf(z_name, sizeof(z_name), "%s_%s_%d",
eth_dev->device->driver->name,
@@ -274,12 +279,18 @@ i40e_fdir_teardown(struct i40e_pf *pf)
vsi = pf->fdir.fdir_vsi;
if (!vsi)
return;
+
+   /* disable FDIR MSIX interrupt */
+   i40e_vsi_queues_unbind_intr(vsi);
+   i40e_vsi_disable_queues_intr(vsi);
+
int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
+
i40e_dev_rx_queue_release(pf->fdir.rxq);
rte_eth_dma_zone_free(dev, "fdir_rx_ring", pf->fdir.rxq->queue_id);
pf->fdir.rxq = NULL;
-- 
2.17.1



[dpdk-dev] [PATCH V2] net/i40e: fix fdir cannot receive rx writeback issue

2020-07-15 Thread chenmin . sun
From: Chenmin Sun 

This patch fixes the fdir cannot receive rx writeback packet issue,
by setting the fdir_vsi->nb_used_qps to 1.
Besides this, to make sure fdir programming works fine when the port
is stopped, move the fdir interrupt configure from start/stop to
setup/teardown.

Fixes: cfd662d22e ("net/i40e: fix interrupt throttling setting in PF")

Signed-off-by: Chenmin Sun 
---

v2:
* Fix commit message typo
---
 drivers/net/i40e/i40e_ethdev.c | 15 ++-
 drivers/net/i40e/i40e_ethdev.h |  2 ++
 drivers/net/i40e/i40e_fdir.c   | 11 +++
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..8933a39f2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2068,7 +2068,7 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t 
itr_idx)
}
 }
 
-static void
+void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2095,7 +2095,7 @@ i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
I40E_WRITE_FLUSH(hw);
 }
 
-static void
+void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2317,13 +2317,6 @@ i40e_dev_start(struct rte_eth_dev *dev)
i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
}
 
-   /* enable FDIR MSIX interrupt */
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi,
- I40E_ITR_INDEX_NONE);
-   i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi);
-   }
-
/* Enable all queues which have been configured */
for (nb_rxq = 0; nb_rxq < dev->data->nb_rx_queues; nb_rxq++) {
ret = i40e_dev_rx_queue_start(dev, nb_rxq);
@@ -2459,10 +2452,6 @@ i40e_dev_stop(struct rte_eth_dev *dev)
i40e_vsi_queues_unbind_intr(pf->vmdq[i].vsi);
}
 
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_unbind_intr(pf->fdir.fdir_vsi);
-   i40e_vsi_disable_queues_intr(pf->fdir.fdir_vsi);
-   }
/* Clear all queues and release memory */
i40e_dev_clear_queues(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..886c98b15 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1268,6 +1268,7 @@ void i40e_pf_enable_irq0(struct i40e_hw *hw);
 int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx);
 void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi);
+void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi);
 int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
   struct i40e_vsi_vlan_pvid_info *info);
 int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
@@ -1277,6 +1278,7 @@ uint64_t i40e_parse_hena(const struct i40e_adapter 
*adapter, uint64_t flags);
 enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);
 enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);
 int i40e_fdir_setup(struct i40e_pf *pf);
+void i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi);
 const struct rte_memzone *i40e_memzone_reserve(const char *name,
uint32_t len,
int socket_id);
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 71eb31fb8..60eeccc1a 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -228,6 +228,11 @@ i40e_fdir_setup(struct i40e_pf *pf)
goto fail_mem;
}
 
+   /* enable FDIR MSIX interrupt */
+   vsi->nb_used_qps = 1;
+   i40e_vsi_queues_bind_intr(vsi, I40E_ITR_INDEX_NONE);
+   i40e_vsi_enable_queues_intr(vsi);
+
/* reserve memory for the fdir programming packet */
snprintf(z_name, sizeof(z_name), "%s_%s_%d",
eth_dev->device->driver->name,
@@ -274,12 +279,18 @@ i40e_fdir_teardown(struct i40e_pf *pf)
vsi = pf->fdir.fdir_vsi;
if (!vsi)
return;
+
+   /* disable FDIR MSIX interrupt */
+   i40e_vsi_queues_unbind_intr(vsi);
+   i40e_vsi_disable_queues_intr(vsi);
+
int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
+
i40e_dev_rx_queue_release(pf->fdir.rxq);
rte_eth_dma_zone_free(dev, "fdir_rx_ring", pf->fdir.rxq->queue_id);
pf->fdir.rxq = NULL;
-- 
2.17.1



[dpdk-dev] [PATCH v3] net/i40e: fix fdir cannot receive rx writeback issue

2020-07-16 Thread chenmin . sun
From: Chenmin Sun 

This patch fixes the fdir cannot receive rx writeback packet issue.
The root cause is FDIR interrupt is not correctly enabled.

Beside this, to make sure fdir programming works fine when the port
is stopped, move the fdir interrupt configure from start/stop to
setup/teardown.

Fixes: cfd662d22e7b ("net/i40e: fix interrupt throttling setting in PF")

Signed-off-by: Chenmin Sun 
---

v3:
* Refine commit log
v2:
* Fix commit message typo
---
 drivers/net/i40e/i40e_ethdev.c | 15 ++-
 drivers/net/i40e/i40e_ethdev.h |  2 ++
 drivers/net/i40e/i40e_fdir.c   | 11 +++
 3 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..8933a39f2 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2068,7 +2068,7 @@ i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t 
itr_idx)
}
 }
 
-static void
+void
 i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2095,7 +2095,7 @@ i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi)
I40E_WRITE_FLUSH(hw);
 }
 
-static void
+void
 i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi)
 {
struct rte_eth_dev *dev = vsi->adapter->eth_dev;
@@ -2317,13 +2317,6 @@ i40e_dev_start(struct rte_eth_dev *dev)
i40e_vsi_enable_queues_intr(pf->vmdq[i].vsi);
}
 
-   /* enable FDIR MSIX interrupt */
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_bind_intr(pf->fdir.fdir_vsi,
- I40E_ITR_INDEX_NONE);
-   i40e_vsi_enable_queues_intr(pf->fdir.fdir_vsi);
-   }
-
/* Enable all queues which have been configured */
for (nb_rxq = 0; nb_rxq < dev->data->nb_rx_queues; nb_rxq++) {
ret = i40e_dev_rx_queue_start(dev, nb_rxq);
@@ -2459,10 +2452,6 @@ i40e_dev_stop(struct rte_eth_dev *dev)
i40e_vsi_queues_unbind_intr(pf->vmdq[i].vsi);
}
 
-   if (pf->fdir.fdir_vsi) {
-   i40e_vsi_queues_unbind_intr(pf->fdir.fdir_vsi);
-   i40e_vsi_disable_queues_intr(pf->fdir.fdir_vsi);
-   }
/* Clear all queues and release memory */
i40e_dev_clear_queues(dev);
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..886c98b15 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -1268,6 +1268,7 @@ void i40e_pf_enable_irq0(struct i40e_hw *hw);
 int i40e_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete);
 void i40e_vsi_queues_bind_intr(struct i40e_vsi *vsi, uint16_t itr_idx);
 void i40e_vsi_queues_unbind_intr(struct i40e_vsi *vsi);
+void i40e_vsi_disable_queues_intr(struct i40e_vsi *vsi);
 int i40e_vsi_vlan_pvid_set(struct i40e_vsi *vsi,
   struct i40e_vsi_vlan_pvid_info *info);
 int i40e_vsi_config_vlan_stripping(struct i40e_vsi *vsi, bool on);
@@ -1277,6 +1278,7 @@ uint64_t i40e_parse_hena(const struct i40e_adapter 
*adapter, uint64_t flags);
 enum i40e_status_code i40e_fdir_setup_tx_resources(struct i40e_pf *pf);
 enum i40e_status_code i40e_fdir_setup_rx_resources(struct i40e_pf *pf);
 int i40e_fdir_setup(struct i40e_pf *pf);
+void i40e_vsi_enable_queues_intr(struct i40e_vsi *vsi);
 const struct rte_memzone *i40e_memzone_reserve(const char *name,
uint32_t len,
int socket_id);
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index 71eb31fb8..60eeccc1a 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -228,6 +228,11 @@ i40e_fdir_setup(struct i40e_pf *pf)
goto fail_mem;
}
 
+   /* enable FDIR MSIX interrupt */
+   vsi->nb_used_qps = 1;
+   i40e_vsi_queues_bind_intr(vsi, I40E_ITR_INDEX_NONE);
+   i40e_vsi_enable_queues_intr(vsi);
+
/* reserve memory for the fdir programming packet */
snprintf(z_name, sizeof(z_name), "%s_%s_%d",
eth_dev->device->driver->name,
@@ -274,12 +279,18 @@ i40e_fdir_teardown(struct i40e_pf *pf)
vsi = pf->fdir.fdir_vsi;
if (!vsi)
return;
+
+   /* disable FDIR MSIX interrupt */
+   i40e_vsi_queues_unbind_intr(vsi);
+   i40e_vsi_disable_queues_intr(vsi);
+
int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
if (err)
PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
+
i40e_dev_rx_queue_release(pf->fdir.rxq);
rte_eth_dma_zone_free(dev, "fdir_rx_ring", pf->fdir.rxq->queue_id);
pf->fdir.rxq = NULL;
-- 
2.17.1



[dpdk-dev] [PATCH v5 0/4] i40e FDIR update rate optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

[PATCH v5 1/4] net/i40e: introducing the fdir guaranteed/shared space tracking
[PATCH v5 2/4] net/i40e: FDIR flow memory management optimization
[PATCH v5 2/4] net/i40e: move the i40e_get_outer_vlan to where it real needed
[PATCH v5 2/4] net/i40e: FDIR update rate optimization

v5:
* Remove duplicated macro definition
* Replace multiplication and division with bitwise operators
v4:
* Split the patch to 4
* New two functions for fdir mempool get/put.
* Rewrite function i40e_find_available_buffer().
* Move the fdir space tracking logic to i40e_flow_add_del_fdir_filter().
v3:
* Split the patch into two.
* Renamed some data structures and added some descriptions.
v2:
* Refine commit message and code comments.
* Refine code style.
* Fixed several memory free bugs.
* Replace the bin_serch() with rte_bsf64()

Chenmin Sun (4):
  net/i40e: introducing the fdir space tracking
  net/i40e: FDIR flow memory management optimization
  net/i40e: move the i40e_get_outer_vlan to where it real needed
  net/i40e: FDIR update rate optimization

 drivers/net/i40e/i40e_ethdev.c | 135 +++-
 drivers/net/i40e/i40e_ethdev.h |  83 --
 drivers/net/i40e/i40e_fdir.c   | 271 ++---
 drivers/net/i40e/i40e_flow.c   | 108 +
 drivers/net/i40e/i40e_rxtx.c   |   7 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 6 files changed, 494 insertions(+), 113 deletions(-)

-- 
2.17.1



[dpdk-dev] [PATCH v5 1/4] net/i40e: introducing the fdir space tracking

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch introduces a fdir flow management for guaranteed/shared
space tracking.
The fdir space is reported by the
i40e_hw_capabilities.fd_filters_guaranteed and fd_filters_best_effort.
The fdir space is managed by hardware and now is tracking in software.
The management algorithm is controlled by the GLQF_CTL.INVALPRIO.
Detailed implementation please check in the datasheet and the
description of struct i40e_fdir_info.fdir_invalprio.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c | 41 ++
 drivers/net/i40e/i40e_ethdev.h | 28 +--
 drivers/net/i40e/i40e_fdir.c   | 16 +
 drivers/net/i40e/i40e_flow.c   |  5 +
 drivers/net/i40e/i40e_rxtx.c   |  1 +
 5 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..dca84a1f1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,11 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
+   uint32_t best = hw->func_caps.fd_filters_best_effort;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1071,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
return -EINVAL;
}
+
fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
  sizeof(struct i40e_fdir_filter *) *
  I40E_MAX_FDIR_FILTER_NUM,
@@ -1077,6 +1082,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
ret = -ENOMEM;
goto err_fdir_hash_map_alloc;
}
+
+   fdir_info->fdir_space_size = alloc + best;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_total_space = alloc;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_total_space;
+
+   PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
+
return 0;
 
 err_fdir_hash_map_alloc:
@@ -1101,6 +1115,30 @@ i40e_init_customized_info(struct i40e_pf *pf)
pf->esp_support = false;
 }
 
+static void
+i40e_init_filter_invalidation(struct i40e_pf *pf)
+{
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+   struct i40e_fdir_info *fdir_info = &pf->fdir;
+   uint32_t glqf_ctl_reg = 0;
+
+   glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+   } else {
+   if (glqf_ctl_reg & I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
+   }
+}
+
 void
 i40e_init_queue_region_conf(struct rte_eth_dev *dev)
 {
@@ -1654,6 +1692,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
/* Initialize customized information */
i40e_init_customized_info(pf);
 
+   /* Initialize the filter invalidation configuration */
+   i40e_init_filter_invalidation(pf);
+
ret = i40e_init_ethtype_filter_list(dev);
if (ret < 0)
goto err_init_ethtype_filter_list;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..eb505c799 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -698,6 +698,30 @@ struct i40e_fdir_info {
struct i40e_fdir_filter **hash_map;
struct rte_hash *hash_table;
 
+   /*
+* Priority ordering at filter invalidation(destroying a flow) between
+* "best effort" space and "guaranteed" sp

[dpdk-dev] [PATCH v5 4/4] net/i40e: FDIR update rate optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking
whether the fdir rule being inserted into the guaranteed space
or shared space.
For the flows that are inserted to the guaranteed space, we assume
that the insertion will always succeed as the hardware only report
the "no enough space left" error. In this case, the software can
directly return success and no need to retrieve the result from
the hardware. When destroying a flow, we also assume the operation
will succeed as the software has checked the flow is indeed in
the hardware.
See the fdir programming status descriptor format in the datasheet
for more details.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.h |  12 ++-
 drivers/net/i40e/i40e_fdir.c   | 138 ++---
 drivers/net/i40e/i40e_rxtx.c   |   6 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 4 files changed, 124 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f4f34dad3..d3bda0272 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -264,6 +264,8 @@ enum i40e_flxpld_layer_idx {
 #define I40E_DEFAULT_DCB_APP_NUM1
 #define I40E_DEFAULT_DCB_APP_PRIO   3
 
+#define I40E_FDIR_PRG_PKT_CNT   128
+
 /*
  * Struct to store flow created.
  */
@@ -709,8 +711,14 @@ struct i40e_fdir_info {
uint16_t match_counter_index;  /* Statistic counter index used for 
fdir*/
struct i40e_tx_queue *txq;
struct i40e_rx_queue *rxq;
-   void *prg_pkt; /* memory for fdir program packet */
-   uint64_t dma_addr; /* physic address of packet memory*/
+   void *prg_pkt[I40E_FDIR_PRG_PKT_CNT]; /* memory for fdir program 
packet */
+   uint64_t dma_addr[I40E_FDIR_PRG_PKT_CNT]; /* physic address of packet 
memory*/
+   /*
+* txq available buffer counter, indicates how many available buffers
+* for fdir programming, initialized as I40E_FDIR_PRG_PKT_CNT
+*/
+   int txq_available_buf_count;
+
/* input set bits for each pctype */
uint64_t input_set[I40E_FILTER_PCTYPE_MAX];
/*
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index fb778202f..ec35345d6 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -100,7 +100,7 @@ static int
 i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
  enum i40e_filter_pctype pctype,
  const struct i40e_fdir_filter_conf *filter,
- bool add);
+ bool add, bool wait_status);
 
 static int
 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
@@ -164,6 +164,7 @@ i40e_fdir_setup(struct i40e_pf *pf)
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz = NULL;
struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
+   uint16_t i;
 
if ((pf->flags & I40E_FLAG_FDIR) == 0) {
PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
@@ -235,15 +236,21 @@ i40e_fdir_setup(struct i40e_pf *pf)
eth_dev->device->driver->name,
I40E_FDIR_MZ_NAME,
eth_dev->data->port_id);
-   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
+   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN *
+   I40E_FDIR_PRG_PKT_CNT, SOCKET_ID_ANY);
if (!mz) {
PMD_DRV_LOG(ERR, "Cannot init memzone for "
 "flow director program packet.");
err = I40E_ERR_NO_MEMORY;
goto fail_mem;
}
-   pf->fdir.prg_pkt = mz->addr;
-   pf->fdir.dma_addr = mz->iova;
+
+   for (i = 0; i < I40E_FDIR_PRG_PKT_CNT; i++) {
+   pf->fdir.prg_pkt[i] = (uint8_t *)mz->addr +
+   I40E_FDIR_PKT_LEN * i;
+   pf->fdir.dma_addr[i] = mz->iova +
+   I40E_FDIR_PKT_LEN * i;
+   }
 
pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
pf->fdir.fdir_actual_cnt = 0;
@@ -1531,6 +1538,17 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue 
*rxq)
return ret;
 }
 
+static inline void
+i40e_fdir_programming_status_cleanup(struct i40e_rx_queue *rxq)
+{
+   uint16_t retry_count = 0;
+
+   /* capture the previous error report(if any) from rx ring */
+   while ((i40e_check_fdir_programming_status(rxq) < 0) &&
+   (++retry_count < I40E_FDIR_NUM_RX_DESC))
+   PMD_DRV_LOG(INFO, "error report captured.");
+}
+
 static int
 i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
 struct i40e_fdir_filter *filter)
@@ -1687,7 +1705

[dpdk-dev] [PATCH v5 3/4] net/i40e: move the i40e_get_outer_vlan to where it real needed

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch moves the fetching the device tpid to where it really needs,
rather than fetching it every time when entered the functions.
This is because this operation costs too many cycles and it is used only
when matching the ethernet header.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_flow.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8c36f29b9..9a8bca46f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2047,9 +2047,6 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
const struct rte_flow_item_eth *eth_spec;
const struct rte_flow_item_eth *eth_mask;
enum rte_flow_item_type item_type;
-   uint16_t outer_tpid;
-
-   outer_tpid = i40e_get_outer_vlan(dev);
 
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2109,7 +2106,7 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
filter->ether_type == RTE_ETHER_TYPE_LLDP ||
-   filter->ether_type == outer_tpid) {
+   filter->ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
   RTE_FLOW_ERROR_TYPE_ITEM,
   item,
@@ -2611,7 +2608,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
uint16_t flex_size;
bool cfg_flex_pit = true;
bool cfg_flex_msk = true;
-   uint16_t outer_tpid;
uint16_t ether_type;
uint32_t vtc_flow_cpu;
bool outer_ip = true;
@@ -2620,7 +2616,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
memset(off_arr, 0, sizeof(off_arr));
memset(len_arr, 0, sizeof(len_arr));
memset(flex_mask, 0, I40E_FDIR_MAX_FLEX_LEN);
-   outer_tpid = i40e_get_outer_vlan(dev);
filter->input.flow_ext.customized_pctype = false;
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2688,7 +2683,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
if (next_type == RTE_FLOW_ITEM_TYPE_VLAN ||
ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
@@ -2732,7 +2727,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
if (ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
-- 
2.17.1



[dpdk-dev] [PATCH v5 2/4] net/i40e: FDIR flow memory management optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch allocated some memory pool for flow management to avoid
calling rte_zmalloc/rte_free every time.
This patch also improves the hash table operation. When adding/removing
a flow, the software will directly add/delete it from the hash table.
If any error occurs, it then roll back the operation it just done.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c |  94 +++--
 drivers/net/i40e/i40e_ethdev.h |  43 +---
 drivers/net/i40e/i40e_fdir.c   | 121 -
 drivers/net/i40e/i40e_flow.c   |  92 ++---
 4 files changed, 280 insertions(+), 70 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index dca84a1f1..690164320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1051,6 +1051,10 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
char fdir_hash_name[RTE_HASH_NAMESIZE];
uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
uint32_t best = hw->func_caps.fd_filters_best_effort;
+   struct rte_bitmap *bmp = NULL;
+   uint32_t bmp_size;
+   void *mem = NULL;
+   uint32_t i = 0;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1083,6 +1087,18 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
goto err_fdir_hash_map_alloc;
}
 
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct i40e_fdir_filter) *
+   I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   if (!fdir_info->fdir_filter_array) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir filter 
array!");
+   ret = -ENOMEM;
+   goto err_fdir_filter_array_alloc;
+   }
+
fdir_info->fdir_space_size = alloc + best;
fdir_info->fdir_actual_cnt = 0;
fdir_info->fdir_guarantee_total_space = alloc;
@@ -1091,8 +1107,53 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 
PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
 
+   fdir_info->fdir_flow_pool.pool =
+   rte_zmalloc("i40e_fdir_entry",
+   sizeof(struct i40e_fdir_entry) *
+   fdir_info->fdir_space_size,
+   0);
+
+   if (!fdir_info->fdir_flow_pool.pool) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for bitmap flow!");
+   ret = -ENOMEM;
+   goto err_fdir_bitmap_flow_alloc;
+   }
+
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   fdir_info->fdir_flow_pool.pool[i].idx = i;
+
+   bmp_size =
+   rte_bitmap_get_memory_footprint(fdir_info->fdir_space_size);
+   mem = rte_zmalloc("fdir_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+   if (mem == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_mem_alloc;
+   }
+   bmp = rte_bitmap_init(fdir_info->fdir_space_size, mem, bmp_size);
+   if (bmp == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to initialization fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_bmp_alloc;
+   }
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   rte_bitmap_set(bmp, i);
+
+   fdir_info->fdir_flow_pool.bitmap = bmp;
+
return 0;
 
+err_fdir_bmp_alloc:
+   rte_free(mem);
+err_fdir_mem_alloc:
+   rte_free(fdir_info->fdir_flow_pool.pool);
+err_fdir_bitmap_flow_alloc:
+   rte_free(fdir_info->fdir_filter_array);
+err_fdir_filter_array_alloc:
+   rte_free(fdir_info->hash_map);
 err_fdir_hash_map_alloc:
rte_hash_free(fdir_info->hash_table);
 
@@ -1790,16 +1851,30 @@ i40e_rm_fdir_filter_list(struct i40e_pf *pf)
struct i40e_fdir_info *fdir_info;
 
fdir_info = &pf->fdir;
-   /* Remove all flow director rules and hash */
+
+   /* Remove all flow director rules */
+   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list)))
+   TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+}
+
+static void
+i40e_fdir_memory_cleanup(struct i40e_pf *pf)
+{
+   struct i40e_fdir_info *fdir_info;
+
+   fdir_info = &pf->fdir;
+
+   /* flow director memory cleanup */
if (fdir_info->hash_map)
rte_free(fdir_info->hash_map);
if (fdir_info->hash_table)
rte_hash_free(fdir_info->hash_table);
-
-   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))

[dpdk-dev] [PATCH v6 0/4] i40e FDIR update rate optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

[PATCH v6 1/4] net/i40e: introducing the fdir guaranteed/shared space tracking
[PATCH v6 2/4] net/i40e: FDIR flow memory management optimization
[PATCH v6 2/4] net/i40e: move the i40e_get_outer_vlan to where it real needed
[PATCH v6 2/4] net/i40e: FDIR update rate optimization

v6:
* Fix a code style issue
v5:
* Remove duplicated macro definition
* Replace multiplication and division with bitwise operators
v4:
* Split the patch to 4
* New two functions for fdir mempool get/put.
* Rewrite function i40e_find_available_buffer().
* Move the fdir space tracking logic to i40e_flow_add_del_fdir_filter().
v3:
* Split the patch into two.
* Renamed some data structures and added some descriptions.
v2:
* Refine commit message and code comments.
* Refine code style.
* Fixed several memory free bugs.
* Replace the bin_serch() with rte_bsf64()

Chenmin Sun (4):
  net/i40e: introducing the fdir space tracking
  net/i40e: FDIR flow memory management optimization
  net/i40e: move the i40e_get_outer_vlan to where it real needed
  net/i40e: FDIR update rate optimization

 drivers/net/i40e/i40e_ethdev.c | 135 +++-
 drivers/net/i40e/i40e_ethdev.h |  83 --
 drivers/net/i40e/i40e_fdir.c   | 271 ++---
 drivers/net/i40e/i40e_flow.c   | 108 +
 drivers/net/i40e/i40e_rxtx.c   |   7 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 6 files changed, 494 insertions(+), 113 deletions(-)

-- 
2.17.1



[dpdk-dev] [PATCH v6 4/4] net/i40e: FDIR update rate optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch optimized the fdir update rate for i40e PF, by tracking
whether the fdir rule being inserted into the guaranteed space
or shared space.
For the flows that are inserted to the guaranteed space, we assume
that the insertion will always succeed as the hardware only report
the "no enough space left" error. In this case, the software can
directly return success and no need to retrieve the result from
the hardware. When destroying a flow, we also assume the operation
will succeed as the software has checked the flow is indeed in
the hardware.
See the fdir programming status descriptor format in the datasheet
for more details.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.h |  12 ++-
 drivers/net/i40e/i40e_fdir.c   | 138 ++---
 drivers/net/i40e/i40e_rxtx.c   |   6 +-
 drivers/net/i40e/i40e_rxtx.h   |   3 +
 4 files changed, 124 insertions(+), 35 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index f4f34dad3..d3bda0272 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -264,6 +264,8 @@ enum i40e_flxpld_layer_idx {
 #define I40E_DEFAULT_DCB_APP_NUM1
 #define I40E_DEFAULT_DCB_APP_PRIO   3
 
+#define I40E_FDIR_PRG_PKT_CNT   128
+
 /*
  * Struct to store flow created.
  */
@@ -709,8 +711,14 @@ struct i40e_fdir_info {
uint16_t match_counter_index;  /* Statistic counter index used for 
fdir*/
struct i40e_tx_queue *txq;
struct i40e_rx_queue *rxq;
-   void *prg_pkt; /* memory for fdir program packet */
-   uint64_t dma_addr; /* physic address of packet memory*/
+   void *prg_pkt[I40E_FDIR_PRG_PKT_CNT]; /* memory for fdir program 
packet */
+   uint64_t dma_addr[I40E_FDIR_PRG_PKT_CNT]; /* physic address of packet 
memory*/
+   /*
+* txq available buffer counter, indicates how many available buffers
+* for fdir programming, initialized as I40E_FDIR_PRG_PKT_CNT
+*/
+   int txq_available_buf_count;
+
/* input set bits for each pctype */
uint64_t input_set[I40E_FILTER_PCTYPE_MAX];
/*
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index fb778202f..9998e5d4f 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -100,7 +100,7 @@ static int
 i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
  enum i40e_filter_pctype pctype,
  const struct i40e_fdir_filter_conf *filter,
- bool add);
+ bool add, bool wait_status);
 
 static int
 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
@@ -164,6 +164,7 @@ i40e_fdir_setup(struct i40e_pf *pf)
char z_name[RTE_MEMZONE_NAMESIZE];
const struct rte_memzone *mz = NULL;
struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
+   uint16_t i;
 
if ((pf->flags & I40E_FLAG_FDIR) == 0) {
PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
@@ -235,15 +236,21 @@ i40e_fdir_setup(struct i40e_pf *pf)
eth_dev->device->driver->name,
I40E_FDIR_MZ_NAME,
eth_dev->data->port_id);
-   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
+   mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN *
+   I40E_FDIR_PRG_PKT_CNT, SOCKET_ID_ANY);
if (!mz) {
PMD_DRV_LOG(ERR, "Cannot init memzone for "
 "flow director program packet.");
err = I40E_ERR_NO_MEMORY;
goto fail_mem;
}
-   pf->fdir.prg_pkt = mz->addr;
-   pf->fdir.dma_addr = mz->iova;
+
+   for (i = 0; i < I40E_FDIR_PRG_PKT_CNT; i++) {
+   pf->fdir.prg_pkt[i] = (uint8_t *)mz->addr +
+   I40E_FDIR_PKT_LEN * i;
+   pf->fdir.dma_addr[i] = mz->iova +
+   I40E_FDIR_PKT_LEN * i;
+   }
 
pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
pf->fdir.fdir_actual_cnt = 0;
@@ -1531,6 +1538,17 @@ i40e_check_fdir_programming_status(struct i40e_rx_queue 
*rxq)
return ret;
 }
 
+static inline void
+i40e_fdir_programming_status_cleanup(struct i40e_rx_queue *rxq)
+{
+   uint16_t retry_count = 0;
+
+   /* capture the previous error report(if any) from rx ring */
+   while ((i40e_check_fdir_programming_status(rxq) < 0) &&
+   (++retry_count < I40E_FDIR_NUM_RX_DESC))
+   PMD_DRV_LOG(INFO, "error report captured.");
+}
+
 static int
 i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
 struct i40e_fdir_filter *filter)
@@ -1687,7 +1705

[dpdk-dev] [PATCH v6 3/4] net/i40e: move the i40e_get_outer_vlan to where it real needed

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch moves the fetching the device tpid to where it really needs,
rather than fetching it every time when entered the functions.
This is because this operation costs too many cycles and it is used only
when matching the ethernet header.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_flow.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 8c36f29b9..9a8bca46f 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2047,9 +2047,6 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
const struct rte_flow_item_eth *eth_spec;
const struct rte_flow_item_eth *eth_mask;
enum rte_flow_item_type item_type;
-   uint16_t outer_tpid;
-
-   outer_tpid = i40e_get_outer_vlan(dev);
 
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2109,7 +2106,7 @@ i40e_flow_parse_ethertype_pattern(struct rte_eth_dev *dev,
if (filter->ether_type == RTE_ETHER_TYPE_IPV4 ||
filter->ether_type == RTE_ETHER_TYPE_IPV6 ||
filter->ether_type == RTE_ETHER_TYPE_LLDP ||
-   filter->ether_type == outer_tpid) {
+   filter->ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
   RTE_FLOW_ERROR_TYPE_ITEM,
   item,
@@ -2611,7 +2608,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
uint16_t flex_size;
bool cfg_flex_pit = true;
bool cfg_flex_msk = true;
-   uint16_t outer_tpid;
uint16_t ether_type;
uint32_t vtc_flow_cpu;
bool outer_ip = true;
@@ -2620,7 +2616,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
memset(off_arr, 0, sizeof(off_arr));
memset(len_arr, 0, sizeof(len_arr));
memset(flex_mask, 0, I40E_FDIR_MAX_FLEX_LEN);
-   outer_tpid = i40e_get_outer_vlan(dev);
filter->input.flow_ext.customized_pctype = false;
for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
if (item->last) {
@@ -2688,7 +2683,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
if (next_type == RTE_FLOW_ITEM_TYPE_VLAN ||
ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
@@ -2732,7 +2727,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 
if (ether_type == RTE_ETHER_TYPE_IPV4 ||
ether_type == RTE_ETHER_TYPE_IPV6 ||
-   ether_type == outer_tpid) {
+   ether_type == i40e_get_outer_vlan(dev)) {
rte_flow_error_set(error, EINVAL,
 RTE_FLOW_ERROR_TYPE_ITEM,
 item,
-- 
2.17.1



[dpdk-dev] [PATCH v6 2/4] net/i40e: FDIR flow memory management optimization

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch allocated some memory pool for flow management to avoid
calling rte_zmalloc/rte_free every time.
This patch also improves the hash table operation. When adding/removing
a flow, the software will directly add/delete it from the hash table.
If any error occurs, it then roll back the operation it just done.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c |  94 +++--
 drivers/net/i40e/i40e_ethdev.h |  43 +---
 drivers/net/i40e/i40e_fdir.c   | 121 -
 drivers/net/i40e/i40e_flow.c   |  92 ++---
 4 files changed, 280 insertions(+), 70 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index dca84a1f1..690164320 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1051,6 +1051,10 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
char fdir_hash_name[RTE_HASH_NAMESIZE];
uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
uint32_t best = hw->func_caps.fd_filters_best_effort;
+   struct rte_bitmap *bmp = NULL;
+   uint32_t bmp_size;
+   void *mem = NULL;
+   uint32_t i = 0;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1083,6 +1087,18 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
goto err_fdir_hash_map_alloc;
}
 
+   fdir_info->fdir_filter_array = rte_zmalloc("fdir_filter",
+   sizeof(struct i40e_fdir_filter) *
+   I40E_MAX_FDIR_FILTER_NUM,
+   0);
+
+   if (!fdir_info->fdir_filter_array) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir filter 
array!");
+   ret = -ENOMEM;
+   goto err_fdir_filter_array_alloc;
+   }
+
fdir_info->fdir_space_size = alloc + best;
fdir_info->fdir_actual_cnt = 0;
fdir_info->fdir_guarantee_total_space = alloc;
@@ -1091,8 +1107,53 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 
PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
 
+   fdir_info->fdir_flow_pool.pool =
+   rte_zmalloc("i40e_fdir_entry",
+   sizeof(struct i40e_fdir_entry) *
+   fdir_info->fdir_space_size,
+   0);
+
+   if (!fdir_info->fdir_flow_pool.pool) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for bitmap flow!");
+   ret = -ENOMEM;
+   goto err_fdir_bitmap_flow_alloc;
+   }
+
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   fdir_info->fdir_flow_pool.pool[i].idx = i;
+
+   bmp_size =
+   rte_bitmap_get_memory_footprint(fdir_info->fdir_space_size);
+   mem = rte_zmalloc("fdir_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
+   if (mem == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to allocate memory for fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_mem_alloc;
+   }
+   bmp = rte_bitmap_init(fdir_info->fdir_space_size, mem, bmp_size);
+   if (bmp == NULL) {
+   PMD_INIT_LOG(ERR,
+"Failed to initialization fdir bitmap!");
+   ret = -ENOMEM;
+   goto err_fdir_bmp_alloc;
+   }
+   for (i = 0; i < fdir_info->fdir_space_size; i++)
+   rte_bitmap_set(bmp, i);
+
+   fdir_info->fdir_flow_pool.bitmap = bmp;
+
return 0;
 
+err_fdir_bmp_alloc:
+   rte_free(mem);
+err_fdir_mem_alloc:
+   rte_free(fdir_info->fdir_flow_pool.pool);
+err_fdir_bitmap_flow_alloc:
+   rte_free(fdir_info->fdir_filter_array);
+err_fdir_filter_array_alloc:
+   rte_free(fdir_info->hash_map);
 err_fdir_hash_map_alloc:
rte_hash_free(fdir_info->hash_table);
 
@@ -1790,16 +1851,30 @@ i40e_rm_fdir_filter_list(struct i40e_pf *pf)
struct i40e_fdir_info *fdir_info;
 
fdir_info = &pf->fdir;
-   /* Remove all flow director rules and hash */
+
+   /* Remove all flow director rules */
+   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list)))
+   TAILQ_REMOVE(&fdir_info->fdir_list, p_fdir, rules);
+}
+
+static void
+i40e_fdir_memory_cleanup(struct i40e_pf *pf)
+{
+   struct i40e_fdir_info *fdir_info;
+
+   fdir_info = &pf->fdir;
+
+   /* flow director memory cleanup */
if (fdir_info->hash_map)
rte_free(fdir_info->hash_map);
if (fdir_info->hash_table)
rte_hash_free(fdir_info->hash_table);
-
-   while ((p_fdir = TAILQ_FIRST(&fdir_info->fdir_list))

[dpdk-dev] [PATCH v6 1/4] net/i40e: introducing the fdir space tracking

2020-07-17 Thread chenmin . sun
From: Chenmin Sun 

This patch introduces a fdir flow management for guaranteed/shared
space tracking.
The fdir space is reported by the
i40e_hw_capabilities.fd_filters_guaranteed and fd_filters_best_effort.
The fdir space is managed by hardware and now is tracking in software.
The management algorithm is controlled by the GLQF_CTL.INVALPRIO.
Detailed implementation please check in the datasheet and the
description of struct i40e_fdir_info.fdir_invalprio.

This patch changes the global register GLQF_CTL. Therefore, when devarg
``support-multi-driver`` is set, the patch will not take effect to
avoid affecting the normal behavior of other i40e drivers, e.g., Linux
kernel driver.

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c | 41 ++
 drivers/net/i40e/i40e_ethdev.h | 28 +--
 drivers/net/i40e/i40e_fdir.c   | 16 +
 drivers/net/i40e/i40e_flow.c   |  5 +
 drivers/net/i40e/i40e_rxtx.c   |  1 +
 5 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 393b5320f..dca84a1f1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "i40e_logs.h"
 #include "base/i40e_prototype.h"
@@ -1045,8 +1046,11 @@ static int
 i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 {
struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
struct i40e_fdir_info *fdir_info = &pf->fdir;
char fdir_hash_name[RTE_HASH_NAMESIZE];
+   uint32_t alloc = hw->func_caps.fd_filters_guaranteed;
+   uint32_t best = hw->func_caps.fd_filters_best_effort;
int ret;
 
struct rte_hash_parameters fdir_hash_params = {
@@ -1067,6 +1071,7 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
PMD_INIT_LOG(ERR, "Failed to create fdir hash table!");
return -EINVAL;
}
+
fdir_info->hash_map = rte_zmalloc("i40e_fdir_hash_map",
  sizeof(struct i40e_fdir_filter *) *
  I40E_MAX_FDIR_FILTER_NUM,
@@ -1077,6 +1082,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
ret = -ENOMEM;
goto err_fdir_hash_map_alloc;
}
+
+   fdir_info->fdir_space_size = alloc + best;
+   fdir_info->fdir_actual_cnt = 0;
+   fdir_info->fdir_guarantee_total_space = alloc;
+   fdir_info->fdir_guarantee_free_space =
+   fdir_info->fdir_guarantee_total_space;
+
+   PMD_DRV_LOG(INFO, "FDIR guarantee space: %u, best_effort space %u.", 
alloc, best);
+
return 0;
 
 err_fdir_hash_map_alloc:
@@ -1101,6 +1115,30 @@ i40e_init_customized_info(struct i40e_pf *pf)
pf->esp_support = false;
 }
 
+static void
+i40e_init_filter_invalidation(struct i40e_pf *pf)
+{
+   struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+   struct i40e_fdir_info *fdir_info = &pf->fdir;
+   uint32_t glqf_ctl_reg = 0;
+
+   glqf_ctl_reg = i40e_read_rx_ctl(hw, I40E_GLQF_CTL);
+   if (!pf->support_multi_driver) {
+   fdir_info->fdir_invalprio = 1;
+   glqf_ctl_reg |= I40E_GLQF_CTL_INVALPRIO_MASK;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO set to guaranteed first");
+   i40e_write_rx_ctl(hw, I40E_GLQF_CTL, glqf_ctl_reg);
+   } else {
+   if (glqf_ctl_reg & I40E_GLQF_CTL_INVALPRIO_MASK) {
+   fdir_info->fdir_invalprio = 1;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: guaranteed 
first");
+   } else {
+   fdir_info->fdir_invalprio = 0;
+   PMD_DRV_LOG(INFO, "FDIR INVALPRIO is: shared first");
+   }
+   }
+}
+
 void
 i40e_init_queue_region_conf(struct rte_eth_dev *dev)
 {
@@ -1654,6 +1692,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev, void 
*init_params __rte_unused)
/* Initialize customized information */
i40e_init_customized_info(pf);
 
+   /* Initialize the filter invalidation configuration */
+   i40e_init_filter_invalidation(pf);
+
ret = i40e_init_ethtype_filter_list(dev);
if (ret < 0)
goto err_init_ethtype_filter_list;
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 31ca05de9..eb505c799 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -698,6 +698,30 @@ struct i40e_fdir_info {
struct i40e_fdir_filter **hash_map;
struct rte_hash *hash_table;
 
+   /*
+* Priority ordering at filter invalidation(destroying a flow) between
+* "best effort" space and "guaranteed" sp

[dpdk-dev] [PATCH] net/i40e: fix a wrong bitmap free call

2020-07-27 Thread chenmin . sun
From: Chenmin Sun 

This patch fixes the coverity warning #361024.
rte_bitmap_free() is not a right way to free a bitmap, replacing
it with rte_free().

Signed-off-by: Chenmin Sun 
---
 drivers/net/i40e/i40e_ethdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 05d5f2861..a17bc9bab 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1870,7 +1870,7 @@ i40e_fdir_memory_cleanup(struct i40e_pf *pf)
if (fdir_info->hash_table)
rte_hash_free(fdir_info->hash_table);
if (fdir_info->fdir_flow_pool.bitmap)
-   rte_bitmap_free(fdir_info->fdir_flow_pool.bitmap);
+   rte_free(fdir_info->fdir_flow_pool.bitmap);
if (fdir_info->fdir_flow_pool.pool)
rte_free(fdir_info->fdir_flow_pool.pool);
if (fdir_info->fdir_filter_array)
-- 
2.17.1