All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] net/i40e: API to configure queue regions for RSS
@ 2017-08-24  3:26 Wei Zhao
  2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
                   ` (2 more replies)
  0 siblings, 3 replies; 87+ messages in thread
From: Wei Zhao @ 2017-08-24  3:26 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.


root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                    | 319 ++++++++++++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.h            |   6 +
 drivers/net/i40e/rte_pmd_i40e.c           | 287 +++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  39 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   7 +
 5 files changed, 658 insertions(+)

-- 
2.9.3

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

* [PATCH 1/2] net/i40e: queue region set and flush
  2017-08-24  3:26 [PATCH 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-08-24  3:26 ` Wei Zhao
  2017-08-31 16:18   ` Ferruh Yigit
  2017-09-05 23:52   ` Chilikin, Andrey
  2017-08-24  3:26 ` [PATCH 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 2 replies; 87+ messages in thread
From: Wei Zhao @ 2017-08-24  3:26 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF/VF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.h            |   6 +
 drivers/net/i40e/rte_pmd_i40e.c           | 287 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  39 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   7 +
 4 files changed, 339 insertions(+)

diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 48abc05..1d6e9b2 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_TCREGION_MAX_INDEX 7
+/* The max queue region userpriority is 7. */
+#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
+/* The max pctype index is 63. */
+#define I40E_REGION_PCTYPE_MAX_INDEX 63
 
 /**
  * The overhead from MTU to max frame size.
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 950a0d6..5d1e1d4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -2117,3 +2117,290 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 
 	return 0;
 }
+
+static int
+i40e_set_queue_region(struct i40e_hw *hw, struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t TCREGION, TC_OFFSET, TC_SIZE;
+	uint16_t TC_SIZE_TB[7] = {1, 2, 4, 8, 16, 32, 64};
+	uint16_t i, index;
+	uint16_t main_vsi_seid = pf->main_vsi_seid;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	uint32_t ret = -EINVAL;
+
+	index = conf_ptr->region_id >> 1;
+	for (i = 0; i < I40E_TCREGION_MAX_INDEX; i++)
+		if (conf_ptr->queue_num == TC_SIZE_TB[i])
+			break;
+
+	if (i == I40E_TCREGION_MAX_INDEX) {
+		printf("The region sizes should be any of the following "
+		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+		"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id >= I40E_TCREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_startIndex + conf_ptr->queue_num)
+					> main_vsi->nb_qps) {
+		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	TCREGION = i40e_read_rx_ctl(hw,
+				I40E_VSIQF_TCREGION(index, main_vsi_seid));
+	if ((conf_ptr->region_id & 1) == 0) {
+		TC_OFFSET = (conf_ptr->queue_startIndex <<
+					I40E_VSIQF_TCREGION_TC_OFFSET_SHIFT) &
+					I40E_VSIQF_TCREGION_TC_OFFSET_MASK;
+		TC_SIZE = i << I40E_VSIQF_TCREGION_TC_SIZE_SHIFT;
+	} else {
+		TC_OFFSET = (conf_ptr->queue_startIndex <<
+					I40E_VSIQF_TCREGION_TC_OFFSET2_SHIFT) &
+					I40E_VSIQF_TCREGION_TC_OFFSET2_MASK;
+		TC_SIZE = i << I40E_VSIQF_TCREGION_TC_SIZE2_SHIFT;
+	}
+	TCREGION |= TC_OFFSET;
+	TCREGION |= TC_SIZE;
+	i40e_write_rx_ctl(hw, I40E_VSIQF_TCREGION(index, main_vsi_seid),
+						TCREGION);
+
+	return 0;
+}
+
+static int
+i40e_set_region_flowtype_pf(struct i40e_hw *hw,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t PFQF_HREGION;
+	uint32_t ret = -EINVAL;
+	uint16_t index;
+
+	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_INIT_LOG(ERR, "the flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+	index = conf_ptr->flowtype >> 3;
+	PFQF_HREGION = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+	if ((conf_ptr->flowtype & 0x7) == 0) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_0_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 1) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_1_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 2) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_2_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 3) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_3_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 4) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_4_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 5) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_5_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 6) {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_6_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+	} else {
+		PFQF_HREGION |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_7_SHIFT;
+		PFQF_HREGION |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+	}
+
+	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), PFQF_HREGION);
+
+	return 0;
+}
+
+static int
+i40e_set_region_flowtype_vf(struct i40e_hw *hw,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t VFQF_HREGION;
+	uint32_t ret = -EINVAL;
+	uint16_t index;
+
+	if (conf_ptr->region_id > I40E_VFQF_HREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->flowtype > I40E_REGION_PCTYPE_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+	index = conf_ptr->flowtype >> 3;
+	VFQF_HREGION = i40e_read_rx_ctl(hw, I40E_VFQF_HREGION(index));
+
+	if ((conf_ptr->flowtype & 0x7) == 0) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_0_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 1) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_1_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 2) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_2_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 3) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_3_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 4) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_4_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 5) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_5_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+	} else if ((conf_ptr->flowtype & 0x7) == 6) {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_6_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+	} else {
+		VFQF_HREGION |= conf_ptr->region_id <<
+				I40E_VFQF_HREGION_REGION_7_SHIFT;
+		VFQF_HREGION |= 1 << I40E_VFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+	}
+
+	i40e_write_rx_ctl(hw, I40E_VFQF_HREGION(index), VFQF_HREGION);
+
+	return 0;
+}
+
+static int
+i40e_set_up_tc(struct i40e_hw *hw,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t PRTDCB_RUP2TC;
+	uint32_t ret = -EINVAL;
+
+	if (conf_ptr->UserPriority > I40E_REGION_USERPRIORITY_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->TrafficClasses >= I40E_TCREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the TrafficClasses max index is 7");
+		return ret;
+	}
+
+	PRTDCB_RUP2TC  = I40E_READ_REG(hw, I40E_PRTDCB_RUP2TC);
+	if (conf_ptr->UserPriority == 0)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP0TC_SHIFT;
+	else if (conf_ptr->UserPriority == 1)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP1TC_SHIFT;
+	else if (conf_ptr->UserPriority == 2)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP2TC_SHIFT;
+	else if (conf_ptr->UserPriority == 3)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP3TC_SHIFT;
+	else if (conf_ptr->UserPriority == 4)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP4TC_SHIFT;
+	else if (conf_ptr->UserPriority == 5)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP5TC_SHIFT;
+	else if (conf_ptr->UserPriority == 6)
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP6TC_SHIFT;
+	else
+		PRTDCB_RUP2TC |= conf_ptr->TrafficClasses <<
+				I40E_PRTDCB_RUP2TC_UP7TC_SHIFT;
+
+	I40E_WRITE_REG(hw, I40E_PRTDCB_RUP2TC, PRTDCB_RUP2TC);
+
+	return 0;
+}
+
+static int
+i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf)
+{
+	uint32_t SET_ZERO = 0;
+	uint16_t i;
+	uint16_t main_vsi_seid = pf->main_vsi_seid;
+
+	I40E_WRITE_REG(hw, I40E_PRTDCB_RUP2TC, SET_ZERO);
+
+	for (i = 0; i < 4; i++)
+		i40e_write_rx_ctl(hw, I40E_VSIQF_TCREGION(i, main_vsi_seid),
+						SET_ZERO);
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), SET_ZERO);
+
+	for (i = 0; i < I40E_VFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_VFQF_HREGION(i), SET_ZERO);
+
+	return 0;
+}
+
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+			struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
+	uint32_t ret;
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_set_queue_region(hw, pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
+		ret = i40e_set_region_flowtype_pf(hw, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
+		ret = i40e_set_region_flowtype_vf(hw, conf_ptr);
+		break;
+	case RTE_PMD_I40E_UP_TC_SET:
+		ret = i40e_set_up_tc(hw, conf_ptr);
+		break;
+
+	case RTE_PMD_I40E_REGION_ALL_FLUSH:
+		ret = i40e_flush_region_all_conf(hw, pf);
+		break;
+
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 356fa89..e85997a 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,19 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED = 0,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set*/
+	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region pctype set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region pctype set */
+	RTE_PMD_I40E_UP_TC_SET,   /**< add queue region pctype set */
+	RTE_PMD_I40E_REGION_ALL_FLUSH,   /**< flush all configuration */
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +159,19 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region information get from CLI.
+ */
+struct rte_i40e_rss_region_conf {
+	uint8_t region_id;
+	uint8_t flowtype;
+	uint8_t queue_startIndex;
+	uint8_t queue_num;
+	uint8_t UserPriority;
+	uint8_t TrafficClasses;
+	enum rte_pmd_i40e_queue_region_op  op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -637,4 +663,17 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 				       uint8_t mask,
 				       uint32_t pkt_type);
 
+/**
+ * Get RSS queue region info from CLI and do configuration for
+ * that port as the command otion type
+ *
+ * @param port
+ *    pointer to port identifier of the device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+		struct rte_i40e_rss_region_conf *conf_ptr);
+
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 20cc980..77ac385 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -45,3 +45,10 @@ DPDK_17.08 {
 	rte_pmd_i40e_get_ddp_info;
 
 } DPDK_17.05;
+
+DPDK_17.11 {
+	global:
+
+	rte_pmd_i40e_queue_region_conf;
+
+} DPDK_17.08;
-- 
2.9.3

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

* [PATCH 2/2] app/testpmd: add API for configuration of queue region
  2017-08-24  3:26 [PATCH 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-08-24  3:26 ` Wei Zhao
  2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-08-24  3:26 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 319 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index cd8c358..a49e6c5 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_startIndex (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set (pf|vf) port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) TCs (value)\n"
+			"    Set the mapping of User Priority to "
+			"Traffic Classes on a port\n\n"
+
+			"queue-region flush port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8213,6 +8228,306 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_startIndex;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_id;
+	region_conf.queue_startIndex = res->queue_num_value;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_startIndex =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_startIndex, "queue_startIndex");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_startIndex <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_startIndex,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "pf") == 0)
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET;
+	else
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_what =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				what, "pf#vf");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set pf|vf port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_what,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to Traffic Classes (TC) set *** */
+struct cmd_UserPriority_TrafficClasses_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t UserPriority;
+	uint8_t  UserPriority_id;
+	cmdline_fixed_string_t TrafficClasses;
+	uint8_t  TrafficClasses_id;
+};
+
+static void
+cmd_UserPriority_TrafficClasses_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_UserPriority_TrafficClasses_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_UP_TC_SET;
+	region_conf.UserPriority = res->UserPriority_id;
+	region_conf.TrafficClasses = res->TrafficClasses_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("UserPriority TrafficClasses config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_UserPriority_TrafficClasses_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_UserPriority_TrafficClasses_set =
+TOKEN_STRING_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_UserPriority_TrafficClasses_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_UserPriority_TrafficClasses_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_UserPriority_TrafficClasses_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				UserPriority, "UP");
+cmdline_parse_token_num_t cmd_UserPriority_TrafficClasses_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				UserPriority_id, UINT8);
+cmdline_parse_token_string_t cmd_UserPriority_TrafficClasses_TCs =
+	TOKEN_STRING_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				TrafficClasses, "TC");
+cmdline_parse_token_num_t cmd_UserPriority_TrafficClasses_TCs_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_UserPriority_TrafficClasses_result,
+				TrafficClasses_id, UINT8);
+
+cmdline_parse_inst_t cmd_UserPriority_TrafficClasses = {
+	.f = cmd_UserPriority_TrafficClasses_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"TCs <value>: Set the mapping of User Priority (UP) "
+		"to Traffic Classes (TC) ",
+	.tokens = {
+		(void *)&cmd_UserPriority_TrafficClasses_cmd,
+		(void *)&cmd_UserPriority_TrafficClasses_set,
+		(void *)&cmd_UserPriority_TrafficClasses_port,
+		(void *)&cmd_UserPriority_TrafficClasses_port_index,
+		(void *)&cmd_UserPriority_TrafficClasses_UP,
+		(void *)&cmd_UserPriority_TrafficClasses_UP_id,
+		(void *)&cmd_UserPriority_TrafficClasses_TCs,
+		(void *)&cmd_UserPriority_TrafficClasses_TCs_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_REGION_ALL_FLUSH;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14376,6 +14691,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_UserPriority_TrafficClasses,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
 	NULL,
 };
 
-- 
2.9.3

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-08-31 16:18   ` Ferruh Yigit
  2017-09-01  2:38     ` Zhao1, Wei
  2017-09-05 23:52   ` Chilikin, Andrey
  1 sibling, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-08-31 16:18 UTC (permalink / raw)
  To: Wei Zhao, dev

On 8/24/2017 4:26 AM, Wei Zhao wrote:
> This feature enable queue regions configuration for RSS in PF/VF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and
> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>

Hi Wei,

I wonder if this can be implemented using rte_flow, instead of PMD
specific API?

And if not, what is missing in rte_flow for this?

Thanks,
ferruh

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-08-31 16:18   ` Ferruh Yigit
@ 2017-09-01  2:38     ` Zhao1, Wei
  2017-09-06  9:11       ` Ferruh Yigit
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-01  2:38 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

HI,  Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Friday, September 1, 2017 12:18 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> 
> On 8/24/2017 4:26 AM, Wei Zhao wrote:
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> 
> Hi Wei,
> 
> I wonder if this can be implemented using rte_flow, instead of PMD specific
> API?
> 
> And if not, what is missing in rte_flow for this?

Yes, at first I have plan to use rte_flow to implement this feature.
But there are many opposition for this, for example, this  feature is only support by i40e but not igb/ixgbe
From hardware capacity, not all NIC. So, private API is selected.

> 
> Thanks,
> ferruh

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-08-31 16:18   ` Ferruh Yigit
@ 2017-09-05 23:52   ` Chilikin, Andrey
  2017-09-06  7:21     ` Zhao1, Wei
  1 sibling, 1 reply; 87+ messages in thread
From: Chilikin, Andrey @ 2017-09-05 23:52 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei, Xing, Beilei, Wu, Jingjing



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Wednesday, August 23, 2017 8:26 PM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> 
> This feature enable queue regions configuration for RSS in PF/VF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and
> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.h            |   6 +
>  drivers/net/i40e/rte_pmd_i40e.c           | 287
> ++++++++++++++++++++++++++++++
>  drivers/net/i40e/rte_pmd_i40e.h           |  39 ++++
>  drivers/net/i40e/rte_pmd_i40e_version.map |   7 +
>  4 files changed, 339 insertions(+)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.h
> b/drivers/net/i40e/i40e_ethdev.h
> index 48abc05..1d6e9b2 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
>  #define I40E_QOS_BW_WEIGHT_MIN 1
>  /* The max bandwidth weight is 127. */
>  #define I40E_QOS_BW_WEIGHT_MAX 127
> +/* The max queue region index is 7. */
> +#define I40E_TCREGION_MAX_INDEX 7
> +/* The max queue region userpriority is 7. */
> +#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
> +/* The max pctype index is 63. */
> +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> 
>  /**
>   * The overhead from MTU to max frame size.
> diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> b/drivers/net/i40e/rte_pmd_i40e.c
> index 950a0d6..5d1e1d4 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.c
> +++ b/drivers/net/i40e/rte_pmd_i40e.c
> @@ -2117,3 +2117,290 @@ int
> rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
> 
>  	return 0;
>  }
> +
> +static int
> +i40e_set_queue_region(struct i40e_hw *hw, struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint32_t TCREGION, TC_OFFSET, TC_SIZE;
Please follow DPDK coding style guide and use only low case for variables names. 

> +	uint16_t TC_SIZE_TB[7] = {1, 2, 4, 8, 16, 32, 64};
> +	uint16_t i, index;
> +	uint16_t main_vsi_seid = pf->main_vsi_seid;

<snip>

> 
>  /**
> @@ -146,6 +159,19 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
> 
>  /**
> + * Queue region information get from CLI.
> + */
> +struct rte_i40e_rss_region_conf {
> +	uint8_t region_id;
> +	uint8_t flowtype;
As this is internal i40e flow type (PCTYPE), it is better name it hw_flowtype. As an option - use RTE level sw_flowtype and map it to internal hw_flowtype using corresponding i40e API.

> +	uint8_t queue_startIndex;
> +	uint8_t queue_num;
> +	uint8_t UserPriority;
Low case for naming.

> +	uint8_t TrafficClasses;
> +	enum rte_pmd_i40e_queue_region_op  op;
> +};
> +
> +/**
>   * Notify VF when PF link status changes.
>   *
>   * @param port
> @@ -637,4 +663,17 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t
> port,
>  				       uint8_t mask,
>  				       uint32_t pkt_type);
> 
> +/**
> + * Get RSS queue region info from CLI and do configuration for
> + * that port as the command otion type
> + *
> + * @param port
> + *    pointer to port identifier of the device
> + * @param conf_ptr
> + *    pointer to the struct that contain all the
> + *    region configuration parameters
> + */
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> +		struct rte_i40e_rss_region_conf *conf_ptr);
> +
>  #endif /* _PMD_I40E_H_ */
> diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> b/drivers/net/i40e/rte_pmd_i40e_version.map
> index 20cc980..77ac385 100644
> --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> @@ -45,3 +45,10 @@ DPDK_17.08 {
>  	rte_pmd_i40e_get_ddp_info;
> 
>  } DPDK_17.05;
> +
> +DPDK_17.11 {
> +	global:
> +
> +	rte_pmd_i40e_queue_region_conf;
> +
> +} DPDK_17.08;
> --
> 2.9.3

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-05 23:52   ` Chilikin, Andrey
@ 2017-09-06  7:21     ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-06  7:21 UTC (permalink / raw)
  To: Chilikin, Andrey, dev; +Cc: Xing, Beilei, Wu, Jingjing

Hi,  Andrey

> -----Original Message-----
> From: Chilikin, Andrey
> Sent: Wednesday, September 6, 2017 7:52 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Xing, Beilei <beilei.xing@intel.com>;
> Wu, Jingjing <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Wednesday, August 23, 2017 8:26 PM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> >
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.h            |   6 +
> >  drivers/net/i40e/rte_pmd_i40e.c           | 287
> > ++++++++++++++++++++++++++++++
> >  drivers/net/i40e/rte_pmd_i40e.h           |  39 ++++
> >  drivers/net/i40e/rte_pmd_i40e_version.map |   7 +
> >  4 files changed, 339 insertions(+)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index 48abc05..1d6e9b2 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {  #define
> > I40E_QOS_BW_WEIGHT_MIN 1
> >  /* The max bandwidth weight is 127. */  #define
> > I40E_QOS_BW_WEIGHT_MAX 127
> > +/* The max queue region index is 7. */ #define
> > +I40E_TCREGION_MAX_INDEX 7
> > +/* The max queue region userpriority is 7. */ #define
> > +I40E_REGION_USERPRIORITY_MAX_INDEX 7
> > +/* The max pctype index is 63. */
> > +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> >
> >  /**
> >   * The overhead from MTU to max frame size.
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> > b/drivers/net/i40e/rte_pmd_i40e.c index 950a0d6..5d1e1d4 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.c
> > +++ b/drivers/net/i40e/rte_pmd_i40e.c
> > @@ -2117,3 +2117,290 @@ int
> > rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
> >
> >  	return 0;
> >  }
> > +
> > +static int
> > +i40e_set_queue_region(struct i40e_hw *hw, struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint32_t TCREGION, TC_OFFSET, TC_SIZE;
> Please follow DPDK coding style guide and use only low case for variables
> names.
> 
> > +	uint16_t TC_SIZE_TB[7] = {1, 2, 4, 8, 16, 32, 64};
> > +	uint16_t i, index;
> > +	uint16_t main_vsi_seid = pf->main_vsi_seid;
> 
> <snip>
> 
> >
> >  /**
> > @@ -146,6 +159,19 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region information get from CLI.
> > + */
> > +struct rte_i40e_rss_region_conf {
> > +	uint8_t region_id;
> > +	uint8_t flowtype;
> As this is internal i40e flow type (PCTYPE), it is better name it hw_flowtype.
> As an option - use RTE level sw_flowtype and map it to internal hw_flowtype
> using corresponding i40e API.

Ok, I will change that name to  " hw_flowtype " in v2 patch set.

> 
> > +	uint8_t queue_startIndex;
> > +	uint8_t queue_num;
> > +	uint8_t UserPriority;
> Low case for naming.

Ok, I will change code style in v2 patch set.

> 
> > +	uint8_t TrafficClasses;
> > +	enum rte_pmd_i40e_queue_region_op  op; };
> > +
> > +/**
> >   * Notify VF when PF link status changes.
> >   *
> >   * @param port
> > @@ -637,4 +663,17 @@ int
> rte_pmd_i40e_ptype_mapping_replace(uint8_t
> > port,
> >  				       uint8_t mask,
> >  				       uint32_t pkt_type);
> >
> > +/**
> > + * Get RSS queue region info from CLI and do configuration for
> > + * that port as the command otion type
> > + *
> > + * @param port
> > + *    pointer to port identifier of the device
> > + * @param conf_ptr
> > + *    pointer to the struct that contain all the
> > + *    region configuration parameters
> > + */
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +		struct rte_i40e_rss_region_conf *conf_ptr);
> > +
> >  #endif /* _PMD_I40E_H_ */
> > diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> > b/drivers/net/i40e/rte_pmd_i40e_version.map
> > index 20cc980..77ac385 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> > +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> > @@ -45,3 +45,10 @@ DPDK_17.08 {
> >  	rte_pmd_i40e_get_ddp_info;
> >
> >  } DPDK_17.05;
> > +
> > +DPDK_17.11 {
> > +	global:
> > +
> > +	rte_pmd_i40e_queue_region_conf;
> > +
> > +} DPDK_17.08;
> > --
> > 2.9.3

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-01  2:38     ` Zhao1, Wei
@ 2017-09-06  9:11       ` Ferruh Yigit
  2017-09-15 11:00         ` Ferruh Yigit
  2017-09-18  3:38         ` Zhao1, Wei
  0 siblings, 2 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-06  9:11 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/1/2017 3:38 AM, Zhao1, Wei wrote:
> HI,  Ferruh
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Friday, September 1, 2017 12:18 AM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
>>
>> On 8/24/2017 4:26 AM, Wei Zhao wrote:
>>> This feature enable queue regions configuration for RSS in PF/VF, so
>>> that different traffic classes or different packet classification
>>> types can be separated to different queues in different queue
>>> regions.This patch can set queue region range, it include queue number
>>> in a region and the index of first queue.
>>> This patch enable mapping between different priorities (UP) and
>>> different traffic classes.It also enable mapping between a region
>>> index and a sepcific flowtype(PCTYPE).It also provide the solution of
>>> flush all configuration about queue region the above described.
>>>
>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>
>> Hi Wei,
>>
>> I wonder if this can be implemented using rte_flow, instead of PMD specific
>> API?
>>
>> And if not, what is missing in rte_flow for this?
> 
> Yes, at first I have plan to use rte_flow to implement this feature.
> But there are many opposition for this, for example, this  feature is only support by i40e but not igb/ixgbe
> From hardware capacity, not all NIC. So, private API is selected.

I guess rte_flow headers needs to be updated for this support, how big
that update, what is missing in rte_flow for this?

Even this is only for i40e, rte_flow can be an option. I believe this
increases the usability of the feature for the driver.

> 
>>
>> Thanks,
>> ferruh

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

* [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS
  2017-08-24  3:26 [PATCH 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-08-24  3:26 ` [PATCH 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-13  6:04 ` Wei Zhao
  2017-09-13  6:04   ` [PATCH v2 1/2] net/i40e: queue region set and flush Wei Zhao
                     ` (2 more replies)
  2 siblings, 3 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-13  6:04 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                    | 324 ++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.c            |  19 +-
 drivers/net/i40e/i40e_ethdev.h            |  30 ++
 drivers/net/i40e/rte_pmd_i40e.c           | 484 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 6 files changed, 892 insertions(+), 4 deletions(-)

-- 
2.9.3

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

* [PATCH v2 1/2] net/i40e: queue region set and flush
  2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-13  6:04   ` Wei Zhao
  2017-09-13  6:04   ` [PATCH v2 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-13  6:04 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF/VF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  19 +-
 drivers/net/i40e/i40e_ethdev.h            |  30 ++
 drivers/net/i40e/rte_pmd_i40e.c           | 484 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 568 insertions(+), 4 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8e0580c..1663fc0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+static void
+i40e_init_queue_region_conf(struct rte_eth_dev *dev)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1309,6 +1314,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+	/* Remove all the queue region configuration */
+	i40e_flush_region_all_conf(hw, pf, 0);
+
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..d612886 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+/* The max queue region userpriority is 7. */
+#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
+/* The max pctype index is 63. */
+#define I40E_REGION_PCTYPE_MAX_INDEX 63
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	uint8_t region_id;
+	uint8_t queue_start_index;
+	uint8_t queue_num;
+	uint8_t user_priority_num;
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	uint8_t flowtype_num;
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +802,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_flush_region_all_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf, uint16_t on);
+
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index d69a472..1e97200 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,486 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	uint32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
+		for (i = 0; i < vsi->nb_qps; i++)
+			vsi_info->queue_mapping[i] =
+				rte_cpu_to_le_16(vsi->base_queue + i);
+	} else {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	}
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to configure queue region "
+			"mapping = %d ", hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+		sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_set_queue_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint32_t ret = -EINVAL;
+
+	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
+		if (conf_ptr->queue_num == tc_size_tb[i])
+			break;
+
+	if (i == I40E_REGION_MAX_INDEX) {
+		printf("The region sizes should be any of the following "
+		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+		"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if ((i == info->queue_region_number) &&
+			(i <= I40E_REGION_MAX_INDEX)) {
+			info->region[i].region_id = conf_ptr->region_id;
+			info->region[i].queue_num = conf_ptr->queue_num;
+			info->region[i].queue_start_index =
+				conf_ptr->queue_start_index;
+			info->queue_region_number++;
+		} else if (i > I40E_REGION_MAX_INDEX) {
+			PMD_INIT_LOG(ERR, "queue region number "
+				"exceeds maxnum 8");
+			return ret;
+		} else {
+			PMD_INIT_LOG(ERR, "queue region id has "
+				"been set before");
+			return ret;
+		}
+	} else {
+		info->region[0].region_id = conf_ptr->region_id;
+		info->region[0].queue_num = conf_ptr->queue_num;
+		info->region[0].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	}
+
+	return 0;
+}
+
+static int
+i40e_set_region_flowtype_pf(struct i40e_hw *hw,
+		struct i40e_pf *pf, struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t pfqf_hregion;
+	uint32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j, index, flowtype_set = 0;
+	uint16_t region_index, flowtype_index;
+
+	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if (i == info->queue_region_number) {
+			PMD_INIT_LOG(ERR, "that region id has not "
+				"been set before");
+			return ret;
+		}
+		region_index = i;
+
+		for (i = 0; i < info->queue_region_number; i++) {
+			for (j = 0; j < info->region[i].flowtype_num; j++) {
+				if (conf_ptr->hw_flowtype ==
+					info->region[i].hw_flowtype[j]) {
+					flowtype_set = 1;
+					break;
+				}
+			}
+		}
+
+		if (flowtype_set) {
+			PMD_INIT_LOG(ERR, "that hw_flowtype "
+				"has been set before");
+			return ret;
+		}
+		flowtype_index = info->region[region_index].flowtype_num;
+		info->region[region_index].hw_flowtype[flowtype_index] =
+						conf_ptr->hw_flowtype;
+		info->region[region_index].flowtype_num++;
+	} else  {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	index = conf_ptr->hw_flowtype >> 3;
+	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_0_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_1_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_2_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_3_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_4_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_5_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_6_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+	} else {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_7_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+	}
+
+	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
+
+	return 0;
+}
+
+static int
+i40e_set_up_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint32_t ret = -EINVAL;
+	uint16_t i, j, region_index, up_set = 0;
+
+	if (conf_ptr->user_priority > I40E_REGION_USERPRIORITY_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if (i == info->queue_region_number) {
+			PMD_INIT_LOG(ERR, "that region id "
+				"has not been set before");
+			return ret;
+		}
+		region_index = i;
+
+		for (i = 0; i < info->queue_region_number; i++) {
+			for (j = 0; j <
+				info->region[i].user_priority_num; j++) {
+				if (info->region[i].user_priority[j] ==
+					conf_ptr->user_priority) {
+					up_set = 1;
+					break;
+				}
+			}
+		}
+
+		if (up_set) {
+			PMD_INIT_LOG(ERR, "that user priority "
+				"has been set before");
+			return ret;
+		}
+
+		j = info->region[region_index].user_priority_num;
+		info->region[region_index].user_priority[j] =
+						conf_ptr->user_priority;
+		info->region[region_index].user_priority_num++;
+	} else {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	uint32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed, err"
+			" %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
+{
+	uint16_t i;
+	uint32_t ret = -EINVAL;
+
+	memset(&hw->local_dcbx_config, 0,
+	sizeof(struct i40e_dcbx_config));
+	/* set dcb default configuration */
+	hw->local_dcbx_config.etscfg.willing = 0;
+	hw->local_dcbx_config.etscfg.maxtcs = 0;
+	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
+	hw->local_dcbx_config.etscfg.tsatable[0] =
+			I40E_IEEE_TSA_ETS;
+	/* all UPs mapping to region 0 */
+	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
+		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
+	hw->local_dcbx_config.etsrec =
+		hw->local_dcbx_config.etscfg;
+	hw->local_dcbx_config.pfc.willing = 0;
+	hw->local_dcbx_config.pfc.pfccap =
+			I40E_MAX_TRAFFIC_CLASS;
+	/* FW needs one App to configure HW */
+	hw->local_dcbx_config.numapps = 1;
+	hw->local_dcbx_config.app[0].selector =
+			I40E_APP_SEL_ETHTYPE;
+	hw->local_dcbx_config.app[0].priority = 3;
+	hw->local_dcbx_config.app[0].protocolid =
+			I40E_APP_PROTOID_FCOE;
+	ret = i40e_set_dcb_config(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+		"default dcb config fails. err = %d, aq_err = %d.",
+			ret, hw->aq.asq_last_status);
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
+				uint16_t on)
+{
+	uint16_t i;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_vsi_update_queue_region_mapping(hw, pf);
+		i40e_queue_region_dcb_configure(hw, pf);
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	i40e_vsi_update_queue_region_mapping(hw, pf);
+	i40e_queue_region_dcb_configure_default(hw);
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+
+	return 0;
+}
+
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+			struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
+	uint32_t ret;
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_set_queue_region(pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
+		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
+		ret = -EINVAL;
+		break;
+	case RTE_PMD_I40E_UP_REGION_SET:
+		ret = i40e_set_up_region(pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_region_all_conf(hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_region_all_conf(hw, pf, 0);
+		break;
+
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..a1329f4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED = 0,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set*/
+	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region pctype set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region pctype set */
+	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype set */
+	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all configuration */
+	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all configuration */
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region information get from CLI.
+ */
+struct rte_i40e_rss_region_conf {
+	uint8_t region_id;
+	uint8_t hw_flowtype;
+	uint8_t queue_start_index;
+	uint8_t queue_num;
+	uint8_t user_priority;
+	enum rte_pmd_i40e_queue_region_op  op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +683,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Get RSS queue region info from CLI and do configuration for
+ * that port as the command otion type
+ *
+ * @param port
+ *    pointer to port identifier of the device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+		struct rte_i40e_rss_region_conf *conf_ptr);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..c3ee2da 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.9.3

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

* [PATCH v2 2/2] app/testpmd: add API for configuration of queue region
  2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-13  6:04   ` [PATCH v2 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-13  6:04   ` Wei Zhao
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-13  6:04 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 324 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0144191..2350e75 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set (pf|vf) port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"queue-region flush (on|off) port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8224,6 +8239,315 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "pf") == 0)
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET;
+	else
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_what =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				what, "pf#vf");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set pf|vf port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_what,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_UP_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush on|off port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
-- 
2.9.3

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

* [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS
  2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-13  6:04   ` [PATCH v2 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-13  6:04   ` [PATCH v2 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-15  3:13   ` Wei Zhao
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
                       ` (3 more replies)
  2 siblings, 4 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-15  3:13 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c 

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                    | 328 ++++++++++++++++++++
 drivers/net/i40e/i40e_ethdev.c            |  19 +-
 drivers/net/i40e/i40e_ethdev.h            |  30 ++
 drivers/net/i40e/rte_pmd_i40e.c           | 482 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 6 files changed, 894 insertions(+), 4 deletions(-)

-- 
2.9.3

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

* [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-15  3:13     ` Wei Zhao
  2017-09-20 10:36       ` Ferruh Yigit
                         ` (2 more replies)
  2017-09-15  3:13     ` [PATCH v3 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
                       ` (2 subsequent siblings)
  3 siblings, 3 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-15  3:13 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF/VF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  19 +-
 drivers/net/i40e/i40e_ethdev.h            |  30 ++
 drivers/net/i40e/rte_pmd_i40e.c           | 482 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 566 insertions(+), 4 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 8e0580c..1663fc0 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+static void
+i40e_init_queue_region_conf(struct rte_eth_dev *dev)
+{
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1309,6 +1314,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+	/* Remove all the queue region configuration */
+	i40e_flush_region_all_conf(hw, pf, 0);
+
 	return 0;
 }
 
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..d612886 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+/* The max queue region userpriority is 7. */
+#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
+/* The max pctype index is 63. */
+#define I40E_REGION_PCTYPE_MAX_INDEX 63
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	uint8_t region_id;
+	uint8_t queue_start_index;
+	uint8_t queue_num;
+	uint8_t user_priority_num;
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	uint8_t flowtype_num;
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +802,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_flush_region_all_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf, uint16_t on);
+
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index d69a472..9a75f21 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	uint32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
+		for (i = 0; i < vsi->nb_qps; i++)
+			vsi_info->queue_mapping[i] =
+				rte_cpu_to_le_16(vsi->base_queue + i);
+	} else {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	}
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Failed to configure queue region "
+			"mapping = %d ", hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+		sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_set_queue_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint32_t ret = -EINVAL;
+
+	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
+		if (conf_ptr->queue_num == tc_size_tb[i])
+			break;
+
+	if (i == I40E_REGION_MAX_INDEX) {
+		printf("The region sizes should be any of the following "
+		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+		"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if ((i == info->queue_region_number) &&
+			(i <= I40E_REGION_MAX_INDEX)) {
+			info->region[i].region_id = conf_ptr->region_id;
+			info->region[i].queue_num = conf_ptr->queue_num;
+			info->region[i].queue_start_index =
+				conf_ptr->queue_start_index;
+			info->queue_region_number++;
+		} else {
+			PMD_INIT_LOG(ERR, "queue region number "
+				"exceeds maxnum 8 or the "
+				"queue region id has "
+				"been set before");
+			return ret;
+		}
+	} else {
+		info->region[0].region_id = conf_ptr->region_id;
+		info->region[0].queue_num = conf_ptr->queue_num;
+		info->region[0].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	}
+
+	return 0;
+}
+
+static int
+i40e_set_region_flowtype_pf(struct i40e_hw *hw,
+		struct i40e_pf *pf, struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint32_t pfqf_hregion;
+	uint32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j, index, flowtype_set = 0;
+	uint16_t region_index, flowtype_index;
+
+	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if (i == info->queue_region_number) {
+			PMD_INIT_LOG(ERR, "that region id has not "
+				"been set before");
+			return ret;
+		}
+		region_index = i;
+
+		for (i = 0; i < info->queue_region_number; i++) {
+			for (j = 0; j < info->region[i].flowtype_num; j++) {
+				if (conf_ptr->hw_flowtype ==
+					info->region[i].hw_flowtype[j]) {
+					flowtype_set = 1;
+					break;
+				}
+			}
+		}
+
+		if (flowtype_set) {
+			PMD_INIT_LOG(ERR, "that hw_flowtype "
+				"has been set before");
+			return ret;
+		}
+		flowtype_index = info->region[region_index].flowtype_num;
+		info->region[region_index].hw_flowtype[flowtype_index] =
+						conf_ptr->hw_flowtype;
+		info->region[region_index].flowtype_num++;
+	} else  {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	index = conf_ptr->hw_flowtype >> 3;
+	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_0_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_1_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_2_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_3_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_4_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_5_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_6_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+	} else {
+		pfqf_hregion |= conf_ptr->region_id <<
+				I40E_PFQF_HREGION_REGION_7_SHIFT;
+		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+	}
+
+	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
+
+	return 0;
+}
+
+static int
+i40e_set_up_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint32_t ret = -EINVAL;
+	uint16_t i, j, region_index, up_set = 0;
+
+	if (conf_ptr->user_priority > I40E_REGION_USERPRIORITY_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_INIT_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	if (info->queue_region_number) {
+		for (i = 0; i < info->queue_region_number; i++)
+			if (conf_ptr->region_id == info->region[i].region_id)
+				break;
+
+		if (i == info->queue_region_number) {
+			PMD_INIT_LOG(ERR, "that region id "
+				"has not been set before");
+			return ret;
+		}
+		region_index = i;
+
+		for (i = 0; i < info->queue_region_number; i++) {
+			for (j = 0; j <
+				info->region[i].user_priority_num; j++) {
+				if (info->region[i].user_priority[j] ==
+					conf_ptr->user_priority) {
+					up_set = 1;
+					break;
+				}
+			}
+		}
+
+		if (up_set) {
+			PMD_INIT_LOG(ERR, "that user priority "
+				"has been set before");
+			return ret;
+		}
+
+		j = info->region[region_index].user_priority_num;
+		info->region[region_index].user_priority[j] =
+						conf_ptr->user_priority;
+		info->region[region_index].user_priority_num++;
+	} else {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	uint32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed, err"
+			" %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
+{
+	uint16_t i;
+	uint32_t ret = -EINVAL;
+
+	memset(&hw->local_dcbx_config, 0,
+	sizeof(struct i40e_dcbx_config));
+	/* set dcb default configuration */
+	hw->local_dcbx_config.etscfg.willing = 0;
+	hw->local_dcbx_config.etscfg.maxtcs = 0;
+	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
+	hw->local_dcbx_config.etscfg.tsatable[0] =
+			I40E_IEEE_TSA_ETS;
+	/* all UPs mapping to region 0 */
+	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
+		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
+	hw->local_dcbx_config.etsrec =
+		hw->local_dcbx_config.etscfg;
+	hw->local_dcbx_config.pfc.willing = 0;
+	hw->local_dcbx_config.pfc.pfccap =
+			I40E_MAX_TRAFFIC_CLASS;
+	/* FW needs one App to configure HW */
+	hw->local_dcbx_config.numapps = 1;
+	hw->local_dcbx_config.app[0].selector =
+			I40E_APP_SEL_ETHTYPE;
+	hw->local_dcbx_config.app[0].priority = 3;
+	hw->local_dcbx_config.app[0].protocolid =
+			I40E_APP_PROTOID_FCOE;
+	ret = i40e_set_dcb_config(hw);
+	if (ret) {
+		PMD_INIT_LOG(ERR,
+		"default dcb config fails. err = %d, aq_err = %d.",
+			ret, hw->aq.asq_last_status);
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
+				uint16_t on)
+{
+	uint16_t i;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_vsi_update_queue_region_mapping(hw, pf);
+		i40e_queue_region_dcb_configure(hw, pf);
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	i40e_vsi_update_queue_region_mapping(hw, pf);
+	i40e_queue_region_dcb_configure_default(hw);
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+
+	return 0;
+}
+
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+			struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
+	uint32_t ret;
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_set_queue_region(pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
+		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
+		ret = -EINVAL;
+		break;
+	case RTE_PMD_I40E_UP_REGION_SET:
+		ret = i40e_set_up_region(pf, conf_ptr);
+		break;
+	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_region_all_conf(hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_region_all_conf(hw, pf, 0);
+		break;
+
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+		break;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..a1329f4 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED = 0,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set*/
+	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region pctype set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region pctype set */
+	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype set */
+	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all configuration */
+	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all configuration */
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region information get from CLI.
+ */
+struct rte_i40e_rss_region_conf {
+	uint8_t region_id;
+	uint8_t hw_flowtype;
+	uint8_t queue_start_index;
+	uint8_t queue_num;
+	uint8_t user_priority;
+	enum rte_pmd_i40e_queue_region_op  op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +683,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Get RSS queue region info from CLI and do configuration for
+ * that port as the command otion type
+ *
+ * @param port
+ *    pointer to port identifier of the device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+		struct rte_i40e_rss_region_conf *conf_ptr);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..c3ee2da 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.9.3

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

* [PATCH v3 2/2] app/testpmd: add API for configuration of queue region
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-15  3:13     ` Wei Zhao
  2017-09-20 10:45       ` Ferruh Yigit
  2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 1 reply; 87+ messages in thread
From: Wei Zhao @ 2017-09-15  3:13 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 328 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 0144191..060fcb1 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set (pf|vf) port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"queue-region flush (on|off) port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8224,6 +8239,315 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "pf") == 0)
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET;
+	else
+		region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_what =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				what, "pf#vf");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set pf|vf port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_what,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_UP_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush on|off port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14387,6 +14711,10 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
 	NULL,
 };
 
-- 
2.9.3

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-06  9:11       ` Ferruh Yigit
@ 2017-09-15 11:00         ` Ferruh Yigit
  2017-09-20  3:20           ` Zhao1, Wei
  2017-09-18  3:38         ` Zhao1, Wei
  1 sibling, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-15 11:00 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/6/2017 10:11 AM, Ferruh Yigit wrote:
> On 9/1/2017 3:38 AM, Zhao1, Wei wrote:
>> HI,  Ferruh
>>
>>> -----Original Message-----
>>> From: Yigit, Ferruh
>>> Sent: Friday, September 1, 2017 12:18 AM
>>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>>> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
>>>
>>> On 8/24/2017 4:26 AM, Wei Zhao wrote:
>>>> This feature enable queue regions configuration for RSS in PF/VF, so
>>>> that different traffic classes or different packet classification
>>>> types can be separated to different queues in different queue
>>>> regions.This patch can set queue region range, it include queue number
>>>> in a region and the index of first queue.
>>>> This patch enable mapping between different priorities (UP) and
>>>> different traffic classes.It also enable mapping between a region
>>>> index and a sepcific flowtype(PCTYPE).It also provide the solution of
>>>> flush all configuration about queue region the above described.
>>>>
>>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>>
>>> Hi Wei,
>>>
>>> I wonder if this can be implemented using rte_flow, instead of PMD specific
>>> API?
>>>
>>> And if not, what is missing in rte_flow for this?
>>
>> Yes, at first I have plan to use rte_flow to implement this feature.
>> But there are many opposition for this, for example, this  feature is only support by i40e but not igb/ixgbe
>> From hardware capacity, not all NIC. So, private API is selected.
> 
> I guess rte_flow headers needs to be updated for this support, how big
> that update, what is missing in rte_flow for this?

Hi Wei,

Would you mind answering this?

Thanks,
ferruh

> 
> Even this is only for i40e, rte_flow can be an option. I believe this
> increases the usability of the feature for the driver.
> 
>>
>>>
>>> Thanks,
>>> ferruh
> 

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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-06  9:11       ` Ferruh Yigit
  2017-09-15 11:00         ` Ferruh Yigit
@ 2017-09-18  3:38         ` Zhao1, Wei
  1 sibling, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-18  3:38 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Hi, Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, September 6, 2017 5:11 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> 
> On 9/1/2017 3:38 AM, Zhao1, Wei wrote:
> > HI,  Ferruh
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Friday, September 1, 2017 12:18 AM
> >> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> >> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and
> >> flush
> >>
> >> On 8/24/2017 4:26 AM, Wei Zhao wrote:
> >>> This feature enable queue regions configuration for RSS in PF/VF, so
> >>> that different traffic classes or different packet classification
> >>> types can be separated to different queues in different queue
> >>> regions.This patch can set queue region range, it include queue
> >>> number in a region and the index of first queue.
> >>> This patch enable mapping between different priorities (UP) and
> >>> different traffic classes.It also enable mapping between a region
> >>> index and a sepcific flowtype(PCTYPE).It also provide the solution
> >>> of flush all configuration about queue region the above described.
> >>>
> >>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> >>
> >> Hi Wei,
> >>
> >> I wonder if this can be implemented using rte_flow, instead of PMD
> >> specific API?
> >>
> >> And if not, what is missing in rte_flow for this?
> >
> > Yes, at first I have plan to use rte_flow to implement this feature.
> > But there are many opposition for this, for example, this  feature is
> > only support by i40e but not igb/ixgbe From hardware capacity, not all NIC.
> So, private API is selected.
> 
> I guess rte_flow headers needs to be updated for this support, how big that
> update, what is missing in rte_flow for this?
> 

If we want rte_flow also to support this feature, although there will be many new CLI command need to be
Add to testpmd app, and some code change in ethdev, for example  add new member in enum rte_filter_type and so on.
But the biggest problem is to get recognize and support from expert and authority in DPDK community for this new change.
By now, rte_flow has no support for rss config application, but only filter configuration. But maybe this can be a work in next release.
  

> Even this is only for i40e, rte_flow can be an option. I believe this increases
> the usability of the feature for the driver.
> 
> >
> >>
> >> Thanks,
> >> ferruh


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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-15 11:00         ` Ferruh Yigit
@ 2017-09-20  3:20           ` Zhao1, Wei
  2017-09-20 10:32             ` Ferruh Yigit
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-20  3:20 UTC (permalink / raw)
  To: Yigit, Ferruh, dev; +Cc: Yigit, Ferruh

Hi, Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Friday, September 15, 2017 7:01 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
> 
> On 9/6/2017 10:11 AM, Ferruh Yigit wrote:
> > On 9/1/2017 3:38 AM, Zhao1, Wei wrote:
> >> HI,  Ferruh
> >>
> >>> -----Original Message-----
> >>> From: Yigit, Ferruh
> >>> Sent: Friday, September 1, 2017 12:18 AM
> >>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> >>> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and
> >>> flush
> >>>
> >>> On 8/24/2017 4:26 AM, Wei Zhao wrote:
> >>>> This feature enable queue regions configuration for RSS in PF/VF,
> >>>> so that different traffic classes or different packet
> >>>> classification types can be separated to different queues in
> >>>> different queue regions.This patch can set queue region range, it
> >>>> include queue number in a region and the index of first queue.
> >>>> This patch enable mapping between different priorities (UP) and
> >>>> different traffic classes.It also enable mapping between a region
> >>>> index and a sepcific flowtype(PCTYPE).It also provide the solution
> >>>> of flush all configuration about queue region the above described.
> >>>>
> >>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> >>>
> >>> Hi Wei,
> >>>
> >>> I wonder if this can be implemented using rte_flow, instead of PMD
> >>> specific API?
> >>>
> >>> And if not, what is missing in rte_flow for this?
> >>
> >> Yes, at first I have plan to use rte_flow to implement this feature.
> >> But there are many opposition for this, for example, this  feature is
> >> only support by i40e but not igb/ixgbe From hardware capacity, not all NIC.
> So, private API is selected.
> >
> > I guess rte_flow headers needs to be updated for this support, how big
> > that update, what is missing in rte_flow for this?
> 
> Hi Wei,
> 
> Would you mind answering this?

If we want rte_flow also to support this feature,
although there will be many new CLI command need to be Add to testpmd app,
and some code change in ethdev, for example  add new member in enum rte_filter_type and so on.
But the biggest problem is to get recognize and support from expert and authority in DPDK community for this new change.
By now, rte_flow has no support for rss config application, but only filter configuration. But maybe this can be a work in next release.


> 
> Thanks,
> ferruh
> 
> >
> > Even this is only for i40e, rte_flow can be an option. I believe this
> > increases the usability of the feature for the driver.
> >
> >>
> >>>
> >>> Thanks,
> >>> ferruh
> >


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

* Re: [PATCH 1/2] net/i40e: queue region set and flush
  2017-09-20  3:20           ` Zhao1, Wei
@ 2017-09-20 10:32             ` Ferruh Yigit
  0 siblings, 0 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-20 10:32 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/20/2017 4:20 AM, Zhao1, Wei wrote:
> Hi, Ferruh
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Friday, September 15, 2017 7:01 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
>>
>> On 9/6/2017 10:11 AM, Ferruh Yigit wrote:
>>> On 9/1/2017 3:38 AM, Zhao1, Wei wrote:
>>>> HI,  Ferruh
>>>>
>>>>> -----Original Message-----
>>>>> From: Yigit, Ferruh
>>>>> Sent: Friday, September 1, 2017 12:18 AM
>>>>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>>>>> Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and
>>>>> flush
>>>>>
>>>>> On 8/24/2017 4:26 AM, Wei Zhao wrote:
>>>>>> This feature enable queue regions configuration for RSS in PF/VF,
>>>>>> so that different traffic classes or different packet
>>>>>> classification types can be separated to different queues in
>>>>>> different queue regions.This patch can set queue region range, it
>>>>>> include queue number in a region and the index of first queue.
>>>>>> This patch enable mapping between different priorities (UP) and
>>>>>> different traffic classes.It also enable mapping between a region
>>>>>> index and a sepcific flowtype(PCTYPE).It also provide the solution
>>>>>> of flush all configuration about queue region the above described.
>>>>>>
>>>>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>>>>
>>>>> Hi Wei,
>>>>>
>>>>> I wonder if this can be implemented using rte_flow, instead of PMD
>>>>> specific API?
>>>>>
>>>>> And if not, what is missing in rte_flow for this?
>>>>
>>>> Yes, at first I have plan to use rte_flow to implement this feature.
>>>> But there are many opposition for this, for example, this  feature is
>>>> only support by i40e but not igb/ixgbe From hardware capacity, not all NIC.
>> So, private API is selected.
>>>
>>> I guess rte_flow headers needs to be updated for this support, how big
>>> that update, what is missing in rte_flow for this?
>>
>> Hi Wei,
>>
>> Would you mind answering this?
> 
> If we want rte_flow also to support this feature,
> although there will be many new CLI command need to be Add to testpmd app,
> and some code change in ethdev, for example  add new member in enum rte_filter_type and so on.

new CLI part is side effect of the rte_flow, to demonstrate how to use
flow modes. I was more interested in how much change required in
rte_flow header.

> But the biggest problem is to get recognize and support from expert and authority in DPDK community for this new change.

Is this is referring previous push back for rte_filter_type update, I
think this can be evaluated case by case. As far as I remember
previously it is rejected in favor of improving rte_flow, this time
update is required to be able to use rte_flow, so I assume can be OK.
I believe this can be discussed out of this patch scope.

> By now, rte_flow has no support for rss config application, but only filter configuration. But maybe this can be a work in next release.

At least it is good that this effort can be re-used later for rte_flow,
I still believe this option worth investigating for further releases.

> 
> 
>>
>> Thanks,
>> ferruh
>>
>>>
>>> Even this is only for i40e, rte_flow can be an option. I believe this
>>> increases the usability of the feature for the driver.
>>>
>>>>
>>>>>
>>>>> Thanks,
>>>>> ferruh
>>>
> 

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-20 10:36       ` Ferruh Yigit
  2017-09-21  6:48         ` Zhao1, Wei
                           ` (2 more replies)
  2017-09-21 19:53       ` Chilikin, Andrey
  2017-09-24 16:01       ` Wu, Jingjing
  2 siblings, 3 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-20 10:36 UTC (permalink / raw)
  To: Wei Zhao, dev

On 9/15/2017 4:13 AM, Wei Zhao wrote:
> This feature enable queue regions configuration for RSS in PF/VF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.

Is following correct:
So instead of distributing packets to the multiple queues, this will
distribute packets into queue reqions which may consists of multiple queues.

If so, is there a way to control how packets distributed within same
queue region to multiple queues?

And is this feature only supported with RSS? Can it be part of RSS
configuration instead of PMD specific API?

> This patch enable mapping between different priorities (UP) and

User priorities (UP)

> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c            |  19 +-
>  drivers/net/i40e/i40e_ethdev.h            |  30 ++
>  drivers/net/i40e/rte_pmd_i40e.c           | 482 ++++++++++++++++++++++++++++++
>  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
>  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
>  5 files changed, 566 insertions(+), 4 deletions(-)
> 

<...>

> +static int
> +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> +			      struct i40e_pf *pf)
> +{
> +	uint16_t i;
> +	struct i40e_vsi *vsi = pf->main_vsi;
> +	uint16_t queue_offset, bsf, tc_index;
> +	struct i40e_vsi_context ctxt;
> +	struct i40e_aqc_vsi_properties_data *vsi_info;
> +	struct i40e_queue_region_info *region_info =
> +				&pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	if (!region_info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");

Can you please re-check the log message.

> +		return ret;
> +	}
> +
> +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> +
> +	/* Update Queue Pairs Mapping for currently enabled UPs */
> +	ctxt.seid = vsi->seid;
> +	ctxt.pf_num = hw->pf_id;
> +	ctxt.vf_num = 0;
> +	ctxt.uplink_seid = vsi->uplink_seid;
> +	ctxt.info = vsi->info;
> +	vsi_info = &ctxt.info;
> +
> +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> +
> +	/**
> +	 * Configure queue region and queue mapping parameters,
> +	 * for enabled queue region, allocate queues to this region.
> +	 */
> +
> +	for (i = 0; i < region_info->queue_region_number; i++) {
> +		tc_index = region_info->region[i].region_id;
> +		bsf = rte_bsf32(region_info->region[i].queue_num);
> +		queue_offset = region_info->region[i].queue_start_index;
> +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> +			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> +				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> +	}
> +
> +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
> +	if (vsi->type == I40E_VSI_SRIOV) {
> +		vsi_info->mapping_flags |=
> +			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> +		for (i = 0; i < vsi->nb_qps; i++)
> +			vsi_info->queue_mapping[i] =
> +				rte_cpu_to_le_16(vsi->base_queue + i);
> +	} else {
> +		vsi_info->mapping_flags |=
> +			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
> +	}
> +	vsi_info->valid_sections |=
> +		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> +
> +	/* Update the VSI after updating the VSI queue-mapping information */
> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> +			"mapping = %d ", hw->aq.asq_last_status);

Please don't split log message.

> +		return ret;
> +	}
> +	/* update the local VSI info with updated queue map */
> +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> +					sizeof(vsi->info.tc_mapping));
> +	(void)rte_memcpy(&vsi->info.queue_mapping,
> +			&ctxt.info.queue_mapping,
> +		sizeof(vsi->info.queue_mapping));

Please keep line allignment same with above line.

> +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> +	vsi->info.valid_sections = 0;
> +
> +	return 0;
> +}
> +
> +
> +static int
> +i40e_set_queue_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> +	uint16_t i;
> +	struct i40e_vsi *main_vsi = pf->main_vsi;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> +		if (conf_ptr->queue_num == tc_size_tb[i])
> +			break;
> +
> +	if (i == I40E_REGION_MAX_INDEX) {
> +		printf("The region sizes should be any of the following "
> +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> +		"total number of queues do not exceed the VSI allocation");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> +					> main_vsi->nb_used_qps) {
> +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI range");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if ((i == info->queue_region_number) &&
> +			(i <= I40E_REGION_MAX_INDEX)) {


Please use one more level indentaion here, and pharantesis looks extra
can you please double check?

> +			info->region[i].region_id = conf_ptr->region_id;
> +			info->region[i].queue_num = conf_ptr->queue_num;
> +			info->region[i].queue_start_index =
> +				conf_ptr->queue_start_index;
> +			info->queue_region_number++;
> +		} else {
> +			PMD_INIT_LOG(ERR, "queue region number "
> +				"exceeds maxnum 8 or the "
> +				"queue region id has "
> +				"been set before");

please don't split log message.

> +			return ret;
> +		}
> +	} else {
> +		info->region[0].region_id = conf_ptr->region_id;
> +		info->region[0].queue_num = conf_ptr->queue_num;
> +		info->region[0].queue_start_index =
> +			conf_ptr->queue_start_index;
> +		info->queue_region_number++;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf *conf_ptr)

What do you think starting all functions, even they are static, with
"i40e_queue_region_" prefix?

> +{
> +	uint32_t pfqf_hregion;
> +	uint32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i, j, index, flowtype_set = 0;
> +	uint16_t region_index, flowtype_index;
> +
> +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id has not "
> +				"been set before");
> +			return ret;
> +		}
> +		region_index = i;
> +
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> +				if (conf_ptr->hw_flowtype ==
> +					info->region[i].hw_flowtype[j]) {
> +					flowtype_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (flowtype_set) {
> +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> +				"has been set before");

Please don't split log messages.

> +			return ret;
> +		}
> +		flowtype_index = info->region[region_index].flowtype_num;
> +		info->region[region_index].hw_flowtype[flowtype_index] =
> +						conf_ptr->hw_flowtype;
> +		info->region[region_index].flowtype_num++;
> +	} else  {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	index = conf_ptr->hw_flowtype >> 3;
> +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> +
> +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> +	} else {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> +	}
> +
> +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_up_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)

The API name looks like "setup" but that up part is user_priority, can
you please long form against "up"?

> +{
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +	uint16_t i, j, region_index, up_set = 0;

Same abrevation comment for "upset", please use long form.

> +
> +	if (conf_ptr->user_priority > I40E_REGION_USERPRIORITY_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id "
> +				"has not been set before");
> +			return ret;
> +		}
> +		region_index = i;
> +
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j <
> +				info->region[i].user_priority_num; j++) {

Please break line after ";"

> +				if (info->region[i].user_priority[j] ==
> +					conf_ptr->user_priority) {
> +					up_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (up_set) {
> +			PMD_INIT_LOG(ERR, "that user priority "
> +				"has been set before");
> +			return ret;
> +		}
> +
> +		j = info->region[region_index].user_priority_num;
> +		info->region[region_index].user_priority[j] =
> +						conf_ptr->user_priority;
> +		info->region[region_index].user_priority_num++;
> +	} else {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> +				struct i40e_pf *pf)
> +{
> +	struct i40e_dcbx_config dcb_cfg_local;
> +	struct i40e_dcbx_config *dcb_cfg;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> +	uint32_t ret = -EINVAL;

Please use signed variable, there are more above.

> +	uint16_t i, j, prio_index, region_index;
> +	uint8_t tc_map, tc_bw, bw_lf;
> +
> +	if (!info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	dcb_cfg = &dcb_cfg_local;
> +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> +
> +	/* assume each tc has the same bw */
> +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> +	/* to ensure the sum of tcbw is equal to 100 */
> +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> +	for (i = 0; i < bw_lf; i++)
> +		dcb_cfg->etscfg.tcbwtable[i]++;
> +
> +	/* assume each tc has the same Transmission Selection Algorithm */
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> +			prio_index = info->region[i].user_priority[j];
> +			region_index = info->region[i].region_id;
> +			dcb_cfg->etscfg.prioritytable[prio_index] =
> +						region_index;
> +		}
> +	}
> +
> +	/* FW needs one App to configure HW */
> +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> +
> +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> +
> +	dcb_cfg->pfc.willing = 0;
> +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> +	dcb_cfg->pfc.pfcenable = tc_map;
> +
> +	/* Copy the new config to the current config */
> +	*old_cfg = *dcb_cfg;
> +	old_cfg->etsrec = old_cfg->etscfg;
> +	ret = i40e_set_dcb_config(hw);
> +
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed, err"
> +			" %s aq_err %s",

Please don't split the log message.

> +			 i40e_stat_str(hw, ret),
> +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
> +{
> +	uint16_t i;
> +	uint32_t ret = -EINVAL;

Please use signed variable here.

> +
> +	memset(&hw->local_dcbx_config, 0,
> +	sizeof(struct i40e_dcbx_config));

Wrong indentation.

> +	/* set dcb default configuration */
> +	hw->local_dcbx_config.etscfg.willing = 0;
> +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> +	hw->local_dcbx_config.etscfg.tsatable[0] =
> +			I40E_IEEE_TSA_ETS;
> +	/* all UPs mapping to region 0 */
> +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> +	hw->local_dcbx_config.etsrec =
> +		hw->local_dcbx_config.etscfg;
> +	hw->local_dcbx_config.pfc.willing = 0;
> +	hw->local_dcbx_config.pfc.pfccap =
> +			I40E_MAX_TRAFFIC_CLASS;
> +	/* FW needs one App to configure HW */
> +	hw->local_dcbx_config.numapps = 1;
> +	hw->local_dcbx_config.app[0].selector =
> +			I40E_APP_SEL_ETHTYPE;
> +	hw->local_dcbx_config.app[0].priority = 3;
> +	hw->local_dcbx_config.app[0].protocolid =
> +			I40E_APP_PROTOID_FCOE;
> +	ret = i40e_set_dcb_config(hw);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR,
> +		"default dcb config fails. err = %d, aq_err = %d.",
> +			ret, hw->aq.asq_last_status);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> +				uint16_t on)
> +{
> +	uint16_t i;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	if (on) {
> +		i40e_vsi_update_queue_region_mapping(hw, pf);
> +		i40e_queue_region_dcb_configure(hw, pf);
> +		return 0;
> +	}
> +
> +	info->queue_region_number = 1;
> +	info->region[0].queue_num = 64;
> +	info->region[0].queue_start_index = 0;
> +
> +	i40e_vsi_update_queue_region_mapping(hw, pf);
> +	i40e_queue_region_dcb_configure_default(hw);
> +
> +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> +
> +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> +
> +	return 0;
> +}
> +
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> +			struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port];

you need to verify port_id, since this is public API now. Please check
other APIs in this file.

> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> +	uint32_t ret;

This should be signed variable, since you are using it for return and
assigning negative values.

> +
> +	if (!is_i40e_supported(dev))
> +		return -ENOTSUP;
> +
> +	switch (op_type) {
> +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> +		ret = i40e_set_queue_region(pf, conf_ptr);
> +		break;

Does it make sense to add another type to get the current queue region
config?

> +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> +		ret = -EINVAL;

Will this be implemented later, or not a valid case at all?

> +		break;
> +	case RTE_PMD_I40E_UP_REGION_SET:> +		ret = i40e_set_up_region(pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> +		break;
> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> +		ret = i40e_flush_region_all_conf(hw, pf, 0);

Can you please describe what flush_on and flush_off are, you can comment
to code if also.

> +		break;
> +
> +	default:
> +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> +			    op_type);

Line break not required.

> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	I40E_WRITE_FLUSH(hw);
> +
> +	return ret;
> +}
> diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
> index 155b7e8..a1329f4 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.h
> +++ b/drivers/net/i40e/rte_pmd_i40e.h
> @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
>  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
>  };
>  
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED = 0,

No need to set to zero, it is default value.

> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set*/

I would suggest using same namespace for the enum ites, there are
"RTE_PMD_I40E_REGION" and "RTE_PMD_I40E_QUEUE_REGION".
"RTE_PMD_I40E_QUEUE_REGION" looks better. Or if it makes sense, perhaps
"RTE_PMD_I40E_RSS_QUEUE_REGION"? But please stick with one.

> +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region pctype set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region pctype set */
> +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype set */

is this comment correct, this type should be for user priority

> +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all configuration */
> +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all configuration */
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
>  
>  /**
> @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
>  
>  /**
> + * Queue region information get from CLI.

It doesn't need to be from CLI, can drop that part

> + */
> +struct rte_i40e_rss_region_conf {

This is now public struct, can you please comment items.

> +	uint8_t region_id;
> +	uint8_t hw_flowtype;
> +	uint8_t queue_start_index;
> +	uint8_t queue_num;
> +	uint8_t user_priority;
> +	enum rte_pmd_i40e_queue_region_op  op;

Extra space before "op"

> +};
> +
> +/**
>   * Notify VF when PF link status changes.
>   *
>   * @param port
> @@ -657,4 +683,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
>  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
>  				 struct ether_addr *mac_addr);
>  
> +/**
> + * Get RSS queue region info from CLI and do configuration for

Again now this is an API, not just for testpmd, please drop CLI

> + * that port as the command otion type

s/otion/options

> + *
> + * @param port
> + *    pointer to port identifier of the device

Not pointer.
Also this will conflict with patch that updates port storage to
uint16_t. Can you please follow the status of the patch, and if this
merged after that one, please ping to remind to update the storage.

> + * @param conf_ptr
> + *    pointer to the struct that contain all the
> + *    region configuration parameters
> + */
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,

Can you please use port_id as variable name to be consistent.

> +		struct rte_i40e_rss_region_conf *conf_ptr);

conf_ptr variable name doesn't say much, although it is OK in this
context. I would suggest something like rss_region_conf

>  #endif /* _PMD_I40E_H_ */
> diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
> index ef8882b..c3ee2da 100644
> --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> @@ -50,5 +50,6 @@ DPDK_17.11 {
>  	global:
>  
>  	rte_pmd_i40e_add_vf_mac_addr;
> +	rte_pmd_i40e_queue_region_conf;

The feature has been mention as "rss queue region" above a few places,
do you think rte_pmd_i40e_rss_queue_region_conf() or
rte_pmd_i40e_queue_region_conf() is better for API name?

>  
>  } DPDK_17.08;
> 

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

* Re: [PATCH v3 2/2] app/testpmd: add API for configuration of queue region
  2017-09-15  3:13     ` [PATCH v3 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-20 10:45       ` Ferruh Yigit
  2017-09-25  9:25         ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-20 10:45 UTC (permalink / raw)
  To: Wei Zhao, dev, Jingjing Wu

On 9/15/2017 4:13 AM, Wei Zhao wrote:
> This patch add a API configuration of queue region in rss.
> It can parse the parameters of region index, queue number,
> queue start index, user priority, traffic classes and so on.
> According to commands from command line, it will call i40e
> private API and start the process of set or flush queue region
> configure. As this feature is specific for i40e, so private API
> will be used.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  app/test-pmd/cmdline.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++

Testpmd documentation also needs to be updated.

>  1 file changed, 328 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 0144191..060fcb1 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
>  			"    Update a ptype mapping item on a port\n\n"
>  
> +			"queue-region set port (port_id) region_id (value) "
> +			"queue_start_index (value) queue_num (value)\n"
> +			"    Set a queue region on a port\n\n"
> +
> +			"queue-region set (pf|vf) port (port_id) region_id (value) "
> +			"flowtype (value)\n"
> +			"    Set a flowtype region index on a port\n\n"
> +
> +			"queue-region set port (port_id) UP (value) region_id (value)\n"
> +			"    Set the mapping of User Priority to "
> +			"queue region on a port\n\n"
> +
> +			"queue-region flush (on|off) port (port_id)\n"
> +			"    flush all queue region related configuration\n\n"

I keep doing same comment but I will do it again...

Each patch adding a new feature looking from its own context and adding
a new root level command and this is making overall testpmd confusing.

Since this is to set an option of the port, what do you think making
this command part of existing commands, like:
"port config #P queue-region ...."
OR
"set port #P queue-region ..." ?

> +
>  			, list_pkt_forwarding_modes()
>  		);
>  	}
> @@ -8224,6 +8239,315 @@ cmdline_parse_inst_t cmd_syn_filter = {
>  		NULL,
>  	},
>  };
> +/* *** queue region set *** */
> +struct cmd_queue_region_result {
> +	cmdline_fixed_string_t cmd;
> +	cmdline_fixed_string_t set;
> +	cmdline_fixed_string_t port;
> +	uint8_t  port_id;
> +	cmdline_fixed_string_t region;
> +	uint8_t  region_id;
> +	cmdline_fixed_string_t queue_start_index;
> +	uint8_t  queue_id;
> +	cmdline_fixed_string_t queue_num;
> +	uint8_t  queue_num_value;
> +};
> +
> +static void
> +cmd_queue_region_parsed(void *parsed_result,
> +			__attribute__((unused)) struct cmdline *cl,
> +			__attribute__((unused)) void *data)
> +{
> +	struct cmd_queue_region_result *res = parsed_result;
> +	struct rte_i40e_rss_region_conf region_conf;
> +	int ret = 0;
> +
> +	memset(&region_conf, 0, sizeof(region_conf));
> +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> +	region_conf.region_id = res->region_id;
> +	region_conf.queue_num = res->queue_num_value;
> +	region_conf.queue_start_index = res->queue_id;
> +
> +	ret = rte_pmd_i40e_queue_region_conf(res->port_id, &region_conf);

It is not safe to directly call PMD specific APIs from testpmd? What if
that PMD is not enabled? There are samples how to do this, can you
please check them?

<...>

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-20 10:36       ` Ferruh Yigit
@ 2017-09-21  6:48         ` Zhao1, Wei
  2017-09-21  7:10           ` Ferruh Yigit
  2017-09-25  7:40         ` Zhao1, Wei
  2017-09-26  8:54         ` Zhao1, Wei
  2 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-21  6:48 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Hi,  Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, September 20, 2017 6:36 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> 
> Is following correct:
> So instead of distributing packets to the multiple queues, this will distribute
> packets into queue reqions which may consists of multiple queues.
> 
> If so, is there a way to control how packets distributed within same queue
> region to multiple queues?
> 
> And is this feature only supported with RSS? Can it be part of RSS
> configuration instead of PMD specific API?
> 
> > This patch enable mapping between different priorities (UP) and
> 
> User priorities (UP)
> 
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
> ++++++++++++++++++++++++++++++
> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
> >  5 files changed, 566 insertions(+), 4 deletions(-)
> >
> 
> <...>
> 
> > +static int
> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> > +			      struct i40e_pf *pf)
> > +{
> > +	uint16_t i;
> > +	struct i40e_vsi *vsi = pf->main_vsi;
> > +	uint16_t queue_offset, bsf, tc_index;
> > +	struct i40e_vsi_context ctxt;
> > +	struct i40e_aqc_vsi_properties_data *vsi_info;
> > +	struct i40e_queue_region_info *region_info =
> > +				&pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	if (!region_info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> 
> Can you please re-check the log message.
> 
> > +		return ret;
> > +	}
> > +
> > +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> > +
> > +	/* Update Queue Pairs Mapping for currently enabled UPs */
> > +	ctxt.seid = vsi->seid;
> > +	ctxt.pf_num = hw->pf_id;
> > +	ctxt.vf_num = 0;
> > +	ctxt.uplink_seid = vsi->uplink_seid;
> > +	ctxt.info = vsi->info;
> > +	vsi_info = &ctxt.info;
> > +
> > +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> > +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> > +
> > +	/**
> > +	 * Configure queue region and queue mapping parameters,
> > +	 * for enabled queue region, allocate queues to this region.
> > +	 */
> > +
> > +	for (i = 0; i < region_info->queue_region_number; i++) {
> > +		tc_index = region_info->region[i].region_id;
> > +		bsf = rte_bsf32(region_info->region[i].queue_num);
> > +		queue_offset = region_info->region[i].queue_start_index;
> > +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> > +			(queue_offset <<
> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> > +				(bsf <<
> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> > +	}
> > +
> > +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> */
> > +	if (vsi->type == I40E_VSI_SRIOV) {
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> > +		for (i = 0; i < vsi->nb_qps; i++)
> > +			vsi_info->queue_mapping[i] =
> > +				rte_cpu_to_le_16(vsi->base_queue + i);
> > +	} else {
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> > +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-
> >base_queue);
> > +	}
> > +	vsi_info->valid_sections |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> > +
> > +	/* Update the VSI after updating the VSI queue-mapping
> information */
> > +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> > +			"mapping = %d ", hw->aq.asq_last_status);
> 
> Please don't split log message.

If I do not spli it , the line will has more 80 character, there will be warning in patch check log!
So, which way do you think will be better? Split or warning log?


> 
> > +		return ret;
> > +	}
> > +	/* update the local VSI info with updated queue map */
> > +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> > +					sizeof(vsi->info.tc_mapping));
> > +	(void)rte_memcpy(&vsi->info.queue_mapping,
> > +			&ctxt.info.queue_mapping,
> > +		sizeof(vsi->info.queue_mapping));
> 
> Please keep line allignment same with above line.
> 
> > +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> > +	vsi->info.valid_sections = 0;
> > +
> > +	return 0;
> > +}
> > +
> > +
> > +static int
> > +i40e_set_queue_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> > +	uint16_t i;
> > +	struct i40e_vsi *main_vsi = pf->main_vsi;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> > +		if (conf_ptr->queue_num == tc_size_tb[i])
> > +			break;
> > +
> > +	if (i == I40E_REGION_MAX_INDEX) {
> > +		printf("The region sizes should be any of the following "
> > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > +		"total number of queues do not exceed the VSI allocation");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> > +					> main_vsi->nb_used_qps) {
> > +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI
> range");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if ((i == info->queue_region_number) &&
> > +			(i <= I40E_REGION_MAX_INDEX)) {
> 
> 
> Please use one more level indentaion here, and pharantesis looks extra can
> you please double check?
> 
> > +			info->region[i].region_id = conf_ptr->region_id;
> > +			info->region[i].queue_num = conf_ptr->queue_num;
> > +			info->region[i].queue_start_index =
> > +				conf_ptr->queue_start_index;
> > +			info->queue_region_number++;
> > +		} else {
> > +			PMD_INIT_LOG(ERR, "queue region number "
> > +				"exceeds maxnum 8 or the "
> > +				"queue region id has "
> > +				"been set before");
> 
> please don't split log message.

If I do not spli it , the line will has more 80 character, there will be warning in patch check log!

> 
> > +			return ret;
> > +		}
> > +	} else {
> > +		info->region[0].region_id = conf_ptr->region_id;
> > +		info->region[0].queue_num = conf_ptr->queue_num;
> > +		info->region[0].queue_start_index =
> > +			conf_ptr->queue_start_index;
> > +		info->queue_region_number++;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> > +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf
> *conf_ptr)
> 
> What do you think starting all functions, even they are static, with
> "i40e_queue_region_" prefix?
> 
> > +{
> > +	uint32_t pfqf_hregion;
> > +	uint32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j, index, flowtype_set = 0;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> > +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index
> is 63");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id has not "
> > +				"been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> > +				if (conf_ptr->hw_flowtype ==
> > +					info->region[i].hw_flowtype[j]) {
> > +					flowtype_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (flowtype_set) {
> > +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> > +				"has been set before");
> 
> Please don't split log messages.
> 
> > +			return ret;
> > +		}
> > +		flowtype_index = info->region[region_index].flowtype_num;
> > +		info->region[region_index].hw_flowtype[flowtype_index] =
> > +						conf_ptr->hw_flowtype;
> > +		info->region[region_index].flowtype_num++;
> > +	} else  {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	index = conf_ptr->hw_flowtype >> 3;
> > +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> > +
> > +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> > +	} else {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> > +	}
> > +
> > +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_up_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr)
> 
> The API name looks like "setup" but that up part is user_priority, can you
> please long form against "up"?
> 
> > +{
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index, up_set = 0;
> 
> Same abrevation comment for "upset", please use long form.
> 
> > +
> > +	if (conf_ptr->user_priority >
> I40E_REGION_USERPRIORITY_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id "
> > +				"has not been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j <
> > +				info->region[i].user_priority_num; j++) {
> 
> Please break line after ";"
> 
> > +				if (info->region[i].user_priority[j] ==
> > +					conf_ptr->user_priority) {
> > +					up_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (up_set) {
> > +			PMD_INIT_LOG(ERR, "that user priority "
> > +				"has been set before");
> > +			return ret;
> > +		}
> > +
> > +		j = info->region[region_index].user_priority_num;
> > +		info->region[region_index].user_priority[j] =
> > +						conf_ptr->user_priority;
> > +		info->region[region_index].user_priority_num++;
> > +	} else {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> > +				struct i40e_pf *pf)
> > +{
> > +	struct i40e_dcbx_config dcb_cfg_local;
> > +	struct i40e_dcbx_config *dcb_cfg;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> > +	uint32_t ret = -EINVAL;
> 
> Please use signed variable, there are more above.
> 
> > +	uint16_t i, j, prio_index, region_index;
> > +	uint8_t tc_map, tc_bw, bw_lf;
> > +
> > +	if (!info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	dcb_cfg = &dcb_cfg_local;
> > +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> > +
> > +	/* assume each tc has the same bw */
> > +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> > +	/* to ensure the sum of tcbw is equal to 100 */
> > +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> > +	for (i = 0; i < bw_lf; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i]++;
> > +
> > +	/* assume each tc has the same Transmission Selection Algorithm */
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			prio_index = info->region[i].user_priority[j];
> > +			region_index = info->region[i].region_id;
> > +			dcb_cfg->etscfg.prioritytable[prio_index] =
> > +						region_index;
> > +		}
> > +	}
> > +
> > +	/* FW needs one App to configure HW */
> > +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> > +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> > +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> > +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> > +
> > +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> > +
> > +	dcb_cfg->pfc.willing = 0;
> > +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> > +	dcb_cfg->pfc.pfcenable = tc_map;
> > +
> > +	/* Copy the new config to the current config */
> > +	*old_cfg = *dcb_cfg;
> > +	old_cfg->etsrec = old_cfg->etscfg;
> > +	ret = i40e_set_dcb_config(hw);
> > +
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,
> err"
> > +			" %s aq_err %s",
> 
> Please don't split the log message.
> 
> > +			 i40e_stat_str(hw, ret),
> > +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw) {
> > +	uint16_t i;
> > +	uint32_t ret = -EINVAL;
> 
> Please use signed variable here.
> 
> > +
> > +	memset(&hw->local_dcbx_config, 0,
> > +	sizeof(struct i40e_dcbx_config));
> 
> Wrong indentation.
> 
> > +	/* set dcb default configuration */
> > +	hw->local_dcbx_config.etscfg.willing = 0;
> > +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> > +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> > +	hw->local_dcbx_config.etscfg.tsatable[0] =
> > +			I40E_IEEE_TSA_ETS;
> > +	/* all UPs mapping to region 0 */
> > +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> > +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> > +	hw->local_dcbx_config.etsrec =
> > +		hw->local_dcbx_config.etscfg;
> > +	hw->local_dcbx_config.pfc.willing = 0;
> > +	hw->local_dcbx_config.pfc.pfccap =
> > +			I40E_MAX_TRAFFIC_CLASS;
> > +	/* FW needs one App to configure HW */
> > +	hw->local_dcbx_config.numapps = 1;
> > +	hw->local_dcbx_config.app[0].selector =
> > +			I40E_APP_SEL_ETHTYPE;
> > +	hw->local_dcbx_config.app[0].priority = 3;
> > +	hw->local_dcbx_config.app[0].protocolid =
> > +			I40E_APP_PROTOID_FCOE;
> > +	ret = i40e_set_dcb_config(hw);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR,
> > +		"default dcb config fails. err = %d, aq_err = %d.",
> > +			ret, hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int
> > +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> > +				uint16_t on)
> > +{
> > +	uint16_t i;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		i40e_queue_region_dcb_configure(hw, pf);
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	i40e_queue_region_dcb_configure_default(hw);
> > +
> > +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> > +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> > +
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> > +
> > +	return 0;
> > +}
> > +
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +			struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> 
> you need to verify port_id, since this is public API now. Please check other
> APIs in this file.
> 
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> > +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> > +	uint32_t ret;
> 
> This should be signed variable, since you are using it for return and assigning
> negative values.
> 
> > +
> > +	if (!is_i40e_supported(dev))
> > +		return -ENOTSUP;
> > +
> > +	switch (op_type) {
> > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > +		break;
> 
> Does it make sense to add another type to get the current queue region
> config?
> 
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > +		ret = -EINVAL;
> 
> Will this be implemented later, or not a valid case at all?
> 
> > +		break;
> > +	case RTE_PMD_I40E_UP_REGION_SET:> +		ret =
> i40e_set_up_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> 
> Can you please describe what flush_on and flush_off are, you can comment
> to code if also.
> 
> > +		break;
> > +
> > +	default:
> > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > +			    op_type);
> 
> Line break not required.
> 
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	I40E_WRITE_FLUSH(hw);
> > +
> > +	return ret;
> > +}
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..a1329f4 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.h
> > +++ b/drivers/net/i40e/rte_pmd_i40e.h
> > @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
> >  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };
> >
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> 
> No need to set to zero, it is default value.
> 
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region
> set*/
> 
> I would suggest using same namespace for the enum ites, there are
> "RTE_PMD_I40E_REGION" and "RTE_PMD_I40E_QUEUE_REGION".
> "RTE_PMD_I40E_QUEUE_REGION" looks better. Or if it makes sense,
> perhaps "RTE_PMD_I40E_RSS_QUEUE_REGION"? But please stick with one.
> 
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region
> pctype set */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region
> pctype set */
> > +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype
> set */
> 
> is this comment correct, this type should be for user priority
> 
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all
> configuration */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all
> configuration */
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region information get from CLI.
> 
> It doesn't need to be from CLI, can drop that part
> 
> > + */
> > +struct rte_i40e_rss_region_conf {
> 
> This is now public struct, can you please comment items.
> 
> > +	uint8_t region_id;
> > +	uint8_t hw_flowtype;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority;
> > +	enum rte_pmd_i40e_queue_region_op  op;
> 
> Extra space before "op"
> 
> > +};
> > +
> > +/**
> >   * Notify VF when PF link status changes.
> >   *
> >   * @param port
> > @@ -657,4 +683,16 @@ int
> rte_pmd_i40e_ptype_mapping_replace(uint8_t
> > port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
> >  				 struct ether_addr *mac_addr);
> >
> > +/**
> > + * Get RSS queue region info from CLI and do configuration for
> 
> Again now this is an API, not just for testpmd, please drop CLI
> 
> > + * that port as the command otion type
> 
> s/otion/options
> 
> > + *
> > + * @param port
> > + *    pointer to port identifier of the device
> 
> Not pointer.
> Also this will conflict with patch that updates port storage to uint16_t. Can
> you please follow the status of the patch, and if this merged after that one,
> please ping to remind to update the storage.
> 
> > + * @param conf_ptr
> > + *    pointer to the struct that contain all the
> > + *    region configuration parameters
> > + */
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> 
> Can you please use port_id as variable name to be consistent.
> 
> > +		struct rte_i40e_rss_region_conf *conf_ptr);
> 
> conf_ptr variable name doesn't say much, although it is OK in this context. I
> would suggest something like rss_region_conf
> 
> >  #endif /* _PMD_I40E_H_ */
> > diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> > b/drivers/net/i40e/rte_pmd_i40e_version.map
> > index ef8882b..c3ee2da 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> > +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> > @@ -50,5 +50,6 @@ DPDK_17.11 {
> >  	global:
> >
> >  	rte_pmd_i40e_add_vf_mac_addr;
> > +	rte_pmd_i40e_queue_region_conf;
> 
> The feature has been mention as "rss queue region" above a few places, do
> you think rte_pmd_i40e_rss_queue_region_conf() or
> rte_pmd_i40e_queue_region_conf() is better for API name?
> 
> >
> >  } DPDK_17.08;
> >


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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-21  6:48         ` Zhao1, Wei
@ 2017-09-21  7:10           ` Ferruh Yigit
  2017-09-21  7:26             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-21  7:10 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/21/2017 7:48 AM, Zhao1, Wei wrote:
> Hi,  Ferruh
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, September 20, 2017 6:36 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
>>
>> On 9/15/2017 4:13 AM, Wei Zhao wrote:
>>> This feature enable queue regions configuration for RSS in PF/VF, so
>>> that different traffic classes or different packet classification
>>> types can be separated to different queues in different queue
>>> regions.This patch can set queue region range, it include queue number
>>> in a region and the index of first queue.
>>
>> Is following correct:
>> So instead of distributing packets to the multiple queues, this will distribute
>> packets into queue reqions which may consists of multiple queues.
>>
>> If so, is there a way to control how packets distributed within same queue
>> region to multiple queues?
>>
>> And is this feature only supported with RSS? Can it be part of RSS
>> configuration instead of PMD specific API?
>>
>>> This patch enable mapping between different priorities (UP) and
>>
>> User priorities (UP)
>>
>>> different traffic classes.It also enable mapping between a region
>>> index and a sepcific flowtype(PCTYPE).It also provide the solution of
>>> flush all configuration about queue region the above described.
>>>
>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>

<...>

>>> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
>>> +	if (ret) {
>>> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
>>> +			"mapping = %d ", hw->aq.asq_last_status);
>>
>> Please don't split log message.
> 
> If I do not spli it , the line will has more 80 character, there will be warning in patch check log!
> So, which way do you think will be better? Split or warning log?

Checkpatch detects log lines and shouldn't complain about them.

Even it does I thinks checkpatch warning is better, assuming reasonable
length.

And you can do as following to reduce the line length:

PMD_INIT_LOG(ERR,
	"Failed to configure queue region mapping = %d ", 	
	hw->aq.asq_last_status);

<...>

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-21  7:10           ` Ferruh Yigit
@ 2017-09-21  7:26             ` Zhao1, Wei
  2017-09-21 15:45               ` Ferruh Yigit
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-21  7:26 UTC (permalink / raw)
  To: Yigit, Ferruh, dev



> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, September 21, 2017 3:10 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> On 9/21/2017 7:48 AM, Zhao1, Wei wrote:
> > Hi,  Ferruh
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, September 20, 2017 6:36 PM
> >> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> >> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> >> flush
> >>
> >> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> >>> This feature enable queue regions configuration for RSS in PF/VF, so
> >>> that different traffic classes or different packet classification
> >>> types can be separated to different queues in different queue
> >>> regions.This patch can set queue region range, it include queue
> >>> number in a region and the index of first queue.
> >>
> >> Is following correct:
> >> So instead of distributing packets to the multiple queues, this will
> >> distribute packets into queue reqions which may consists of multiple
> queues.
> >>
> >> If so, is there a way to control how packets distributed within same
> >> queue region to multiple queues?
> >>
> >> And is this feature only supported with RSS? Can it be part of RSS
> >> configuration instead of PMD specific API?
> >>
> >>> This patch enable mapping between different priorities (UP) and
> >>
> >> User priorities (UP)
> >>
> >>> different traffic classes.It also enable mapping between a region
> >>> index and a sepcific flowtype(PCTYPE).It also provide the solution
> >>> of flush all configuration about queue region the above described.
> >>>
> >>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> 
> <...>
> 
> >>> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> >>> +	if (ret) {
> >>> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> >>> +			"mapping = %d ", hw->aq.asq_last_status);
> >>
> >> Please don't split log message.
> >
> > If I do not spli it , the line will has more 80 character, there will be warning in
> patch check log!
> > So, which way do you think will be better? Split or warning log?
> 
> Checkpatch detects log lines and shouldn't complain about them.
> 
> Even it does I thinks checkpatch warning is better, assuming reasonable
> length.
> 
> And you can do as following to reduce the line length:
> 
> PMD_INIT_LOG(ERR,
> 	"Failed to configure queue region mapping = %d ",
> 	hw->aq.asq_last_status);
> 
> <...>

Ok, I will change to that way, but there will be warning in patch check.
Because at first I do not split them, then after patch check, I find that I must eliminate these over 80 warning.



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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-21  7:26             ` Zhao1, Wei
@ 2017-09-21 15:45               ` Ferruh Yigit
  0 siblings, 0 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-21 15:45 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/21/2017 8:26 AM, Zhao1, Wei wrote:
> 
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Thursday, September 21, 2017 3:10 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
>>
>> On 9/21/2017 7:48 AM, Zhao1, Wei wrote:
>>> Hi,  Ferruh
>>>
>>>> -----Original Message-----
>>>> From: Yigit, Ferruh
>>>> Sent: Wednesday, September 20, 2017 6:36 PM
>>>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>>>> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
>>>> flush
>>>>
>>>> On 9/15/2017 4:13 AM, Wei Zhao wrote:
>>>>> This feature enable queue regions configuration for RSS in PF/VF, so
>>>>> that different traffic classes or different packet classification
>>>>> types can be separated to different queues in different queue
>>>>> regions.This patch can set queue region range, it include queue
>>>>> number in a region and the index of first queue.
>>>>
>>>> Is following correct:
>>>> So instead of distributing packets to the multiple queues, this will
>>>> distribute packets into queue reqions which may consists of multiple
>> queues.
>>>>
>>>> If so, is there a way to control how packets distributed within same
>>>> queue region to multiple queues?
>>>>
>>>> And is this feature only supported with RSS? Can it be part of RSS
>>>> configuration instead of PMD specific API?
>>>>
>>>>> This patch enable mapping between different priorities (UP) and
>>>>
>>>> User priorities (UP)
>>>>
>>>>> different traffic classes.It also enable mapping between a region
>>>>> index and a sepcific flowtype(PCTYPE).It also provide the solution
>>>>> of flush all configuration about queue region the above described.
>>>>>
>>>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>
>> <...>
>>
>>>>> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
>>>>> +	if (ret) {
>>>>> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
>>>>> +			"mapping = %d ", hw->aq.asq_last_status);
>>>>
>>>> Please don't split log message.
>>>
>>> If I do not spli it , the line will has more 80 character, there will be warning in
>> patch check log!
>>> So, which way do you think will be better? Split or warning log?
>>
>> Checkpatch detects log lines and shouldn't complain about them.
>>
>> Even it does I thinks checkpatch warning is better, assuming reasonable
>> length.
>>
>> And you can do as following to reduce the line length:
>>
>> PMD_INIT_LOG(ERR,
>> 	"Failed to configure queue region mapping = %d ",
>> 	hw->aq.asq_last_status);
>>
>> <...>
> 
> Ok, I will change to that way, but there will be warning in patch check.
> Because at first I do not split them, then after patch check, I find that I must eliminate these over 80 warning.

If you are using devtools/checkpatches.sh script, it ignores the
LONG_LINE_STRING warnings, so long log messages shouldn't be generating
warning. I just confirmed it is working as expected.

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-20 10:36       ` Ferruh Yigit
@ 2017-09-21 19:53       ` Chilikin, Andrey
  2017-09-22  8:49         ` Zhao1, Wei
  2017-09-24 16:01       ` Wu, Jingjing
  2 siblings, 1 reply; 87+ messages in thread
From: Chilikin, Andrey @ 2017-09-21 19:53 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei, Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Friday, September 15, 2017 4:13 AM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> This feature enable queue regions configuration for RSS in PF/VF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and
> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c            |  19 +-
>  drivers/net/i40e/i40e_ethdev.h            |  30 ++
>  drivers/net/i40e/rte_pmd_i40e.c           | 482
> ++++++++++++++++++++++++++++++
>  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
>  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
>  5 files changed, 566 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 8e0580c..1663fc0 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -137,10 +137,6 @@
>  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
>  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> 
> -#define I40E_MAX_PERCENT            100
> -#define I40E_DEFAULT_DCB_APP_NUM    1
> -#define I40E_DEFAULT_DCB_APP_PRIO   3
> -
>  /**
>   * Below are values for writing un-exposed registers suggested
>   * by silicon experts
> @@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
>  	return ret;
>  }
> 
> +static void
> +i40e_init_queue_region_conf(struct rte_eth_dev *dev)
> +{
> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> +}
> +
>  static int
>  eth_i40e_dev_init(struct rte_eth_dev *dev)
>  {
> @@ -1309,6 +1314,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
>  	if (ret < 0)
>  		goto err_init_fdir_filter_list;
> 
> +	/* initialize queue region configuration */
> +	i40e_init_queue_region_conf(dev);
> +
>  	return 0;
> 
>  err_init_fdir_filter_list:
> @@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
>  	/* Remove all Traffic Manager configuration */
>  	i40e_tm_conf_uninit(dev);
> 
> +	/* Remove all the queue region configuration */
> +	i40e_flush_region_all_conf(hw, pf, 0);
> +
>  	return 0;
>  }
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.h
> b/drivers/net/i40e/i40e_ethdev.h
> index ad80f0f..d612886 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {
>  #define I40E_QOS_BW_WEIGHT_MIN 1
>  /* The max bandwidth weight is 127. */
>  #define I40E_QOS_BW_WEIGHT_MAX 127
> +/* The max queue region index is 7. */
> +#define I40E_REGION_MAX_INDEX 7
> +/* The max queue region userpriority is 7. */
> +#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
> +/* The max pctype index is 63. */
> +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> +
> +#define I40E_MAX_PERCENT            100
> +#define I40E_DEFAULT_DCB_APP_NUM    1
> +#define I40E_DEFAULT_DCB_APP_PRIO   3
> 
>  /**
>   * The overhead from MTU to max frame size.
> @@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
>  	struct rte_hash *hash_table;
>  };
> 
> +/* queue region info */
> +struct i40e_region_info {
> +	uint8_t region_id;
> +	uint8_t queue_start_index;
> +	uint8_t queue_num;
> +	uint8_t user_priority_num;
> +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> +	uint8_t flowtype_num;
> +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> +};
> +
> +struct i40e_queue_region_info {
> +	uint16_t queue_region_number;
> +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
> +};
> +
>  /* Tunnel filter number HW supports */
>  #define I40E_MAX_TUNNEL_FILTER_NUM 400
> 
> @@ -776,6 +802,7 @@ struct i40e_pf {
>  	struct i40e_fdir_info fdir; /* flow director info */
>  	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
>  	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
> +	struct i40e_queue_region_info queue_region; /* queue region info
> */
>  	struct i40e_fc_conf fc_conf; /* Flow control conf */
>  	struct i40e_mirror_rule_list mirror_list;
>  	uint16_t nb_mirror_rule;   /* The number of mirror rules */
> @@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw,
> uint32_t addr, uint32_t val);
>  int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
>  void i40e_tm_conf_init(struct rte_eth_dev *dev);
>  void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> +int i40e_flush_region_all_conf(struct i40e_hw *hw,
> +				struct i40e_pf *pf, uint16_t on);
> +
> 
>  #define I40E_DEV_TO_PCI(eth_dev) \
>  	RTE_DEV_TO_PCI((eth_dev)->device)
> diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> b/drivers/net/i40e/rte_pmd_i40e.c
> index d69a472..9a75f21 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.c
> +++ b/drivers/net/i40e/rte_pmd_i40e.c
> @@ -35,6 +35,7 @@
>  #include <rte_tailq.h>
> 
>  #include "base/i40e_prototype.h"
> +#include "base/i40e_dcb.h"
>  #include "i40e_ethdev.h"
>  #include "i40e_pf.h"
>  #include "i40e_rxtx.h"
> @@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port,
> uint16_t vf_id,
> 
>  	return 0;
>  }
> +
> +static int
> +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> +			      struct i40e_pf *pf)
> +{
> +	uint16_t i;
> +	struct i40e_vsi *vsi = pf->main_vsi;
> +	uint16_t queue_offset, bsf, tc_index;
> +	struct i40e_vsi_context ctxt;
> +	struct i40e_aqc_vsi_properties_data *vsi_info;
> +	struct i40e_queue_region_info *region_info =
> +				&pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	if (!region_info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> +		return ret;
> +	}
> +
> +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> +
> +	/* Update Queue Pairs Mapping for currently enabled UPs */
> +	ctxt.seid = vsi->seid;
> +	ctxt.pf_num = hw->pf_id;
> +	ctxt.vf_num = 0;
> +	ctxt.uplink_seid = vsi->uplink_seid;
> +	ctxt.info = vsi->info;
> +	vsi_info = &ctxt.info;
> +
> +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> +
> +	/**
> +	 * Configure queue region and queue mapping parameters,
> +	 * for enabled queue region, allocate queues to this region.
> +	 */
> +
> +	for (i = 0; i < region_info->queue_region_number; i++) {
> +		tc_index = region_info->region[i].region_id;
> +		bsf = rte_bsf32(region_info->region[i].queue_num);
> +		queue_offset = region_info->region[i].queue_start_index;
> +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> +			(queue_offset <<
> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> +				(bsf <<
> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> +	}
> +
> +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> */
> +	if (vsi->type == I40E_VSI_SRIOV) {
> +		vsi_info->mapping_flags |=
> +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> +		for (i = 0; i < vsi->nb_qps; i++)
> +			vsi_info->queue_mapping[i] =
> +				rte_cpu_to_le_16(vsi->base_queue + i);
> +	} else {
> +		vsi_info->mapping_flags |=
> +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-
> >base_queue);
> +	}
> +	vsi_info->valid_sections |=
> +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> +
> +	/* Update the VSI after updating the VSI queue-mapping
> information */
> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> +			"mapping = %d ", hw->aq.asq_last_status);
> +		return ret;
> +	}
> +	/* update the local VSI info with updated queue map */
> +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> +					sizeof(vsi->info.tc_mapping));
> +	(void)rte_memcpy(&vsi->info.queue_mapping,
> +			&ctxt.info.queue_mapping,
> +		sizeof(vsi->info.queue_mapping));
> +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> +	vsi->info.valid_sections = 0;
> +
> +	return 0;
> +}
> +
> +
> +static int
> +i40e_set_queue_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> +	uint16_t i;
> +	struct i40e_vsi *main_vsi = pf->main_vsi;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> +		if (conf_ptr->queue_num == tc_size_tb[i])
> +			break;
> +
> +	if (i == I40E_REGION_MAX_INDEX) {
> +		printf("The region sizes should be any of the following "
> +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> +		"total number of queues do not exceed the VSI allocation");

printf?

> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> +					> main_vsi->nb_used_qps) {
> +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI
> range");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if ((i == info->queue_region_number) &&
> +			(i <= I40E_REGION_MAX_INDEX)) {
> +			info->region[i].region_id = conf_ptr->region_id;
> +			info->region[i].queue_num = conf_ptr-
> >queue_num;
> +			info->region[i].queue_start_index =
> +				conf_ptr->queue_start_index;
> +			info->queue_region_number++;
> +		} else {
> +			PMD_INIT_LOG(ERR, "queue region number "
> +				"exceeds maxnum 8 or the "
> +				"queue region id has "
> +				"been set before");
> +			return ret;
> +		}
> +	} else {
> +		info->region[0].region_id = conf_ptr->region_id;
> +		info->region[0].queue_num = conf_ptr->queue_num;
> +		info->region[0].queue_start_index =
> +			conf_ptr->queue_start_index;
> +		info->queue_region_number++;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf
> *conf_ptr)
> +{
> +	uint32_t pfqf_hregion;
> +	uint32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i, j, index, flowtype_set = 0;
> +	uint16_t region_index, flowtype_index;
> +
> +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index
> is 63");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id has not "
> +				"been set before");
> +			return ret;
> +		}
> +		region_index = i;
> +
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> +				if (conf_ptr->hw_flowtype ==
> +					info->region[i].hw_flowtype[j]) {
> +					flowtype_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (flowtype_set) {
> +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> +				"has been set before");
> +			return ret;
> +		}
> +		flowtype_index = info-
> >region[region_index].flowtype_num;
> +		info->region[region_index].hw_flowtype[flowtype_index] =
> +						conf_ptr->hw_flowtype;
> +		info->region[region_index].flowtype_num++;
> +	} else  {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> +		return ret;
> +	}
> +
> +	index = conf_ptr->hw_flowtype >> 3;
> +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> +
> +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> +	} else {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> +	}
> +
> +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_up_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +	uint16_t i, j, region_index, up_set = 0;
> +
> +	if (conf_ptr->user_priority >
> I40E_REGION_USERPRIORITY_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id "
> +				"has not been set before");
> +			return ret;
> +		}
> +		region_index = i;
> +
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j <
> +				info->region[i].user_priority_num; j++) {
> +				if (info->region[i].user_priority[j] ==
> +					conf_ptr->user_priority) {
> +					up_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (up_set) {
> +			PMD_INIT_LOG(ERR, "that user priority "
> +				"has been set before");
> +			return ret;
> +		}
> +
> +		j = info->region[region_index].user_priority_num;
> +		info->region[region_index].user_priority[j] =
> +						conf_ptr->user_priority;
> +		info->region[region_index].user_priority_num++;
> +	} else {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> +				struct i40e_pf *pf)
> +{
> +	struct i40e_dcbx_config dcb_cfg_local;
> +	struct i40e_dcbx_config *dcb_cfg;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> +	uint32_t ret = -EINVAL;
> +	uint16_t i, j, prio_index, region_index;
> +	uint8_t tc_map, tc_bw, bw_lf;
> +
> +	if (!info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> +		return ret;
> +	}
> +
> +	dcb_cfg = &dcb_cfg_local;
> +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> +
> +	/* assume each tc has the same bw */
> +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> +	/* to ensure the sum of tcbw is equal to 100 */
> +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> +	for (i = 0; i < bw_lf; i++)
> +		dcb_cfg->etscfg.tcbwtable[i]++;
> +
> +	/* assume each tc has the same Transmission Selection Algorithm */
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> +			prio_index = info->region[i].user_priority[j];
> +			region_index = info->region[i].region_id;
> +			dcb_cfg->etscfg.prioritytable[prio_index] =
> +						region_index;
> +		}
> +	}
> +
> +	/* FW needs one App to configure HW */
> +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> +
> +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> +
> +	dcb_cfg->pfc.willing = 0;
> +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> +	dcb_cfg->pfc.pfcenable = tc_map;
> +
> +	/* Copy the new config to the current config */
> +	*old_cfg = *dcb_cfg;
> +	old_cfg->etsrec = old_cfg->etscfg;
> +	ret = i40e_set_dcb_config(hw);
> +
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,
> err"
> +			" %s aq_err %s",
> +			 i40e_stat_str(hw, ret),
> +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
> +{
> +	uint16_t i;
> +	uint32_t ret = -EINVAL;
> +
> +	memset(&hw->local_dcbx_config, 0,
> +	sizeof(struct i40e_dcbx_config));
> +	/* set dcb default configuration */
> +	hw->local_dcbx_config.etscfg.willing = 0;
> +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> +	hw->local_dcbx_config.etscfg.tsatable[0] =
> +			I40E_IEEE_TSA_ETS;
> +	/* all UPs mapping to region 0 */
> +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> +	hw->local_dcbx_config.etsrec =
> +		hw->local_dcbx_config.etscfg;
> +	hw->local_dcbx_config.pfc.willing = 0;
> +	hw->local_dcbx_config.pfc.pfccap =
> +			I40E_MAX_TRAFFIC_CLASS;
> +	/* FW needs one App to configure HW */
> +	hw->local_dcbx_config.numapps = 1;
> +	hw->local_dcbx_config.app[0].selector =
> +			I40E_APP_SEL_ETHTYPE;
> +	hw->local_dcbx_config.app[0].priority = 3;
> +	hw->local_dcbx_config.app[0].protocolid =
> +			I40E_APP_PROTOID_FCOE;
> +	ret = i40e_set_dcb_config(hw);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR,
> +		"default dcb config fails. err = %d, aq_err = %d.",
> +			ret, hw->aq.asq_last_status);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> +				uint16_t on)
> +{
> +	uint16_t i;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	if (on) {
> +		i40e_vsi_update_queue_region_mapping(hw, pf);
> +		i40e_queue_region_dcb_configure(hw, pf);
> +		return 0;
> +	}
> +
> +	info->queue_region_number = 1;
> +	info->region[0].queue_num = 64;
> +	info->region[0].queue_start_index = 0;
> +
> +	i40e_vsi_update_queue_region_mapping(hw, pf);
> +	i40e_queue_region_dcb_configure_default(hw);
> +
> +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> +
> +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> +
> +	return 0;
> +}
> +
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> +			struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> +	uint32_t ret;
> +
> +	if (!is_i40e_supported(dev))
> +		return -ENOTSUP;
> +
> +	switch (op_type) {
> +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> +		ret = i40e_set_queue_region(pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> +		ret = -EINVAL;
> +		break;

Why setting of flowtype mapping is separated to two different option?
Does it mean that application will need to detect which driver it uses before
calling this API? Application should not care which driver is in use, it tracks the
number of queues used for RSS and just configures these queues to
different regions, regardless if it runs on top of PF or VF. Difference
in configuration for PF/VF should be hidden from application, so
only single RTE_PMD_I40E_REGION_FLOWTYPE_SET should be used.

All other options do not have separate check.
Will they work on both PF and VF?

> +	case RTE_PMD_I40E_UP_REGION_SET:
> +		ret = i40e_set_up_region(pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> +		break;
> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> +		break;
> +
> +	default:
> +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> +			    op_type);
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	I40E_WRITE_FLUSH(hw);
> +
> +	return ret;
> +}

How this API can be tested, is there a separate testpmd patch?

> diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> b/drivers/net/i40e/rte_pmd_i40e.h
> index 155b7e8..a1329f4 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.h
> +++ b/drivers/net/i40e/rte_pmd_i40e.h
> @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
>  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
>  };
> 
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region
> set*/
> +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region
> pctype set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region
> pctype set */
> +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype
> set */
> +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all
> configuration */
> +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all
> configuration */
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> 
>  /**
> @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
> 
>  /**
> + * Queue region information get from CLI.
> + */
> +struct rte_i40e_rss_region_conf {
> +	uint8_t region_id;
> +	uint8_t hw_flowtype;
> +	uint8_t queue_start_index;
> +	uint8_t queue_num;
> +	uint8_t user_priority;
> +	enum rte_pmd_i40e_queue_region_op  op;
> +};
> +
> +/**
>   * Notify VF when PF link status changes.
>   *
>   * @param port
> @@ -657,4 +683,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t
> port,
>  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
>  				 struct ether_addr *mac_addr);
> 
> +/**
> + * Get RSS queue region info from CLI and do configuration for
> + * that port as the command otion type
> + *
> + * @param port
> + *    pointer to port identifier of the device
> + * @param conf_ptr
> + *    pointer to the struct that contain all the
> + *    region configuration parameters
> + */
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> +		struct rte_i40e_rss_region_conf *conf_ptr);
>  #endif /* _PMD_I40E_H_ */
> diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> b/drivers/net/i40e/rte_pmd_i40e_version.map
> index ef8882b..c3ee2da 100644
> --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> @@ -50,5 +50,6 @@ DPDK_17.11 {
>  	global:
> 
>  	rte_pmd_i40e_add_vf_mac_addr;
> +	rte_pmd_i40e_queue_region_conf;
> 
>  } DPDK_17.08;
> --
> 2.9.3

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-21 19:53       ` Chilikin, Andrey
@ 2017-09-22  8:49         ` Zhao1, Wei
  2017-09-22 20:13           ` Chilikin, Andrey
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-22  8:49 UTC (permalink / raw)
  To: Chilikin, Andrey, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi,Andrey

> -----Original Message-----
> From: Chilikin, Andrey
> Sent: Friday, September 22, 2017 3:53 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Friday, September 15, 2017 4:13 AM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
> > ++++++++++++++++++++++++++++++
> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
> >  5 files changed, 566 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 8e0580c..1663fc0 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -137,10 +137,6 @@
> >  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
> >  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> >
> > -#define I40E_MAX_PERCENT            100
> > -#define I40E_DEFAULT_DCB_APP_NUM    1
> > -#define I40E_DEFAULT_DCB_APP_PRIO   3
> > -
> >  /**
> >   * Below are values for writing un-exposed registers suggested
> >   * by silicon experts
> > @@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev
> *dev)
> >  	return ret;
> >  }
> >
> > +static void
> > +i40e_init_queue_region_conf(struct rte_eth_dev *dev) {
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> > >dev_private);
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info)); }
> > +
> >  static int
> >  eth_i40e_dev_init(struct rte_eth_dev *dev)  { @@ -1309,6 +1314,9 @@
> > eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  	if (ret < 0)
> >  		goto err_init_fdir_filter_list;
> >
> > +	/* initialize queue region configuration */
> > +	i40e_init_queue_region_conf(dev);
> > +
> >  	return 0;
> >
> >  err_init_fdir_filter_list:
> > @@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
> >  	/* Remove all Traffic Manager configuration */
> >  	i40e_tm_conf_uninit(dev);
> >
> > +	/* Remove all the queue region configuration */
> > +	i40e_flush_region_all_conf(hw, pf, 0);
> > +
> >  	return 0;
> >  }
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index ad80f0f..d612886 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {  #define
> > I40E_QOS_BW_WEIGHT_MIN 1
> >  /* The max bandwidth weight is 127. */  #define
> > I40E_QOS_BW_WEIGHT_MAX 127
> > +/* The max queue region index is 7. */ #define
> I40E_REGION_MAX_INDEX
> > +7
> > +/* The max queue region userpriority is 7. */ #define
> > +I40E_REGION_USERPRIORITY_MAX_INDEX 7
> > +/* The max pctype index is 63. */
> > +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> > +
> > +#define I40E_MAX_PERCENT            100
> > +#define I40E_DEFAULT_DCB_APP_NUM    1
> > +#define I40E_DEFAULT_DCB_APP_PRIO   3
> >
> >  /**
> >   * The overhead from MTU to max frame size.
> > @@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
> >  	struct rte_hash *hash_table;
> >  };
> >
> > +/* queue region info */
> > +struct i40e_region_info {
> > +	uint8_t region_id;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority_num;
> > +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> > +	uint8_t flowtype_num;
> > +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> > +};
> > +
> > +struct i40e_queue_region_info {
> > +	uint16_t queue_region_number;
> > +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1]; };
> > +
> >  /* Tunnel filter number HW supports */  #define
> > I40E_MAX_TUNNEL_FILTER_NUM 400
> >
> > @@ -776,6 +802,7 @@ struct i40e_pf {
> >  	struct i40e_fdir_info fdir; /* flow director info */
> >  	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
> >  	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
> > +	struct i40e_queue_region_info queue_region; /* queue region info
> > */
> >  	struct i40e_fc_conf fc_conf; /* Flow control conf */
> >  	struct i40e_mirror_rule_list mirror_list;
> >  	uint16_t nb_mirror_rule;   /* The number of mirror rules */
> > @@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw,
> > uint32_t addr, uint32_t val);  int i40e_tm_ops_get(struct rte_eth_dev
> > *dev, void *ops);  void i40e_tm_conf_init(struct rte_eth_dev *dev);
> > void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> > +int i40e_flush_region_all_conf(struct i40e_hw *hw,
> > +				struct i40e_pf *pf, uint16_t on);
> > +
> >
> >  #define I40E_DEV_TO_PCI(eth_dev) \
> >  	RTE_DEV_TO_PCI((eth_dev)->device)
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> > b/drivers/net/i40e/rte_pmd_i40e.c index d69a472..9a75f21 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.c
> > +++ b/drivers/net/i40e/rte_pmd_i40e.c
> > @@ -35,6 +35,7 @@
> >  #include <rte_tailq.h>
> >
> >  #include "base/i40e_prototype.h"
> > +#include "base/i40e_dcb.h"
> >  #include "i40e_ethdev.h"
> >  #include "i40e_pf.h"
> >  #include "i40e_rxtx.h"
> > @@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port,
> > uint16_t vf_id,
> >
> >  	return 0;
> >  }
> > +
> > +static int
> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> > +			      struct i40e_pf *pf)
> > +{
> > +	uint16_t i;
> > +	struct i40e_vsi *vsi = pf->main_vsi;
> > +	uint16_t queue_offset, bsf, tc_index;
> > +	struct i40e_vsi_context ctxt;
> > +	struct i40e_aqc_vsi_properties_data *vsi_info;
> > +	struct i40e_queue_region_info *region_info =
> > +				&pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	if (!region_info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> > before");
> > +		return ret;
> > +	}
> > +
> > +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> > +
> > +	/* Update Queue Pairs Mapping for currently enabled UPs */
> > +	ctxt.seid = vsi->seid;
> > +	ctxt.pf_num = hw->pf_id;
> > +	ctxt.vf_num = 0;
> > +	ctxt.uplink_seid = vsi->uplink_seid;
> > +	ctxt.info = vsi->info;
> > +	vsi_info = &ctxt.info;
> > +
> > +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> > +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> > +
> > +	/**
> > +	 * Configure queue region and queue mapping parameters,
> > +	 * for enabled queue region, allocate queues to this region.
> > +	 */
> > +
> > +	for (i = 0; i < region_info->queue_region_number; i++) {
> > +		tc_index = region_info->region[i].region_id;
> > +		bsf = rte_bsf32(region_info->region[i].queue_num);
> > +		queue_offset = region_info->region[i].queue_start_index;
> > +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> > +			(queue_offset <<
> > I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> > +				(bsf <<
> > I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> > +	}
> > +
> > +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> > */
> > +	if (vsi->type == I40E_VSI_SRIOV) {
> > +		vsi_info->mapping_flags |=
> > +
> > 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> > +		for (i = 0; i < vsi->nb_qps; i++)
> > +			vsi_info->queue_mapping[i] =
> > +				rte_cpu_to_le_16(vsi->base_queue + i);
> > +	} else {
> > +		vsi_info->mapping_flags |=
> > +
> > 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> > +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-
> > >base_queue);
> > +	}
> > +	vsi_info->valid_sections |=
> > +
> > 	rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> > +
> > +	/* Update the VSI after updating the VSI queue-mapping
> > information */
> > +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> > +			"mapping = %d ", hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +	/* update the local VSI info with updated queue map */
> > +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> > +					sizeof(vsi->info.tc_mapping));
> > +	(void)rte_memcpy(&vsi->info.queue_mapping,
> > +			&ctxt.info.queue_mapping,
> > +		sizeof(vsi->info.queue_mapping));
> > +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> > +	vsi->info.valid_sections = 0;
> > +
> > +	return 0;
> > +}
> > +
> > +
> > +static int
> > +i40e_set_queue_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> > +	uint16_t i;
> > +	struct i40e_vsi *main_vsi = pf->main_vsi;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> > +		if (conf_ptr->queue_num == tc_size_tb[i])
> > +			break;
> > +
> > +	if (i == I40E_REGION_MAX_INDEX) {
> > +		printf("The region sizes should be any of the following "
> > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > +		"total number of queues do not exceed the VSI allocation");
> 
> printf?
> 
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> > +					> main_vsi->nb_used_qps) {
> > +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI
> > range");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if ((i == info->queue_region_number) &&
> > +			(i <= I40E_REGION_MAX_INDEX)) {
> > +			info->region[i].region_id = conf_ptr->region_id;
> > +			info->region[i].queue_num = conf_ptr-
> > >queue_num;
> > +			info->region[i].queue_start_index =
> > +				conf_ptr->queue_start_index;
> > +			info->queue_region_number++;
> > +		} else {
> > +			PMD_INIT_LOG(ERR, "queue region number "
> > +				"exceeds maxnum 8 or the "
> > +				"queue region id has "
> > +				"been set before");
> > +			return ret;
> > +		}
> > +	} else {
> > +		info->region[0].region_id = conf_ptr->region_id;
> > +		info->region[0].queue_num = conf_ptr->queue_num;
> > +		info->region[0].queue_start_index =
> > +			conf_ptr->queue_start_index;
> > +		info->queue_region_number++;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> > +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf
> > *conf_ptr)
> > +{
> > +	uint32_t pfqf_hregion;
> > +	uint32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j, index, flowtype_set = 0;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> > +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index
> > is 63");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id has not "
> > +				"been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> > +				if (conf_ptr->hw_flowtype ==
> > +					info->region[i].hw_flowtype[j]) {
> > +					flowtype_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (flowtype_set) {
> > +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> > +				"has been set before");
> > +			return ret;
> > +		}
> > +		flowtype_index = info-
> > >region[region_index].flowtype_num;
> > +		info->region[region_index].hw_flowtype[flowtype_index] =
> > +						conf_ptr->hw_flowtype;
> > +		info->region[region_index].flowtype_num++;
> > +	} else  {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> > before");
> > +		return ret;
> > +	}
> > +
> > +	index = conf_ptr->hw_flowtype >> 3;
> > +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> > +
> > +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> > +	} else {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> > +		pfqf_hregion |= 1 <<
> > I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> > +	}
> > +
> > +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_up_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index, up_set = 0;
> > +
> > +	if (conf_ptr->user_priority >
> > I40E_REGION_USERPRIORITY_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id "
> > +				"has not been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j <
> > +				info->region[i].user_priority_num; j++) {
> > +				if (info->region[i].user_priority[j] ==
> > +					conf_ptr->user_priority) {
> > +					up_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (up_set) {
> > +			PMD_INIT_LOG(ERR, "that user priority "
> > +				"has been set before");
> > +			return ret;
> > +		}
> > +
> > +		j = info->region[region_index].user_priority_num;
> > +		info->region[region_index].user_priority[j] =
> > +						conf_ptr->user_priority;
> > +		info->region[region_index].user_priority_num++;
> > +	} else {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> > before");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> > +				struct i40e_pf *pf)
> > +{
> > +	struct i40e_dcbx_config dcb_cfg_local;
> > +	struct i40e_dcbx_config *dcb_cfg;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, prio_index, region_index;
> > +	uint8_t tc_map, tc_bw, bw_lf;
> > +
> > +	if (!info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> > before");
> > +		return ret;
> > +	}
> > +
> > +	dcb_cfg = &dcb_cfg_local;
> > +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> > +
> > +	/* assume each tc has the same bw */
> > +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> > +	/* to ensure the sum of tcbw is equal to 100 */
> > +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> > +	for (i = 0; i < bw_lf; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i]++;
> > +
> > +	/* assume each tc has the same Transmission Selection Algorithm */
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			prio_index = info->region[i].user_priority[j];
> > +			region_index = info->region[i].region_id;
> > +			dcb_cfg->etscfg.prioritytable[prio_index] =
> > +						region_index;
> > +		}
> > +	}
> > +
> > +	/* FW needs one App to configure HW */
> > +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> > +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> > +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> > +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> > +
> > +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> > +
> > +	dcb_cfg->pfc.willing = 0;
> > +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> > +	dcb_cfg->pfc.pfcenable = tc_map;
> > +
> > +	/* Copy the new config to the current config */
> > +	*old_cfg = *dcb_cfg;
> > +	old_cfg->etsrec = old_cfg->etscfg;
> > +	ret = i40e_set_dcb_config(hw);
> > +
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,
> > err"
> > +			" %s aq_err %s",
> > +			 i40e_stat_str(hw, ret),
> > +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw) {
> > +	uint16_t i;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	memset(&hw->local_dcbx_config, 0,
> > +	sizeof(struct i40e_dcbx_config));
> > +	/* set dcb default configuration */
> > +	hw->local_dcbx_config.etscfg.willing = 0;
> > +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> > +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> > +	hw->local_dcbx_config.etscfg.tsatable[0] =
> > +			I40E_IEEE_TSA_ETS;
> > +	/* all UPs mapping to region 0 */
> > +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> > +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> > +	hw->local_dcbx_config.etsrec =
> > +		hw->local_dcbx_config.etscfg;
> > +	hw->local_dcbx_config.pfc.willing = 0;
> > +	hw->local_dcbx_config.pfc.pfccap =
> > +			I40E_MAX_TRAFFIC_CLASS;
> > +	/* FW needs one App to configure HW */
> > +	hw->local_dcbx_config.numapps = 1;
> > +	hw->local_dcbx_config.app[0].selector =
> > +			I40E_APP_SEL_ETHTYPE;
> > +	hw->local_dcbx_config.app[0].priority = 3;
> > +	hw->local_dcbx_config.app[0].protocolid =
> > +			I40E_APP_PROTOID_FCOE;
> > +	ret = i40e_set_dcb_config(hw);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR,
> > +		"default dcb config fails. err = %d, aq_err = %d.",
> > +			ret, hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int
> > +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> > +				uint16_t on)
> > +{
> > +	uint16_t i;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		i40e_queue_region_dcb_configure(hw, pf);
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	i40e_queue_region_dcb_configure_default(hw);
> > +
> > +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> > +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> > +
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> > +
> > +	return 0;
> > +}
> > +
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +			struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> > >dev_private);
> > +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> > >dev_private);
> > +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> > +	uint32_t ret;
> > +
> > +	if (!is_i40e_supported(dev))
> > +		return -ENOTSUP;
> > +
> > +	switch (op_type) {
> > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > +		ret = -EINVAL;
> > +		break;
> 
> Why setting of flowtype mapping is separated to two different option?
> Does it mean that application will need to detect which driver it uses before
> calling this API? Application should not care which driver is in use, it tracks the
> number of queues used for RSS and just configures these queues to
> different regions, regardless if it runs on top of PF or VF. Difference in
> configuration for PF/VF should be hidden from application, so only single
> RTE_PMD_I40E_REGION_FLOWTYPE_SET should be used.

By now , we only support pf for this config. 
But I think what you said is very reasonable. I can change code to a new scheme:
DPDK i40e driver use   rte_eth_dev ->device->name to detect  whether his name is 
" net_i40e_vf " or " net_i40e"  itself, then  we  can PMD driver decide to config PFQF_HREGION or VFQF_HREGION.
I will make change in v4 later. 

> 
> All other options do not have separate check.
> Will they work on both PF and VF?

No, only WORK on PF. The reason we have talk in other mail before.

> 
> > +	case RTE_PMD_I40E_UP_REGION_SET:
> > +		ret = i40e_set_up_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> > +		break;
> > +
> > +	default:
> > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > +			    op_type);
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	I40E_WRITE_FLUSH(hw);
> > +
> > +	return ret;
> > +}
> 

> How this API can be tested, is there a separate testpmd patch?

Yes, testpmd has add new CLI commands to support it, also can be use by customer.

> 
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..a1329f4 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.h
> > +++ b/drivers/net/i40e/rte_pmd_i40e.h
> > @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
> >  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };
> >
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region
> > set*/
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region
> > pctype set */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region
> > pctype set */
> > +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype
> > set */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all
> > configuration */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all
> > configuration */
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region information get from CLI.
> > + */
> > +struct rte_i40e_rss_region_conf {
> > +	uint8_t region_id;
> > +	uint8_t hw_flowtype;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority;
> > +	enum rte_pmd_i40e_queue_region_op  op; };
> > +
> > +/**
> >   * Notify VF when PF link status changes.
> >   *
> >   * @param port
> > @@ -657,4 +683,16 @@ int
> rte_pmd_i40e_ptype_mapping_replace(uint8_t
> > port,
> >  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
> >  				 struct ether_addr *mac_addr);
> >
> > +/**
> > + * Get RSS queue region info from CLI and do configuration for
> > + * that port as the command otion type
> > + *
> > + * @param port
> > + *    pointer to port identifier of the device
> > + * @param conf_ptr
> > + *    pointer to the struct that contain all the
> > + *    region configuration parameters
> > + */
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +		struct rte_i40e_rss_region_conf *conf_ptr);
> >  #endif /* _PMD_I40E_H_ */
> > diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> > b/drivers/net/i40e/rte_pmd_i40e_version.map
> > index ef8882b..c3ee2da 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> > +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> > @@ -50,5 +50,6 @@ DPDK_17.11 {
> >  	global:
> >
> >  	rte_pmd_i40e_add_vf_mac_addr;
> > +	rte_pmd_i40e_queue_region_conf;
> >
> >  } DPDK_17.08;
> > --
> > 2.9.3
> 


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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-22  8:49         ` Zhao1, Wei
@ 2017-09-22 20:13           ` Chilikin, Andrey
  2017-09-25  2:55             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Chilikin, Andrey @ 2017-09-22 20:13 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi Wei

> -----Original Message-----
> From: Zhao1, Wei
> Sent: Friday, September 22, 2017 9:49 AM
> To: Chilikin, Andrey <andrey.chilikin@intel.com>; dev@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> Hi,Andrey
> 
> > -----Original Message-----
> > From: Chilikin, Andrey
> > Sent: Friday, September 22, 2017 3:53 AM
> > To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> > <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>
> > Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> flush

<snip>

> > > +	if (i == I40E_REGION_MAX_INDEX) {
> > > +		printf("The region sizes should be any of the following "
> > > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > > +		"total number of queues do not exceed the VSI allocation");

 printf?

> > > +		return ret;
> > > +	}
> > > +
> > > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > > +		return ret;
> > > +	}
> > > +

<snip>
> > > +	switch (op_type) {
> > > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > > +		break;
> > > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > > +		break;
> > > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > > +		ret = -EINVAL;
> > > +		break;
> >
> > Why setting of flowtype mapping is separated to two different option?
> > Does it mean that application will need to detect which driver it uses before
> > calling this API? Application should not care which driver is in use, it tracks
> the
> > number of queues used for RSS and just configures these queues to
> > different regions, regardless if it runs on top of PF or VF. Difference in
> > configuration for PF/VF should be hidden from application, so only single
> > RTE_PMD_I40E_REGION_FLOWTYPE_SET should be used.
> 
> By now , we only support pf for this config.
> But I think what you said is very reasonable. I can change code to a new
> scheme:
> DPDK i40e driver use   rte_eth_dev ->device->name to detect  whether his
> name is
> " net_i40e_vf " or " net_i40e"  itself, then  we  can PMD driver decide to
> config PFQF_HREGION or VFQF_HREGION.
> I will make change in v4 later.
> 
> >
> > All other options do not have separate check.
> > Will they work on both PF and VF?
> 
> No, only WORK on PF. The reason we have talk in other mail before.
> 

Yes, it is why I was confused with separating RTE_PMD_I40E_REGION_FLOWTYPE to PF and VF. All options work on PF only, by only FLOWTYPE was split to PF/VF.

> >
> > > +	case RTE_PMD_I40E_UP_REGION_SET:
> > > +		ret = i40e_set_up_region(pf, conf_ptr);
> > > +		break;
> > > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > > +		break;
> > > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> > > +		break;
> > > +

Could you explain what is the difference between FLUSH_OFF and FLUSH_ON and how it can be used by an application?

> > > +	default:
> > > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > > +			    op_type);
> > > +		ret = -EINVAL;
> > > +		break;
> > > +	}
> > > +
> > > +	I40E_WRITE_FLUSH(hw);
> > > +
> > > +	return ret;
> > > +}
> >
> 
> > How this API can be tested, is there a separate testpmd patch?
> 
> Yes, testpmd has add new CLI commands to support it, also can be use by
> customer.

Sorry, missed second part of the patchset.

Regards,
Andrey

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-20 10:36       ` Ferruh Yigit
  2017-09-21 19:53       ` Chilikin, Andrey
@ 2017-09-24 16:01       ` Wu, Jingjing
  2017-09-25  3:26         ` Zhao1, Wei
  2017-09-25  5:55         ` Zhao1, Wei
  2 siblings, 2 replies; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-24 16:01 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Friday, September 15, 2017 11:13 AM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> This feature enable queue regions configuration for RSS in PF/VF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and
> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c            |  19 +-
>  drivers/net/i40e/i40e_ethdev.h            |  30 ++
>  drivers/net/i40e/rte_pmd_i40e.c           | 482
> ++++++++++++++++++++++++++++++
>  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
>  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
>  5 files changed, 566 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 8e0580c..1663fc0 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -137,10 +137,6 @@
>  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
>  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> 
> -#define I40E_MAX_PERCENT            100
> -#define I40E_DEFAULT_DCB_APP_NUM    1
> -#define I40E_DEFAULT_DCB_APP_PRIO   3
> -
>  /**
>   * Below are values for writing un-exposed registers suggested
>   * by silicon experts
> @@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
>  	return ret;
>  }
> 
> +static void
> +i40e_init_queue_region_conf(struct rte_eth_dev *dev)
> +{
> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> +}
> +
>  static int
>  eth_i40e_dev_init(struct rte_eth_dev *dev)
>  {
> @@ -1309,6 +1314,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
>  	if (ret < 0)
>  		goto err_init_fdir_filter_list;
> 
> +	/* initialize queue region configuration */
> +	i40e_init_queue_region_conf(dev);
> +
If this func i40e_init_queue_region_conf is only called here, then it is
Not necessary? Because all the pf struct has been zeroed at probe time.

>  	return 0;
> 
>  err_init_fdir_filter_list:
> @@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
>  	/* Remove all Traffic Manager configuration */
>  	i40e_tm_conf_uninit(dev);
> 
> +	/* Remove all the queue region configuration */
> +	i40e_flush_region_all_conf(hw, pf, 0);
> +
>  	return 0;
>  }
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> index ad80f0f..d612886 100644
> --- a/drivers/net/i40e/i40e_ethdev.h
> +++ b/drivers/net/i40e/i40e_ethdev.h
> @@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {
>  #define I40E_QOS_BW_WEIGHT_MIN 1
>  /* The max bandwidth weight is 127. */
>  #define I40E_QOS_BW_WEIGHT_MAX 127
> +/* The max queue region index is 7. */
> +#define I40E_REGION_MAX_INDEX 7
> +/* The max queue region userpriority is 7. */
> +#define I40E_REGION_USERPRIORITY_MAX_INDEX 7
You can reuse I40E_MAX_USER_PRIORITY.

> +/* The max pctype index is 63. */
> +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> +
You can use I40E_FILTER_PCTYPE_MAX

> +#define I40E_MAX_PERCENT            100
> +#define I40E_DEFAULT_DCB_APP_NUM    1
> +#define I40E_DEFAULT_DCB_APP_PRIO   3
> 
>  /**
>   * The overhead from MTU to max frame size.
> @@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
>  	struct rte_hash *hash_table;
>  };
> 
> +/* queue region info */
> +struct i40e_region_info {
> +	uint8_t region_id;
> +	uint8_t queue_start_index;
> +	uint8_t queue_num;
> +	uint8_t user_priority_num;
> +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
Please comment what is the meaning of this array?

> +	uint8_t flowtype_num;
> +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
The same, please comment it.

> +};
> +
> +struct i40e_queue_region_info {
> +	uint16_t queue_region_number;
> +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
> +};
> +
>  /* Tunnel filter number HW supports */
>  #define I40E_MAX_TUNNEL_FILTER_NUM 400
> 
> @@ -776,6 +802,7 @@ struct i40e_pf {
>  	struct i40e_fdir_info fdir; /* flow director info */
>  	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
>  	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
> +	struct i40e_queue_region_info queue_region; /* queue region info */
>  	struct i40e_fc_conf fc_conf; /* Flow control conf */
>  	struct i40e_mirror_rule_list mirror_list;
>  	uint16_t nb_mirror_rule;   /* The number of mirror rules */
> @@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr,
> uint32_t val);
>  int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
>  void i40e_tm_conf_init(struct rte_eth_dev *dev);
>  void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> +int i40e_flush_region_all_conf(struct i40e_hw *hw,
> +				struct i40e_pf *pf, uint16_t on);
> +
> 
>  #define I40E_DEV_TO_PCI(eth_dev) \
>  	RTE_DEV_TO_PCI((eth_dev)->device)
> diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
> index d69a472..9a75f21 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.c
> +++ b/drivers/net/i40e/rte_pmd_i40e.c
> @@ -35,6 +35,7 @@
>  #include <rte_tailq.h>
> 
>  #include "base/i40e_prototype.h"
> +#include "base/i40e_dcb.h"
>  #include "i40e_ethdev.h"
>  #include "i40e_pf.h"
>  #include "i40e_rxtx.h"
> @@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t
> vf_id,
> 
>  	return 0;
>  }
> +
> +static int
> +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> +			      struct i40e_pf *pf)
> +{
> +	uint16_t i;
> +	struct i40e_vsi *vsi = pf->main_vsi;
> +	uint16_t queue_offset, bsf, tc_index;
> +	struct i40e_vsi_context ctxt;
> +	struct i40e_aqc_vsi_properties_data *vsi_info;
> +	struct i40e_queue_region_info *region_info =
> +				&pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	if (!region_info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> +
> +	/* Update Queue Pairs Mapping for currently enabled UPs */
> +	ctxt.seid = vsi->seid;
> +	ctxt.pf_num = hw->pf_id;
> +	ctxt.vf_num = 0;
> +	ctxt.uplink_seid = vsi->uplink_seid;
> +	ctxt.info = vsi->info;
> +	vsi_info = &ctxt.info;
> +
Please use the vsi_info stored in i40e_vsi to avoid missing parameters.

> +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> +
Ctxt has been zeroed, no need to memset tc_mapping and queue_mapping again.
> +	/**
> +	 * Configure queue region and queue mapping parameters,
> +	 * for enabled queue region, allocate queues to this region.
> +	 */
> +
> +	for (i = 0; i < region_info->queue_region_number; i++) {
> +		tc_index = region_info->region[i].region_id;
> +		bsf = rte_bsf32(region_info->region[i].queue_num);
> +		queue_offset = region_info->region[i].queue_start_index;
> +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> +			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> +				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> +	}
> +
> +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
> +	if (vsi->type == I40E_VSI_SRIOV) {
Vsi is main vsi, it is impossible that the type to be SRIOV. If you want to configure
Queue mapping on sriov VSI, you need to scan all the SRIOV VSIs.

> +		vsi_info->mapping_flags |=
> +			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> +		for (i = 0; i < vsi->nb_qps; i++)
> +			vsi_info->queue_mapping[i] =
> +				rte_cpu_to_le_16(vsi->base_queue + i);
> +	} else {
> +		vsi_info->mapping_flags |=
> +			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
> +	}
> +	vsi_info->valid_sections |=
> +		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> +
> +	/* Update the VSI after updating the VSI queue-mapping information */
> +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
PMD_INIT_LOG  -> PMD_DRV_LOG
> +			"mapping = %d ", hw->aq.asq_last_status);
> +		return ret;
> +	}
> +	/* update the local VSI info with updated queue map */
> +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> +					sizeof(vsi->info.tc_mapping));
> +	(void)rte_memcpy(&vsi->info.queue_mapping,
> +			&ctxt.info.queue_mapping,
> +		sizeof(vsi->info.queue_mapping));
> +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> +	vsi->info.valid_sections = 0;
> +
> +	return 0;
> +}
> +
> +
> +static int
> +i40e_set_queue_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> +	uint16_t i;
> +	struct i40e_vsi *main_vsi = pf->main_vsi;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +
> +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> +		if (conf_ptr->queue_num == tc_size_tb[i])
> +			break;
> +
> +	if (i == I40E_REGION_MAX_INDEX) {
> +		printf("The region sizes should be any of the following "
> +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> +		"total number of queues do not exceed the VSI allocation");
> +		return ret;
> +	}
> +
If you just want to check if the queue_nume is one of {1, 2,4,8,16,32,64}
You can use 

If (rte_is_power_of_2(queue_num) && queue_num <= 64)


> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> +					> main_vsi->nb_used_qps) {
> +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI range");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if ((i == info->queue_region_number) &&
> +			(i <= I40E_REGION_MAX_INDEX)) {
It is impossible that i > I40E_REGION_MAX_INDEX, right?

> +			info->region[i].region_id = conf_ptr->region_id;
> +			info->region[i].queue_num = conf_ptr->queue_num;
> +			info->region[i].queue_start_index =
> +				conf_ptr->queue_start_index;
> +			info->queue_region_number++;
> +		} else {
> +			PMD_INIT_LOG(ERR, "queue region number "
> +				"exceeds maxnum 8 or the "
> +				"queue region id has "
> +				"been set before");
Does it mean we can not change the set of one queue region whose id is set before?

> +			return ret;
> +		}
> +	} else {
> +		info->region[0].region_id = conf_ptr->region_id;
> +		info->region[0].queue_num = conf_ptr->queue_num;
> +		info->region[0].queue_start_index =
> +			conf_ptr->queue_start_index;
> +		info->queue_region_number++;
> +	}
I think this part of code can be refined. 
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint32_t pfqf_hregion;
> +	uint32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i, j, index, flowtype_set = 0;
> +	uint16_t region_index, flowtype_index;
> +
> +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id has not "
> +				"been set before");
> +			return ret;
> +		}
If info->queue_region_number==0, then i would be 0. So, the outer wrap
if (info->queue_region_number) {} can be omit. The same at above func,
I think this part of code can be refined.
> +		region_index = i;
> +	
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> +				if (conf_ptr->hw_flowtype ==
> +					info->region[i].hw_flowtype[j]) {
> +					flowtype_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (flowtype_set) {
> +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> +				"has been set before");
> +			return ret;
Is that right to return -EINVAL when it has been set. And it seems
In this function, the error code is only -EINVAL, if so, why we define
ret?
> +		}
> +		flowtype_index = info->region[region_index].flowtype_num;
> +		info->region[region_index].hw_flowtype[flowtype_index] =
> +						conf_ptr->hw_flowtype;
> +		info->region[region_index].flowtype_num++;
> +	} else  {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");

Again, please use PMD_DRV_LOG. Because the func is not called at initialization time.
Please replace it in all the patch.
> +		return ret;
> +	}
> +
> +	index = conf_ptr->hw_flowtype >> 3;
> +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> +
> +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
What is the (conf_ptr->hw_flowtype & 0x7) == 1/2/3/4/5/6 meanings? Please avoid
coding with integer number. Can not understand the relationship with flow type.
And the hw_flowtype is API to users, you need to make it clear enough.

> +	} else {
> +		pfqf_hregion |= conf_ptr->region_id <<
> +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> +		pfqf_hregion |= 1 << I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> +	}
> +
> +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_set_up_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint32_t ret = -EINVAL;
> +	uint16_t i, j, region_index, up_set = 0;
> +
> +	if (conf_ptr->user_priority > I40E_REGION_USERPRIORITY_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> +		return ret;
> +	}
> +
> +	if (info->queue_region_number) {
> +		for (i = 0; i < info->queue_region_number; i++)
> +			if (conf_ptr->region_id == info->region[i].region_id)
> +				break;
> +
> +		if (i == info->queue_region_number) {
> +			PMD_INIT_LOG(ERR, "that region id "
> +				"has not been set before");
> +			return ret;
> +		}
> +		region_index = i;
> +
> +		for (i = 0; i < info->queue_region_number; i++) {
> +			for (j = 0; j <
> +				info->region[i].user_priority_num; j++) {
> +				if (info->region[i].user_priority[j] ==
> +					conf_ptr->user_priority) {
> +					up_set = 1;
> +					break;
> +				}
> +			}
> +		}
> +
> +		if (up_set) {
> +			PMD_INIT_LOG(ERR, "that user priority "
> +				"has been set before");
> +			return ret;
> +		}
> +
> +		j = info->region[region_index].user_priority_num;
> +		info->region[region_index].user_priority[j] =
> +						conf_ptr->user_priority;
> +		info->region[region_index].user_priority_num++;
> +	} else {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> +				struct i40e_pf *pf)
> +{
> +	struct i40e_dcbx_config dcb_cfg_local;
> +	struct i40e_dcbx_config *dcb_cfg;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> +	uint32_t ret = -EINVAL;
> +	uint16_t i, j, prio_index, region_index;
> +	uint8_t tc_map, tc_bw, bw_lf;
> +
> +	if (!info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	dcb_cfg = &dcb_cfg_local;
> +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> +
> +	/* assume each tc has the same bw */
> +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> +	/* to ensure the sum of tcbw is equal to 100 */
> +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> +	for (i = 0; i < bw_lf; i++)
> +		dcb_cfg->etscfg.tcbwtable[i]++;
> +
> +	/* assume each tc has the same Transmission Selection Algorithm */
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> +			prio_index = info->region[i].user_priority[j];
> +			region_index = info->region[i].region_id;
> +			dcb_cfg->etscfg.prioritytable[prio_index] =
> +						region_index;
> +		}
> +	}
> +
> +	/* FW needs one App to configure HW */
> +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> +
> +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> +
> +	dcb_cfg->pfc.willing = 0;
> +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> +	dcb_cfg->pfc.pfcenable = tc_map;
> +
> +	/* Copy the new config to the current config */
> +	*old_cfg = *dcb_cfg;
> +	old_cfg->etsrec = old_cfg->etscfg;
> +	ret = i40e_set_dcb_config(hw);
> +
> +	if (ret) {
> +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed, err"
> +			" %s aq_err %s",
> +			 i40e_stat_str(hw, ret),
> +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)

Can i40e_dcb_init_configure do what this func did here?

> +{
> +	uint16_t i;
> +	uint32_t ret = -EINVAL;
> +
> +	memset(&hw->local_dcbx_config, 0,
> +	sizeof(struct i40e_dcbx_config));
> +	/* set dcb default configuration */
> +	hw->local_dcbx_config.etscfg.willing = 0;
> +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> +	hw->local_dcbx_config.etscfg.tsatable[0] =
> +			I40E_IEEE_TSA_ETS;
> +	/* all UPs mapping to region 0 */
> +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> +	hw->local_dcbx_config.etsrec =
> +		hw->local_dcbx_config.etscfg;
> +	hw->local_dcbx_config.pfc.willing = 0;
> +	hw->local_dcbx_config.pfc.pfccap =
> +			I40E_MAX_TRAFFIC_CLASS;
> +	/* FW needs one App to configure HW */
> +	hw->local_dcbx_config.numapps = 1;
> +	hw->local_dcbx_config.app[0].selector =
> +			I40E_APP_SEL_ETHTYPE;
> +	hw->local_dcbx_config.app[0].priority = 3;
> +	hw->local_dcbx_config.app[0].protocolid =
> +			I40E_APP_PROTOID_FCOE;
> +	ret = i40e_set_dcb_config(hw);
> +	if (ret) {
> +		PMD_INIT_LOG(ERR,
> +		"default dcb config fails. err = %d, aq_err = %d.",
> +			ret, hw->aq.asq_last_status);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> +				uint16_t on)
> +{
> +	uint16_t i;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	if (on) {
> +		i40e_vsi_update_queue_region_mapping(hw, pf);
> +		i40e_queue_region_dcb_configure(hw, pf);
Don't check all the return code?

> +		return 0;
> +	}
> +
> +	info->queue_region_number = 1;
> +	info->region[0].queue_num = 64;
> +	info->region[0].queue_start_index = 0;
> +
> +	i40e_vsi_update_queue_region_mapping(hw, pf);
> +	i40e_queue_region_dcb_configure_default(hw);
> +
> +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> +
> +	return 0;
> +}
> +
> +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> +			struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> +	uint32_t ret;
> +
> +	if (!is_i40e_supported(dev))
> +		return -ENOTSUP;
> +
> +	switch (op_type) {
> +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> +		ret = i40e_set_queue_region(pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> +		ret = -EINVAL;
> +		break;
If it is not supported, why to define this op?

> +	case RTE_PMD_I40E_UP_REGION_SET:
> +		ret = i40e_set_up_region(pf, conf_ptr);
> +		break;
> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> +		break;
What is the FLUSH on meaning? Commit all configure to HW?
If so, what makes me confused that:
RTE_PMD_I40E_QUEUE_REGION_SET only touch the software stored in driver.
But RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET set the I40E_PFQF_HREGION register.
Those behaviors are not consist.

And FLUSH OFF means delete all?

You need to add more comments.

> +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> +		break;
> +
> +	default:
> +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> +			    op_type);
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	I40E_WRITE_FLUSH(hw);
> +
> +	return ret;
> +}
> diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
> index 155b7e8..a1329f4 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.h
> +++ b/drivers/net/i40e/rte_pmd_i40e.h
> @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
>  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
>  };
> 
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set*/
> +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region pctype set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region pctype set */
> +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype set */
> +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all configuration */
> +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all configuration */
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> 
>  /**
> @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
> 
>  /**
> + * Queue region information get from CLI.
> + */
> +struct rte_i40e_rss_region_conf {
> +	uint8_t region_id;
> +	uint8_t hw_flowtype;
> +	uint8_t queue_start_index;
> +	uint8_t queue_num;
> +	uint8_t user_priority;
> +	enum rte_pmd_i40e_queue_region_op  op;
> +};
This is API struct, you need to comment them in detail

Thanks
Jingjing

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-22 20:13           ` Chilikin, Andrey
@ 2017-09-25  2:55             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-25  2:55 UTC (permalink / raw)
  To: Chilikin, Andrey, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi, Andrey

> -----Original Message-----
> From: Chilikin, Andrey
> Sent: Saturday, September 23, 2017 4:14 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> Hi Wei
> 
> > -----Original Message-----
> > From: Zhao1, Wei
> > Sent: Friday, September 22, 2017 9:49 AM
> > To: Chilikin, Andrey <andrey.chilikin@intel.com>; dev@dpdk.org
> > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> > <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> > Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >
> > Hi,Andrey
> >
> > > -----Original Message-----
> > > From: Chilikin, Andrey
> > > Sent: Friday, September 22, 2017 3:53 AM
> > > To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> > > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> > > <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu,
> > > Jingjing <jingjing.wu@intel.com>
> > > Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set
> > > and
> > flush
> 
> <snip>
> 
> > > > +	if (i == I40E_REGION_MAX_INDEX) {
> > > > +		printf("The region sizes should be any of the following "
> > > > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > > > +		"total number of queues do not exceed the VSI allocation");
> 
>  printf?

Yes, just a reminder for user, you think I should use " PMD_INIT_LOG( )" instead?
I will change to that.

> 
> > > > +		return ret;
> > > > +	}
> > > > +
> > > > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > > > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > > > +		return ret;
> > > > +	}
> > > > +
> 
> <snip>
> > > > +	switch (op_type) {
> > > > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > > > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > > > +		break;
> > > > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > > > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > > > +		break;
> > > > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > > > +		ret = -EINVAL;
> > > > +		break;
> > >
> > > Why setting of flowtype mapping is separated to two different option?
> > > Does it mean that application will need to detect which driver it
> > > uses before calling this API? Application should not care which
> > > driver is in use, it tracks
> > the
> > > number of queues used for RSS and just configures these queues to
> > > different regions, regardless if it runs on top of PF or VF.
> > > Difference in configuration for PF/VF should be hidden from
> > > application, so only single RTE_PMD_I40E_REGION_FLOWTYPE_SET
> should be used.
> >
> > By now , we only support pf for this config.
> > But I think what you said is very reasonable. I can change code to a
> > new
> > scheme:
> > DPDK i40e driver use   rte_eth_dev ->device->name to detect  whether his
> > name is
> > " net_i40e_vf " or " net_i40e"  itself, then  we  can PMD driver
> > decide to config PFQF_HREGION or VFQF_HREGION.
> > I will make change in v4 later.
> >
> > >
> > > All other options do not have separate check.
> > > Will they work on both PF and VF?
> >
> > No, only WORK on PF. The reason we have talk in other mail before.
> >
> 
> Yes, it is why I was confused with separating
> RTE_PMD_I40E_REGION_FLOWTYPE to PF and VF. All options work on PF
> only, by only FLOWTYPE was split to PF/VF.

Yes,   I will point out that only pf support in commit log in v4.

> 
> > >
> > > > +	case RTE_PMD_I40E_UP_REGION_SET:
> > > > +		ret = i40e_set_up_region(pf, conf_ptr);
> > > > +		break;
> > > > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > > > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > > > +		break;
> > > > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > > > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> > > > +		break;
> > > > +
> 
> Could you explain what is the difference between FLUSH_OFF and
> FLUSH_ON and how it can be used by an application?

ALL config from CLI at first will only keep in DPDK software stored in driver, only after " FLUSH_ON ", it commit all configure to HW.
Because I have to set hardware config at a time, so I have to record all CLI command at first.
" FLUSH_OFF " is just clean all configuration about queue region  just now, and restore all to DPDK i40e driver default config when start up.
The following is my test process in CLI: 

./x86_64-native-linuxapp-gcc/app/testpmd -c 1ffff -n 4 -- -i --nb-cores=8  --rxq=8 --txq=8 --port-topology=chained
set fwd rxonly
port config all rss all
queue-region set port 0 region_id 0 queue_start_index 2 queue_num 2 
queue-region set port 0 region_id 1 queue_start_index 4 queue_num 2 
queue-region set pf port 0 region_id 0 flowtype 31
queue-region set pf port 0 region_id 1 flowtype 33
queue-region set pf port 0 region_id 1 flowtype 34
queue-region set port 0 UP 1 region_id 0
queue-region set port 0 UP 3 region_id 1
queue-region flush on  port 0
start
set verbose 1
sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/Dot1Q(prio=3)/IP(src="10.0.0.1",dst="192.168.0.2")/TCP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10)
sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/SCTP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10)
sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/UDP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10)

> 
> > > > +	default:
> > > > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > > > +			    op_type);
> > > > +		ret = -EINVAL;
> > > > +		break;
> > > > +	}
> > > > +
> > > > +	I40E_WRITE_FLUSH(hw);
> > > > +
> > > > +	return ret;
> > > > +}
> > >
> >
> > > How this API can be tested, is there a separate testpmd patch?
> >
> > Yes, testpmd has add new CLI commands to support it, also can be use
> > by customer.
> 
> Sorry, missed second part of the patchset.
> 
> Regards,
> Andrey

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-24 16:01       ` Wu, Jingjing
@ 2017-09-25  3:26         ` Zhao1, Wei
  2017-09-25  5:55         ` Zhao1, Wei
  1 sibling, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-25  3:26 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Hi, jingjing

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Monday, September 25, 2017 12:02 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Friday, September 15, 2017 11:13 AM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
> > ++++++++++++++++++++++++++++++
> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
> >  5 files changed, 566 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 8e0580c..1663fc0 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -137,10 +137,6 @@
> >  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
> >  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> >
> > -#define I40E_MAX_PERCENT            100
> > -#define I40E_DEFAULT_DCB_APP_NUM    1
> > -#define I40E_DEFAULT_DCB_APP_PRIO   3
> > -
> >  /**
> >   * Below are values for writing un-exposed registers suggested
> >   * by silicon experts
> > @@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev
> *dev)
> >  	return ret;
> >  }
> >
> > +static void
> > +i40e_init_queue_region_conf(struct rte_eth_dev *dev) {
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info)); }
> > +
> >  static int
> >  eth_i40e_dev_init(struct rte_eth_dev *dev)  { @@ -1309,6 +1314,9 @@
> > eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  	if (ret < 0)
> >  		goto err_init_fdir_filter_list;
> >
> > +	/* initialize queue region configuration */
> > +	i40e_init_queue_region_conf(dev);
> > +
> If this func i40e_init_queue_region_conf is only called here, then it is Not
> necessary? Because all the pf struct has been zeroed at probe time.
> 

I find that t should also be called in i40e_flush_region_all_conf() to replace the code " memset(info, 0, sizeof(struct i40e_queue_region_info)); "
So, in v4 I will change to that. Another reason is to set zero after restart process from CLI command " start -stop -start...."

> >  	return 0;
> >
> >  err_init_fdir_filter_list:
> > @@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
> >  	/* Remove all Traffic Manager configuration */
> >  	i40e_tm_conf_uninit(dev);
> >
> > +	/* Remove all the queue region configuration */
> > +	i40e_flush_region_all_conf(hw, pf, 0);
> > +
> >  	return 0;
> >  }
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index ad80f0f..d612886 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {  #define
> > I40E_QOS_BW_WEIGHT_MIN 1
> >  /* The max bandwidth weight is 127. */  #define
> > I40E_QOS_BW_WEIGHT_MAX 127
> > +/* The max queue region index is 7. */ #define
> I40E_REGION_MAX_INDEX
> > +7
> > +/* The max queue region userpriority is 7. */ #define
> > +I40E_REGION_USERPRIORITY_MAX_INDEX 7
> You can reuse I40E_MAX_USER_PRIORITY.

Ok, change in v4

> 
> > +/* The max pctype index is 63. */
> > +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> > +
> You can use I40E_FILTER_PCTYPE_MAX

Ok, change in v4

> 
> > +#define I40E_MAX_PERCENT            100
> > +#define I40E_DEFAULT_DCB_APP_NUM    1
> > +#define I40E_DEFAULT_DCB_APP_PRIO   3
> >
> >  /**
> >   * The overhead from MTU to max frame size.
> > @@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
> >  	struct rte_hash *hash_table;
> >  };
> >
> > +/* queue region info */
> > +struct i40e_region_info {
> > +	uint8_t region_id;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority_num;
> > +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> Please comment what is the meaning of this array?

Ok, change in v4

> 
> > +	uint8_t flowtype_num;
> > +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> The same, please comment it.

Ok, change in v4

> 
> > +};
> > +
> > +struct i40e_queue_region_info {
> > +	uint16_t queue_region_number;
> > +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1]; };
> > +
> >  /* Tunnel filter number HW supports */  #define
> > I40E_MAX_TUNNEL_FILTER_NUM 400
> >
> > @@ -776,6 +802,7 @@ struct i40e_pf {
> >  	struct i40e_fdir_info fdir; /* flow director info */
> >  	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
> >  	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
> > +	struct i40e_queue_region_info queue_region; /* queue region info
> */
> >  	struct i40e_fc_conf fc_conf; /* Flow control conf */
> >  	struct i40e_mirror_rule_list mirror_list;
> >  	uint16_t nb_mirror_rule;   /* The number of mirror rules */
> > @@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw,
> > uint32_t addr, uint32_t val);  int i40e_tm_ops_get(struct rte_eth_dev
> > *dev, void *ops);  void i40e_tm_conf_init(struct rte_eth_dev *dev);
> > void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> > +int i40e_flush_region_all_conf(struct i40e_hw *hw,
> > +				struct i40e_pf *pf, uint16_t on);
> > +
> >
> >  #define I40E_DEV_TO_PCI(eth_dev) \
> >  	RTE_DEV_TO_PCI((eth_dev)->device)
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> > b/drivers/net/i40e/rte_pmd_i40e.c index d69a472..9a75f21 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.c
> > +++ b/drivers/net/i40e/rte_pmd_i40e.c
> > @@ -35,6 +35,7 @@
> >  #include <rte_tailq.h>
> >
> >  #include "base/i40e_prototype.h"
> > +#include "base/i40e_dcb.h"
> >  #include "i40e_ethdev.h"
> >  #include "i40e_pf.h"
> >  #include "i40e_rxtx.h"
> > @@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port,
> > uint16_t vf_id,
> >
> >  	return 0;
> >  }
> > +
> > +static int
> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> > +			      struct i40e_pf *pf)
> > +{
> > +	uint16_t i;
> > +	struct i40e_vsi *vsi = pf->main_vsi;
> > +	uint16_t queue_offset, bsf, tc_index;
> > +	struct i40e_vsi_context ctxt;
> > +	struct i40e_aqc_vsi_properties_data *vsi_info;
> > +	struct i40e_queue_region_info *region_info =
> > +				&pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	if (!region_info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> > +
> > +	/* Update Queue Pairs Mapping for currently enabled UPs */
> > +	ctxt.seid = vsi->seid;
> > +	ctxt.pf_num = hw->pf_id;
> > +	ctxt.vf_num = 0;
> > +	ctxt.uplink_seid = vsi->uplink_seid;
> > +	ctxt.info = vsi->info;
> > +	vsi_info = &ctxt.info;
> > +
> Please use the vsi_info stored in i40e_vsi to avoid missing parameters.
> 
> > +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> > +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> > +
> Ctxt has been zeroed, no need to memset tc_mapping and queue_mapping
> again.

Ok, change in v4

> > +	/**
> > +	 * Configure queue region and queue mapping parameters,
> > +	 * for enabled queue region, allocate queues to this region.
> > +	 */
> > +
> > +	for (i = 0; i < region_info->queue_region_number; i++) {
> > +		tc_index = region_info->region[i].region_id;
> > +		bsf = rte_bsf32(region_info->region[i].queue_num);
> > +		queue_offset = region_info->region[i].queue_start_index;
> > +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> > +			(queue_offset <<
> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> > +				(bsf <<
> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> > +	}
> > +
> > +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> */
> > +	if (vsi->type == I40E_VSI_SRIOV) {
> Vsi is main vsi, it is impossible that the type to be SRIOV. If you want to
> configure Queue mapping on sriov VSI, you need to scan all the SRIOV VSIs.

Ok.

> 
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> > +		for (i = 0; i < vsi->nb_qps; i++)
> > +			vsi_info->queue_mapping[i] =
> > +				rte_cpu_to_le_16(vsi->base_queue + i);
> > +	} else {
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> > +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-
> >base_queue);
> > +	}
> > +	vsi_info->valid_sections |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> > +
> > +	/* Update the VSI after updating the VSI queue-mapping
> information */
> > +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> PMD_INIT_LOG  -> PMD_DRV_LOG
> > +			"mapping = %d ", hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +	/* update the local VSI info with updated queue map */
> > +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> > +					sizeof(vsi->info.tc_mapping));
> > +	(void)rte_memcpy(&vsi->info.queue_mapping,
> > +			&ctxt.info.queue_mapping,
> > +		sizeof(vsi->info.queue_mapping));
> > +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> > +	vsi->info.valid_sections = 0;
> > +
> > +	return 0;
> > +}
> > +
> > +
> > +static int
> > +i40e_set_queue_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> > +	uint16_t i;
> > +	struct i40e_vsi *main_vsi = pf->main_vsi;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> > +		if (conf_ptr->queue_num == tc_size_tb[i])
> > +			break;
> > +
> > +	if (i == I40E_REGION_MAX_INDEX) {
> > +		printf("The region sizes should be any of the following "
> > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > +		"total number of queues do not exceed the VSI allocation");
> > +		return ret;
> > +	}
> > +
> If you just want to check if the queue_nume is one of {1, 2,4,8,16,32,64} You
> can use
> 
> If (rte_is_power_of_2(queue_num) && queue_num <= 64)
> 
> 
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> > +					> main_vsi->nb_used_qps) {
> > +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI
> range");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if ((i == info->queue_region_number) &&
> > +			(i <= I40E_REGION_MAX_INDEX)) {
> It is impossible that i > I40E_REGION_MAX_INDEX, right?
> 
> > +			info->region[i].region_id = conf_ptr->region_id;
> > +			info->region[i].queue_num = conf_ptr->queue_num;
> > +			info->region[i].queue_start_index =
> > +				conf_ptr->queue_start_index;
> > +			info->queue_region_number++;
> > +		} else {
> > +			PMD_INIT_LOG(ERR, "queue region number "
> > +				"exceeds maxnum 8 or the "
> > +				"queue region id has "
> > +				"been set before");
> Does it mean we can not change the set of one queue region whose id is set
> before?
> 
> > +			return ret;
> > +		}
> > +	} else {
> > +		info->region[0].region_id = conf_ptr->region_id;
> > +		info->region[0].queue_num = conf_ptr->queue_num;
> > +		info->region[0].queue_start_index =
> > +			conf_ptr->queue_start_index;
> > +		info->queue_region_number++;
> > +	}
> I think this part of code can be refined.
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> > +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf
> *conf_ptr) {
> > +	uint32_t pfqf_hregion;
> > +	uint32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j, index, flowtype_set = 0;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> > +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index
> is 63");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id has not "
> > +				"been set before");
> > +			return ret;
> > +		}
> If info->queue_region_number==0, then i would be 0. So, the outer wrap if
> (info->queue_region_number) {} can be omit. The same at above func, I
> think this part of code can be refined.

Let me have a little think about it.

> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> > +				if (conf_ptr->hw_flowtype ==
> > +					info->region[i].hw_flowtype[j]) {
> > +					flowtype_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (flowtype_set) {
> > +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> > +				"has been set before");
> > +			return ret;
> Is that right to return -EINVAL when it has been set. And it seems In this
> function, the error code is only -EINVAL, if so, why we define ret?

Yes, if it has been set , I will not do a second time. 
Other code also use rte as this way.
 

> > +		}
> > +		flowtype_index = info->region[region_index].flowtype_num;
> > +		info->region[region_index].hw_flowtype[flowtype_index] =
> > +						conf_ptr->hw_flowtype;
> > +		info->region[region_index].flowtype_num++;
> > +	} else  {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> 
> Again, please use PMD_DRV_LOG. Because the func is not called at
> initialization time.


Ok, change in v4

> Please replace it in all the patch.
> > +		return ret;
> > +	}
> > +
> > +	index = conf_ptr->hw_flowtype >> 3;
> > +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> > +
> > +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> What is the (conf_ptr->hw_flowtype & 0x7) == 1/2/3/4/5/6 meanings?
> Please avoid coding with integer number. Can not understand the
> relationship with flow type.
> And the hw_flowtype is API to users, you need to make it clear enough.

No practical meaning, just find position for that pctype, because 8 type pctype reuse one register.
We support 64 types of them.

> 
> > +	} else {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> > +	}
> > +
> > +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_up_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index, up_set = 0;
> > +
> > +	if (conf_ptr->user_priority >
> I40E_REGION_USERPRIORITY_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id "
> > +				"has not been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j <
> > +				info->region[i].user_priority_num; j++) {
> > +				if (info->region[i].user_priority[j] ==
> > +					conf_ptr->user_priority) {
> > +					up_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (up_set) {
> > +			PMD_INIT_LOG(ERR, "that user priority "
> > +				"has been set before");
> > +			return ret;
> > +		}
> > +
> > +		j = info->region[region_index].user_priority_num;
> > +		info->region[region_index].user_priority[j] =
> > +						conf_ptr->user_priority;
> > +		info->region[region_index].user_priority_num++;
> > +	} else {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> > +				struct i40e_pf *pf)
> > +{
> > +	struct i40e_dcbx_config dcb_cfg_local;
> > +	struct i40e_dcbx_config *dcb_cfg;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, prio_index, region_index;
> > +	uint8_t tc_map, tc_bw, bw_lf;
> > +
> > +	if (!info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	dcb_cfg = &dcb_cfg_local;
> > +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> > +
> > +	/* assume each tc has the same bw */
> > +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> > +	/* to ensure the sum of tcbw is equal to 100 */
> > +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> > +	for (i = 0; i < bw_lf; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i]++;
> > +
> > +	/* assume each tc has the same Transmission Selection Algorithm */
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			prio_index = info->region[i].user_priority[j];
> > +			region_index = info->region[i].region_id;
> > +			dcb_cfg->etscfg.prioritytable[prio_index] =
> > +						region_index;
> > +		}
> > +	}
> > +
> > +	/* FW needs one App to configure HW */
> > +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> > +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> > +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> > +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> > +
> > +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> > +
> > +	dcb_cfg->pfc.willing = 0;
> > +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> > +	dcb_cfg->pfc.pfcenable = tc_map;
> > +
> > +	/* Copy the new config to the current config */
> > +	*old_cfg = *dcb_cfg;
> > +	old_cfg->etsrec = old_cfg->etscfg;
> > +	ret = i40e_set_dcb_config(hw);
> > +
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,
> err"
> > +			" %s aq_err %s",
> > +			 i40e_stat_str(hw, ret),
> > +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
> 
> Can i40e_dcb_init_configure do what this func did here?

It seems ok, change in v4.
 
> 
> > +{
> > +	uint16_t i;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	memset(&hw->local_dcbx_config, 0,
> > +	sizeof(struct i40e_dcbx_config));
> > +	/* set dcb default configuration */
> > +	hw->local_dcbx_config.etscfg.willing = 0;
> > +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> > +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> > +	hw->local_dcbx_config.etscfg.tsatable[0] =
> > +			I40E_IEEE_TSA_ETS;
> > +	/* all UPs mapping to region 0 */
> > +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> > +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> > +	hw->local_dcbx_config.etsrec =
> > +		hw->local_dcbx_config.etscfg;
> > +	hw->local_dcbx_config.pfc.willing = 0;
> > +	hw->local_dcbx_config.pfc.pfccap =
> > +			I40E_MAX_TRAFFIC_CLASS;
> > +	/* FW needs one App to configure HW */
> > +	hw->local_dcbx_config.numapps = 1;
> > +	hw->local_dcbx_config.app[0].selector =
> > +			I40E_APP_SEL_ETHTYPE;
> > +	hw->local_dcbx_config.app[0].priority = 3;
> > +	hw->local_dcbx_config.app[0].protocolid =
> > +			I40E_APP_PROTOID_FCOE;
> > +	ret = i40e_set_dcb_config(hw);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR,
> > +		"default dcb config fails. err = %d, aq_err = %d.",
> > +			ret, hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int
> > +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> > +				uint16_t on)
> > +{
> > +	uint16_t i;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		i40e_queue_region_dcb_configure(hw, pf);
> Don't check all the return code?

> 
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	i40e_queue_region_dcb_configure_default(hw);
> > +
> > +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> > +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> > +
> > +	return 0;
> > +}
> > +
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +			struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> > +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> > +	uint32_t ret;
> > +
> > +	if (!is_i40e_supported(dev))
> > +		return -ENOTSUP;
> > +
> > +	switch (op_type) {
> > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > +		ret = -EINVAL;
> > +		break;
> If it is not supported, why to define this op?
> 
> > +	case RTE_PMD_I40E_UP_REGION_SET:
> > +		ret = i40e_set_up_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > +		break;
> What is the FLUSH on meaning? Commit all configure to HW?
> If so, what makes me confused that:
> RTE_PMD_I40E_QUEUE_REGION_SET only touch the software stored in
> driver.
> But RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET set the
> I40E_PFQF_HREGION register.
> Those behaviors are not consist.
> 
> And FLUSH OFF means delete all?
> 
> You need to add more comments.

I will add more comment in function comment.
ALL config from CLI at first will only keep in DPDK software stored in driver, only after " FLUSH_ON ", it commit all configure to HW.
Because I have to set hardware config at a time, so I have to record all CLI command at first.
" FLUSH_OFF " is just clean all configuration about queue region  just now, and restore all to DPDK i40e driver default config when start up.
The following is my test process in CLI: 

./x86_64-native-linuxapp-gcc/app/testpmd -c 1ffff -n 4 -- -i --nb-cores=8  --rxq=8 --txq=8 --port-topology=chained set fwd rxonly port config all rss all queue-region set port 0 region_id 0 queue_start_index 2 queue_num 2 queue-region set port 0 region_id 1 queue_start_index 4 queue_num 2 queue-region set pf port 0 region_id 0 flowtype 31 queue-region set pf port 0 region_id 1 flowtype 33 queue-region set pf port 0 region_id 1 flowtype 34 queue-region set port 0 UP 1 region_id 0 queue-region set port 0 UP 3 region_id 1 queue-region flush on  port 0 start set verbose 1 sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/Dot1Q(prio=3)/IP(src="10.0.0.1",dst="192.168.0.2")/TCP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10) sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/SCTP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10) sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/UDP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10)


> 
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> > +		break;
> > +
> > +	default:
> > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > +			    op_type);
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	I40E_WRITE_FLUSH(hw);
> > +
> > +	return ret;
> > +}
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..a1329f4 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.h
> > +++ b/drivers/net/i40e/rte_pmd_i40e.h
> > @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
> >  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };
> >
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region
> set*/
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region
> pctype set */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region
> pctype set */
> > +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype
> set */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all
> configuration */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all
> configuration */
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region information get from CLI.
> > + */
> > +struct rte_i40e_rss_region_conf {
> > +	uint8_t region_id;
> > +	uint8_t hw_flowtype;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority;
> > +	enum rte_pmd_i40e_queue_region_op  op; };
> This is API struct, you need to comment them in detail

Ok, change in v4

> 
> Thanks
> Jingjing

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-24 16:01       ` Wu, Jingjing
  2017-09-25  3:26         ` Zhao1, Wei
@ 2017-09-25  5:55         ` Zhao1, Wei
  1 sibling, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-25  5:55 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Hi, jingjing

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Monday, September 25, 2017 12:02 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> 
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Friday, September 15, 2017 11:13 AM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >
> > This feature enable queue regions configuration for RSS in PF/VF, so
> > that different traffic classes or different packet classification
> > types can be separated to different queues in different queue
> > regions.This patch can set queue region range, it include queue number
> > in a region and the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
> > ++++++++++++++++++++++++++++++
> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
> >  5 files changed, 566 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > b/drivers/net/i40e/i40e_ethdev.c index 8e0580c..1663fc0 100644
> > --- a/drivers/net/i40e/i40e_ethdev.c
> > +++ b/drivers/net/i40e/i40e_ethdev.c
> > @@ -137,10 +137,6 @@
> >  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
> >  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> >
> > -#define I40E_MAX_PERCENT            100
> > -#define I40E_DEFAULT_DCB_APP_NUM    1
> > -#define I40E_DEFAULT_DCB_APP_PRIO   3
> > -
> >  /**
> >   * Below are values for writing un-exposed registers suggested
> >   * by silicon experts
> > @@ -1034,6 +1030,15 @@ i40e_init_fdir_filter_list(struct rte_eth_dev
> *dev)
> >  	return ret;
> >  }
> >
> > +static void
> > +i40e_init_queue_region_conf(struct rte_eth_dev *dev) {
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info)); }
> > +
> >  static int
> >  eth_i40e_dev_init(struct rte_eth_dev *dev)  { @@ -1309,6 +1314,9 @@
> > eth_i40e_dev_init(struct rte_eth_dev *dev)
> >  	if (ret < 0)
> >  		goto err_init_fdir_filter_list;
> >
> > +	/* initialize queue region configuration */
> > +	i40e_init_queue_region_conf(dev);
> > +
> If this func i40e_init_queue_region_conf is only called here, then it is Not
> necessary? Because all the pf struct has been zeroed at probe time.
> 
> >  	return 0;
> >
> >  err_init_fdir_filter_list:
> > @@ -1464,6 +1472,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
> >  	/* Remove all Traffic Manager configuration */
> >  	i40e_tm_conf_uninit(dev);
> >
> > +	/* Remove all the queue region configuration */
> > +	i40e_flush_region_all_conf(hw, pf, 0);
> > +
> >  	return 0;
> >  }
> >
> > diff --git a/drivers/net/i40e/i40e_ethdev.h
> > b/drivers/net/i40e/i40e_ethdev.h index ad80f0f..d612886 100644
> > --- a/drivers/net/i40e/i40e_ethdev.h
> > +++ b/drivers/net/i40e/i40e_ethdev.h
> > @@ -260,6 +260,16 @@ enum i40e_flxpld_layer_idx {  #define
> > I40E_QOS_BW_WEIGHT_MIN 1
> >  /* The max bandwidth weight is 127. */  #define
> > I40E_QOS_BW_WEIGHT_MAX 127
> > +/* The max queue region index is 7. */ #define
> I40E_REGION_MAX_INDEX
> > +7
> > +/* The max queue region userpriority is 7. */ #define
> > +I40E_REGION_USERPRIORITY_MAX_INDEX 7
> You can reuse I40E_MAX_USER_PRIORITY.
> 
> > +/* The max pctype index is 63. */
> > +#define I40E_REGION_PCTYPE_MAX_INDEX 63
> > +
> You can use I40E_FILTER_PCTYPE_MAX
> 
> > +#define I40E_MAX_PERCENT            100
> > +#define I40E_DEFAULT_DCB_APP_NUM    1
> > +#define I40E_DEFAULT_DCB_APP_PRIO   3
> >
> >  /**
> >   * The overhead from MTU to max frame size.
> > @@ -541,6 +551,22 @@ struct i40e_ethertype_rule {
> >  	struct rte_hash *hash_table;
> >  };
> >
> > +/* queue region info */
> > +struct i40e_region_info {
> > +	uint8_t region_id;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority_num;
> > +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> Please comment what is the meaning of this array?
> 
> > +	uint8_t flowtype_num;
> > +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> The same, please comment it.
> 
> > +};
> > +
> > +struct i40e_queue_region_info {
> > +	uint16_t queue_region_number;
> > +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1]; };
> > +
> >  /* Tunnel filter number HW supports */  #define
> > I40E_MAX_TUNNEL_FILTER_NUM 400
> >
> > @@ -776,6 +802,7 @@ struct i40e_pf {
> >  	struct i40e_fdir_info fdir; /* flow director info */
> >  	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
> >  	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
> > +	struct i40e_queue_region_info queue_region; /* queue region info
> */
> >  	struct i40e_fc_conf fc_conf; /* Flow control conf */
> >  	struct i40e_mirror_rule_list mirror_list;
> >  	uint16_t nb_mirror_rule;   /* The number of mirror rules */
> > @@ -1003,6 +1030,9 @@ void i40e_check_write_reg(struct i40e_hw *hw,
> > uint32_t addr, uint32_t val);  int i40e_tm_ops_get(struct rte_eth_dev
> > *dev, void *ops);  void i40e_tm_conf_init(struct rte_eth_dev *dev);
> > void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
> > +int i40e_flush_region_all_conf(struct i40e_hw *hw,
> > +				struct i40e_pf *pf, uint16_t on);
> > +
> >
> >  #define I40E_DEV_TO_PCI(eth_dev) \
> >  	RTE_DEV_TO_PCI((eth_dev)->device)
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.c
> > b/drivers/net/i40e/rte_pmd_i40e.c index d69a472..9a75f21 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.c
> > +++ b/drivers/net/i40e/rte_pmd_i40e.c
> > @@ -35,6 +35,7 @@
> >  #include <rte_tailq.h>
> >
> >  #include "base/i40e_prototype.h"
> > +#include "base/i40e_dcb.h"
> >  #include "i40e_ethdev.h"
> >  #include "i40e_pf.h"
> >  #include "i40e_rxtx.h"
> > @@ -2161,3 +2162,484 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port,
> > uint16_t vf_id,
> >
> >  	return 0;
> >  }
> > +
> > +static int
> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> > +			      struct i40e_pf *pf)
> > +{
> > +	uint16_t i;
> > +	struct i40e_vsi *vsi = pf->main_vsi;
> > +	uint16_t queue_offset, bsf, tc_index;
> > +	struct i40e_vsi_context ctxt;
> > +	struct i40e_aqc_vsi_properties_data *vsi_info;
> > +	struct i40e_queue_region_info *region_info =
> > +				&pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	if (!region_info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> > +
> > +	/* Update Queue Pairs Mapping for currently enabled UPs */
> > +	ctxt.seid = vsi->seid;
> > +	ctxt.pf_num = hw->pf_id;
> > +	ctxt.vf_num = 0;
> > +	ctxt.uplink_seid = vsi->uplink_seid;
> > +	ctxt.info = vsi->info;
> > +	vsi_info = &ctxt.info;
> > +
> Please use the vsi_info stored in i40e_vsi to avoid missing parameters.
> 
> > +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> > +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> > +
> Ctxt has been zeroed, no need to memset tc_mapping and queue_mapping
> again.
> > +	/**
> > +	 * Configure queue region and queue mapping parameters,
> > +	 * for enabled queue region, allocate queues to this region.
> > +	 */
> > +
> > +	for (i = 0; i < region_info->queue_region_number; i++) {
> > +		tc_index = region_info->region[i].region_id;
> > +		bsf = rte_bsf32(region_info->region[i].queue_num);
> > +		queue_offset = region_info->region[i].queue_start_index;
> > +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> > +			(queue_offset <<
> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> > +				(bsf <<
> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> > +	}
> > +
> > +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> */
> > +	if (vsi->type == I40E_VSI_SRIOV) {
> Vsi is main vsi, it is impossible that the type to be SRIOV. If you want to
> configure Queue mapping on sriov VSI, you need to scan all the SRIOV VSIs.
> 
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
> > +		for (i = 0; i < vsi->nb_qps; i++)
> > +			vsi_info->queue_mapping[i] =
> > +				rte_cpu_to_le_16(vsi->base_queue + i);
> > +	} else {
> > +		vsi_info->mapping_flags |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
> > +		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-
> >base_queue);
> > +	}
> > +	vsi_info->valid_sections |=
> > +
> 	rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
> > +
> > +	/* Update the VSI after updating the VSI queue-mapping
> information */
> > +	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Failed to configure queue region "
> PMD_INIT_LOG  -> PMD_DRV_LOG
> > +			"mapping = %d ", hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +	/* update the local VSI info with updated queue map */
> > +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> > +					sizeof(vsi->info.tc_mapping));
> > +	(void)rte_memcpy(&vsi->info.queue_mapping,
> > +			&ctxt.info.queue_mapping,
> > +		sizeof(vsi->info.queue_mapping));
> > +	vsi->info.mapping_flags = ctxt.info.mapping_flags;
> > +	vsi->info.valid_sections = 0;
> > +
> > +	return 0;
> > +}
> > +
> > +
> > +static int
> > +i40e_set_queue_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};
> > +	uint16_t i;
> > +	struct i40e_vsi *main_vsi = pf->main_vsi;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	for (i = 0; i < I40E_REGION_MAX_INDEX; i++)
> > +		if (conf_ptr->queue_num == tc_size_tb[i])
> > +			break;
> > +
> > +	if (i == I40E_REGION_MAX_INDEX) {
> > +		printf("The region sizes should be any of the following "
> > +		"values: 1, 2, 4, 8, 16, 32, 64 as long as the "
> > +		"total number of queues do not exceed the VSI allocation");
> > +		return ret;
> > +	}
> > +
> If you just want to check if the queue_nume is one of {1, 2,4,8,16,32,64} You
> can use
> 
> If (rte_is_power_of_2(queue_num) && queue_num <= 64)
> 
> 
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> > +					> main_vsi->nb_used_qps) {
> > +		PMD_INIT_LOG(ERR, "the queue index exceeds the VSI
> range");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if ((i == info->queue_region_number) &&
> > +			(i <= I40E_REGION_MAX_INDEX)) {
> It is impossible that i > I40E_REGION_MAX_INDEX, right?

Yes, only support 8 queue region max.

> 
> > +			info->region[i].region_id = conf_ptr->region_id;
> > +			info->region[i].queue_num = conf_ptr->queue_num;
> > +			info->region[i].queue_start_index =
> > +				conf_ptr->queue_start_index;
> > +			info->queue_region_number++;
> > +		} else {
> > +			PMD_INIT_LOG(ERR, "queue region number "
> > +				"exceeds maxnum 8 or the "
> > +				"queue region id has "
> > +				"been set before");
> Does it mean we can not change the set of one queue region whose id is set
> before?

No, FLUSH_OFF can clear all the config
> 
> > +			return ret;
> > +		}
> > +	} else {
> > +		info->region[0].region_id = conf_ptr->region_id;
> > +		info->region[0].queue_num = conf_ptr->queue_num;
> > +		info->region[0].queue_start_index =
> > +			conf_ptr->queue_start_index;
> > +		info->queue_region_number++;
> > +	}
> I think this part of code can be refined.
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> > +		struct i40e_pf *pf, struct rte_i40e_rss_region_conf
> *conf_ptr) {
> > +	uint32_t pfqf_hregion;
> > +	uint32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j, index, flowtype_set = 0;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> > +		PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index
> is 63");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id has not "
> > +				"been set before");
> > +			return ret;
> > +		}
> If info->queue_region_number==0, then i would be 0. So, the outer wrap if
> (info->queue_region_number) {} can be omit. The same at above func, I
> think this part of code can be refined.

Ok,change in v4

> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j < info->region[i].flowtype_num; j++) {
> > +				if (conf_ptr->hw_flowtype ==
> > +					info->region[i].hw_flowtype[j]) {
> > +					flowtype_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (flowtype_set) {
> > +			PMD_INIT_LOG(ERR, "that hw_flowtype "
> > +				"has been set before");
> > +			return ret;
> Is that right to return -EINVAL when it has been set. And it seems In this
> function, the error code is only -EINVAL, if so, why we define ret?
> > +		}
> > +		flowtype_index = info->region[region_index].flowtype_num;
> > +		info->region[region_index].hw_flowtype[flowtype_index] =
> > +						conf_ptr->hw_flowtype;
> > +		info->region[region_index].flowtype_num++;
> > +	} else  {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> 
> Again, please use PMD_DRV_LOG. Because the func is not called at
> initialization time.
> Please replace it in all the patch.
> > +		return ret;
> > +	}
> > +
> > +	index = conf_ptr->hw_flowtype >> 3;
> > +	pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
> > +
> > +	if ((conf_ptr->hw_flowtype & 0x7) == 0) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_0_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 1) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_1_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 2) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_2_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 3) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_3_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 4) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_4_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 5) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_5_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
> > +	} else if ((conf_ptr->hw_flowtype & 0x7) == 6) {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_6_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
> What is the (conf_ptr->hw_flowtype & 0x7) == 1/2/3/4/5/6 meanings?
> Please avoid coding with integer number. Can not understand the
> relationship with flow type.
> And the hw_flowtype is API to users, you need to make it clear enough.
> 
> > +	} else {
> > +		pfqf_hregion |= conf_ptr->region_id <<
> > +				I40E_PFQF_HREGION_REGION_7_SHIFT;
> > +		pfqf_hregion |= 1 <<
> I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
> > +	}
> > +
> > +	i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_set_up_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index, up_set = 0;
> > +
> > +	if (conf_ptr->user_priority >
> I40E_REGION_USERPRIORITY_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_INIT_LOG(ERR, "the region_id max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (info->queue_region_number) {
> > +		for (i = 0; i < info->queue_region_number; i++)
> > +			if (conf_ptr->region_id == info->region[i].region_id)
> > +				break;
> > +
> > +		if (i == info->queue_region_number) {
> > +			PMD_INIT_LOG(ERR, "that region id "
> > +				"has not been set before");
> > +			return ret;
> > +		}
> > +		region_index = i;
> > +
> > +		for (i = 0; i < info->queue_region_number; i++) {
> > +			for (j = 0; j <
> > +				info->region[i].user_priority_num; j++) {
> > +				if (info->region[i].user_priority[j] ==
> > +					conf_ptr->user_priority) {
> > +					up_set = 1;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +
> > +		if (up_set) {
> > +			PMD_INIT_LOG(ERR, "that user priority "
> > +				"has been set before");
> > +			return ret;
> > +		}
> > +
> > +		j = info->region[region_index].user_priority_num;
> > +		info->region[region_index].user_priority[j] =
> > +						conf_ptr->user_priority;
> > +		info->region[region_index].user_priority_num++;
> > +	} else {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> > +				struct i40e_pf *pf)
> > +{
> > +	struct i40e_dcbx_config dcb_cfg_local;
> > +	struct i40e_dcbx_config *dcb_cfg;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> > +	uint32_t ret = -EINVAL;
> > +	uint16_t i, j, prio_index, region_index;
> > +	uint8_t tc_map, tc_bw, bw_lf;
> > +
> > +	if (!info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	dcb_cfg = &dcb_cfg_local;
> > +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> > +
> > +	/* assume each tc has the same bw */
> > +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> > +	/* to ensure the sum of tcbw is equal to 100 */
> > +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> > +	for (i = 0; i < bw_lf; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i]++;
> > +
> > +	/* assume each tc has the same Transmission Selection Algorithm */
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			prio_index = info->region[i].user_priority[j];
> > +			region_index = info->region[i].region_id;
> > +			dcb_cfg->etscfg.prioritytable[prio_index] =
> > +						region_index;
> > +		}
> > +	}
> > +
> > +	/* FW needs one App to configure HW */
> > +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> > +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> > +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> > +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> > +
> > +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> > +
> > +	dcb_cfg->pfc.willing = 0;
> > +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> > +	dcb_cfg->pfc.pfcenable = tc_map;
> > +
> > +	/* Copy the new config to the current config */
> > +	*old_cfg = *dcb_cfg;
> > +	old_cfg->etsrec = old_cfg->etscfg;
> > +	ret = i40e_set_dcb_config(hw);
> > +
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,
> err"
> > +			" %s aq_err %s",
> > +			 i40e_stat_str(hw, ret),
> > +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw)
> 
> Can i40e_dcb_init_configure do what this func did here?
> 
> > +{
> > +	uint16_t i;
> > +	uint32_t ret = -EINVAL;
> > +
> > +	memset(&hw->local_dcbx_config, 0,
> > +	sizeof(struct i40e_dcbx_config));
> > +	/* set dcb default configuration */
> > +	hw->local_dcbx_config.etscfg.willing = 0;
> > +	hw->local_dcbx_config.etscfg.maxtcs = 0;
> > +	hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;
> > +	hw->local_dcbx_config.etscfg.tsatable[0] =
> > +			I40E_IEEE_TSA_ETS;
> > +	/* all UPs mapping to region 0 */
> > +	for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
> > +		hw->local_dcbx_config.etscfg.prioritytable[i] = 0;
> > +	hw->local_dcbx_config.etsrec =
> > +		hw->local_dcbx_config.etscfg;
> > +	hw->local_dcbx_config.pfc.willing = 0;
> > +	hw->local_dcbx_config.pfc.pfccap =
> > +			I40E_MAX_TRAFFIC_CLASS;
> > +	/* FW needs one App to configure HW */
> > +	hw->local_dcbx_config.numapps = 1;
> > +	hw->local_dcbx_config.app[0].selector =
> > +			I40E_APP_SEL_ETHTYPE;
> > +	hw->local_dcbx_config.app[0].priority = 3;
> > +	hw->local_dcbx_config.app[0].protocolid =
> > +			I40E_APP_PROTOID_FCOE;
> > +	ret = i40e_set_dcb_config(hw);
> > +	if (ret) {
> > +		PMD_INIT_LOG(ERR,
> > +		"default dcb config fails. err = %d, aq_err = %d.",
> > +			ret, hw->aq.asq_last_status);
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int
> > +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,
> > +				uint16_t on)
> > +{
> > +	uint16_t i;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		i40e_queue_region_dcb_configure(hw, pf);
> Don't check all the return code?
> 
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	i40e_queue_region_dcb_configure_default(hw);
> > +
> > +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> > +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> > +	memset(info, 0, sizeof(struct i40e_queue_region_info));
> > +
> > +	return 0;
> > +}
> > +
> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> > +			struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port];
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> > +	enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> > +	uint32_t ret;
> > +
> > +	if (!is_i40e_supported(dev))
> > +		return -ENOTSUP;
> > +
> > +	switch (op_type) {
> > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > +		ret = i40e_set_queue_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> > +		ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> > +		ret = -EINVAL;
> > +		break;
> If it is not supported, why to define this op?
> 
> > +	case RTE_PMD_I40E_UP_REGION_SET:
> > +		ret = i40e_set_up_region(pf, conf_ptr);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 1);
> > +		break;
> What is the FLUSH on meaning? Commit all configure to HW?
> If so, what makes me confused that:
> RTE_PMD_I40E_QUEUE_REGION_SET only touch the software stored in
> driver.
> But RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET set the
> I40E_PFQF_HREGION register.
> Those behaviors are not consist.
> 
> And FLUSH OFF means delete all?
> 
> You need to add more comments.
> 
> > +	case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> > +		ret = i40e_flush_region_all_conf(hw, pf, 0);
> > +		break;
> > +
> > +	default:
> > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > +			    op_type);
> > +		ret = -EINVAL;
> > +		break;
> > +	}
> > +
> > +	I40E_WRITE_FLUSH(hw);
> > +
> > +	return ret;
> > +}
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..a1329f4 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.h
> > +++ b/drivers/net/i40e/rte_pmd_i40e.h
> > @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {
> >  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };
> >
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED = 0,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region
> set*/
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region
> pctype set */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region
> pctype set */
> > +	RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype
> set */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all
> configuration */
> > +	RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all
> configuration */
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region information get from CLI.
> > + */
> > +struct rte_i40e_rss_region_conf {
> > +	uint8_t region_id;
> > +	uint8_t hw_flowtype;
> > +	uint8_t queue_start_index;
> > +	uint8_t queue_num;
> > +	uint8_t user_priority;
> > +	enum rte_pmd_i40e_queue_region_op  op; };
> This is API struct, you need to comment them in detail
> 
> Thanks
> Jingjing

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-20 10:36       ` Ferruh Yigit
  2017-09-21  6:48         ` Zhao1, Wei
@ 2017-09-25  7:40         ` Zhao1, Wei
  2017-09-25  9:31           ` Ferruh Yigit
  2017-09-26  8:54         ` Zhao1, Wei
  2 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-25  7:40 UTC (permalink / raw)
  To: Yigit, Ferruh; +Cc: dev

Hi, Ferruh



> -----Original Message-----

> From: Yigit, Ferruh

> Sent: Wednesday, September 20, 2017 6:36 PM

> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org

> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush

>

> On 9/15/2017 4:13 AM, Wei Zhao wrote:

> > This feature enable queue regions configuration for RSS in PF/VF, so

> > that different traffic classes or different packet classification

> > types can be separated to different queues in different queue

> > regions.This patch can set queue region range, it include queue number

> > in a region and the index of first queue.

>

> Is following correct:

> So instead of distributing packets to the multiple queues, this will distribute

> packets into queue reqions which may consists of multiple queues.

>

> If so, is there a way to control how packets distributed within same queue

> region to multiple queues?

>



distributed within same queue region is based on a rss algorithm, it is implemented by NIC self, software can not control it.





> And is this feature only supported with RSS? Can it be part of RSS

> configuration instead of PMD specific API?

>



Yes, only valid after rss enable.May be in the feature, in rte_flow mode, we can combine them together.



> > This patch enable mapping between different priorities (UP) and

>

> User priorities (UP)



oK, change in v4



>

> > different traffic classes.It also enable mapping between a region

> > index and a sepcific flowtype(PCTYPE).It also provide the solution of

> > flush all configuration about queue region the above described.

> >

> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com<mailto:wei.zhao1@intel.com>>

> > ---

> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-

> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++

> >  drivers/net/i40e/rte_pmd_i40e.c           | 482

> ++++++++++++++++++++++++++++++

> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++

> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +

> >  5 files changed, 566 insertions(+), 4 deletions(-)

> >

>

> <...>

>

> > +static int

> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,

> > +                                            struct i40e_pf *pf)

> > +{

> > +      uint16_t i;

> > +      struct i40e_vsi *vsi = pf->main_vsi;

> > +      uint16_t queue_offset, bsf, tc_index;

> > +      struct i40e_vsi_context ctxt;

> > +      struct i40e_aqc_vsi_properties_data *vsi_info;

> > +      struct i40e_queue_region_info *region_info =

> > +                                                      &pf->queue_region;

> > +      uint32_t ret = -EINVAL;

> > +

> > +      if (!region_info->queue_region_number) {

> > +                      PMD_INIT_LOG(ERR, "there is no that region id been set

> before");

>

> Can you please re-check the log message.



oK, change in v4



>

> > +                      return ret;

> > +      }

> > +

> > +      memset(&ctxt, 0, sizeof(struct i40e_vsi_context));

> > +

> > +      /* Update Queue Pairs Mapping for currently enabled UPs */

> > +      ctxt.seid = vsi->seid;

> > +      ctxt.pf_num = hw->pf_id;

> > +      ctxt.vf_num = 0;

> > +      ctxt.uplink_seid = vsi->uplink_seid;

> > +      ctxt.info = vsi->info;

> > +      vsi_info = &ctxt.info;

> > +

> > +      memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);

> > +      memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);

> > +

> > +      /**

> > +      * Configure queue region and queue mapping parameters,

> > +      * for enabled queue region, allocate queues to this region.

> > +      */

> > +

> > +      for (i = 0; i < region_info->queue_region_number; i++) {

> > +                      tc_index = region_info->region[i].region_id;

> > +                      bsf = rte_bsf32(region_info->region[i].queue_num);

> > +                      queue_offset = region_info->region[i].queue_start_index;

> > +                      vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(

> > +                                      (queue_offset <<

> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |

> > +                                                      (bsf <<

> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));

> > +      }

> > +

> > +      /* Associate queue number with VSI, Keep vsi->nb_qps unchanged

> */

> > +      if (vsi->type == I40E_VSI_SRIOV) {

> > +                      vsi_info->mapping_flags |=

> > +

>             rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);

> > +                      for (i = 0; i < vsi->nb_qps; i++)

> > +                                      vsi_info->queue_mapping[i] =

> > +                                                      rte_cpu_to_le_16(vsi->base_queue + i);

> > +      } else {

> > +                      vsi_info->mapping_flags |=

> > +

>             rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);

> > +                      vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi-

> >base_queue);

> > +      }

> > +      vsi_info->valid_sections |=

> > +

>             rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);

> > +

> > +      /* Update the VSI after updating the VSI queue-mapping

> information */

> > +      ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);

> > +      if (ret) {

> > +                      PMD_INIT_LOG(ERR, "Failed to configure queue region "

> > +                                      "mapping = %d ", hw->aq.asq_last_status);

>

> Please don't split log message.



oK, change in v4





>

> > +                      return ret;

> > +      }

> > +      /* update the local VSI info with updated queue map */

> > +      (void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,

> > +                                                                      sizeof(vsi->info.tc_mapping));

> > +      (void)rte_memcpy(&vsi->info.queue_mapping,

> > +                                      &ctxt.info.queue_mapping,

> > +                      sizeof(vsi->info.queue_mapping));

>

> Please keep line allignment same with above line.



oK, change in v4, but can not the same.

(void)rte_memcpy(&vsi->info.queue_mapping, &ctxt.info.queue_mapping,

                                                sizeof(vsi->info.queue_mapping));

will over 80 maxnumber.



>

> > +      vsi->info.mapping_flags = ctxt.info.mapping_flags;

> > +      vsi->info.valid_sections = 0;

> > +

> > +      return 0;

> > +}

> > +

> > +

> > +static int

> > +i40e_set_queue_region(struct i40e_pf *pf,

> > +                                                      struct rte_i40e_rss_region_conf *conf_ptr) {

> > +      uint16_t tc_size_tb[7] = {1, 2, 4, 8, 16, 32, 64};

> > +      uint16_t i;

> > +      struct i40e_vsi *main_vsi = pf->main_vsi;

> > +      struct i40e_queue_region_info *info = &pf->queue_region;

> > +      uint32_t ret = -EINVAL;

> > +

> > +      for (i = 0; i < I40E_REGION_MAX_INDEX; i++)

> > +                      if (conf_ptr->queue_num == tc_size_tb[i])

> > +                                      break;

> > +

> > +      if (i == I40E_REGION_MAX_INDEX) {

> > +                      printf("The region sizes should be any of the following "

> > +                      "values: 1, 2, 4, 8, 16, 32, 64 as long as the "

> > +                      "total number of queues do not exceed the VSI allocation");

> > +                      return ret;

> > +      }

> > +

> > +      if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {

> > +                      PMD_INIT_LOG(ERR, "the queue region max index is 7");

> > +                      return ret;

> > +      }

> > +

> > +      if ((conf_ptr->queue_start_index + conf_ptr->queue_num)

> > +                                                                      > main_vsi->nb_used_qps) {

> > +                      PMD_INIT_LOG(ERR, "the queue index exceeds the VSI

> range");

> > +                      return ret;

> > +      }

> > +

> > +      if (info->queue_region_number) {

> > +                      for (i = 0; i < info->queue_region_number; i++)

> > +                                      if (conf_ptr->region_id == info->region[i].region_id)

> > +                                                      break;

> > +

> > +                      if ((i == info->queue_region_number) &&

> > +                                      (i <= I40E_REGION_MAX_INDEX)) {

>

>

> Please use one more level indentaion here, and pharantesis looks extra can

> you please double check?



You mean,you want the following moede ?

                                if (i == info->queue_region_number) {

                                                if(i <= I40E_REGION_MAX_INDEX) {

                                                                ...........................

                                                }

                                }

>

> > +                                      info->region[i].region_id = conf_ptr->region_id;

> > +                                      info->region[i].queue_num = conf_ptr->queue_num;

> > +                                      info->region[i].queue_start_index =

> > +                                                      conf_ptr->queue_start_index;

> > +                                      info->queue_region_number++;

> > +                      } else {

> > +                                      PMD_INIT_LOG(ERR, "queue region number "

> > +                                                      "exceeds maxnum 8 or the "

> > +                                                      "queue region id has "

> > +                                                      "been set before");

>

> please don't split log message.



oK, change in v4



>

> > +                                      return ret;

> > +                      }

> > +      } else {

> > +                      info->region[0].region_id = conf_ptr->region_id;

> > +                      info->region[0].queue_num = conf_ptr->queue_num;

> > +                      info->region[0].queue_start_index =

> > +                                      conf_ptr->queue_start_index;

> > +                      info->queue_region_number++;

> > +      }

> > +

> > +      return 0;

> > +}

> > +

> > +static int

> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,

> > +                      struct i40e_pf *pf, struct rte_i40e_rss_region_conf

> *conf_ptr)

>

> What do you think starting all functions, even they are static, with

> "i40e_queue_region_" prefix?



                                ret = i40e_set_queue_region(pf, conf_ptr);

                                break;

                case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:

                                ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);

                                break;

                case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:

                                ret = -EINVAL;

                                break;

                case RTE_PMD_I40E_UP_REGION_SET:

                                ret = i40e_set_up_region(pf, conf_ptr);



I have use the format of i40e_set_  as prefix?

Because many set is not related directly to queue region.



>

> > +{

> > +      uint32_t pfqf_hregion;

> > +      uint32_t ret = -EINVAL;

> > +      struct i40e_queue_region_info *info = &pf->queue_region;

> > +      uint16_t i, j, index, flowtype_set = 0;

> > +      uint16_t region_index, flowtype_index;

> > +

> > +      if (conf_ptr->region_id > I40E_PFQF_HREGION_MAX_INDEX) {

> > +                      PMD_INIT_LOG(ERR, "the queue region max index is 7");

> > +                      return ret;

> > +      }

> > +

> > +      if (conf_ptr->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {

> > +                      PMD_INIT_LOG(ERR, "the hw_flowtype or PCTYPE max index

> is 63");

> > +                      return ret;

> > +      }

> > +

> > +      if (info->queue_region_number) {

> > +                      for (i = 0; i < info->queue_region_number; i++)

> > +                                      if (conf_ptr->region_id == info->region[i].region_id)

> > +                                                      break;

> > +

> > +                      if (i == info->queue_region_number) {

> > +                                      PMD_INIT_LOG(ERR, "that region id has not "

> > +                                                      "been set before");

> > +                                      return ret;

> > +                      }

> > +                      region_index = i;

> > +

> > +                      for (i = 0; i < info->queue_region_number; i++) {

> > +                                      for (j = 0; j < info->region[i].flowtype_num; j++) {

> > +                                                      if (conf_ptr->hw_flowtype ==

> > +                                                                      info->region[i].hw_flowtype[j]) {

> > +                                                                      flowtype_set = 1;

> > +                                                                      break;

> > +                                                      }

> > +                                      }

> > +                      }

> > +

> > +                      if (flowtype_set) {

> > +                                      PMD_INIT_LOG(ERR, "that hw_flowtype "

> > +                                                      "has been set before");

>

> Please don't split log messages.



Ok.





>

> > +                                      return ret;

> > +                      }

> > +                      flowtype_index = info->region[region_index].flowtype_num;

> > +                      info->region[region_index].hw_flowtype[flowtype_index] =

> > +                                                                                      conf_ptr->hw_flowtype;

> > +                      info->region[region_index].flowtype_num++;

> > +      } else  {

> > +                      PMD_INIT_LOG(ERR, "there is no that region id been set

> before");

> > +                      return ret;

> > +      }

> > +

> > +      index = conf_ptr->hw_flowtype >> 3;

> > +      pfqf_hregion = i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));

> > +

> > +      if ((conf_ptr->hw_flowtype & 0x7) == 0) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_0_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 1) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_1_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 2) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_2_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 3) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_3_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 4) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_4_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 5) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_5_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;

> > +      } else if ((conf_ptr->hw_flowtype & 0x7) == 6) {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_6_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;

> > +      } else {

> > +                      pfqf_hregion |= conf_ptr->region_id <<

> > +                                                      I40E_PFQF_HREGION_REGION_7_SHIFT;

> > +                      pfqf_hregion |= 1 <<

> I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;

> > +      }

> > +

> > +      i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index), pfqf_hregion);

> > +

> > +      return 0;

> > +}

> > +

> > +static int

> > +i40e_set_up_region(struct i40e_pf *pf,

> > +                                                      struct rte_i40e_rss_region_conf *conf_ptr)

>

> The API name looks like "setup" but that up part is user_priority, can you

> please long form against "up"?



Ok, I will change to “user_priority” instead of “up”



>

> > +{

> > +      struct i40e_queue_region_info *info = &pf->queue_region;

> > +      uint32_t ret = -EINVAL;

> > +      uint16_t i, j, region_index, up_set = 0;

>

> Same abrevation comment for "upset", please use long form.

>

> > +

> > +      if (conf_ptr->user_priority >

> I40E_REGION_USERPRIORITY_MAX_INDEX) {

> > +                      PMD_INIT_LOG(ERR, "the queue region max index is 7");

> > +                      return ret;

> > +      }

> > +

> > +      if (conf_ptr->region_id >= I40E_REGION_MAX_INDEX) {

> > +                      PMD_INIT_LOG(ERR, "the region_id max index is 7");

> > +                      return ret;

> > +      }

> > +

> > +      if (info->queue_region_number) {

> > +                      for (i = 0; i < info->queue_region_number; i++)

> > +                                      if (conf_ptr->region_id == info->region[i].region_id)

> > +                                                      break;

> > +

> > +                      if (i == info->queue_region_number) {

> > +                                      PMD_INIT_LOG(ERR, "that region id "

> > +                                                      "has not been set before");

> > +                                      return ret;

> > +                      }

> > +                      region_index = i;

> > +

> > +                      for (i = 0; i < info->queue_region_number; i++) {

> > +                                      for (j = 0; j <

> > +                                                      info->region[i].user_priority_num; j++) {

>

> Please break line after ";"



Ok.





>

> > +                                                      if (info->region[i].user_priority[j] ==

> > +                                                                      conf_ptr->user_priority) {

> > +                                                                      up_set = 1;

> > +                                                                      break;

> > +                                                      }

> > +                                      }

> > +                      }

> > +

> > +                      if (up_set) {

> > +                                      PMD_INIT_LOG(ERR, "that user priority "

> > +                                                      "has been set before");

> > +                                      return ret;

> > +                      }

> > +

> > +                      j = info->region[region_index].user_priority_num;

> > +                      info->region[region_index].user_priority[j] =

> > +                                                                                      conf_ptr->user_priority;

> > +                      info->region[region_index].user_priority_num++;

> > +      } else {

> > +                      PMD_INIT_LOG(ERR, "there is no that region id been set

> before");

> > +                      return ret;

> > +      }

> > +

> > +      return 0;

> > +}

> > +

> > +static int

> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,

> > +                                                      struct i40e_pf *pf)

> > +{

> > +      struct i40e_dcbx_config dcb_cfg_local;

> > +      struct i40e_dcbx_config *dcb_cfg;

> > +      struct i40e_queue_region_info *info = &pf->queue_region;

> > +      struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;

> > +      uint32_t ret = -EINVAL;

>

> Please use signed variable, there are more above.



Ok

>

> > +      uint16_t i, j, prio_index, region_index;

> > +      uint8_t tc_map, tc_bw, bw_lf;

> > +

> > +      if (!info->queue_region_number) {

> > +                      PMD_INIT_LOG(ERR, "there is no that region id been set

> before");

> > +                      return ret;

> > +      }

> > +

> > +      dcb_cfg = &dcb_cfg_local;

> > +      memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));

> > +

> > +      /* assume each tc has the same bw */

> > +      tc_bw = I40E_MAX_PERCENT / info->queue_region_number;

> > +      for (i = 0; i < info->queue_region_number; i++)

> > +                      dcb_cfg->etscfg.tcbwtable[i] = tc_bw;

> > +      /* to ensure the sum of tcbw is equal to 100 */

> > +      bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;

> > +      for (i = 0; i < bw_lf; i++)

> > +                      dcb_cfg->etscfg.tcbwtable[i]++;

> > +

> > +      /* assume each tc has the same Transmission Selection Algorithm */

> > +      for (i = 0; i < info->queue_region_number; i++)

> > +                      dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;

> > +

> > +      for (i = 0; i < info->queue_region_number; i++) {

> > +                      for (j = 0; j < info->region[i].user_priority_num; j++) {

> > +                                      prio_index = info->region[i].user_priority[j];

> > +                                      region_index = info->region[i].region_id;

> > +                                      dcb_cfg->etscfg.prioritytable[prio_index] =

> > +                                                                                      region_index;

> > +                      }

> > +      }

> > +

> > +      /* FW needs one App to configure HW */

> > +      dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;

> > +      dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;

> > +      dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;

> > +      dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;

> > +

> > +      tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);

> > +

> > +      dcb_cfg->pfc.willing = 0;

> > +      dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;

> > +      dcb_cfg->pfc.pfcenable = tc_map;

> > +

> > +      /* Copy the new config to the current config */

> > +      *old_cfg = *dcb_cfg;

> > +      old_cfg->etsrec = old_cfg->etscfg;

> > +      ret = i40e_set_dcb_config(hw);

> > +

> > +      if (ret) {

> > +                      PMD_INIT_LOG(ERR, "Set queue region DCB Config failed,

> err"

> > +                                      " %s aq_err %s",

>

> Please don't split the log message.



Ok



>

> > +                                      i40e_stat_str(hw, ret),

> > +                                      i40e_aq_str(hw, hw->aq.asq_last_status));

> > +                      return ret;

> > +      }

> > +

> > +      return 0;

> > +}

> > +

> > +static int

> > +i40e_queue_region_dcb_configure_default(struct i40e_hw *hw) {

> > +      uint16_t i;

> > +      uint32_t ret = -EINVAL;

>

> Please use signed variable here.



Ok



>

> > +

> > +      memset(&hw->local_dcbx_config, 0,

> > +      sizeof(struct i40e_dcbx_config));

>

> Wrong indentation.

>

> > +      /* set dcb default configuration */

> > +      hw->local_dcbx_config.etscfg.willing = 0;

> > +      hw->local_dcbx_config.etscfg.maxtcs = 0;

> > +      hw->local_dcbx_config.etscfg.tcbwtable[0] = 100;

> > +      hw->local_dcbx_config.etscfg.tsatable[0] =

> > +                                      I40E_IEEE_TSA_ETS;

> > +      /* all UPs mapping to region 0 */

> > +      for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)

> > +                      hw->local_dcbx_config.etscfg.prioritytable[i] = 0;

> > +      hw->local_dcbx_config.etsrec =

> > +                      hw->local_dcbx_config.etscfg;

> > +      hw->local_dcbx_config.pfc.willing = 0;

> > +      hw->local_dcbx_config.pfc.pfccap =

> > +                                      I40E_MAX_TRAFFIC_CLASS;

> > +      /* FW needs one App to configure HW */

> > +      hw->local_dcbx_config.numapps = 1;

> > +      hw->local_dcbx_config.app[0].selector =

> > +                                      I40E_APP_SEL_ETHTYPE;

> > +      hw->local_dcbx_config.app[0].priority = 3;

> > +      hw->local_dcbx_config.app[0].protocolid =

> > +                                      I40E_APP_PROTOID_FCOE;

> > +      ret = i40e_set_dcb_config(hw);

> > +      if (ret) {

> > +                      PMD_INIT_LOG(ERR,

> > +                      "default dcb config fails. err = %d, aq_err = %d.",

> > +                                      ret, hw->aq.asq_last_status);

> > +                      return ret;

> > +      }

> > +

> > +      return 0;

> > +}

> > +

> > +int

> > +i40e_flush_region_all_conf(struct i40e_hw *hw, struct i40e_pf *pf,

> > +                                                      uint16_t on)

> > +{

> > +      uint16_t i;

> > +      struct i40e_queue_region_info *info = &pf->queue_region;

> > +

> > +      if (on) {

> > +                      i40e_vsi_update_queue_region_mapping(hw, pf);

> > +                      i40e_queue_region_dcb_configure(hw, pf);

> > +                      return 0;

> > +      }

> > +

> > +      info->queue_region_number = 1;

> > +      info->region[0].queue_num = 64;

> > +      info->region[0].queue_start_index = 0;

> > +

> > +      i40e_vsi_update_queue_region_mapping(hw, pf);

> > +      i40e_queue_region_dcb_configure_default(hw);

> > +

> > +      for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)

> > +                      i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);

> > +

> > +      memset(info, 0, sizeof(struct i40e_queue_region_info));

> > +

> > +      return 0;

> > +}

> > +

> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,

> > +                                      struct rte_i40e_rss_region_conf *conf_ptr) {

> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];

>

> you need to verify port_id, since this is public API now. Please check other

> APIs in this file.

>

> > +      struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-

> >dev_private);

> > +      struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-

> >dev_private);

> > +      enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;

> > +      uint32_t ret;

>

> This should be signed variable, since you are using it for return and assigning

> negative values.

>

> > +

> > +      if (!is_i40e_supported(dev))

> > +                      return -ENOTSUP;

> > +

> > +      switch (op_type) {

> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:

> > +                      ret = i40e_set_queue_region(pf, conf_ptr);

> > +                      break;

>

> Does it make sense to add another type to get the current queue region

> config?

>

> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:

> > +                      ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);

> > +                      break;

> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:

> > +                      ret = -EINVAL;

>

> Will this be implemented later, or not a valid case at all?

>

> > +                      break;

> > +      case RTE_PMD_I40E_UP_REGION_SET:> +                          ret =

> i40e_set_up_region(pf, conf_ptr);

> > +                      break;

> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:

> > +                      ret = i40e_flush_region_all_conf(hw, pf, 1);

> > +                      break;

> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:

> > +                      ret = i40e_flush_region_all_conf(hw, pf, 0);

>

> Can you please describe what flush_on and flush_off are, you can comment

> to code if also.

>

> > +                      break;

> > +

> > +      default:

> > +                      PMD_DRV_LOG(WARNING, "op type (%d) not supported",

> > +                                          op_type);

>

> Line break not required.



Ok, delete in v4

>

> > +                      ret = -EINVAL;

> > +                      break;

> > +      }

> > +

> > +      I40E_WRITE_FLUSH(hw);

> > +

> > +      return ret;

> > +}

> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h

> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..a1329f4 100644

> > --- a/drivers/net/i40e/rte_pmd_i40e.h

> > +++ b/drivers/net/i40e/rte_pmd_i40e.h

> > @@ -91,6 +91,20 @@ enum rte_pmd_i40e_package_info {

> >          RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };

> >

> > +/**

> > + *  Option types of queue region.

> > + */

> > +enum rte_pmd_i40e_queue_region_op {

> > +      RTE_PMD_I40E_REGION_UNDEFINED = 0,

>

> No need to set to zero, it is default value.





Ok



>

> > +      RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region

> set*/

>

> I would suggest using same namespace for the enum ites, there are

> "RTE_PMD_I40E_REGION" and "RTE_PMD_I40E_QUEUE_REGION".

> "RTE_PMD_I40E_QUEUE_REGION" looks better. Or if it makes sense,

> perhaps "RTE_PMD_I40E_RSS_QUEUE_REGION"? But please stick with one.

>

> > +      RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET,   /**< add pf region

> pctype set */

> > +      RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET,   /**< add vf region

> pctype set */

> > +      RTE_PMD_I40E_UP_REGION_SET,   /**< add queue region pctype

> set */

>

> is this comment correct, this type should be for user priority



Ok, fix in v4



>

> > +      RTE_PMD_I40E_REGION_ALL_FLUSH_ON,   /**< flush on all

> configuration */

> > +      RTE_PMD_I40E_REGION_ALL_FLUSH_OFF,   /**< flush off all

> configuration */

> > +      RTE_PMD_I40E_QUEUE_REGION_OP_MAX

> > +};

> > +

> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32

> >

> >  /**

> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };

> >

> >  /**

> > + * Queue region information get from CLI.

>

> It doesn't need to be from CLI, can drop that part

>

> > + */

> > +struct rte_i40e_rss_region_conf {

>

> This is now public struct, can you please comment items.



Ok. Add in v4



>

> > +      uint8_t region_id;

> > +      uint8_t hw_flowtype;

> > +      uint8_t queue_start_index;

> > +      uint8_t queue_num;

> > +      uint8_t user_priority;

> > +      enum rte_pmd_i40e_queue_region_op  op;

>

> Extra space before "op"



Maybe, I SHOULD add uint8_t raw[3] before “op”





>

> > +};

> > +

> > +/**

> >   * Notify VF when PF link status changes.

> >   *

> >   * @param port

> > @@ -657,4 +683,16 @@ int

> rte_pmd_i40e_ptype_mapping_replace(uint8_t

> > port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,

> >                                                           struct ether_addr *mac_addr);

> >

> > +/**

> > + * Get RSS queue region info from CLI and do configuration for

>

> Again now this is an API, not just for testpmd, please drop CLI

>

> > + * that port as the command otion type

>

> s/otion/options

>

> > + *

> > + * @param port

> > + *    pointer to port identifier of the device

>

> Not pointer.

> Also this will conflict with patch that updates port storage to uint16_t. Can



Ok, change in v4

> you please follow the status of the patch, and if this merged after that one,

> please ping to remind to update the storage.



Ok ,I will commit a new v4 to fix these , then remind you of the new version



>

> > + * @param conf_ptr

> > + *    pointer to the struct that contain all the

> > + *    region configuration parameters

> > + */

> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,

>

> Can you please use port_id as variable name to be consistent.

>

> > +                      struct rte_i40e_rss_region_conf *conf_ptr);

>

> conf_ptr variable name doesn't say much, although it is OK in this context. I

> would suggest something like rss_region_conf



Ok.

>

> >  #endif /* _PMD_I40E_H_ */

> > diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map

> > b/drivers/net/i40e/rte_pmd_i40e_version.map

> > index ef8882b..c3ee2da 100644

> > --- a/drivers/net/i40e/rte_pmd_i40e_version.map

> > +++ b/drivers/net/i40e/rte_pmd_i40e_version.map

> > @@ -50,5 +50,6 @@ DPDK_17.11 {

> >          global:

> >

> >          rte_pmd_i40e_add_vf_mac_addr;

> > +      rte_pmd_i40e_queue_region_conf;

>

> The feature has been mention as "rss queue region" above a few places, do

> you think rte_pmd_i40e_rss_queue_region_conf() or

> rte_pmd_i40e_queue_region_conf() is better for API name?



Ok, I will change to rte_pmd_i40e_rss_queue_region_conf



>

> >

> >  } DPDK_17.08;

> >



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

* Re: [PATCH v3 2/2] app/testpmd: add API for configuration of queue region
  2017-09-20 10:45       ` Ferruh Yigit
@ 2017-09-25  9:25         ` Zhao1, Wei
  2017-09-25  9:43           ` Ferruh Yigit
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-25  9:25 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Wu, Jingjing

Hi, Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, September 20, 2017 6:46 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org; Wu, Jingjing
> <jingjing.wu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
> configuration of queue region
> 
> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> > This patch add a API configuration of queue region in rss.
> > It can parse the parameters of region index, queue number, queue start
> > index, user priority, traffic classes and so on.
> > According to commands from command line, it will call i40e private API
> > and start the process of set or flush queue region configure. As this
> > feature is specific for i40e, so private API will be used.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  app/test-pmd/cmdline.c | 328
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> 
> Testpmd documentation also needs to be updated.

Do you mean the following doc or others?
dpdk\doc\guides\testpmd_app_ug.rst


> 
> >  1 file changed, 328 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 0144191..060fcb1 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> >  			"ptype mapping update (port_id) (hw_ptype)
> (sw_ptype)\n"
> >  			"    Update a ptype mapping item on a port\n\n"
> >
> > +			"queue-region set port (port_id) region_id (value) "
> > +			"queue_start_index (value) queue_num (value)\n"
> > +			"    Set a queue region on a port\n\n"
> > +
> > +			"queue-region set (pf|vf) port (port_id) region_id
> (value) "
> > +			"flowtype (value)\n"
> > +			"    Set a flowtype region index on a port\n\n"
> > +
> > +			"queue-region set port (port_id) UP (value)
> region_id (value)\n"
> > +			"    Set the mapping of User Priority to "
> > +			"queue region on a port\n\n"
> > +
> > +			"queue-region flush (on|off) port (port_id)\n"
> > +			"    flush all queue region related configuration\n\n"
> 
> I keep doing same comment but I will do it again...
> 
> Each patch adding a new feature looking from its own context and adding a
> new root level command and this is making overall testpmd confusing.
> 
> Since this is to set an option of the port, what do you think making this
> command part of existing commands, like:
> "port config #P queue-region ...."
> OR
> "set port #P queue-region ..." ?

What you said is very meaningful, but other feature liake ptype mapping use the same mode  and so on.
maybe we should do a whole work to make CLI command style consistent.


> 
> > +
> >  			, list_pkt_forwarding_modes()
> >  		);
> >  	}
> > @@ -8224,6 +8239,315 @@ cmdline_parse_inst_t cmd_syn_filter = {
> >  		NULL,
> >  	},
> >  };
> > +/* *** queue region set *** */
> > +struct cmd_queue_region_result {
> > +	cmdline_fixed_string_t cmd;
> > +	cmdline_fixed_string_t set;
> > +	cmdline_fixed_string_t port;
> > +	uint8_t  port_id;
> > +	cmdline_fixed_string_t region;
> > +	uint8_t  region_id;
> > +	cmdline_fixed_string_t queue_start_index;
> > +	uint8_t  queue_id;
> > +	cmdline_fixed_string_t queue_num;
> > +	uint8_t  queue_num_value;
> > +};
> > +
> > +static void
> > +cmd_queue_region_parsed(void *parsed_result,
> > +			__attribute__((unused)) struct cmdline *cl,
> > +			__attribute__((unused)) void *data) {
> > +	struct cmd_queue_region_result *res = parsed_result;
> > +	struct rte_i40e_rss_region_conf region_conf;
> > +	int ret = 0;
> > +
> > +	memset(&region_conf, 0, sizeof(region_conf));
> > +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> > +	region_conf.region_id = res->region_id;
> > +	region_conf.queue_num = res->queue_num_value;
> > +	region_conf.queue_start_index = res->queue_id;
> > +
> > +	ret = rte_pmd_i40e_queue_region_conf(res->port_id,
> &region_conf);
> 
> It is not safe to directly call PMD specific APIs from testpmd? What if that
> PMD is not enabled? There are samples how to do this, can you please check
> them?
> 

Good idea, I will add check code in PMD code to make sure RSS is enable.
If not, code will return fail.


> <...>


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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-25  7:40         ` Zhao1, Wei
@ 2017-09-25  9:31           ` Ferruh Yigit
  2017-09-26  7:46             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-25  9:31 UTC (permalink / raw)
  To: Zhao1, Wei; +Cc: dev

On 9/25/2017 8:40 AM, Zhao1, Wei wrote:
> Hi, Ferruh
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, September 20, 2017 6:36 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> flush
>>
>> On 9/15/2017 4:13 AM, Wei Zhao wrote:
>> > This feature enable queue regions configuration for RSS in PF/VF, so
>> > that different traffic classes or different packet classification
>> > types can be separated to different queues in different queue
>> > regions.This patch can set queue region range, it include queue number
>> > in a region and the index of first queue.
>>
>> Is following correct:
>> So instead of distributing packets to the multiple queues, this will
> distribute
>> packets into queue reqions which may consists of multiple queues.
>>
>> If so, is there a way to control how packets distributed within same queue
>> region to multiple queues?
>>
> 
> distributed within same queue region is based on a rss algorithm, it is
> implemented by NIC self, software can not control it.

I was thinking RSS used to select queue region, but no first queue
region selected, later RSS used to select queue within the region.
Thanks for clarification.

<...>
                                                               
> sizeof(vsi->info.tc_mapping));
>> > +      (void)rte_memcpy(&vsi->info.queue_mapping,
>> > +                                      &ctxt.info.queue_mapping,
>> > +                      sizeof(vsi->info.queue_mapping));
>>
>> Please keep line allignment same with above line.
> 
> oK, change in v4, but can not the same.
> (void)rte_memcpy(&vsi->info.queue_mapping, &ctxt.info.queue_mapping,
>                                                
> sizeof(vsi->info.queue_mapping));
> will over 80 maxnumber.

Someting like following, new lines aligned:

	(void)rte_memcpy(&vsi->info.queue_mapping,
		&ctxt.info.queue_mapping,
		sizeof(vsi->info.queue_mapping));

<...>

>> > +                      if ((i == info->queue_region_number) &&
>> > +                                      (i <= I40E_REGION_MAX_INDEX)) {
>>
>>
>> Please use one more level indentaion here, and pharantesis looks extra can
>> you please double check?
> 
> You mean,you want the following moede ?
>         if (i == info->queue_region_number) {
>         	if(i <= I40E_REGION_MAX_INDEX) {
> 			...........................
>         	}
>        }
> 

No, continuation of the "if" should be easy to recognized from body of
the "if", something like:

	if ((i == info->queue_region_number) &&
			(i <= I40E_REGION_MAX_INDEX)) {
		info->region[i].region_id = conf_ptr->region_id;
		info->region[i].queue_num = conf_ptr->queue_num;

<...>


>> > +static int
>> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
>> > +                      struct i40e_pf *pf, struct
> rte_i40e_rss_region_conf
>> *conf_ptr)
>>
>> What do you think starting all functions, even they are static, with
>> "i40e_queue_region_" prefix? 
>                                 ret = i40e_set_queue_region(pf, conf_ptr);
>                                 break;
>                 case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
>                                 ret = i40e_set_region_flowtype_pf(hw,
> pf, conf_ptr);
>                                 break;
>                 case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
>                                 ret = -EINVAL;
>                                 break;
>                 case RTE_PMD_I40E_UP_REGION_SET:
>                                 ret = i40e_set_up_region(pf, conf_ptr);
> 
> I have use the format ofi40e_set_  as prefix?
> Because many set is not related directly to queue region.

When looking to this patch what functions are doing is clear, but it
also should be clear when looking the source code some time later what
that function is about.

That is why I believe a namespace is useful, like
"i40e_queue_region_xx", so you can immediately say this function is
about "RSS queue region" feature.

This function is "rte_pmd_i40e_queue_region_conf", it is applying
provided queue region configuration based of region op type, so I
assumed all these functions are directly related to the fature.

If you believe function name will be wrong with that prefix, of course
just don't use it, but please try to stick with a name space, that will
make easy to understand these features in all source code.

<...>


>> > +
>> > +      memset(&hw->local_dcbx_config, 0,
>> > +      sizeof(struct i40e_dcbx_config));
>>
>> Wrong indentation.

Reminder of this one incase missed.

<...>

>> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
>> > +                                      struct
> rte_i40e_rss_region_conf *conf_ptr) {
>> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];
>>
>> you need to verify port_id, since this is public API now. Please check
> other
>> APIs in this file.

Reminder of this one incase missed.

I mean is_i40e_supported() call that other APIs have.

<...>

>> > +
>> > +      if (!is_i40e_supported(dev))
>> > +                      return -ENOTSUP;
>> > +
>> > +      switch (op_type) {
>> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:
>> > +                      ret = i40e_set_queue_region(pf, conf_ptr);
>> > +                      break;
>>
>> Does it make sense to add another type to get the current queue region
>> config?

Reminder of this one incase missed.

> 
>> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
>> > +                      ret = i40e_set_region_flowtype_pf(hw, pf,
> conf_ptr);
>> > +                      break;
>> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
>> > +                      ret = -EINVAL;
>>
>> Will this be implemented later, or not a valid case at all?

Reminder of this one incase missed.

>> > +                      break;
>> > +      case RTE_PMD_I40E_UP_REGION_SET:> +                         
> ret =
>> i40e_set_up_region(pf, conf_ptr);
>> > +                      break;
>> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
>> > +                      ret = i40e_flush_region_all_conf(hw, pf, 1);
>> > +                      break;
>> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
>> > +                      ret = i40e_flush_region_all_conf(hw, pf, 0);
>>
>> Can you please describe what flush_on and flush_off are, you can comment
>> to code if also.

Reminder of this one incase missed.

<...>

>> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
>> >
>> >  /**
>> > + * Queue region information get from CLI.
>>
>> It doesn't need to be from CLI, can drop that part

Reminder of this one incase missed.

<...>

>> > +      uint8_t user_priority;
>> > +      enum rte_pmd_i40e_queue_region_op  op;
>>
>> Extra space before "op"
> 
> Maybe, I SHOULD add uint8_t raw[3] before “op”

Sorry, I didn't get this one.

<...>

>> rte_pmd_i40e_ptype_mapping_replace(uint8_t
>> > port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
>> >                                                           struct
> ether_addr *mac_addr);
>> >
>> > +/**
>> > + * Get RSS queue region info from CLI and do configuration for
>>
>> Again now this is an API, not just for testpmd, please drop CLI

Reminder of this one incase missed.

>>
>> > + * that port as the command otion type
>>
>> s/otion/options
>>

Reminder of this one incase missed.

<...>

>> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
>>
>> Can you please use port_id as variable name to be consistent.

Reminder of this one incase missed.

<...>

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

* Re: [PATCH v3 2/2] app/testpmd: add API for configuration of queue region
  2017-09-25  9:25         ` Zhao1, Wei
@ 2017-09-25  9:43           ` Ferruh Yigit
  2017-09-26  5:30             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-25  9:43 UTC (permalink / raw)
  To: Zhao1, Wei, dev, Wu, Jingjing

On 9/25/2017 10:25 AM, Zhao1, Wei wrote:
> Hi, Ferruh
> 
>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, September 20, 2017 6:46 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org; Wu, Jingjing
>> <jingjing.wu@intel.com>
>> Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
>> configuration of queue region
>>
>> On 9/15/2017 4:13 AM, Wei Zhao wrote:
>>> This patch add a API configuration of queue region in rss.
>>> It can parse the parameters of region index, queue number, queue start
>>> index, user priority, traffic classes and so on.
>>> According to commands from command line, it will call i40e private API
>>> and start the process of set or flush queue region configure. As this
>>> feature is specific for i40e, so private API will be used.
>>>
>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>> ---
>>>  app/test-pmd/cmdline.c | 328
>>> +++++++++++++++++++++++++++++++++++++++++++++++++
>>
>> Testpmd documentation also needs to be updated.
> 
> Do you mean the following doc or others?
> dpdk\doc\guides\testpmd_app_ug.rst

Yes this one, thanks.

> 
> 
>>
>>>  1 file changed, 328 insertions(+)
>>>
>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
>>> 0144191..060fcb1 100644
>>> --- a/app/test-pmd/cmdline.c
>>> +++ b/app/test-pmd/cmdline.c
>>> @@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void
>> *parsed_result,
>>>  			"ptype mapping update (port_id) (hw_ptype)
>> (sw_ptype)\n"
>>>  			"    Update a ptype mapping item on a port\n\n"
>>>
>>> +			"queue-region set port (port_id) region_id (value) "
>>> +			"queue_start_index (value) queue_num (value)\n"
>>> +			"    Set a queue region on a port\n\n"
>>> +
>>> +			"queue-region set (pf|vf) port (port_id) region_id
>> (value) "
>>> +			"flowtype (value)\n"
>>> +			"    Set a flowtype region index on a port\n\n"
>>> +
>>> +			"queue-region set port (port_id) UP (value)
>> region_id (value)\n"
>>> +			"    Set the mapping of User Priority to "
>>> +			"queue region on a port\n\n"
>>> +
>>> +			"queue-region flush (on|off) port (port_id)\n"
>>> +			"    flush all queue region related configuration\n\n"
>>
>> I keep doing same comment but I will do it again...
>>
>> Each patch adding a new feature looking from its own context and adding a
>> new root level command and this is making overall testpmd confusing.
>>
>> Since this is to set an option of the port, what do you think making this
>> command part of existing commands, like:
>> "port config #P queue-region ...."
>> OR
>> "set port #P queue-region ..." ?
> 
> What you said is very meaningful, but other feature liake ptype mapping use the same mode  and so on.
> maybe we should do a whole work to make CLI command style consistent.

Yes ptype does it, is seems it is one of the missed ones. Although we
can do a whole work for CLI commands, meanwhile I think new ones can be
added properly.

This may be good opportunity to remember broken window theory [1] :)

[1]
https://blog.codinghorror.com/the-broken-window-theory/

<...>

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

* Re: [PATCH v3 2/2] app/testpmd: add API for configuration of queue region
  2017-09-25  9:43           ` Ferruh Yigit
@ 2017-09-26  5:30             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-26  5:30 UTC (permalink / raw)
  To: Yigit, Ferruh, dev, Wu, Jingjing


Hi,Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Monday, September 25, 2017 5:43 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org; Wu, Jingjing
> <jingjing.wu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
> configuration of queue region
> 
> On 9/25/2017 10:25 AM, Zhao1, Wei wrote:
> > Hi, Ferruh
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, September 20, 2017 6:46 PM
> >> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org; Wu, Jingjing
> >> <jingjing.wu@intel.com>
> >> Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
> >> configuration of queue region
> >>
> >> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> >>> This patch add a API configuration of queue region in rss.
> >>> It can parse the parameters of region index, queue number, queue
> >>> start index, user priority, traffic classes and so on.
> >>> According to commands from command line, it will call i40e private
> >>> API and start the process of set or flush queue region configure. As
> >>> this feature is specific for i40e, so private API will be used.
> >>>
> >>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> >>> ---
> >>>  app/test-pmd/cmdline.c | 328
> >>> +++++++++++++++++++++++++++++++++++++++++++++++++
> >>
> >> Testpmd documentation also needs to be updated.
> >
> > Do you mean the following doc or others?
> > dpdk\doc\guides\testpmd_app_ug.rst
> 
> Yes this one, thanks.
> 
> >
> >
> >>
> >>>  1 file changed, 328 insertions(+)
> >>>
> >>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> >>> 0144191..060fcb1 100644
> >>> --- a/app/test-pmd/cmdline.c
> >>> +++ b/app/test-pmd/cmdline.c
> >>> @@ -637,6 +637,21 @@ static void cmd_help_long_parsed(void
> >> *parsed_result,
> >>>  			"ptype mapping update (port_id) (hw_ptype)
> >> (sw_ptype)\n"
> >>>  			"    Update a ptype mapping item on a port\n\n"
> >>>
> >>> +			"queue-region set port (port_id) region_id (value) "
> >>> +			"queue_start_index (value) queue_num (value)\n"
> >>> +			"    Set a queue region on a port\n\n"
> >>> +
> >>> +			"queue-region set (pf|vf) port (port_id) region_id
> >> (value) "
> >>> +			"flowtype (value)\n"
> >>> +			"    Set a flowtype region index on a port\n\n"
> >>> +
> >>> +			"queue-region set port (port_id) UP (value)
> >> region_id (value)\n"
> >>> +			"    Set the mapping of User Priority to "
> >>> +			"queue region on a port\n\n"
> >>> +
> >>> +			"queue-region flush (on|off) port (port_id)\n"
> >>> +			"    flush all queue region related configuration\n\n"
> >>
> >> I keep doing same comment but I will do it again...
> >>
> >> Each patch adding a new feature looking from its own context and
> >> adding a new root level command and this is making overall testpmd
> confusing.
> >>
> >> Since this is to set an option of the port, what do you think making
> >> this command part of existing commands, like:
> >> "port config #P queue-region ...."
> >> OR
> >> "set port #P queue-region ..." ?
> >
> > What you said is very meaningful, but other feature liake ptype mapping
> use the same mode  and so on.
> > maybe we should do a whole work to make CLI command style consistent.
> 
> Yes ptype does it, is seems it is one of the missed ones. Although we can do a
> whole work for CLI commands, meanwhile I think new ones can be added
> properly.
> 
> This may be good opportunity to remember broken window theory [1] :)


But  this type of CLI for queue region has been discussion when this feature skype meeting
We have do a ppt, which  review by DPDK-ENG-TECH-COMMITTEE, they have support and approve this type of command for this feature.
I think we should respect their review wok and decision  of other committee member.
AND also, The minority is subordinate to the majority, do you think so ?
I do not want do hold a second meeting later to  persuade them accept the new type of CLI command.
They may not also not change their idea too.


> 
> [1]
> https://blog.codinghorror.com/the-broken-window-theory/
> 
> <...>


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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-25  9:31           ` Ferruh Yigit
@ 2017-09-26  7:46             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-26  7:46 UTC (permalink / raw)
  To: Yigit, Ferruh; +Cc: dev


Hi,  Ferruh

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Monday, September 25, 2017 5:32 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> On 9/25/2017 8:40 AM, Zhao1, Wei wrote:
> > Hi, Ferruh
> >
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, September 20, 2017 6:36 PM
> >> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> >> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >>
> >> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> >> > This feature enable queue regions configuration for RSS in PF/VF,
> >> > so that different traffic classes or different packet
> >> > classification types can be separated to different queues in
> >> > different queue regions.This patch can set queue region range, it
> >> > include queue number in a region and the index of first queue.
> >>
> >> Is following correct:
> >> So instead of distributing packets to the multiple queues, this will
> > distribute
> >> packets into queue reqions which may consists of multiple queues.
> >>
> >> If so, is there a way to control how packets distributed within same
> >> queue region to multiple queues?
> >>
> >
> > distributed within same queue region is based on a rss algorithm, it
> > is implemented by NIC self, software can not control it.
> 
> I was thinking RSS used to select queue region, but no first queue region
> selected, later RSS used to select queue within the region.
> Thanks for clarification.

OK

> 
> <...>
> 
> > sizeof(vsi->info.tc_mapping));
> >> > +      (void)rte_memcpy(&vsi->info.queue_mapping,
> >> > +                                      &ctxt.info.queue_mapping,
> >> > +                      sizeof(vsi->info.queue_mapping));
> >>
> >> Please keep line allignment same with above line.
> >
> > oK, change in v4, but can not the same.
> > (void)rte_memcpy(&vsi->info.queue_mapping,
> &ctxt.info.queue_mapping,
> >
> > sizeof(vsi->info.queue_mapping));
> > will over 80 maxnumber.
> 
> Someting like following, new lines aligned:
> 
> 	(void)rte_memcpy(&vsi->info.queue_mapping,
> 		&ctxt.info.queue_mapping,
> 		sizeof(vsi->info.queue_mapping));


Ok, change in v4

> 
> <...>
> 
> >> > +                      if ((i == info->queue_region_number) &&
> >> > +                                      (i <=
> >> > +I40E_REGION_MAX_INDEX)) {
> >>
> >>
> >> Please use one more level indentaion here, and pharantesis looks
> >> extra can you please double check?
> >
> > You mean,you want the following moede ?
> >         if (i == info->queue_region_number) {
> >         	if(i <= I40E_REGION_MAX_INDEX) {
> > 			...........................
> >         	}
> >        }
> >
> 
> No, continuation of the "if" should be easy to recognized from body of the
> "if", something like:
> 
> 	if ((i == info->queue_region_number) &&
> 			(i <= I40E_REGION_MAX_INDEX)) {
> 		info->region[i].region_id = conf_ptr->region_id;
> 		info->region[i].queue_num = conf_ptr->queue_num;
> 
> <...>
> 

Ok, change in v4

> 
> >> > +static int
> >> > +i40e_set_region_flowtype_pf(struct i40e_hw *hw,
> >> > +                      struct i40e_pf *pf, struct
> > rte_i40e_rss_region_conf
> >> *conf_ptr)
> >>
> >> What do you think starting all functions, even they are static, with
> >> "i40e_queue_region_" prefix?
> >                                 ret = i40e_set_queue_region(pf,
> > conf_ptr);
> >                                 break;
> >                 case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> >                                 ret = i40e_set_region_flowtype_pf(hw,
> > pf, conf_ptr);
> >                                 break;
> >                 case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> >                                 ret = -EINVAL;
> >                                 break;
> >                 case RTE_PMD_I40E_UP_REGION_SET:
> >                                 ret = i40e_set_up_region(pf,
> > conf_ptr);
> >
> > I have use the format ofi40e_set_  as prefix?
> > Because many set is not related directly to queue region.
> 
> When looking to this patch what functions are doing is clear, but it also should
> be clear when looking the source code some time later what that function is
> about.
> 
> That is why I believe a namespace is useful, like "i40e_queue_region_xx", so
> you can immediately say this function is about "RSS queue region" feature.
> 
> This function is "rte_pmd_i40e_queue_region_conf", it is applying provided
> queue region configuration based of region op type, so I assumed all these
> functions are directly related to the fature.
> 
> If you believe function name will be wrong with that prefix, of course just
> don't use it, but please try to stick with a name space, that will make easy to
> understand these features in all source code.
> 
> <...>

Ok, fix in v4


> 
> 
> >> > +
> >> > +      memset(&hw->local_dcbx_config, 0,
> >> > +      sizeof(struct i40e_dcbx_config));
> >>
> >> Wrong indentation.
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> <...>
> 
> >> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> >> > +                                      struct
> > rte_i40e_rss_region_conf *conf_ptr) {
> >> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];
> >>
> >> you need to verify port_id, since this is public API now. Please
> >> check
> > other
> >> APIs in this file.
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> I mean is_i40e_supported() call that other APIs have.
> 
> <...>
> 
> >> > +
> >> > +      if (!is_i40e_supported(dev))
> >> > +                      return -ENOTSUP;
> >> > +
> >> > +      switch (op_type) {
> >> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:
> >> > +                      ret = i40e_set_queue_region(pf, conf_ptr);
> >> > +                      break;
> >>
> >> Does it make sense to add another type to get the current queue
> >> region config?
> 
> Reminder of this one incase missed.

I will add a get command.

> 
> >
> >> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_PF_SET:
> >> > +                      ret = i40e_set_region_flowtype_pf(hw, pf,
> > conf_ptr);
> >> > +                      break;
> >> > +      case RTE_PMD_I40E_REGION_FLOWTYPE_VF_SET:
> >> > +                      ret = -EINVAL;
> >>
> >> Will this be implemented later, or not a valid case at all?
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> >> > +                      break;
> >> > +      case RTE_PMD_I40E_UP_REGION_SET:> +
> > ret =
> >> i40e_set_up_region(pf, conf_ptr);
> >> > +                      break;
> >> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_ON:
> >> > +                      ret = i40e_flush_region_all_conf(hw, pf, 1);
> >> > +                      break;
> >> > +      case RTE_PMD_I40E_REGION_ALL_FLUSH_OFF:
> >> > +                      ret = i40e_flush_region_all_conf(hw, pf, 0);
> >>
> >> Can you please describe what flush_on and flush_off are, you can
> >> comment to code if also.
> 
> Reminder of this one incase missed.

I will comment to code in v4.
ALL config from CLI at first will only keep in DPDK software stored in driver, only after " FLUSH_ON ", it commit all configure to HW.
Because I have to set hardware config at a time, so I have to record all CLI command at first.
" FLUSH_OFF " is just clean all configuration about queue region  just now, and restore all to DPDK i40e driver default config when start up.
The following is my test process in CLI: 

./x86_64-native-linuxapp-gcc/app/testpmd -c 1ffff -n 4 -- -i --nb-cores=8  --rxq=8 --txq=8 --port-topology=chained set fwd rxonly port config all rss all queue-region set port 0 region_id 0 queue_start_index 2 queue_num 2 queue-region set port 0 region_id 1 queue_start_index 4 queue_num 2 
queue-region set pf port 0 region_id 0 flowtype 31 
queue-region set pf port 0 region_id 1 flowtype 33 
queue-region set pf port 0 region_id 1 flowtype 34 
queue-region set port 0 UP 1 region_id 0 
queue-region set port 0 UP 3 region_id 1 
queue-region flush on  port 0 
start set verbose 1 sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/Dot1Q(prio=3)/IP(src="10.0.0.1",dst="192.168.0.2")/TCP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10) sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/SCTP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10) sendp([Ether(dst="3C:FD:FE:9F:70:B8", src="52:00:00:00:00:00")/IP(src="10.0.0.1",dst="192.168.0.2")/UDP(dport=80, sport=80 )/("X"*48)], iface="ens5f2", count=10)

> 
> <...>
> 
> >> > @@ -146,6 +160,18 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >> >
> >> >  /**
> >> > + * Queue region information get from CLI.
> >>
> >> It doesn't need to be from CLI, can drop that part
> 
> Reminder of this one incase missed.
> 

Ok, change in v4

> <...>
> 
> >> > +      uint8_t user_priority;
> >> > +      enum rte_pmd_i40e_queue_region_op  op;
> >>
> >> Extra space before "op"
> >
> > Maybe, I SHOULD add uint8_t raw[3] before “op”
> 
> Sorry, I didn't get this one.

Ok

> 
> <...>
> 
> >> rte_pmd_i40e_ptype_mapping_replace(uint8_t
> >> > port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t
> >> >vf_id,
> >> >                                                           struct
> > ether_addr *mac_addr);
> >> >
> >> > +/**
> >> > + * Get RSS queue region info from CLI and do configuration for
> >>
> >> Again now this is an API, not just for testpmd, please drop CLI
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> >>
> >> > + * that port as the command otion type
> >>
> >> s/otion/options
> >>
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> <...>
> 
> >> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> >>
> >> Can you please use port_id as variable name to be consistent.
> 
> Reminder of this one incase missed.

Ok, change in v4

> 
> <...>

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-20 10:36       ` Ferruh Yigit
  2017-09-21  6:48         ` Zhao1, Wei
  2017-09-25  7:40         ` Zhao1, Wei
@ 2017-09-26  8:54         ` Zhao1, Wei
  2017-09-27 19:13           ` Ferruh Yigit
  2 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-26  8:54 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Hi,  Ferruh



> -----Original Message-----

> From: Yigit, Ferruh

> Sent: Wednesday, September 20, 2017 6:36 PM

> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org

> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush

>

> On 9/15/2017 4:13 AM, Wei Zhao wrote:

> > This feature enable queue regions configuration for RSS in PF/VF, so

> > that different traffic classes or different packet classification

> > types can be separated to different queues in different queue

> > regions.This patch can set queue region range, it include queue number

> > in a region and the index of first queue.

>

> Is following correct:

> So instead of distributing packets to the multiple queues, this will distribute

> packets into queue reqions which may consists of multiple queues.

>

> If so, is there a way to control how packets distributed within same queue

> region to multiple queues?

>

> And is this feature only supported with RSS? Can it be part of RSS

> configuration instead of PMD specific API?

>

> > This patch enable mapping between different priorities (UP) and

>

> User priorities (UP)

>

> > different traffic classes.It also enable mapping between a region

> > index and a sepcific flowtype(PCTYPE).It also provide the solution of

> > flush all configuration about queue region the above described.

> >

> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com<mailto:wei.zhao1@intel.com>>

> > ---

> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-

> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++

> >  drivers/net/i40e/rte_pmd_i40e.c           | 482

> ++++++++++++++++++++++++++++++

> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++

> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +

> >  5 files changed, 566 insertions(+), 4 deletions(-)

> >

>

> <...>

>

> > +static int

> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,

> > +                                            struct i40e_pf *pf)

> > +{

> > +      uint16_t i;

> > +      struct i40e_vsi *vsi = pf->main_vsi;

> > +      uint16_t queue_offset, bsf, tc_index;

> > +      struct i40e_vsi_context ctxt;

> > +      struct i40e_aqc_vsi_properties_data *vsi_info;

> > +      struct i40e_queue_region_info *region_info =

> > +                                                      &pf->queue_region;

> > +      uint32_t ret = -EINVAL;

> > +

> > +      if (!region_info->queue_region_number) {



....................



> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,

> > +                                      struct rte_i40e_rss_region_conf *conf_ptr) {

> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];

>

> you need to verify port_id, since this is public API now. Please check other

> APIs in this file.



I have already "if (!is_i40e_supported(dev))" code in v3 in function  rte_pmd_i40e_queue_region_conf.

So, I do not know what is your meaning.







>

> > +      struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-

> >dev_private);

> > +      struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-

> >dev_private);

> > +      enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;

> > +      uint32_t ret;

>

> This should be signed variable, since you are using it for return and assigning

> negative values.

>

> > +

> > +      if (!is_i40e_supported(dev))

> > +                      return -ENOTSUP;

> > +

> > +      switch (op_type) {

> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:

> > +                      ret = i40e_set_queue_region(pf, conf_ptr);

> > +                      break;

>



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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-26  8:54         ` Zhao1, Wei
@ 2017-09-27 19:13           ` Ferruh Yigit
  2017-09-28  2:40             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-09-27 19:13 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 9/26/2017 9:54 AM, Zhao1, Wei wrote:
> Hi,  Ferruh

Hi Wei,

>> -----Original Message-----
>> From: Yigit, Ferruh
>> Sent: Wednesday, September 20, 2017 6:36 PM
>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> flush
>>
>> On 9/15/2017 4:13 AM, Wei Zhao wrote:
>> > This feature enable queue regions configuration for RSS in PF/VF, so
>> > that different traffic classes or different packet classification
>> > types can be separated to different queues in different queue
>> > regions.This patch can set queue region range, it include queue number
>> > in a region and the index of first queue.
>>
>> Is following correct:
>> So instead of distributing packets to the multiple queues, this will
> distribute
>> packets into queue reqions which may consists of multiple queues.
>>
>> If so, is there a way to control how packets distributed within same queue
>> region to multiple queues?
>>
>> And is this feature only supported with RSS? Can it be part of RSS
>> configuration instead of PMD specific API?
>>
>> > This patch enable mapping between different priorities (UP) and
>>
>> User priorities (UP)
>>
>> > different traffic classes.It also enable mapping between a region
>> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
>> > flush all configuration about queue region the above described.
>> >
>> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com
> <mailto:wei.zhao1@intel.com>>
>> > ---
>> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
>> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
>> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
>> ++++++++++++++++++++++++++++++
>> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
>> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
>> >  5 files changed, 566 insertions(+), 4 deletions(-)
>> >
>>
>> <...>
>>
>> > +static int
>> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
>> > +                                            struct i40e_pf *pf)
>> > +{
>> > +      uint16_t i;
>> > +      struct i40e_vsi *vsi = pf->main_vsi;
>> > +      uint16_t queue_offset, bsf, tc_index;
>> > +      struct i40e_vsi_context ctxt;
>> > +      struct i40e_aqc_vsi_properties_data *vsi_info;
>> > +      struct i40e_queue_region_info *region_info =
>> > +                                                     
> &pf->queue_region;
>> > +      uint32_t ret = -EINVAL;
>> > +
>> > +      if (!region_info->queue_region_number) {
>  
> ....................
> 
>> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
>> > +                                      struct
> rte_i40e_rss_region_conf *conf_ptr) {
>> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];
>>
>> you need to verify port_id, since this is public API now. Please check
> other
>> APIs in this file.
> 
> I have already "if (!is_i40e_supported(dev))" code in v3 in function
>  rte_pmd_i40e_queue_region_conf.
> 
> So, I do not know what is your meaning.

RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);

Normally we don't need to worry about this in PMD because abstraction
layer APIs do this check already. But since this is public API, user can
give any value as port_id parameter, better to verify it.

> 
>>
>> > +      struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
>> >dev_private);
>> > +      struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
>> >dev_private);
>> > +      enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
>> > +      uint32_t ret;
>>
>> This should be signed variable, since you are using it for return and
> assigning
>> negative values.
>>
>> > +
>> > +      if (!is_i40e_supported(dev))
>> > +                      return -ENOTSUP;
>> > +
>> > +      switch (op_type) {
>> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:
>> > +                      ret = i40e_set_queue_region(pf, conf_ptr);
>> > +                      break;
>>

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

* Re: [PATCH v3 1/2] net/i40e: queue region set and flush
  2017-09-27 19:13           ` Ferruh Yigit
@ 2017-09-28  2:40             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-28  2:40 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Thank you.

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, September 28, 2017 3:13 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
> 
> On 9/26/2017 9:54 AM, Zhao1, Wei wrote:
> > Hi,  Ferruh
> 
> Hi Wei,
> 
> >> -----Original Message-----
> >> From: Yigit, Ferruh
> >> Sent: Wednesday, September 20, 2017 6:36 PM
> >> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> >> Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
> > flush
> >>
> >> On 9/15/2017 4:13 AM, Wei Zhao wrote:
> >> > This feature enable queue regions configuration for RSS in PF/VF,
> >> > so that different traffic classes or different packet
> >> > classification types can be separated to different queues in
> >> > different queue regions.This patch can set queue region range, it
> >> > include queue number in a region and the index of first queue.
> >>
> >> Is following correct:
> >> So instead of distributing packets to the multiple queues, this will
> > distribute
> >> packets into queue reqions which may consists of multiple queues.
> >>
> >> If so, is there a way to control how packets distributed within same
> >> queue region to multiple queues?
> >>
> >> And is this feature only supported with RSS? Can it be part of RSS
> >> configuration instead of PMD specific API?
> >>
> >> > This patch enable mapping between different priorities (UP) and
> >>
> >> User priorities (UP)
> >>
> >> > different traffic classes.It also enable mapping between a region
> >> > index and a sepcific flowtype(PCTYPE).It also provide the solution
> >> > of flush all configuration about queue region the above described.
> >> >
> >> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com
> > <mailto:wei.zhao1@intel.com>>
> >> > ---
> >> >  drivers/net/i40e/i40e_ethdev.c            |  19 +-
> >> >  drivers/net/i40e/i40e_ethdev.h            |  30 ++
> >> >  drivers/net/i40e/rte_pmd_i40e.c           | 482
> >> ++++++++++++++++++++++++++++++
> >> >  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
> >> >  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
> >> >  5 files changed, 566 insertions(+), 4 deletions(-)
> >> >
> >>
> >> <...>
> >>
> >> > +static int
> >> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> >> > +                                            struct i40e_pf *pf) {
> >> > +      uint16_t i;
> >> > +      struct i40e_vsi *vsi = pf->main_vsi;
> >> > +      uint16_t queue_offset, bsf, tc_index;
> >> > +      struct i40e_vsi_context ctxt;
> >> > +      struct i40e_aqc_vsi_properties_data *vsi_info;
> >> > +      struct i40e_queue_region_info *region_info =
> >> > +
> > &pf->queue_region;
> >> > +      uint32_t ret = -EINVAL;
> >> > +
> >> > +      if (!region_info->queue_region_number) {
> >
> > ....................
> >
> >> > +int rte_pmd_i40e_queue_region_conf(uint8_t port,
> >> > +                                      struct
> > rte_i40e_rss_region_conf *conf_ptr) {
> >> > +      struct rte_eth_dev *dev = &rte_eth_devices[port];
> >>
> >> you need to verify port_id, since this is public API now. Please
> >> check
> > other
> >> APIs in this file.
> >
> > I have already "if (!is_i40e_supported(dev))" code in v3 in function
> >  rte_pmd_i40e_queue_region_conf.
> >
> > So, I do not know what is your meaning.
> 
> RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
> 
> Normally we don't need to worry about this in PMD because abstraction
> layer APIs do this check already. But since this is public API, user can give any
> value as port_id parameter, better to verify it.
> 
> >
> >>
> >> > +      struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >> >dev_private);
> >> > +      struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >> >dev_private);
> >> > +      enum rte_pmd_i40e_queue_region_op op_type = conf_ptr->op;
> >> > +      uint32_t ret;
> >>
> >> This should be signed variable, since you are using it for return and
> > assigning
> >> negative values.
> >>
> >> > +
> >> > +      if (!is_i40e_supported(dev))
> >> > +                      return -ENOTSUP;
> >> > +
> >> > +      switch (op_type) {
> >> > +      case RTE_PMD_I40E_QUEUE_REGION_SET:
> >> > +                      ret = i40e_set_queue_region(pf, conf_ptr);
> >> > +                      break;
> >>

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

* [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-15  3:13     ` [PATCH v3 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-28  9:04     ` Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
                         ` (2 more replies)
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 3 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:04 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

 app/test-pmd/cmdline.c                      | 379 ++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  40 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 ++
 drivers/net/i40e/rte_pmd_i40e.c             | 536 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   1 +
 7 files changed, 1076 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [PATCH v4 1/3] net/i40e: queue region set and flush
  2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-28  9:04       ` Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:04 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 536 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 657 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 720f067..1a5b73e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1311,6 +1320,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+		/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -1466,6 +1478,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+		/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	return 0;
 }
 
@@ -10419,7 +10434,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..3d237cd 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +810,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1038,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index c08e07a..e475e78 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,538 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
+		for (i = 0; i < vsi->nb_qps; i++)
+			vsi_info->queue_mapping[i] =
+				rte_cpu_to_le_16(vsi->base_queue + i);
+	} else {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	}
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				(conf_ptr->queue_num <= 64))) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if ((i == info->queue_region_number) &&
+				(i <= I40E_REGION_MAX_INDEX)) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j, flowtype_set = 0;
+	uint16_t region_index, flowtype_index;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				flowtype_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (flowtype_set) {
+		PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+		return 0;
+	}
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index, user_priority_set = 0;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				user_priority_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (user_priority_set) {
+		PMD_DRV_LOG(ERR, "that user priority has been set before");
+		return 0;
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+	if (hw->mac.type == I40E_MAC_X722)
+		hena &= I40E_RSS_HENA_ALL_X722;
+	else
+		hena &= I40E_RSS_HENA_ALL;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_get_all_info(struct i40e_pf *pf, uint16_t port_id)
+{
+	uint16_t i, j;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		PMD_DRV_LOG(ERR, "there is no has been region set before");
+
+	printf("\n  %s All queue region info for port=%2d %s\n",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("  queue_region_number: %-14u \n", info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("  region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is  %-14u :",
+				info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n  flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+		printf("\n");
+	}
+
+	printf("\n\n");
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
+	int32_t ret;
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/**
+	 * This queue region feature only support pf by now.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		i40e_queue_region_get_all_info(pf, port_id);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..2806cc1 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/**< add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_i40e_rss_region_conf {
+	/**< the region id for this configuration */
+	uint8_t region_id;
+	/**< the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/**< the start queue index for this region */
+	uint8_t queue_start_index;
+	/**< the total queue number of this queue region */
+	uint8_t queue_num;
+	/**< the packet's user priority for this region */
+	uint8_t user_priority;
+	 /**< Option types of queue region */
+	enum rte_pmd_i40e_queue_region_op op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port
+ *    pointer id for that port device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		struct rte_i40e_rss_region_conf *rss_region_conf);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..29d6b74 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v4 2/3] app/testpmd: add API for configuration of queue region
  2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-28  9:04       ` Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:04 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4f2d731..fc2444f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"queue-region flush (on|off) port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"queue-region get port (port_id)\n"
+			"	 get all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8228,6 +8246,362 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush on|off port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_get_queue_region_info {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_get_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_get_queue_region_info *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config info get error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_get_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_get_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				get, "get");
+cmdline_parse_token_string_t cmd_get_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_get_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_get_queue_region_info,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_get_queue_region_info_all = {
+	.f = cmd_get_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "queue-region get port <port_id> "
+		": get all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_get_queue_region_info_cmd,
+		(void *)&cmd_get_queue_region_info_get,
+		(void *)&cmd_get_queue_region_info_port,
+		(void *)&cmd_get_queue_region_info_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14391,6 +14765,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_get_queue_region_info_all,
 	NULL,
 };
 
-- 
2.7.4

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

* [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for queue region
  2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
  2017-09-28  9:04       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-28  9:04       ` Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:04 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 40 +++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2ed62f5..f31ec5f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -842,6 +842,46 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> queue-region flush (on|off) port (port_id)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Get all queue region related configuration info on a port::
+
+   testpmd> queue-region get port (port_id)
+
+.. note::
+Queue region only support on PF by now, so thses command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS
  2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
                       ` (2 preceding siblings ...)
  2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-28  9:10     ` Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
                         ` (3 more replies)
  3 siblings, 4 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:10 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

 app/test-pmd/cmdline.c                      | 379 ++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  40 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 ++
 drivers/net/i40e/rte_pmd_i40e.c             | 536 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   1 +
 7 files changed, 1076 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [PATCH v4 1/3] net/i40e: queue region set and flush
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-28  9:10       ` Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:10 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 536 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 657 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 720f067..1a5b73e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1311,6 +1320,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+		/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -1466,6 +1478,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+		/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	return 0;
 }
 
@@ -10419,7 +10434,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..3d237cd 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +810,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1038,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index c08e07a..e475e78 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,538 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
+		for (i = 0; i < vsi->nb_qps; i++)
+			vsi_info->queue_mapping[i] =
+				rte_cpu_to_le_16(vsi->base_queue + i);
+	} else {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	}
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				(conf_ptr->queue_num <= 64))) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if ((i == info->queue_region_number) &&
+				(i <= I40E_REGION_MAX_INDEX)) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j, flowtype_set = 0;
+	uint16_t region_index, flowtype_index;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				flowtype_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (flowtype_set) {
+		PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+		return 0;
+	}
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index, user_priority_set = 0;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				user_priority_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (user_priority_set) {
+		PMD_DRV_LOG(ERR, "that user priority has been set before");
+		return 0;
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+	if (hw->mac.type == I40E_MAC_X722)
+		hena &= I40E_RSS_HENA_ALL_X722;
+	else
+		hena &= I40E_RSS_HENA_ALL;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_get_all_info(struct i40e_pf *pf, uint16_t port_id)
+{
+	uint16_t i, j;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		PMD_DRV_LOG(ERR, "there is no has been region set before");
+
+	printf("\n  %s All queue region info for port=%2d %s\n",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("  queue_region_number: %-14u \n", info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("  region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is  %-14u :",
+				info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n  flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+		printf("\n");
+	}
+
+	printf("\n\n");
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
+	int32_t ret;
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/**
+	 * This queue region feature only support pf by now.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		i40e_queue_region_get_all_info(pf, port_id);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..2806cc1 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/**< add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_i40e_rss_region_conf {
+	/**< the region id for this configuration */
+	uint8_t region_id;
+	/**< the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/**< the start queue index for this region */
+	uint8_t queue_start_index;
+	/**< the total queue number of this queue region */
+	uint8_t queue_num;
+	/**< the packet's user priority for this region */
+	uint8_t user_priority;
+	 /**< Option types of queue region */
+	enum rte_pmd_i40e_queue_region_op op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port
+ *    pointer id for that port device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		struct rte_i40e_rss_region_conf *rss_region_conf);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..29d6b74 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v4 2/3] app/testpmd: add API for configuration of queue region
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-28  9:10       ` Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:10 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4f2d731..fc2444f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"queue-region flush (on|off) port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"queue-region get port (port_id)\n"
+			"	 get all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8228,6 +8246,362 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush on|off port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_get_queue_region_info {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_get_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_get_queue_region_info *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config info get error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_get_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_get_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				get, "get");
+cmdline_parse_token_string_t cmd_get_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_get_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_get_queue_region_info,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_get_queue_region_info_all = {
+	.f = cmd_get_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "queue-region get port <port_id> "
+		": get all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_get_queue_region_info_cmd,
+		(void *)&cmd_get_queue_region_info_get,
+		(void *)&cmd_get_queue_region_info_port,
+		(void *)&cmd_get_queue_region_info_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14391,6 +14765,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_get_queue_region_info_all,
 	NULL,
 };
 
-- 
2.7.4

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

* [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for queue region
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
  2017-09-28  9:10       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-28  9:10       ` Wei Zhao
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-28  9:10 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 40 +++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2ed62f5..f31ec5f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -842,6 +842,46 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> queue-region flush (on|off) port (port_id)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Get all queue region related configuration info on a port::
+
+   testpmd> queue-region get port (port_id)
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS
  2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
                         ` (2 preceding siblings ...)
  2017-09-28  9:10       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
@ 2017-09-29  2:56       ` Wei Zhao
  2017-09-29  2:56         ` [PATCH v5 1/3] net/i40e: queue region set and flush Wei Zhao
                           ` (3 more replies)
  3 siblings, 4 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  2:56 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning
-add port id check

root (3):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region
  doc/testpmd_app_ug: add doc info for queue region

 app/test-pmd/cmdline.c                      | 379 ++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  40 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 ++
 drivers/net/i40e/rte_pmd_i40e.c             | 537 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   1 +
 7 files changed, 1077 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [PATCH v5 1/3] net/i40e: queue region set and flush
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-29  2:56         ` Wei Zhao
  2017-09-29  4:54           ` Wu, Jingjing
  2017-09-29  2:56         ` [PATCH v5 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  2:56 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 537 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 658 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 720f067..1a5b73e 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1311,6 +1320,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+		/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -1466,6 +1478,9 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
 	/* Remove all Traffic Manager configuration */
 	i40e_tm_conf_uninit(dev);
 
+		/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	return 0;
 }
 
@@ -10419,7 +10434,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..3d237cd 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +810,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1038,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index c08e07a..68be84b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,539 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	if (vsi->type == I40E_VSI_SRIOV) {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_NONCONTIG);
+		for (i = 0; i < vsi->nb_qps; i++)
+			vsi_info->queue_mapping[i] =
+				rte_cpu_to_le_16(vsi->base_queue + i);
+	} else {
+		vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+		vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	}
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				conf_ptr->queue_num <= 64)) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number &&
+				i <= I40E_REGION_MAX_INDEX) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j, flowtype_set = 0;
+	uint16_t region_index, flowtype_index;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				flowtype_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (flowtype_set) {
+		PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+		return 0;
+	}
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index, user_priority_set = 0;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id >= I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				user_priority_set = 1;
+				break;
+			}
+		}
+	}
+
+	if (user_priority_set) {
+		PMD_DRV_LOG(ERR, "that user priority has been set before");
+		return 0;
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+	if (hw->mac.type == I40E_MAC_X722)
+		hena &= I40E_RSS_HENA_ALL_X722;
+	else
+		hena &= I40E_RSS_HENA_ALL;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_get_all_info(struct i40e_pf *pf, uint16_t port_id)
+{
+	uint16_t i, j;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		PMD_DRV_LOG(ERR, "there is no has been region set before");
+
+	printf("\n  %s All queue region info for port=%2d %s",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("\n  queue_region_number: %-14u \n", info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("\n  region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is  %-14u :",
+				info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n  flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+	}
+
+	printf("\n\n");
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
+	int32_t ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/**
+	 * This queue region feature only support pf by now.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		i40e_queue_region_get_all_info(pf, port_id);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..2806cc1 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/**< add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_i40e_rss_region_conf {
+	/**< the region id for this configuration */
+	uint8_t region_id;
+	/**< the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/**< the start queue index for this region */
+	uint8_t queue_start_index;
+	/**< the total queue number of this queue region */
+	uint8_t queue_num;
+	/**< the packet's user priority for this region */
+	uint8_t user_priority;
+	 /**< Option types of queue region */
+	enum rte_pmd_i40e_queue_region_op op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port
+ *    pointer id for that port device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		struct rte_i40e_rss_region_conf *rss_region_conf);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..29d6b74 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v5 2/3] app/testpmd: add API for configuration of queue region
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  2:56         ` [PATCH v5 1/3] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29  2:56         ` Wei Zhao
  2017-09-29  5:04           ` Wu, Jingjing
  2017-09-29  2:56         ` [PATCH v5 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
  2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 1 reply; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  2:56 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 379 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4f2d731..fc2444f 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"queue-region set port (port_id) region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"queue-region set port (port_id) region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"queue-region set port (port_id) UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"queue-region flush (on|off) port (port_id)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"queue-region get port (port_id)\n"
+			"	 get all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8228,6 +8246,362 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region set port <port_id> UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "queue-region flush on|off port <port_id> "
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_get_queue_region_info {
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+};
+
+static void
+cmd_get_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_get_queue_region_info *res = parsed_result;
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+
+	if (ret < 0)
+		printf("queue region config info get error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_get_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_get_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				get, "get");
+cmdline_parse_token_string_t cmd_get_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_get_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_get_queue_region_info,
+				port_id, UINT8);
+
+cmdline_parse_inst_t cmd_get_queue_region_info_all = {
+	.f = cmd_get_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "queue-region get port <port_id> "
+		": get all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_get_queue_region_info_cmd,
+		(void *)&cmd_get_queue_region_info_get,
+		(void *)&cmd_get_queue_region_info_port,
+		(void *)&cmd_get_queue_region_info_port_index,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14391,6 +14765,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_get_queue_region_info_all,
 	NULL,
 };
 
-- 
2.7.4

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

* [PATCH v5 3/3] doc/testpmd_app_ug: add doc info for queue region
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  2:56         ` [PATCH v5 1/3] net/i40e: queue region set and flush Wei Zhao
  2017-09-29  2:56         ` [PATCH v5 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-29  2:56         ` Wei Zhao
  2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
  3 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  2:56 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 40 +++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2ed62f5..29b981f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -842,6 +842,46 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> queue-region set port (port_id) UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> queue-region flush (on|off) port (port_id)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Get all queue region related configuration info on a port::
+
+   testpmd> queue-region get port (port_id)
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* Re: [PATCH v5 1/3] net/i40e: queue region set and flush
  2017-09-29  2:56         ` [PATCH v5 1/3] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29  4:54           ` Wu, Jingjing
  2017-09-29  8:27             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-29  4:54 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei

> +static int
> +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> +			      struct i40e_pf *pf)
> +{
> +	uint16_t i;
> +	struct i40e_vsi *vsi = pf->main_vsi;
> +	uint16_t queue_offset, bsf, tc_index;
> +	struct i40e_vsi_context ctxt;
> +	struct i40e_aqc_vsi_properties_data *vsi_info;
> +	struct i40e_queue_region_info *region_info =
> +				&pf->queue_region;
> +	int32_t ret = -EINVAL;
> +
> +	if (!region_info->queue_region_number) {
> +		PMD_INIT_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> +
> +	/* Update Queue Pairs Mapping for currently enabled UPs */
> +	ctxt.seid = vsi->seid;
> +	ctxt.pf_num = hw->pf_id;
> +	ctxt.vf_num = 0;
> +	ctxt.uplink_seid = vsi->uplink_seid;
> +	ctxt.info = vsi->info;
> +	vsi_info = &ctxt.info;
> +
> +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> +
> +	/**
> +	 * Configure queue region and queue mapping parameters,
> +	 * for enabled queue region, allocate queues to this region.
> +	 */
> +
> +	for (i = 0; i < region_info->queue_region_number; i++) {
> +		tc_index = region_info->region[i].region_id;
> +		bsf = rte_bsf32(region_info->region[i].queue_num);
> +		queue_offset = region_info->region[i].queue_start_index;
> +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> +			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> +				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> +	}
> +
> +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
> +	if (vsi->type == I40E_VSI_SRIOV) {
You already assign the vsi to main_vsi in the beginning of the function, so
It is impossible here the type is SRIOV. I think I already commented it in your v3 patch set?
 
[......]
> +static int
> +i40e_queue_region_set_region(struct i40e_pf *pf,
> +				struct rte_i40e_rss_region_conf *conf_ptr)
> +{
> +	uint16_t i;
> +	struct i40e_vsi *main_vsi = pf->main_vsi;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	int32_t ret = -EINVAL;
> +
> +	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
> +				conf_ptr->queue_num <= 64)) {
> +		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1,
> 2, 4, 8, 16, 32, 64 as long as the "
> +			"total number of queues do not exceed the VSI allocation");
> +		return ret;
> +	}
> +
> +	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
> +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> +					> main_vsi->nb_used_qps) {
> +		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
> +		return ret;
> +	}
> +
You are using nb_used_qps for the comparison, is that to say the function
Is supposed to be called after dev_start?

> +	for (i = 0; i < info->queue_region_number; i++)
> +		if (conf_ptr->region_id == info->region[i].region_id)
> +			break;
> +
> +	if (i == info->queue_region_number &&
> +				i <= I40E_REGION_MAX_INDEX) {
> +		info->region[i].region_id = conf_ptr->region_id;
> +		info->region[i].queue_num = conf_ptr->queue_num;
> +		info->region[i].queue_start_index =
> +			conf_ptr->queue_start_index;
> +		info->queue_region_number++;
> +	} else {
> +		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue
> region id has been set before");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_set_flowtype(struct i40e_pf *pf,
> +			struct rte_i40e_rss_region_conf *rss_region_conf)
> +{
> +	int32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i, j, flowtype_set = 0;
> +	uint16_t region_index, flowtype_index;
> +
> +	/**
> +	 * For the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */
> +
Are you meeing the type of hw_flowtype in rss_region_conf
Is defined in i40e_type.h?

> +	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
> +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> +		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
> +		return ret;
> +	}
> +
> +
> +	for (i = 0; i < info->queue_region_number; i++)
> +		if (rss_region_conf->region_id == info->region[i].region_id)
> +			break;
> +
> +	if (i == info->queue_region_number) {
> +		PMD_DRV_LOG(ERR, "that region id has not been set before");
> +		ret = -ENODATA;
> +		return ret;
> +	}
> +	region_index = i;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].flowtype_num; j++) {
> +			if (rss_region_conf->hw_flowtype ==
> +				info->region[i].hw_flowtype[j]) {
> +				flowtype_set = 1;
> +				break;
You can just return here?

> +			}
> +		}
> +	}
> +

 [......]
> +static int
> +i40e_queue_region_set_user_priority(struct i40e_pf *pf,
> +		struct rte_i40e_rss_region_conf *rss_region_conf)
> +{
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	int32_t ret = -EINVAL;
> +	uint16_t i, j, region_index, user_priority_set = 0;
> +
> +	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
> +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> +		return ret;
> +	}
> +
> +	if (rss_region_conf->region_id >= I40E_REGION_MAX_INDEX) {
> +		PMD_DRV_LOG(ERR, "the region_id max index is 7");
> +		return ret;
> +	}
> +
> +	for (i = 0; i < info->queue_region_number; i++)
> +		if (rss_region_conf->region_id == info->region[i].region_id)
> +			break;
> +
> +	if (i == info->queue_region_number) {
> +		PMD_DRV_LOG(ERR, "that region id has not been set before");
> +		ret = -ENODATA;
> +		return ret;
> +	}
> +	region_index = i;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> +			if (info->region[i].user_priority[j] ==
> +				rss_region_conf->user_priority) {
> +				user_priority_set = 1;
The same, you can return here.
> +				break;

[......] 
> +
> +static int
> +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> +				struct i40e_pf *pf)
> +{
> +	struct i40e_dcbx_config dcb_cfg_local;
> +	struct i40e_dcbx_config *dcb_cfg;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> +	int32_t ret = -EINVAL;
> +	uint16_t i, j, prio_index, region_index;
> +	uint8_t tc_map, tc_bw, bw_lf;
> +
> +	if (!info->queue_region_number) {
> +		PMD_DRV_LOG(ERR, "there is no that region id been set before");
> +		return ret;
> +	}
> +
> +	dcb_cfg = &dcb_cfg_local;
> +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> +
> +	/* assume each tc has the same bw */
> +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> +	/* to ensure the sum of tcbw is equal to 100 */
> +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> +	for (i = 0; i < bw_lf; i++)
> +		dcb_cfg->etscfg.tcbwtable[i]++;
> +
> +	/* assume each tc has the same Transmission Selection Algorithm */
> +	for (i = 0; i < info->queue_region_number; i++)
> +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> +			prio_index = info->region[i].user_priority[j];
> +			region_index = info->region[i].region_id;
> +			dcb_cfg->etscfg.prioritytable[prio_index] =
> +						region_index;
> +		}
> +	}
> +
> +	/* FW needs one App to configure HW */
> +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> +
> +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> +
> +	dcb_cfg->pfc.willing = 0;
> +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> +	dcb_cfg->pfc.pfcenable = tc_map;
> +
> +	/* Copy the new config to the current config */
> +	*old_cfg = *dcb_cfg;
> +	old_cfg->etsrec = old_cfg->etscfg;
> +	ret = i40e_set_dcb_config(hw);
> +
> +	if (ret) {
> +		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
> +			 i40e_stat_str(hw, ret),
> +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
> +{
> +	int32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +
> +	if (on) {
> +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> +
> +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> +		if (ret != I40E_SUCCESS) {
> +			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
> +			return ret;
> +		}
> +
> +		ret = i40e_queue_region_dcb_configure(hw, pf);
> +		if (ret != I40E_SUCCESS) {
> +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> +			return ret;
> +		}
> +
> +		return 0;
> +	}
> +
> +	info->queue_region_number = 1;
> +	info->region[0].queue_num = 64;
> +	info->region[0].queue_start_index = 0;
> +
> +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> +	if (ret != I40E_SUCCESS)
> +		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
> +
> +	ret = i40e_dcb_init_configure(dev, TRUE);
> +	if (ret != I40E_SUCCESS) {
> +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> +		pf->flags &= ~I40E_FLAG_DCB;
> +	}
> +
> +	i40e_init_queue_region_conf(dev);
> +
> +	return 0;
> +}
> +
> +static int
> +i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
> +{
> +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> +	uint64_t hena;
> +
> +	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
> +	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
> +	if (hw->mac.type == I40E_MAC_X722)
> +		hena &= I40E_RSS_HENA_ALL_X722;
> +	else
> +		hena &= I40E_RSS_HENA_ALL;
> +
> +	if (!hena)
> +		return -ENOTSUP;
> +
Why made such change? Will it be impacted by kiril's pctype patches and beilei's new pctype patches?

> +	return 0;
> +}
> +
> +static void
> +i40e_queue_region_get_all_info(struct i40e_pf *pf, uint16_t port_id)
> +{
In this function, it looks like you print all the information about queue region?
If so, You can use "display" instead of "get".
In my opinion, generally, we are getting info but not display info in API level.

[......]
> +
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
> +	/**< add queue region user priority set */
If the comments is added before the definition, you need to use /** xxx */ instead of /**< XX */
for doxygen-likely format you can check http://www.dpdk.org/doc/guides/contributing/documentation.html#doxygen-guidelines

Thanks
Jingjing

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

* Re: [PATCH v5 2/3] app/testpmd: add API for configuration of queue region
  2017-09-29  2:56         ` [PATCH v5 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-29  5:04           ` Wu, Jingjing
  2017-09-29  5:21             ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-29  5:04 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei

General comments:

You need to wrap i40e private API by 
#ifdef RTE_LIBRTE_I40E_PMD
#endif

Otherwise it will cause compile error if I40E_PMD is not enable in config.

You can refer to other implementation like cmd_ptype_mapping_get_parsed.

Thanks
Jingjing

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

* Re: [PATCH v5 2/3] app/testpmd: add API for configuration of queue region
  2017-09-29  5:04           ` Wu, Jingjing
@ 2017-09-29  5:21             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-29  5:21 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Ok.

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Friday, September 29, 2017 1:05 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v5 2/3] app/testpmd: add API for
> configuration of queue region
> 
> General comments:
> 
> You need to wrap i40e private API by
> #ifdef RTE_LIBRTE_I40E_PMD
> #endif
> 
> Otherwise it will cause compile error if I40E_PMD is not enable in config.
> 
> You can refer to other implementation like
> cmd_ptype_mapping_get_parsed.
> 
> Thanks
> Jingjing

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

* [PATCH v6] net/i40e: API to configure queue regions for RSS
  2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
                           ` (2 preceding siblings ...)
  2017-09-29  2:56         ` [PATCH v5 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
@ 2017-09-29  8:11         ` Wei Zhao
  2017-09-29  8:11           ` [PATCH v6] app/testpmd: add API for configuration of queue region Wei Zhao
                             ` (2 more replies)
  3 siblings, 3 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  8:11 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

root (1):
  net/i40e: queue region set and flush

 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 520 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 641 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [PATCH v6] app/testpmd: add API for configuration of queue region
  2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-29  8:11           ` Wei Zhao
  2017-09-29  8:11           ` [PATCH v6] net/i40e: queue region set and flush Wei Zhao
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  8:11 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used. Aslo add a document for these new commands.
Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 2 files changed, 430 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4f2d731..da7dc24 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"set port (port_id) queue-region region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"set port (port_id) queue-region region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"set port (port_id) queue-region UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"flush port (port_id) queue-region (on|off)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"get port (port_id) queue-region\n"
+			"	 get all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct cmd_user_priority_region_result *res = parsed_result;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t what;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "flush port <port_id> queue-region on|off"
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_what,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_get_queue_region_info {
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+};
+
+static void
+cmd_get_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_get_queue_region_info *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config info get error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_get_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				get, "get");
+cmdline_parse_token_string_t cmd_get_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_get_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_get_queue_region_info,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_get_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				cmd, "queue-region");
+
+cmdline_parse_inst_t cmd_get_queue_region_info_all = {
+	.f = cmd_get_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "get port <port_id> queue-region"
+		": get all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_get_queue_region_info_get,
+		(void *)&cmd_get_queue_region_info_port,
+		(void *)&cmd_get_queue_region_info_port_index,
+		(void *)&cmd_get_queue_region_info_cmd,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14391,6 +14775,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_get_queue_region_info_all,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2ed62f5..2dffa8f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -842,6 +842,47 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) \
+		queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> flush port (port_id) queue-region (on|off)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Get all queue region related configuration info on a port::
+
+   testpmd> get port (port_id) queue-region
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* [PATCH v6] net/i40e: queue region set and flush
  2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  8:11           ` [PATCH v6] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-29  8:11           ` Wei Zhao
  2017-09-29  9:00             ` Wu, Jingjing
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2 siblings, 1 reply; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  8:11 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 520 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 641 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 720f067..9a67b6d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1311,6 +1320,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+		/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -2123,6 +2135,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* reset hierarchy commit */
 	pf->tm_conf.committed = false;
 
+	/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	hw->adapter_stopped = 1;
 }
 
@@ -10419,7 +10434,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..3d237cd 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +810,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1038,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index c08e07a..6991e86 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,522 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+	vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				conf_ptr->queue_num <= 64)) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number &&
+				i <= I40E_REGION_MAX_INDEX) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j;
+	uint16_t region_index, flowtype_index;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+				return 0;
+
+			}
+		}
+	}
+
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				PMD_DRV_LOG(ERR, "that user priority has been set before");
+				return 0;
+			}
+		}
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t port_id)
+{
+	uint16_t i, j;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		PMD_DRV_LOG(ERR, "there is no has been region set before");
+
+	printf("\n  %s All queue region info for port=%2d %s",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("\n  queue_region_number: %-14u \n", info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("\n  region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is  %-14u :",
+				info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n  flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+	}
+
+	printf("\n\n");
+	return 0;
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
+	int32_t ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/**
+	 * This queue region feature only support pf by now. It should
+	 * be called after dev_start, and will be clear after dev_stop.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		ret = i40e_queue_region_display_all_info(pf, port_id);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..04e326a 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/*** add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_i40e_rss_region_conf {
+	/**< the region id for this configuration */
+	uint8_t region_id;
+	/**< the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/**< the start queue index for this region */
+	uint8_t queue_start_index;
+	/**< the total queue number of this queue region */
+	uint8_t queue_num;
+	/**< the packet's user priority for this region */
+	uint8_t user_priority;
+	 /**< Option types of queue region */
+	enum rte_pmd_i40e_queue_region_op op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port
+ *    pointer id for that port device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		struct rte_i40e_rss_region_conf *rss_region_conf);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..29d6b74 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.7.4

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

* Re: [PATCH v5 1/3] net/i40e: queue region set and flush
  2017-09-29  4:54           ` Wu, Jingjing
@ 2017-09-29  8:27             ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-09-29  8:27 UTC (permalink / raw)
  To: Wu, Jingjing, dev

Hi, jingjing 
  All will be fix in v6

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Friday, September 29, 2017 12:55 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v5 1/3] net/i40e: queue region set and flush
> 
> > +static int
> > +i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
> > +			      struct i40e_pf *pf)
> > +{
> > +	uint16_t i;
> > +	struct i40e_vsi *vsi = pf->main_vsi;
> > +	uint16_t queue_offset, bsf, tc_index;
> > +	struct i40e_vsi_context ctxt;
> > +	struct i40e_aqc_vsi_properties_data *vsi_info;
> > +	struct i40e_queue_region_info *region_info =
> > +				&pf->queue_region;
> > +	int32_t ret = -EINVAL;
> > +
> > +	if (!region_info->queue_region_number) {
> > +		PMD_INIT_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
> > +
> > +	/* Update Queue Pairs Mapping for currently enabled UPs */
> > +	ctxt.seid = vsi->seid;
> > +	ctxt.pf_num = hw->pf_id;
> > +	ctxt.vf_num = 0;
> > +	ctxt.uplink_seid = vsi->uplink_seid;
> > +	ctxt.info = vsi->info;
> > +	vsi_info = &ctxt.info;
> > +
> > +	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
> > +	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
> > +
> > +	/**
> > +	 * Configure queue region and queue mapping parameters,
> > +	 * for enabled queue region, allocate queues to this region.
> > +	 */
> > +
> > +	for (i = 0; i < region_info->queue_region_number; i++) {
> > +		tc_index = region_info->region[i].region_id;
> > +		bsf = rte_bsf32(region_info->region[i].queue_num);
> > +		queue_offset = region_info->region[i].queue_start_index;
> > +		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
> > +			(queue_offset <<
> I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
> > +				(bsf <<
> I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
> > +	}
> > +
> > +	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged
> */
> > +	if (vsi->type == I40E_VSI_SRIOV) {
> You already assign the vsi to main_vsi in the beginning of the function, so It is
> impossible here the type is SRIOV. I think I already commented it in your v3
> patch set?
> 
> [......]
> > +static int
> > +i40e_queue_region_set_region(struct i40e_pf *pf,
> > +				struct rte_i40e_rss_region_conf *conf_ptr) {
> > +	uint16_t i;
> > +	struct i40e_vsi *main_vsi = pf->main_vsi;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	int32_t ret = -EINVAL;
> > +
> > +	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
> > +				conf_ptr->queue_num <= 64)) {
> > +		PMD_DRV_LOG(ERR, "The region sizes should be any of the
> following
> > +values: 1,
> > 2, 4, 8, 16, 32, 64 as long as the "
> > +			"total number of queues do not exceed the VSI
> allocation");
> > +		return ret;
> > +	}
> > +
> > +	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
> > +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
> > +					> main_vsi->nb_used_qps) {
> > +		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI
> range");
> > +		return ret;
> > +	}
> > +
> You are using nb_used_qps for the comparison, is that to say the function Is
> supposed to be called after dev_start?
> 
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		if (conf_ptr->region_id == info->region[i].region_id)
> > +			break;
> > +
> > +	if (i == info->queue_region_number &&
> > +				i <= I40E_REGION_MAX_INDEX) {
> > +		info->region[i].region_id = conf_ptr->region_id;
> > +		info->region[i].queue_num = conf_ptr->queue_num;
> > +		info->region[i].queue_start_index =
> > +			conf_ptr->queue_start_index;
> > +		info->queue_region_number++;
> > +	} else {
> > +		PMD_DRV_LOG(ERR, "queue region number exceeds
> maxnum 8 or the queue
> > region id has been set before");
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_set_flowtype(struct i40e_pf *pf,
> > +			struct rte_i40e_rss_region_conf *rss_region_conf) {
> > +	int32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j, flowtype_set = 0;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	/**
> > +	 * For the pctype or hardware flowtype of packet,
> > +	 * the specific index for each type has been defined
> > +	 * in file i40e_type.h as enum i40e_filter_pctype.
> > +	 */
> > +
> Are you meeing the type of hw_flowtype in rss_region_conf Is defined in
> i40e_type.h?
> 
> > +	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX)
> {
> > +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
> > +		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max
> index is 63");
> > +		return ret;
> > +	}
> > +
> > +
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		if (rss_region_conf->region_id == info->region[i].region_id)
> > +			break;
> > +
> > +	if (i == info->queue_region_number) {
> > +		PMD_DRV_LOG(ERR, "that region id has not been set
> before");
> > +		ret = -ENODATA;
> > +		return ret;
> > +	}
> > +	region_index = i;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].flowtype_num; j++) {
> > +			if (rss_region_conf->hw_flowtype ==
> > +				info->region[i].hw_flowtype[j]) {
> > +				flowtype_set = 1;
> > +				break;
> You can just return here?
> 
> > +			}
> > +		}
> > +	}
> > +
> 
>  [......]
> > +static int
> > +i40e_queue_region_set_user_priority(struct i40e_pf *pf,
> > +		struct rte_i40e_rss_region_conf *rss_region_conf) {
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	int32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index, user_priority_set = 0;
> > +
> > +	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
> > +		PMD_DRV_LOG(ERR, "the queue region max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	if (rss_region_conf->region_id >= I40E_REGION_MAX_INDEX) {
> > +		PMD_DRV_LOG(ERR, "the region_id max index is 7");
> > +		return ret;
> > +	}
> > +
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		if (rss_region_conf->region_id == info->region[i].region_id)
> > +			break;
> > +
> > +	if (i == info->queue_region_number) {
> > +		PMD_DRV_LOG(ERR, "that region id has not been set
> before");
> > +		ret = -ENODATA;
> > +		return ret;
> > +	}
> > +	region_index = i;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			if (info->region[i].user_priority[j] ==
> > +				rss_region_conf->user_priority) {
> > +				user_priority_set = 1;
> The same, you can return here.
> > +				break;
> 
> [......]
> > +
> > +static int
> > +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> > +				struct i40e_pf *pf)
> > +{
> > +	struct i40e_dcbx_config dcb_cfg_local;
> > +	struct i40e_dcbx_config *dcb_cfg;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> > +	int32_t ret = -EINVAL;
> > +	uint16_t i, j, prio_index, region_index;
> > +	uint8_t tc_map, tc_bw, bw_lf;
> > +
> > +	if (!info->queue_region_number) {
> > +		PMD_DRV_LOG(ERR, "there is no that region id been set
> before");
> > +		return ret;
> > +	}
> > +
> > +	dcb_cfg = &dcb_cfg_local;
> > +	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
> > +
> > +	/* assume each tc has the same bw */
> > +	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
> > +	/* to ensure the sum of tcbw is equal to 100 */
> > +	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
> > +	for (i = 0; i < bw_lf; i++)
> > +		dcb_cfg->etscfg.tcbwtable[i]++;
> > +
> > +	/* assume each tc has the same Transmission Selection Algorithm */
> > +	for (i = 0; i < info->queue_region_number; i++)
> > +		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		for (j = 0; j < info->region[i].user_priority_num; j++) {
> > +			prio_index = info->region[i].user_priority[j];
> > +			region_index = info->region[i].region_id;
> > +			dcb_cfg->etscfg.prioritytable[prio_index] =
> > +						region_index;
> > +		}
> > +	}
> > +
> > +	/* FW needs one App to configure HW */
> > +	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
> > +	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
> > +	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
> > +	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
> > +
> > +	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
> > +
> > +	dcb_cfg->pfc.willing = 0;
> > +	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
> > +	dcb_cfg->pfc.pfcenable = tc_map;
> > +
> > +	/* Copy the new config to the current config */
> > +	*old_cfg = *dcb_cfg;
> > +	old_cfg->etsrec = old_cfg->etscfg;
> > +	ret = i40e_set_dcb_config(hw);
> > +
> > +	if (ret) {
> > +		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed,
> err %s aq_err %s",
> > +			 i40e_stat_str(hw, ret),
> > +			 i40e_aq_str(hw, hw->aq.asq_last_status));
> > +		return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int
> > +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> > +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on) {
> > +	int32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> > +
> > +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		if (ret != I40E_SUCCESS) {
> > +			PMD_DRV_LOG(INFO, "Failed to flush queue region
> mapping.");
> > +			return ret;
> > +		}
> > +
> > +		ret = i40e_queue_region_dcb_configure(hw, pf);
> > +		if (ret != I40E_SUCCESS) {
> > +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > +			return ret;
> > +		}
> > +
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	if (ret != I40E_SUCCESS)
> > +		PMD_DRV_LOG(INFO, "Failed to flush queue region
> mapping.");
> > +
> > +	ret = i40e_dcb_init_configure(dev, TRUE);
> > +	if (ret != I40E_SUCCESS) {
> > +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > +		pf->flags &= ~I40E_FLAG_DCB;
> > +	}
> > +
> > +	i40e_init_queue_region_conf(dev);
> > +
> > +	return 0;
> > +}
> > +
> > +static int
> > +i40e_queue_region_pf_check_rss(struct i40e_pf *pf) {
> > +	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
> > +	uint64_t hena;
> > +
> > +	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
> > +	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) <<
> 32;
> > +	if (hw->mac.type == I40E_MAC_X722)
> > +		hena &= I40E_RSS_HENA_ALL_X722;
> > +	else
> > +		hena &= I40E_RSS_HENA_ALL;
> > +
> > +	if (!hena)
> > +		return -ENOTSUP;
> > +
> Why made such change? Will it be impacted by kiril's pctype patches and
> beilei's new pctype patches?
> 
> > +	return 0;
> > +}
> > +
> > +static void
> > +i40e_queue_region_get_all_info(struct i40e_pf *pf, uint16_t port_id)
> > +{
> In this function, it looks like you print all the information about queue region?
> If so, You can use "display" instead of "get".
> In my opinion, generally, we are getting info but not display info in API level.
> 
> [......]
> > +
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set
> */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region
> pctype set */
> > +	/**< add queue region user priority set */
> If the comments is added before the definition, you need to use /** xxx */
> instead of /**< XX */ for doxygen-likely format you can check
> http://www.dpdk.org/doc/guides/contributing/documentation.html#doxyg
> en-guidelines
> 
> Thanks
> Jingjing

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

* Re: [PATCH v6] net/i40e: queue region set and flush
  2017-09-29  8:11           ` [PATCH v6] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29  9:00             ` Wu, Jingjing
  0 siblings, 0 replies; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-29  9:00 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Friday, September 29, 2017 4:12 PM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: [dpdk-dev] [PATCH v6] net/i40e: queue region set and flush
> 
> This feature enable queue regions configuration for RSS in PF, so that different
> traffic classes or different packet classification types can be separated to
> different queues in different queue regions.This patch can set queue region
> range, it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and different
> traffic classes.It also enable mapping between a region index and a sepcific
> flowtype(PCTYPE).It also provide the solution of flush all configuration about
> queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  drivers/net/i40e/i40e_ethdev.c            |  27 +-
>  drivers/net/i40e/i40e_ethdev.h            |  39 +++
>  drivers/net/i40e/rte_pmd_i40e.c           | 520
> ++++++++++++++++++++++++++++++
>  drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
>  drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
>  5 files changed, 641 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
> index 720f067..9a67b6d 100644
> --- a/drivers/net/i40e/i40e_ethdev.c
> +++ b/drivers/net/i40e/i40e_ethdev.c
> @@ -137,10 +137,6 @@
>  #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
>  #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
> 
> -#define I40E_MAX_PERCENT            100
> -#define I40E_DEFAULT_DCB_APP_NUM    1
> -#define I40E_DEFAULT_DCB_APP_PRIO   3
> -
>  /**
>   * Below are values for writing un-exposed registers suggested
>   * by silicon experts
> @@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev
> *dev);  static int i40e_pf_setup(struct i40e_pf *pf);  static int
> i40e_dev_rxtx_init(struct i40e_pf *pf);  static int i40e_vmdq_setup(struct
> rte_eth_dev *dev); -static int i40e_dcb_init_configure(struct rte_eth_dev *dev,
> bool sw_dcb);  static int i40e_dcb_setup(struct rte_eth_dev *dev);  static void
> i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
>  		bool offset_loaded, uint64_t *offset, uint64_t *stat); @@ -
> 1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
>  	return ret;
>  }
> 
> +void
> +i40e_init_queue_region_conf(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);
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i;
> +
> +	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
> +		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
> +
> +	memset(info, 0, sizeof(struct i40e_queue_region_info)); }
> +
>  static int
>  eth_i40e_dev_init(struct rte_eth_dev *dev)  { @@ -1311,6 +1320,9 @@
> eth_i40e_dev_init(struct rte_eth_dev *dev)
>  	if (ret < 0)
>  		goto err_init_fdir_filter_list;
> 
> +		/* initialize queue region configuration */
Indent too much.

[......]
> +i40e_queue_region_dcb_configure(struct i40e_hw *hw,
> +				struct i40e_pf *pf)
> +{
> +	struct i40e_dcbx_config dcb_cfg_local;
> +	struct i40e_dcbx_config *dcb_cfg;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
> +	int32_t ret = -EINVAL;
> +	uint16_t i, j, prio_index, region_index;
> +	uint8_t tc_map, tc_bw, bw_lf;
> +
> +	if (!info->queue_region_number) {
> +		PMD_DRV_LOG(ERR, "there is no that region id been set
> before");

How about "No queue region has been set"?
[......]
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype
> set */
> +	/*** add queue region user priority set */
"***" -> "**"
> +	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
> +	/**
> +	 * ALL configuration about queue region from up layer
> +	 * at first will only keep in DPDK softwarestored in driver,
> +	 * only after " FLUSH_ON ", it commit all configuration to HW.
> +	 * Because PMD had to set hardware configuration at a time, so
> +	 * it will record all up layer command at first.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
> +	/**
> +	 * "FLUSH_OFF " is just clean all configuration about queue
> +	 * region just now, and restore all to DPDK i40e driver default
> +	 * config when start up.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> 
>  /**
> @@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {  };
> 
>  /**
> + * Queue region related information.
> + */
> +struct rte_i40e_rss_region_conf {
> +	/**< the region id for this configuration */
> +	uint8_t region_id;
> +	/**< the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */

Please change "/**<" to "/**", and please check all comments!!!

> +	uint8_t hw_flowtype;
> +	/**< the start queue index for this region */
> +	uint8_t queue_start_index;
> +	/**< the total queue number of this queue region */
> +	uint8_t queue_num;
> +	/**< the packet's user priority for this region */
> +	uint8_t user_priority;
> +	 /**< Option types of queue region */
> +	enum rte_pmd_i40e_queue_region_op op;
> +};
> +
Thanks
Jingjing

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

* [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS
  2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  8:11           ` [PATCH v6] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-09-29  8:11           ` [PATCH v6] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29  9:16           ` Wei Zhao
  2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
                               ` (4 more replies)
  2 siblings, 5 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  9:16 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

v7:
-change some PMD_DRV_LOG log.

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                      | 389 +++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c             | 520 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   1 +
 7 files changed, 1071 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [PATCH v7 1/2] net/i40e: queue region set and flush
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-09-29  9:16             ` Wei Zhao
  2017-09-29 12:22               ` Wu, Jingjing
  2017-10-03 17:54               ` Ferruh Yigit
  2017-09-29  9:16             ` [PATCH v7 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
                               ` (3 subsequent siblings)
  4 siblings, 2 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  9:16 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 520 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
 5 files changed, 641 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 720f067..03511f1 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -137,10 +137,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -309,7 +305,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1036,6 +1031,20 @@ i40e_init_fdir_filter_list(struct rte_eth_dev *dev)
 	return ret;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_region_info));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1311,6 +1320,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -2123,6 +2135,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* reset hierarchy commit */
 	pf->tm_conf.committed = false;
 
+	/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	hw->adapter_stopped = 1;
 }
 
@@ -10419,7 +10434,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index ad80f0f..3d237cd 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_region_info {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -776,6 +810,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_region_info queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1003,6 +1038,10 @@ void i40e_check_write_reg(struct i40e_hw *hw, uint32_t addr, uint32_t val);
 int i40e_tm_ops_get(struct rte_eth_dev *dev, void *ops);
 void i40e_tm_conf_init(struct rte_eth_dev *dev);
 void i40e_tm_conf_uninit(struct rte_eth_dev *dev);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index c08e07a..a8afb3b 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2161,3 +2162,522 @@ rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_region_info *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/**
+	 * Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+	vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	(void)rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_i40e_rss_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				conf_ptr->queue_num <= 64)) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number &&
+				i <= I40E_REGION_MAX_INDEX) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	uint16_t i, j;
+	uint16_t region_index, flowtype_index;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+				return 0;
+
+			}
+		}
+	}
+
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	/**
+	 * For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				PMD_DRV_LOG(ERR, "that user priority has been set before");
+				return 0;
+			}
+		}
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "No queue region been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t port_id)
+{
+	uint16_t i, j;
+	struct i40e_queue_region_info *info = &pf->queue_region;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		PMD_DRV_LOG(ERR, "there is no has been region set before");
+
+	printf("\n  %s All queue region info for port=%2d %s",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("\n  queue_region_number: %-14u \n", info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("\n  region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is  %-14u :",
+				info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n  flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+	}
+
+	printf("\n\n");
+	return 0;
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			struct rte_i40e_rss_region_conf *rss_region_conf)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
+	int32_t ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/**
+	 * This queue region feature only support pf by now. It should
+	 * be called after dev_start, and will be clear after dev_stop.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		ret = i40e_queue_region_display_all_info(pf, port_id);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 155b7e8..2219318 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/*** add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
 
 /**
@@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_i40e_rss_region_conf {
+	/*** the region id for this configuration */
+	uint8_t region_id;
+	/** the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/*** the start queue index for this region */
+	uint8_t queue_start_index;
+	/*** the total queue number of this queue region */
+	uint8_t queue_num;
+	/*** the packet's user priority for this region */
+	uint8_t user_priority;
+	 /*** Option types of queue region */
+	enum rte_pmd_i40e_queue_region_op op;
+};
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
 int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
 				 struct ether_addr *mac_addr);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port
+ *    pointer id for that port device
+ * @param conf_ptr
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		struct rte_i40e_rss_region_conf *rss_region_conf);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index ef8882b..29d6b74 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -50,5 +50,6 @@ DPDK_17.11 {
 	global:
 
 	rte_pmd_i40e_add_vf_mac_addr;
+	rte_pmd_i40e_rss_queue_region_conf;
 
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29  9:16             ` Wei Zhao
  2017-09-29 14:29               ` Wu, Jingjing
  2017-10-03 18:04               ` Ferruh Yigit
  2017-09-29 10:15             ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
                               ` (2 subsequent siblings)
  4 siblings, 2 replies; 87+ messages in thread
From: Wei Zhao @ 2017-09-29  9:16 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used. Aslo add a document for these new commands.
Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 2 files changed, 430 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 4f2d731..da7dc24 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"set port (port_id) queue-region region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"set port (port_id) queue-region region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"set port (port_id) queue-region UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"flush port (port_id) queue-region (on|off)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"get port (port_id) queue-region\n"
+			"	 get all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
 		NULL,
 	},
 };
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct rte_i40e_rss_region_conf region_conf;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct cmd_user_priority_region_result *res = parsed_result;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	region_conf.op = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t what;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "flush port <port_id> queue-region on|off"
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_what,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_get_queue_region_info {
+	cmdline_fixed_string_t get;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+};
+
+static void
+cmd_get_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_get_queue_region_info *res = parsed_result;
+	int ret = 0;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_i40e_rss_region_conf region_conf;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	region_conf.op = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config info get error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_get_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				get, "get");
+cmdline_parse_token_string_t cmd_get_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_get_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_get_queue_region_info,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_get_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_get_queue_region_info,
+				cmd, "queue-region");
+
+cmdline_parse_inst_t cmd_get_queue_region_info_all = {
+	.f = cmd_get_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "get port <port_id> queue-region"
+		": get all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_get_queue_region_info_get,
+		(void *)&cmd_get_queue_region_info_port,
+		(void *)&cmd_get_queue_region_info_port_index,
+		(void *)&cmd_get_queue_region_info_cmd,
+		NULL,
+	},
+};
 
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
@@ -14391,6 +14775,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_replace,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_ptype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_get_queue_region_info_all,
 	NULL,
 };
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 2ed62f5..2dffa8f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -842,6 +842,47 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) \
+		queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> flush port (port_id) queue-region (on|off)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Get all queue region related configuration info on a port::
+
+   testpmd> get port (port_id) queue-region
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* Re: [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-29  9:16             ` [PATCH v7 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-29 10:15             ` Peng, Yuan
  2017-10-11  8:49             ` [PATCH v8 " Wei Zhao
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  4 siblings, 0 replies; 87+ messages in thread
From: Peng, Yuan @ 2017-09-29 10:15 UTC (permalink / raw)
  To: Zhao1, Wei, dev

Tested-by: Peng Yuan <yuan.peng@intel.com>

- Tested Branch: dpdk-next-net/master
- Tested Commit: 9d660ac14ed6aa8688141b33fd6cd69fe3f0e5dd
- OS: 4.5.5-300.fc24.x86_64
- GCC: gcc (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2)
- CPU: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
- NIC: Intel Corporation Device Fortville [8086:1572]
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites:
- Total 3 cases, 3 passed, 0 failed

- Prerequisites command / instruction:
1. Hardware:
   Fortville

2. software:
   dpdk: http://dpdk.org/git/dpdk
   scapy: http://www.secdev.org/projects/scapy/

3. bind the port to dpdk driver::

    ./usertools/dpdk-devbind.py -b igb_uio 05:00.0

   the mac address of 05:00.0 is 00:00:00:00:01:00

4. start the testpmd::

    ./x86_64-native-linuxapp-gcc/app/testpmd -c 1ffff -n 4 -- -i --rxq=16 --txq=16
    testpmd> port config all rss all
    testpmd> set fwd rxonly
    testpmd> set verbose 1
    testpmd> start

- Cases:

Test case 1: different pctype packet can enter the expected queue region
========================================================================

1. Set queue region on a port::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 1 queue_num 1
    testpmd> set port 0 queue-region region_id 1 queue_start_index 3 queue_num 2
    testpmd> set port 0 queue-region region_id 2 queue_start_index 6 queue_num 2
    testpmd> set port 0 queue-region region_id 3 queue_start_index 8 queue_num 2
    testpmd> set port 0 queue-region region_id 4 queue_start_index 11 queue_num 4
    testpmd> set port 0 queue-region region_id 5 queue_start_index 15 queue_num 1

2. Set the mapping of flowtype to region index on a port::

    testpmd> set port 0 queue-region region_id 0 flowtype 31
    testpmd> set port 0 queue-region region_id 1 flowtype 32
    testpmd> set port 0 queue-region region_id 2 flowtype 33
    testpmd> set port 0 queue-region region_id 3 flowtype 34
    testpmd> set port 0 queue-region region_id 4 flowtype 35
    testpmd> set port 0 queue-region region_id 5 flowtype 45
    testpmd> set port 0 queue-region region_id 2 flowtype 41
    testpmd> flush port 0 queue-region on

3. send packet::

    pkt1 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=23,dport=24)/Raw('x'*20)
    pkt2 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=33,dport=34,flags="S")/Raw('x'*20)
    pkt3 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=33,dport=34,flags="PA")/Raw('x' * 20)
    pkt4 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=44,dport=45,tag=1)/SCTPChunkData(data="X" * 20)
    pkt5 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/Raw('x'*20)
    pkt6 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IPv6(src="2001::1", dst="2001::2")/Raw('x' * 20)
    pkt7 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IPv6(src="2001::1", dst="2001::2")/UDP(sport=24,dport=25)/Raw('x'*20)
    pkt8 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=1)/IP(src="192.168.0.1", dst="192.168.0.2")/Raw('x'*20)

   verify the pkt1 to queue 1, pkt2 to queue 3 or queue 4,
   pkt3 to queue 6 or queue 7, pkt4 to queue 8 or queue 9,
   pkt5 to queue 11 or 12 or 13 or 14,
   pkt6 to queue 15, pkt7 to queue 6 or queue 7,
   pkt8 enter the same queue with pkt5.

4. verified the rules can be listed and flushed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off

Notes: fortville can't parse the TCP SYN type packet, fortpark can parse it.
So if fortville, pkt2 to queue 6 or queue 7.

Test case 2: different user priority packet can enter the expected queue region
===============================================================================

1. Set queue region on a port::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 0 queue_num 1
    testpmd> set port 0 queue-region region_id 7 queue_start_index 1 queue_num 8
    testpmd> set port 0 queue-region region_id 2 queue_start_index 10 queue_num 4

2. Set the mapping of User Priority to Traffic Classes on a port::

    testpmd> set port 0 queue-region UP 3 region_id 0
    testpmd> set port 0 queue-region UP 1 region_id 7
    testpmd> set port 0 queue-region UP 2 region_id 2
    testpmd> set port 0 queue-region UP 7 region_id 2
    testpmd> flush port 0 queue-region on

3. send packet::

    pkt1=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=3)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt2=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=1)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt3=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=2)/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=32, dport=33)/Raw('x'*20)
    pkt4=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=7)/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=32, dport=33)/Raw('x'*20)
    pkt5=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=7)/IP(src="192.168.0.3", dst="192.168.0.4")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt6=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.3", dst="192.168.0.4")/UDP(sport=22, dport=23)/Raw('x'*20)

   verify the pkt1 to queue 0,
   pkt2 to queue 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8.
   pkt3 to queue 10 or 11 or 12 or 13.
   pkt4 enter the same queue with pkt3.
   pkt5 to queue 10 or 11 or 12 or 13.
   pkt6 enter different queue from pkt5.

4. verified the rules can be listed and flushed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off

Test case 3: boundary value testing
===================================

1. boundary value testing of "Set a queue region on a port"

   the following three rules are set successfully::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 0 queue_num 16
    testpmd> flush port 0 queue-region on
    testpmd> flush port 0 queue-region off
    testpmd> set port 0 queue-region region_id 0 queue_start_index 15 queue_num 1
    testpmd> flush port 0 queue-region on
    testpmd> flush port 0 queue-region off
    testpmd> set port 0 queue-region region_id 7 queue_start_index 2 queue_num 8
    testpmd> flush port 0 queue-region on

   all the three rules can be listed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off

   the following four rules can't be set successfully.::

    testpmd> set port 0 queue-region region_id 8 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 1 queue_start_index 16 queue_num 1
    testpmd> set port 0 queue-region region_id 2 queue_start_index 15 queue_num 2
    testpmd> set port 0 queue-region region_id 3 queue_start_index 2 queue_num 3

   no rules can be listed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off

2. boundary value testing of "Set the mapping of flowtype to region index
   on a port"::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 7 queue_start_index 4 queue_num 4

   the first two rules can be set successfully::

    testpmd> set port 0 queue-region region_id 0 flowtype 63
    testpmd> set port 0 queue-region region_id 7 flowtype 0

   the first two rules can be listed::

    testpmd> get port 0 queue-region

   the last two rule can't be set successfully::

    testpmd> set port 0 queue-region region_id 0 flowtype 64
    testpmd> set port 0 queue-region region_id 2 flowtype 34
    testpmd> flush port 0 queue-region on

   the last two rules can't be listed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off

3. boundary value testing of "Set the mapping of UP to region index
   on a port"::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 7 queue_start_index 4 queue_num 4

   the first two rules can be set successfully::

    testpmd> set port 0 queue-region UP 7 region_id 0
    testpmd> set port 0 queue-region UP 0 region_id 7

   the first two rules can be listed::

    testpmd> get port 0 queue-region

   the last two rule can't be set successfully::

    testpmd> set port 0 queue-region UP 8 region_id 0
    testpmd> set port 0 queue-region UP 1 region_id 2
    testpmd> flush port 0 queue-region on

   the last two rules can't be listed::

    testpmd> get port 0 queue-region
    testpmd> flush port 0 queue-region off


-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
Sent: Friday, September 29, 2017 5:16 PM
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

v7:
-change some PMD_DRV_LOG log.

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                      | 389 +++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c             | 520 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  60 ++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   1 +
 7 files changed, 1071 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* Re: [PATCH v7 1/2] net/i40e: queue region set and flush
  2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-09-29 12:22               ` Wu, Jingjing
  2017-10-10  1:45                 ` Zhao1, Wei
  2017-10-03 17:54               ` Ferruh Yigit
  1 sibling, 1 reply; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-29 12:22 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei


> +	/* update the local VSI info with updated queue map */
> +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> +					sizeof(vsi->info.tc_mapping));
> +	(void)rte_memcpy(&vsi->info.queue_mapping,
> +			&ctxt.info.queue_mapping,
> +			sizeof(vsi->info.queue_mapping));
(void) can be omitted.

[......]
> +static int
> +i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t port_id)
> +{
Not only the function name changes from "get info" to "display info". You may also
need to change the command name.

But, what I like is changing the keep the "get", but change the function
to return the a struct which contains the info, and user can call it. Otherwise it is
only used for show.

[.....]
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
> +	/*** add queue region user priority set */

I think you missed my comments in last mail. NOT "***" but "**", please read
http://www.dpdk.org/doc/guides/contributing/documentation.html#doxygen-guidelines

> +	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
> +	/**
> +	 * ALL configuration about queue region from up layer
> +	 * at first will only keep in DPDK softwarestored in driver,
> +	 * only after " FLUSH_ON ", it commit all configuration to HW.
> +	 * Because PMD had to set hardware configuration at a time, so
> +	 * it will record all up layer command at first.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
> +	/**
> +	 * "FLUSH_OFF " is just clean all configuration about queue
> +	 * region just now, and restore all to DPDK i40e driver default
> +	 * config when start up.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> 
>  /**
> @@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
> 
>  /**
> + * Queue region related information.
> + */
> +struct rte_i40e_rss_region_conf {
> +	/*** the region id for this configuration */



> +	uint8_t region_id;
> +	/** the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */
> +	uint8_t hw_flowtype;
> +	/*** the start queue index for this region */
> +	uint8_t queue_start_index;
> +	/*** the total queue number of this queue region */
> +	uint8_t queue_num;
> +	/*** the packet's user priority for this region */
> +	uint8_t user_priority;
> +	 /*** Option types of queue region */
> +	enum rte_pmd_i40e_queue_region_op op;

The same ***  ->  **

Thanks
Jingjing

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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-09-29  9:16             ` [PATCH v7 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-09-29 14:29               ` Wu, Jingjing
  2017-10-03 18:04               ` Ferruh Yigit
  1 sibling, 0 replies; 87+ messages in thread
From: Wu, Jingjing @ 2017-09-29 14:29 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei

> +static void
> +cmd_queue_region_parsed(void *parsed_result,
> +			__attribute__((unused)) struct cmdline *cl,
> +			__attribute__((unused)) void *data)
> +{
> +	struct cmd_queue_region_result *res = parsed_result;
> +	int ret = 0;
> +#ifdef RTE_LIBRTE_I40E_PMD
> +	struct rte_i40e_rss_region_conf region_conf;
> +
> +	memset(&region_conf, 0, sizeof(region_conf));
> +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> +	region_conf.region_id = res->region_id;
> +	region_conf.queue_num = res->queue_num_value;
> +	region_conf.queue_start_index = res->queue_id;
> +
> +	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
> +#endif
> +
> +	if (ret < 0)
> +		printf("queue region config programming error: (%s)\n",
> +				strerror(-ret));
> +}

If the RTE_LIBRTE_I40E_PMD is not built. The printf info would be incorrect.
And you need to check it the port id is valid or not.

Please check all new functions in this patch.

Thanks
Jingjing

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

* Re: [PATCH v7 1/2] net/i40e: queue region set and flush
  2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-09-29 12:22               ` Wu, Jingjing
@ 2017-10-03 17:54               ` Ferruh Yigit
  2017-10-10  6:11                 ` Zhao1, Wei
  1 sibling, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-10-03 17:54 UTC (permalink / raw)
  To: Wei Zhao, dev

On 9/29/2017 10:16 AM, Wei Zhao wrote:
> This feature enable queue regions configuration for RSS in PF,
> so that different traffic classes or different packet
> classification types can be separated to different queues in
> different queue regions.This patch can set queue region range,
> it include queue number in a region and the index of first queue.
> This patch enable mapping between different priorities (UP) and
> different traffic classes.It also enable mapping between a region
> index and a sepcific flowtype(PCTYPE).It also provide the solution
> of flush all configuration about queue region the above described.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---

<...>

> @@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
>  	struct rte_hash *hash_table;
>  };
>  
> +/* queue region info */
> +struct i40e_region_info {
> +	/* the region id for this configuration */
> +	uint8_t region_id;
> +	/* the start queue index for this region */
> +	uint8_t queue_start_index;
> +	/* the total queue number of this queue region */
> +	uint8_t queue_num;
> +	/* the total number of user priority for this region */
> +	uint8_t user_priority_num;
> +	/* the packet's user priority for this region */
> +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> +	/* the total number of flowtype for this region */
> +	uint8_t flowtype_num;
> +	/**
> +	 * the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */
> +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> +};
> +
> +struct i40e_queue_region_info {

What do you think renaming:
i40e_region_info -> i40e_queue_region_info
i40e_queue_region_info -> i40e_queue_regions

> +	/* the total number of queue region for this port */
> +	uint16_t queue_region_number;
> +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1];
> +};
> +
>  /* Tunnel filter number HW supports */
>  #define I40E_MAX_TUNNEL_FILTER_NUM 400
>  

<...>

> +static int
> +i40e_queue_region_set_flowtype(struct i40e_pf *pf,
> +			struct rte_i40e_rss_region_conf *rss_region_conf)
> +{
> +	int32_t ret = -EINVAL;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	uint16_t i, j;
> +	uint16_t region_index, flowtype_index;
> +
> +	/**

This is doxygen sytle comment, only nedeed for public headers.

> +	 * For the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */
> +
<...>

> +		}
> +	}
> +}

Missing line.

> +static int
> +i40e_queue_region_set_user_priority(struct i40e_pf *pf,
> +		struct rte_i40e_rss_region_conf *rss_region_conf)
> +{
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	int32_t ret = -EINVAL;
> +	uint16_t i, j, region_index;
> +
<...>

> +static int
> +i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t port_id)
> +{
> +	uint16_t i, j;
> +	struct i40e_queue_region_info *info = &pf->queue_region;
> +	static const char *queue_region_info_stats_border = "-------";
> +
> +	if (!info->queue_region_number)
> +		PMD_DRV_LOG(ERR, "there is no has been region set before");
> +
> +	printf("\n  %s All queue region info for port=%2d %s",
> +			queue_region_info_stats_border, port_id,
> +			queue_region_info_stats_border);

printf ? Please use driver logging functions.

> +	printf("\n  queue_region_number: %-14u \n", info->queue_region_number);
> +
> +	for (i = 0; i < info->queue_region_number; i++) {
> +		printf("\n  region_id: %-14u queue_number: %-14u "
> +			"queue_start_index: %-14u \n",
> +			info->region[i].region_id,
> +			info->region[i].queue_num,
> +			info->region[i].queue_start_index);
> +
> +		printf("  user_priority_num is  %-14u :",
> +				info->region[i].user_priority_num);
> +		for (j = 0; j < info->region[i].user_priority_num; j++)
> +			printf(" %-14u ", info->region[i].user_priority[j]);
> +
> +		printf("\n  flowtype_num is  %-14u :",
> +				info->region[i].flowtype_num);
> +		for (j = 0; j < info->region[i].flowtype_num; j++)
> +			printf(" %-14u ", info->region[i].hw_flowtype[j]);
> +	}
> +
> +	printf("\n\n");
> +	return 0;
> +}
> +
> +int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
> +			struct rte_i40e_rss_region_conf *rss_region_conf)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
> +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
> +	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf->op;
> +	int32_t ret;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +
> +	if (!is_i40e_supported(dev))
> +		return -ENOTSUP;
> +
> +	if (!(!i40e_queue_region_pf_check_rss(pf)))
> +		return -ENOTSUP;
> +
> +	/**
> +	 * This queue region feature only support pf by now. It should
> +	 * be called after dev_start, and will be clear after dev_stop.
> +	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
> +	 * is just an enable function which server for other configuration,
> +	 * it is for all configuration about queue region from up layer,
> +	 * at first will only keep in DPDK softwarestored in driver,
> +	 * only after "FLUSH_ON", it commit all configuration to HW.
> +	 * Because PMD had to set hardware configuration at a time, so
> +	 * it will record all up layer command at first.
> +	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
> +	 * just clean all configuration about queue region just now,
> +	 * and restore all to DPDK i40e driver default
> +	 * config when start up.
> +	 */
> +
> +	switch (op_type) {
> +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> +		ret = i40e_queue_region_set_region(pf, rss_region_conf);
> +		break;
> +	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
> +		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
> +		break;
> +	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
> +		ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
> +		break;
> +	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
> +		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
> +		break;
> +	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
> +		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
> +		break;
> +	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
> +		ret = i40e_queue_region_display_all_info(pf, port_id);

Displaying is not always very useful in API level.
What do you think get fills the rss_region_conf with current device
settings and return back to the caller?

> +		break;
> +	default:
> +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> +			    op_type);
> +		ret = -EINVAL;
> +	}
> +
> +	I40E_WRITE_FLUSH(hw);
> +
> +	return ret;
> +}
> diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
> index 155b7e8..2219318 100644
> --- a/drivers/net/i40e/rte_pmd_i40e.h
> +++ b/drivers/net/i40e/rte_pmd_i40e.h
> @@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
>  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
>  };
>  
> +/**
> + *  Option types of queue region.
> + */
> +enum rte_pmd_i40e_queue_region_op {
> +	RTE_PMD_I40E_REGION_UNDEFINED,
> +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
> +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
> +	/*** add queue region user priority set */
> +	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
> +	/**
> +	 * ALL configuration about queue region from up layer
> +	 * at first will only keep in DPDK softwarestored in driver,
> +	 * only after " FLUSH_ON ", it commit all configuration to HW.
> +	 * Because PMD had to set hardware configuration at a time, so
> +	 * it will record all up layer command at first.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
> +	/**
> +	 * "FLUSH_OFF " is just clean all configuration about queue
> +	 * region just now, and restore all to DPDK i40e driver default
> +	 * config when start up.
> +	 */
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
> +	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
> +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX

These are in public header now.
Can you please use same namespace for all ops.
It can be "RTE_PMD_I40E_RSS_QUEUE_REGION_"

> +};
> +
>  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
>  
>  /**
> @@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {
>  };
>  
>  /**
> + * Queue region related information.
> + */
> +struct rte_i40e_rss_region_conf {

Can you please be consistant in using public names.
There are:
rss_region
queue_region
rss_queue_region

Also there is confusion between using:
rte_i40e_
rte_pmd_i40e_

> +	/*** the region id for this configuration */
> +	uint8_t region_id;
> +	/** the pctype or hardware flowtype of packet,
> +	 * the specific index for each type has been defined
> +	 * in file i40e_type.h as enum i40e_filter_pctype.
> +	 */
> +	uint8_t hw_flowtype;
> +	/*** the start queue index for this region */
> +	uint8_t queue_start_index;
> +	/*** the total queue number of this queue region */
> +	uint8_t queue_num;
> +	/*** the packet's user priority for this region */
> +	uint8_t user_priority;
> +	 /*** Option types of queue region */
> +	enum rte_pmd_i40e_queue_region_op op;
> +};
> +
> +/**
>   * Notify VF when PF link status changes.
>   *
>   * @param port
> @@ -657,4 +705,16 @@ int rte_pmd_i40e_ptype_mapping_replace(uint8_t port,
>  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
>  				 struct ether_addr *mac_addr);
>  
> +/**
> + * Do RSS queue region configuration for that port as
> + * the command option type
> + *
> + * @param port
> + *    pointer id for that port device

port id ?

> + * @param conf_ptr
> + *    pointer to the struct that contain all the
> + *    region configuration parameters
> + */
> +int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,

By defining port_id uint16_t, this patches becomes dependent to the
port_id update patchset, please clarify this in cover letter.

> +		struct rte_i40e_rss_region_conf *rss_region_conf);
>  #endif /* _PMD_I40E_H_ */
> diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
> index ef8882b..29d6b74 100644
> --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> @@ -50,5 +50,6 @@ DPDK_17.11 {
>  	global:
>  
>  	rte_pmd_i40e_add_vf_mac_addr;
> +	rte_pmd_i40e_rss_queue_region_conf;
>  
>  } DPDK_17.08;
> 

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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-09-29  9:16             ` [PATCH v7 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-09-29 14:29               ` Wu, Jingjing
@ 2017-10-03 18:04               ` Ferruh Yigit
  2017-10-10  1:46                 ` Zhao1, Wei
                                   ` (2 more replies)
  1 sibling, 3 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-10-03 18:04 UTC (permalink / raw)
  To: Wei Zhao, dev

On 9/29/2017 10:16 AM, Wei Zhao wrote:
> This patch add a API configuration of queue region in rss.
> It can parse the parameters of region index, queue number,
> queue start index, user priority, traffic classes and so on.
> According to commands from command line, it will call i40e
> private API and start the process of set or flush queue region
> configure. As this feature is specific for i40e, so private API
> will be used. Aslo add a document for these new commands.
> Queue region only support PF by now, so this document is
> only for configuration of queue region on PF port.
> 
> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> ---
>  app/test-pmd/cmdline.c                      | 389 ++++++++++++++++++++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
>  2 files changed, 430 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 4f2d731..da7dc24 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void *parsed_result,
>  			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
>  			"    Update a ptype mapping item on a port\n\n"
>  
> +			"set port (port_id) queue-region region_id (value) "
> +			"queue_start_index (value) queue_num (value)\n"
> +			"    Set a queue region on a port\n\n"
> +
> +			"set port (port_id) queue-region region_id (value) "
> +			"flowtype (value)\n"
> +			"    Set a flowtype region index on a port\n\n"
> +
> +			"set port (port_id) queue-region UP (value) region_id (value)\n"
> +			"    Set the mapping of User Priority to "
> +			"queue region on a port\n\n"
> +
> +			"flush port (port_id) queue-region (on|off)\n"
> +			"    flush all queue region related configuration\n\n"
> +
> +			"get port (port_id) queue-region\n"
> +			"	 get all queue region related configuration info\n\n"
> +

You did same thing and created "flush" and "get" root level commands
this time.

For get, existing "show port #P .." can be used:
"show port #P queue-region"

For flush, what do you think:
"set port #P queue-region flush (on|off)" ?

>  			, list_pkt_forwarding_modes()
>  		);
>  	}
> @@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
>  		NULL,
>  	},
>  };
> +/* *** queue region set *** */
> +struct cmd_queue_region_result {
> +	cmdline_fixed_string_t set;
> +	cmdline_fixed_string_t port;
> +	uint8_t  port_id;
> +	cmdline_fixed_string_t cmd;
> +	cmdline_fixed_string_t region;
> +	uint8_t  region_id;
> +	cmdline_fixed_string_t queue_start_index;
> +	uint8_t  queue_id;
> +	cmdline_fixed_string_t queue_num;
> +	uint8_t  queue_num_value;
> +};
> +
> +static void
> +cmd_queue_region_parsed(void *parsed_result,
> +			__attribute__((unused)) struct cmdline *cl,
> +			__attribute__((unused)) void *data)
> +{
> +	struct cmd_queue_region_result *res = parsed_result;
> +	int ret = 0;

For port_id other than i40e, this call should return "Not supported",
not success. There are samples to this usage can you please check them?

> +#ifdef RTE_LIBRTE_I40E_PMD
> +	struct rte_i40e_rss_region_conf region_conf;
> +
> +	memset(&region_conf, 0, sizeof(region_conf));
> +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> +	region_conf.region_id = res->region_id;
> +	region_conf.queue_num = res->queue_num_value;
> +	region_conf.queue_start_index = res->queue_id;
> +
> +	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id, &region_conf);
> +#endif
> +
> +	if (ret < 0)
> +		printf("queue region config programming error: (%s)\n",
> +				strerror(-ret));
> +}

<...>

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

* Re: [PATCH v7 1/2] net/i40e: queue region set and flush
  2017-09-29 12:22               ` Wu, Jingjing
@ 2017-10-10  1:45                 ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-10  1:45 UTC (permalink / raw)
  To: Wu, Jingjing, dev

HI, jingjing

    I will rework code as your comments in v8.

> -----Original Message-----
> From: Wu, Jingjing
> Sent: Friday, September 29, 2017 8:23 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v7 1/2] net/i40e: queue region set and flush
> 
> 
> > +	/* update the local VSI info with updated queue map */
> > +	(void)rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
> > +					sizeof(vsi->info.tc_mapping));
> > +	(void)rte_memcpy(&vsi->info.queue_mapping,
> > +			&ctxt.info.queue_mapping,
> > +			sizeof(vsi->info.queue_mapping));
> (void) can be omitted.
> 
> [......]
> > +static int
> > +i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t
> > +port_id) {
> Not only the function name changes from "get info" to "display info". You
> may also need to change the command name.
> 
> But, what I like is changing the keep the "get", but change the function to
> return the a struct which contains the info, and user can call it. Otherwise it is
> only used for show.
> 
> [.....]
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set
> */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region
> pctype set */
> > +	/*** add queue region user priority set */
> 
> I think you missed my comments in last mail. NOT "***" but "**", please
> read
> http://www.dpdk.org/doc/guides/contributing/documentation.html#doxyg
> en-guidelines
> 
> > +	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
> > +	/**
> > +	 * ALL configuration about queue region from up layer
> > +	 * at first will only keep in DPDK softwarestored in driver,
> > +	 * only after " FLUSH_ON ", it commit all configuration to HW.
> > +	 * Because PMD had to set hardware configuration at a time, so
> > +	 * it will record all up layer command at first.
> > +	 */
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
> > +	/**
> > +	 * "FLUSH_OFF " is just clean all configuration about queue
> > +	 * region just now, and restore all to DPDK i40e driver default
> > +	 * config when start up.
> > +	 */
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region related information.
> > + */
> > +struct rte_i40e_rss_region_conf {
> > +	/*** the region id for this configuration */
> 
> 
> 
> > +	uint8_t region_id;
> > +	/** the pctype or hardware flowtype of packet,
> > +	 * the specific index for each type has been defined
> > +	 * in file i40e_type.h as enum i40e_filter_pctype.
> > +	 */
> > +	uint8_t hw_flowtype;
> > +	/*** the start queue index for this region */
> > +	uint8_t queue_start_index;
> > +	/*** the total queue number of this queue region */
> > +	uint8_t queue_num;
> > +	/*** the packet's user priority for this region */
> > +	uint8_t user_priority;
> > +	 /*** Option types of queue region */
> > +	enum rte_pmd_i40e_queue_region_op op;
> 
> The same ***  ->  **
> 
> Thanks
> Jingjing

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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-10-03 18:04               ` Ferruh Yigit
@ 2017-10-10  1:46                 ` Zhao1, Wei
  2017-10-10  2:55                 ` Zhao1, Wei
  2017-10-10  3:01                 ` Zhao1, Wei
  2 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-10  1:46 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

HI, Ferruh

    I will rework code as your comments in v8.

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, October 4, 2017 2:04 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
> configuration of queue region
> 
> On 9/29/2017 10:16 AM, Wei Zhao wrote:
> > This patch add a API configuration of queue region in rss.
> > It can parse the parameters of region index, queue number, queue start
> > index, user priority, traffic classes and so on.
> > According to commands from command line, it will call i40e private API
> > and start the process of set or flush queue region configure. As this
> > feature is specific for i40e, so private API will be used. Aslo add a
> > document for these new commands.
> > Queue region only support PF by now, so this document is only for
> > configuration of queue region on PF port.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  app/test-pmd/cmdline.c                      | 389
> ++++++++++++++++++++++++++++
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
> >  2 files changed, 430 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 4f2d731..da7dc24 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> >  			"ptype mapping update (port_id) (hw_ptype)
> (sw_ptype)\n"
> >  			"    Update a ptype mapping item on a port\n\n"
> >
> > +			"set port (port_id) queue-region region_id (value) "
> > +			"queue_start_index (value) queue_num (value)\n"
> > +			"    Set a queue region on a port\n\n"
> > +
> > +			"set port (port_id) queue-region region_id (value) "
> > +			"flowtype (value)\n"
> > +			"    Set a flowtype region index on a port\n\n"
> > +
> > +			"set port (port_id) queue-region UP (value)
> region_id (value)\n"
> > +			"    Set the mapping of User Priority to "
> > +			"queue region on a port\n\n"
> > +
> > +			"flush port (port_id) queue-region (on|off)\n"
> > +			"    flush all queue region related configuration\n\n"
> > +
> > +			"get port (port_id) queue-region\n"
> > +			"	 get all queue region related configuration
> info\n\n"
> > +
> 
> You did same thing and created "flush" and "get" root level commands this
> time.
> 
> For get, existing "show port #P .." can be used:
> "show port #P queue-region"
> 
> For flush, what do you think:
> "set port #P queue-region flush (on|off)" ?
> 
> >  			, list_pkt_forwarding_modes()
> >  		);
> >  	}
> > @@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
> >  		NULL,
> >  	},
> >  };
> > +/* *** queue region set *** */
> > +struct cmd_queue_region_result {
> > +	cmdline_fixed_string_t set;
> > +	cmdline_fixed_string_t port;
> > +	uint8_t  port_id;
> > +	cmdline_fixed_string_t cmd;
> > +	cmdline_fixed_string_t region;
> > +	uint8_t  region_id;
> > +	cmdline_fixed_string_t queue_start_index;
> > +	uint8_t  queue_id;
> > +	cmdline_fixed_string_t queue_num;
> > +	uint8_t  queue_num_value;
> > +};
> > +
> > +static void
> > +cmd_queue_region_parsed(void *parsed_result,
> > +			__attribute__((unused)) struct cmdline *cl,
> > +			__attribute__((unused)) void *data) {
> > +	struct cmd_queue_region_result *res = parsed_result;
> > +	int ret = 0;
> 
> For port_id other than i40e, this call should return "Not supported", not
> success. There are samples to this usage can you please check them?
> 
> > +#ifdef RTE_LIBRTE_I40E_PMD
> > +	struct rte_i40e_rss_region_conf region_conf;
> > +
> > +	memset(&region_conf, 0, sizeof(region_conf));
> > +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> > +	region_conf.region_id = res->region_id;
> > +	region_conf.queue_num = res->queue_num_value;
> > +	region_conf.queue_start_index = res->queue_id;
> > +
> > +	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
> > +&region_conf); #endif
> > +
> > +	if (ret < 0)
> > +		printf("queue region config programming error: (%s)\n",
> > +				strerror(-ret));
> > +}
> 
> <...>


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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-10-03 18:04               ` Ferruh Yigit
  2017-10-10  1:46                 ` Zhao1, Wei
@ 2017-10-10  2:55                 ` Zhao1, Wei
  2017-10-10  3:01                 ` Zhao1, Wei
  2 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-10  2:55 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Hi, 

> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, October 4, 2017 2:04 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
> configuration of queue region
> 
> On 9/29/2017 10:16 AM, Wei Zhao wrote:
> > This patch add a API configuration of queue region in rss.
> > It can parse the parameters of region index, queue number, queue start
> > index, user priority, traffic classes and so on.
> > According to commands from command line, it will call i40e private API
> > and start the process of set or flush queue region configure. As this
> > feature is specific for i40e, so private API will be used. Aslo add a
> > document for these new commands.
> > Queue region only support PF by now, so this document is only for
> > configuration of queue region on PF port.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> >  app/test-pmd/cmdline.c                      | 389
> ++++++++++++++++++++++++++++
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
> >  2 files changed, 430 insertions(+)
> >
> > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > 4f2d731..da7dc24 100644
> > --- a/app/test-pmd/cmdline.c
> > +++ b/app/test-pmd/cmdline.c
> > @@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void
> *parsed_result,
> >  			"ptype mapping update (port_id) (hw_ptype)
> (sw_ptype)\n"
> >  			"    Update a ptype mapping item on a port\n\n"
> >
> > +			"set port (port_id) queue-region region_id (value) "
> > +			"queue_start_index (value) queue_num (value)\n"
> > +			"    Set a queue region on a port\n\n"
> > +
> > +			"set port (port_id) queue-region region_id (value) "
> > +			"flowtype (value)\n"
> > +			"    Set a flowtype region index on a port\n\n"
> > +
> > +			"set port (port_id) queue-region UP (value)
> region_id (value)\n"
> > +			"    Set the mapping of User Priority to "
> > +			"queue region on a port\n\n"
> > +
> > +			"flush port (port_id) queue-region (on|off)\n"
> > +			"    flush all queue region related configuration\n\n"
> > +
> > +			"get port (port_id) queue-region\n"
> > +			"	 get all queue region related configuration
> info\n\n"
> > +
> 
> You did same thing and created "flush" and "get" root level commands this
> time.
> 
> For get, existing "show port #P .." can be used:
> "show port #P queue-region"
> 
> For flush, what do you think:
> "set port #P queue-region flush (on|off)" ?

Ok.

> 
> >  			, list_pkt_forwarding_modes()
> >  		);
> >  	}
> > @@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
> >  		NULL,
> >  	},
> >  };
> > +/* *** queue region set *** */
> > +struct cmd_queue_region_result {
> > +	cmdline_fixed_string_t set;
> > +	cmdline_fixed_string_t port;
> > +	uint8_t  port_id;
> > +	cmdline_fixed_string_t cmd;
> > +	cmdline_fixed_string_t region;
> > +	uint8_t  region_id;
> > +	cmdline_fixed_string_t queue_start_index;
> > +	uint8_t  queue_id;
> > +	cmdline_fixed_string_t queue_num;
> > +	uint8_t  queue_num_value;
> > +};
> > +
> > +static void
> > +cmd_queue_region_parsed(void *parsed_result,
> > +			__attribute__((unused)) struct cmdline *cl,
> > +			__attribute__((unused)) void *data) {
> > +	struct cmd_queue_region_result *res = parsed_result;
> > +	int ret = 0;
> 
> For port_id other than i40e, this call should return "Not supported", not
> success. There are samples to this usage can you please check them?

Do you mean to add the check code :

	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
		return;

maybe all CLI parser function NEED it.


> 
> > +#ifdef RTE_LIBRTE_I40E_PMD
> > +	struct rte_i40e_rss_region_conf region_conf;
> > +
> > +	memset(&region_conf, 0, sizeof(region_conf));
> > +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> > +	region_conf.region_id = res->region_id;
> > +	region_conf.queue_num = res->queue_num_value;
> > +	region_conf.queue_start_index = res->queue_id;
> > +
> > +	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
> > +&region_conf); #endif
> > +
> > +	if (ret < 0)
> > +		printf("queue region config programming error: (%s)\n",
> > +				strerror(-ret));
> > +}
> 
> <...>


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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-10-03 18:04               ` Ferruh Yigit
  2017-10-10  1:46                 ` Zhao1, Wei
  2017-10-10  2:55                 ` Zhao1, Wei
@ 2017-10-10  3:01                 ` Zhao1, Wei
  2017-10-11  2:15                   ` Ferruh Yigit
  2 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-10  3:01 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Hi,Ferruh

> -----Original Message-----
> From: Zhao1, Wei
> Sent: Tuesday, October 10, 2017 10:56 AM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; dev@dpdk.org
> Subject: RE: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
> configuration of queue region
> 
> Hi,
> 
> > -----Original Message-----
> > From: Yigit, Ferruh
> > Sent: Wednesday, October 4, 2017 2:04 AM
> > To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
> > configuration of queue region
> >
> > On 9/29/2017 10:16 AM, Wei Zhao wrote:
> > > This patch add a API configuration of queue region in rss.
> > > It can parse the parameters of region index, queue number, queue
> > > start index, user priority, traffic classes and so on.
> > > According to commands from command line, it will call i40e private
> > > API and start the process of set or flush queue region configure. As
> > > this feature is specific for i40e, so private API will be used. Aslo
> > > add a document for these new commands.
> > > Queue region only support PF by now, so this document is only for
> > > configuration of queue region on PF port.
> > >
> > > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > > ---
> > >  app/test-pmd/cmdline.c                      | 389
> > ++++++++++++++++++++++++++++
> > >  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
> > >  2 files changed, 430 insertions(+)
> > >
> > > diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
> > > 4f2d731..da7dc24 100644
> > > --- a/app/test-pmd/cmdline.c
> > > +++ b/app/test-pmd/cmdline.c
> > > @@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void
> > *parsed_result,
> > >  			"ptype mapping update (port_id) (hw_ptype)
> > (sw_ptype)\n"
> > >  			"    Update a ptype mapping item on a port\n\n"
> > >
> > > +			"set port (port_id) queue-region region_id (value) "
> > > +			"queue_start_index (value) queue_num (value)\n"
> > > +			"    Set a queue region on a port\n\n"
> > > +
> > > +			"set port (port_id) queue-region region_id (value) "
> > > +			"flowtype (value)\n"
> > > +			"    Set a flowtype region index on a port\n\n"
> > > +
> > > +			"set port (port_id) queue-region UP (value)
> > region_id (value)\n"
> > > +			"    Set the mapping of User Priority to "
> > > +			"queue region on a port\n\n"
> > > +
> > > +			"flush port (port_id) queue-region (on|off)\n"
> > > +			"    flush all queue region related configuration\n\n"
> > > +
> > > +			"get port (port_id) queue-region\n"
> > > +			"	 get all queue region related configuration
> > info\n\n"
> > > +
> >
> > You did same thing and created "flush" and "get" root level commands
> > this time.
> >
> > For get, existing "show port #P .." can be used:
> > "show port #P queue-region"
> >
> > For flush, what do you think:
> > "set port #P queue-region flush (on|off)" ?
> 
> Ok.
> 
> >
> > >  			, list_pkt_forwarding_modes()
> > >  		);
> > >  	}
> > > @@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
> > >  		NULL,
> > >  	},
> > >  };
> > > +/* *** queue region set *** */
> > > +struct cmd_queue_region_result {
> > > +	cmdline_fixed_string_t set;
> > > +	cmdline_fixed_string_t port;
> > > +	uint8_t  port_id;
> > > +	cmdline_fixed_string_t cmd;
> > > +	cmdline_fixed_string_t region;
> > > +	uint8_t  region_id;
> > > +	cmdline_fixed_string_t queue_start_index;
> > > +	uint8_t  queue_id;
> > > +	cmdline_fixed_string_t queue_num;
> > > +	uint8_t  queue_num_value;
> > > +};
> > > +
> > > +static void
> > > +cmd_queue_region_parsed(void *parsed_result,
> > > +			__attribute__((unused)) struct cmdline *cl,
> > > +			__attribute__((unused)) void *data) {
> > > +	struct cmd_queue_region_result *res = parsed_result;
> > > +	int ret = 0;
> >
> > For port_id other than i40e, this call should return "Not supported",
> > not success. There are samples to this usage can you please check them?
> 
> Do you mean to add the check code :
> 
> 	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> 		return;
> 
> maybe all CLI parser function NEED it.

Sorry, maybe it should be this mode.
 
	int ret = -ENOTSUP;

	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
		return ret;


> 
> 
> >
> > > +#ifdef RTE_LIBRTE_I40E_PMD
> > > +	struct rte_i40e_rss_region_conf region_conf;
> > > +
> > > +	memset(&region_conf, 0, sizeof(region_conf));
> > > +	region_conf.op = RTE_PMD_I40E_QUEUE_REGION_SET;
> > > +	region_conf.region_id = res->region_id;
> > > +	region_conf.queue_num = res->queue_num_value;
> > > +	region_conf.queue_start_index = res->queue_id;
> > > +
> > > +	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
> > > +&region_conf); #endif
> > > +
> > > +	if (ret < 0)
> > > +		printf("queue region config programming error: (%s)\n",
> > > +				strerror(-ret));
> > > +}
> >
> > <...>


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

* Re: [PATCH v7 1/2] net/i40e: queue region set and flush
  2017-10-03 17:54               ` Ferruh Yigit
@ 2017-10-10  6:11                 ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-10  6:11 UTC (permalink / raw)
  To: Yigit, Ferruh, dev



> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Wednesday, October 4, 2017 1:55 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v7 1/2] net/i40e: queue region set and flush
> 
> On 9/29/2017 10:16 AM, Wei Zhao wrote:
> > This feature enable queue regions configuration for RSS in PF, so that
> > different traffic classes or different packet classification types can
> > be separated to different queues in different queue regions.This patch
> > can set queue region range, it include queue number in a region and
> > the index of first queue.
> > This patch enable mapping between different priorities (UP) and
> > different traffic classes.It also enable mapping between a region
> > index and a sepcific flowtype(PCTYPE).It also provide the solution of
> > flush all configuration about queue region the above described.
> >
> > Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
> > ---
> 
> <...>
> 
> > @@ -541,6 +547,34 @@ struct i40e_ethertype_rule {
> >  	struct rte_hash *hash_table;
> >  };
> >
> > +/* queue region info */
> > +struct i40e_region_info {
> > +	/* the region id for this configuration */
> > +	uint8_t region_id;
> > +	/* the start queue index for this region */
> > +	uint8_t queue_start_index;
> > +	/* the total queue number of this queue region */
> > +	uint8_t queue_num;
> > +	/* the total number of user priority for this region */
> > +	uint8_t user_priority_num;
> > +	/* the packet's user priority for this region */
> > +	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
> > +	/* the total number of flowtype for this region */
> > +	uint8_t flowtype_num;
> > +	/**
> > +	 * the pctype or hardware flowtype of packet,
> > +	 * the specific index for each type has been defined
> > +	 * in file i40e_type.h as enum i40e_filter_pctype.
> > +	 */
> > +	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
> > +};
> > +
> > +struct i40e_queue_region_info {
> 
> What do you think renaming:
> i40e_region_info -> i40e_queue_region_info i40e_queue_region_info ->
> i40e_queue_regions

Ok

> 
> > +	/* the total number of queue region for this port */
> > +	uint16_t queue_region_number;
> > +	struct i40e_region_info region[I40E_REGION_MAX_INDEX + 1]; };
> > +
> >  /* Tunnel filter number HW supports */  #define
> > I40E_MAX_TUNNEL_FILTER_NUM 400
> >
> 
> <...>
> 
> > +static int
> > +i40e_queue_region_set_flowtype(struct i40e_pf *pf,
> > +			struct rte_i40e_rss_region_conf *rss_region_conf) {
> > +	int32_t ret = -EINVAL;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	uint16_t i, j;
> > +	uint16_t region_index, flowtype_index;
> > +
> > +	/**
> 
> This is doxygen sytle comment, only nedeed for public headers.

Ok, I will change to this mode :

	/* For the pctype or hardware flowtype of packet,
	 * the specific index for each type has been defined
	 * in file i40e_type.h as enum i40e_filter_pctype.
	 */

> 
> > +	 * For the pctype or hardware flowtype of packet,
> > +	 * the specific index for each type has been defined
> > +	 * in file i40e_type.h as enum i40e_filter_pctype.
> > +	 */
> > +
> <...>
> 
> > +		}
> > +	}
> > +}
> 
> Missing line.

Ok

> 
> > +static int
> > +i40e_queue_region_set_user_priority(struct i40e_pf *pf,
> > +		struct rte_i40e_rss_region_conf *rss_region_conf) {
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	int32_t ret = -EINVAL;
> > +	uint16_t i, j, region_index;
> > +
> <...>
> 
> > +static int
> > +i40e_queue_region_display_all_info(struct i40e_pf *pf, uint16_t
> > +port_id) {
> > +	uint16_t i, j;
> > +	struct i40e_queue_region_info *info = &pf->queue_region;
> > +	static const char *queue_region_info_stats_border = "-------";
> > +
> > +	if (!info->queue_region_number)
> > +		PMD_DRV_LOG(ERR, "there is no has been region set
> before");
> > +
> > +	printf("\n  %s All queue region info for port=%2d %s",
> > +			queue_region_info_stats_border, port_id,
> > +			queue_region_info_stats_border);
> 
> printf ? Please use driver logging functions.
> 

Ok, I will change to PMD_DRV_LOG()

> > +	printf("\n  queue_region_number: %-14u \n",
> > +info->queue_region_number);
> > +
> > +	for (i = 0; i < info->queue_region_number; i++) {
> > +		printf("\n  region_id: %-14u queue_number: %-14u "
> > +			"queue_start_index: %-14u \n",
> > +			info->region[i].region_id,
> > +			info->region[i].queue_num,
> > +			info->region[i].queue_start_index);
> > +
> > +		printf("  user_priority_num is  %-14u :",
> > +				info->region[i].user_priority_num);
> > +		for (j = 0; j < info->region[i].user_priority_num; j++)
> > +			printf(" %-14u ", info->region[i].user_priority[j]);
> > +
> > +		printf("\n  flowtype_num is  %-14u :",
> > +				info->region[i].flowtype_num);
> > +		for (j = 0; j < info->region[i].flowtype_num; j++)
> > +			printf(" %-14u ", info->region[i].hw_flowtype[j]);
> > +	}
> > +
> > +	printf("\n\n");
> > +	return 0;
> > +}
> > +
> > +int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
> > +			struct rte_i40e_rss_region_conf *rss_region_conf) {
> > +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> > +	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
> >dev_private);
> > +	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
> >dev_private);
> > +	enum rte_pmd_i40e_queue_region_op op_type = rss_region_conf-
> >op;
> > +	int32_t ret;
> > +
> > +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > +
> > +	if (!is_i40e_supported(dev))
> > +		return -ENOTSUP;
> > +
> > +	if (!(!i40e_queue_region_pf_check_rss(pf)))
> > +		return -ENOTSUP;
> > +
> > +	/**
> > +	 * This queue region feature only support pf by now. It should
> > +	 * be called after dev_start, and will be clear after dev_stop.
> > +	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
> > +	 * is just an enable function which server for other configuration,
> > +	 * it is for all configuration about queue region from up layer,
> > +	 * at first will only keep in DPDK softwarestored in driver,
> > +	 * only after "FLUSH_ON", it commit all configuration to HW.
> > +	 * Because PMD had to set hardware configuration at a time, so
> > +	 * it will record all up layer command at first.
> > +	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
> > +	 * just clean all configuration about queue region just now,
> > +	 * and restore all to DPDK i40e driver default
> > +	 * config when start up.
> > +	 */
> > +
> > +	switch (op_type) {
> > +	case RTE_PMD_I40E_QUEUE_REGION_SET:
> > +		ret = i40e_queue_region_set_region(pf, rss_region_conf);
> > +		break;
> > +	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
> > +		ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
> > +		break;
> > +	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
> > +		ret = i40e_queue_region_set_user_priority(pf,
> rss_region_conf);
> > +		break;
> > +	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
> > +		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
> > +		break;
> > +	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
> > +		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
> > +		break;
> > +	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
> > +		ret = i40e_queue_region_display_all_info(pf, port_id);
> 
> Displaying is not always very useful in API level.
> What do you think get fills the rss_region_conf with current device settings
> and return back to the caller?

Ok, it will not only print all region info, but also fill a struct like rss_region_conf.
With the CLI command "show port # queue-region..."


> 
> > +		break;
> > +	default:
> > +		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
> > +			    op_type);
> > +		ret = -EINVAL;
> > +	}
> > +
> > +	I40E_WRITE_FLUSH(hw);
> > +
> > +	return ret;
> > +}
> > diff --git a/drivers/net/i40e/rte_pmd_i40e.h
> > b/drivers/net/i40e/rte_pmd_i40e.h index 155b7e8..2219318 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e.h
> > +++ b/drivers/net/i40e/rte_pmd_i40e.h
> > @@ -91,6 +91,33 @@ enum rte_pmd_i40e_package_info {
> >  	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF  };
> >
> > +/**
> > + *  Option types of queue region.
> > + */
> > +enum rte_pmd_i40e_queue_region_op {
> > +	RTE_PMD_I40E_REGION_UNDEFINED,
> > +	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set
> */
> > +	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region
> pctype set */
> > +	/*** add queue region user priority set */
> > +	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
> > +	/**
> > +	 * ALL configuration about queue region from up layer
> > +	 * at first will only keep in DPDK softwarestored in driver,
> > +	 * only after " FLUSH_ON ", it commit all configuration to HW.
> > +	 * Because PMD had to set hardware configuration at a time, so
> > +	 * it will record all up layer command at first.
> > +	 */
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
> > +	/**
> > +	 * "FLUSH_OFF " is just clean all configuration about queue
> > +	 * region just now, and restore all to DPDK i40e driver default
> > +	 * config when start up.
> > +	 */
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
> > +	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
> > +	RTE_PMD_I40E_QUEUE_REGION_OP_MAX
> 
> These are in public header now.
> Can you please use same namespace for all ops.
> It can be "RTE_PMD_I40E_RSS_QUEUE_REGION_"

Ok

> 
> > +};
> > +
> >  #define RTE_PMD_I40E_DDP_NAME_SIZE 32
> >
> >  /**
> > @@ -146,6 +173,27 @@ struct rte_pmd_i40e_ptype_mapping {  };
> >
> >  /**
> > + * Queue region related information.
> > + */
> > +struct rte_i40e_rss_region_conf {
> 
> Can you please be consistant in using public names.
> There are:
> rss_region
> queue_region
> rss_queue_region
> 
> Also there is confusion between using:
> rte_i40e_
> rte_pmd_i40e_

Ok

> 
> > +	/*** the region id for this configuration */
> > +	uint8_t region_id;
> > +	/** the pctype or hardware flowtype of packet,
> > +	 * the specific index for each type has been defined
> > +	 * in file i40e_type.h as enum i40e_filter_pctype.
> > +	 */
> > +	uint8_t hw_flowtype;
> > +	/*** the start queue index for this region */
> > +	uint8_t queue_start_index;
> > +	/*** the total queue number of this queue region */
> > +	uint8_t queue_num;
> > +	/*** the packet's user priority for this region */
> > +	uint8_t user_priority;
> > +	 /*** Option types of queue region */
> > +	enum rte_pmd_i40e_queue_region_op op; };
> > +
> > +/**
> >   * Notify VF when PF link status changes.
> >   *
> >   * @param port
> > @@ -657,4 +705,16 @@ int
> rte_pmd_i40e_ptype_mapping_replace(uint8_t
> > port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
> >  				 struct ether_addr *mac_addr);
> >
> > +/**
> > + * Do RSS queue region configuration for that port as
> > + * the command option type
> > + *
> > + * @param port
> > + *    pointer id for that port device
> 
> port id ?

Ok

> 
> > + * @param conf_ptr
> > + *    pointer to the struct that contain all the
> > + *    region configuration parameters
> > + */
> > +int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
> 
> By defining port_id uint16_t, this patches becomes dependent to the port_id
> update patchset, please clarify this in cover letter.


Ok

> 
> > +		struct rte_i40e_rss_region_conf *rss_region_conf);
> >  #endif /* _PMD_I40E_H_ */
> > diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map
> > b/drivers/net/i40e/rte_pmd_i40e_version.map
> > index ef8882b..29d6b74 100644
> > --- a/drivers/net/i40e/rte_pmd_i40e_version.map
> > +++ b/drivers/net/i40e/rte_pmd_i40e_version.map
> > @@ -50,5 +50,6 @@ DPDK_17.11 {
> >  	global:
> >
> >  	rte_pmd_i40e_add_vf_mac_addr;
> > +	rte_pmd_i40e_rss_queue_region_conf;
> >
> >  } DPDK_17.08;
> >


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

* Re: [PATCH v7 2/2] app/testpmd: add API for configuration of queue region
  2017-10-10  3:01                 ` Zhao1, Wei
@ 2017-10-11  2:15                   ` Ferruh Yigit
  0 siblings, 0 replies; 87+ messages in thread
From: Ferruh Yigit @ 2017-10-11  2:15 UTC (permalink / raw)
  To: Zhao1, Wei, dev

On 10/10/2017 4:01 AM, Zhao1, Wei wrote:
> Hi,Ferruh
> 
>> -----Original Message-----
>> From: Zhao1, Wei
>> Sent: Tuesday, October 10, 2017 10:56 AM
>> To: Yigit, Ferruh <ferruh.yigit@intel.com>; dev@dpdk.org
>> Subject: RE: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
>> configuration of queue region
>>
>> Hi,
>>
>>> -----Original Message-----
>>> From: Yigit, Ferruh
>>> Sent: Wednesday, October 4, 2017 2:04 AM
>>> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
>>> Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
>>> configuration of queue region
>>>
>>> On 9/29/2017 10:16 AM, Wei Zhao wrote:
>>>> This patch add a API configuration of queue region in rss.
>>>> It can parse the parameters of region index, queue number, queue
>>>> start index, user priority, traffic classes and so on.
>>>> According to commands from command line, it will call i40e private
>>>> API and start the process of set or flush queue region configure. As
>>>> this feature is specific for i40e, so private API will be used. Aslo
>>>> add a document for these new commands.
>>>> Queue region only support PF by now, so this document is only for
>>>> configuration of queue region on PF port.
>>>>
>>>> Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
>>>> ---
>>>>  app/test-pmd/cmdline.c                      | 389
>>> ++++++++++++++++++++++++++++
>>>>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
>>>>  2 files changed, 430 insertions(+)
>>>>
>>>> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index
>>>> 4f2d731..da7dc24 100644
>>>> --- a/app/test-pmd/cmdline.c
>>>> +++ b/app/test-pmd/cmdline.c
>>>> @@ -637,6 +637,24 @@ static void cmd_help_long_parsed(void
>>> *parsed_result,
>>>>  			"ptype mapping update (port_id) (hw_ptype)
>>> (sw_ptype)\n"
>>>>  			"    Update a ptype mapping item on a port\n\n"
>>>>
>>>> +			"set port (port_id) queue-region region_id (value) "
>>>> +			"queue_start_index (value) queue_num (value)\n"
>>>> +			"    Set a queue region on a port\n\n"
>>>> +
>>>> +			"set port (port_id) queue-region region_id (value) "
>>>> +			"flowtype (value)\n"
>>>> +			"    Set a flowtype region index on a port\n\n"
>>>> +
>>>> +			"set port (port_id) queue-region UP (value)
>>> region_id (value)\n"
>>>> +			"    Set the mapping of User Priority to "
>>>> +			"queue region on a port\n\n"
>>>> +
>>>> +			"flush port (port_id) queue-region (on|off)\n"
>>>> +			"    flush all queue region related configuration\n\n"
>>>> +
>>>> +			"get port (port_id) queue-region\n"
>>>> +			"	 get all queue region related configuration
>>> info\n\n"
>>>> +
>>>
>>> You did same thing and created "flush" and "get" root level commands
>>> this time.
>>>
>>> For get, existing "show port #P .." can be used:
>>> "show port #P queue-region"
>>>
>>> For flush, what do you think:
>>> "set port #P queue-region flush (on|off)" ?
>>
>> Ok.
>>
>>>
>>>>  			, list_pkt_forwarding_modes()
>>>>  		);
>>>>  	}
>>>> @@ -8228,6 +8246,372 @@ cmdline_parse_inst_t cmd_syn_filter = {
>>>>  		NULL,
>>>>  	},
>>>>  };
>>>> +/* *** queue region set *** */
>>>> +struct cmd_queue_region_result {
>>>> +	cmdline_fixed_string_t set;
>>>> +	cmdline_fixed_string_t port;
>>>> +	uint8_t  port_id;
>>>> +	cmdline_fixed_string_t cmd;
>>>> +	cmdline_fixed_string_t region;
>>>> +	uint8_t  region_id;
>>>> +	cmdline_fixed_string_t queue_start_index;
>>>> +	uint8_t  queue_id;
>>>> +	cmdline_fixed_string_t queue_num;
>>>> +	uint8_t  queue_num_value;
>>>> +};
>>>> +
>>>> +static void
>>>> +cmd_queue_region_parsed(void *parsed_result,
>>>> +			__attribute__((unused)) struct cmdline *cl,
>>>> +			__attribute__((unused)) void *data) {
>>>> +	struct cmd_queue_region_result *res = parsed_result;
>>>> +	int ret = 0;
>>>
>>> For port_id other than i40e, this call should return "Not supported",
>>> not success. There are samples to this usage can you please check them?
>>
>> Do you mean to add the check code :
>>
>> 	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
>> 		return;
>>
>> maybe all CLI parser function NEED it.
> 
> Sorry, maybe it should be this mode.
>  
> 	int ret = -ENOTSUP;
> 
> 	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
> 		return ret;

Yep, this one.
For the case I40E config not enabled, and when called for devices other
than i40e, function should return -ENOTSUP;

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

* [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
                               ` (2 preceding siblings ...)
  2017-09-29 10:15             ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
@ 2017-10-11  8:49             ` Wei Zhao
  2017-10-11  8:49               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-10-11  8:49               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  4 siblings, 2 replies; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:49 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

v7:
-change some PMD_DRV_LOG log.

v8:
-change CLI command format.
-change some functions name.

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++
 app/test-pmd/config.c                       |  44 +++
 app/test-pmd/testpmd.h                      |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c             | 494 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  91 +++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   2 +-
 9 files changed, 1158 insertions(+), 7 deletions(-)

-- 
2.7.4

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

* [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-11  8:49             ` [PATCH v8 " Wei Zhao
@ 2017-10-11  8:49               ` Wei Zhao
  2017-10-11  8:49               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
  1 sibling, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:49 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 494 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  91 ++++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   2 +-
 5 files changed, 646 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7dfb97..814f458 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -138,10 +138,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -310,7 +306,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1058,6 +1053,20 @@ i40e_init_customized_info(struct i40e_pf *pf)
 	pf->gtp_support = false;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_regions *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_regions));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1337,6 +1346,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -2142,6 +2154,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* reset hierarchy commit */
 	pf->tm_conf.committed = false;
 
+	/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	hw->adapter_stopped = 1;
 }
 
@@ -10471,7 +10486,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 4125a35..2f1905e 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -646,6 +652,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_queue_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_regions {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_queue_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -902,6 +936,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_regions queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1150,6 +1185,10 @@ struct i40e_customized_pctype*
 i40e_find_customized_pctype(struct i40e_pf *pf, uint8_t index);
 void i40e_update_customized_info(struct rte_eth_dev *dev, uint8_t *pkg,
 				 uint32_t pkg_size);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 0988023..4bc1d0c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2430,3 +2431,496 @@ rte_pmd_i40e_flow_type_mapping_update(
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_regions *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/* Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+	vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_pmd_i40e_queue_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				conf_ptr->queue_num <= 64)) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number &&
+				i <= I40E_REGION_MAX_INDEX) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	uint16_t i, j;
+	uint16_t region_index, flowtype_index;
+
+	/* For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+				return 0;
+			}
+		}
+	}
+
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	/* For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
+{
+	struct i40e_queue_regions *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				PMD_DRV_LOG(ERR, "that user priority has been set before");
+				return 0;
+			}
+		}
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "No queue region been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_get_all_info(struct i40e_pf *pf,
+		struct i40e_queue_regions *regions_ptr)
+{
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	rte_memcpy(regions_ptr, info,
+			sizeof(struct i40e_queue_regions));
+
+	return 0;
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		enum rte_pmd_i40e_queue_region_op op_type, void *arg)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	int32_t ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/* This queue region feature only support pf by now. It should
+	 * be called after dev_start, and will be clear after dev_stop.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		ret = i40e_queue_region_get_all_info(pf,
+				(struct i40e_queue_regions *)arg);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 8fa5869..63df26f 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -97,7 +97,37 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/** add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
+#define RTE_PMD_I40E_PCTYPE_MAX 64
+#define RTE_PMD_I40E_REGION_MAX_NUM 8
+#define RTE_PMD_I40E_MAX_USER_PRIORITY		8
 
 /**
  * Version for dynamic device personalization.
@@ -171,6 +201,55 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_pmd_i40e_queue_region_conf {
+	/** the region id for this configuration */
+	uint8_t region_id;
+	/** the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/** the start queue index for this region */
+	uint8_t queue_start_index;
+	/** the total queue number of this queue region */
+	uint8_t queue_num;
+	/** the packet's user priority for this region */
+	uint8_t user_priority;
+};
+
+/* queue region info */
+struct rte_pmd_i40e_queue_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[RTE_PMD_I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[RTE_PMD_I40E_PCTYPE_MAX];
+};
+
+struct rte_pmd_i40e_queue_regions {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct rte_pmd_i40e_queue_region_info
+		region[RTE_PMD_I40E_REGION_MAX_NUM];
+};
+
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -737,4 +816,16 @@ int rte_pmd_i40e_flow_type_mapping_get(
  */
 int rte_pmd_i40e_flow_type_mapping_reset(uint8_t port);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port_id
+ *    port id for that port device
+ * @param rss_region_conf
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			enum rte_pmd_i40e_queue_region_op op_type, void *arg);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 9292454..81946ae 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -53,5 +53,5 @@ DPDK_17.11 {
 	rte_pmd_i40e_flow_type_mapping_update;
 	rte_pmd_i40e_flow_type_mapping_get;
 	rte_pmd_i40e_flow_type_mapping_reset;
-
+	rte_pmd_i40e_rss_queue_region_conf;
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v8 2/2] app/testpmd: add API for configuration of queue region
  2017-10-11  8:49             ` [PATCH v8 " Wei Zhao
  2017-10-11  8:49               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-10-11  8:49               ` Wei Zhao
  1 sibling, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:49 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used. Aslo add a document for these new commands.
Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  44 +++
 app/test-pmd/testpmd.h                      |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 4 files changed, 512 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f996ee3..f873b29 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -660,6 +660,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"set port (port_id) queue-region region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"set port (port_id) queue-region region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"set port (port_id) queue-region UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"set port (port_id) queue-region flush (on|off)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"show port (port_id) queue-region\n"
+			"	 show all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8469,6 +8487,407 @@ cmdline_parse_inst_t cmd_syn_filter = {
 	},
 };
 
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	op_type = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	op_type = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+			op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	op_type = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region flush on|off"
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_set,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_show_queue_region_info {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+};
+
+static void
+cmd_show_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_show_queue_region_info *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_regions rte_pmd_regions;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&rte_pmd_regions, 0, sizeof(rte_pmd_regions));
+
+	op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+					op_type, &rte_pmd_regions);
+
+	port_queue_region_info_display(res->port_id, &rte_pmd_regions);
+
+#endif
+
+	if (ret < 0)
+		printf("queue region config info show error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_show_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				show, "show");
+cmdline_parse_token_string_t cmd_show_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_show_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_queue_region_info,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_show_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				cmd, "queue-region");
+
+cmdline_parse_inst_t cmd_show_queue_region_info_all = {
+	.f = cmd_show_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> queue-region"
+		": show all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_show_queue_region_info_get,
+		(void *)&cmd_show_queue_region_info_port,
+		(void *)&cmd_show_queue_region_info_port_index,
+		(void *)&cmd_show_queue_region_info_cmd,
+		NULL,
+	},
+};
+
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
 	cmdline_fixed_string_t filter;
@@ -15130,6 +15549,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_get,
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_show_queue_region_info_all,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 7ff0bb2..8049c32 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -71,6 +71,9 @@
 #ifdef RTE_LIBRTE_IXGBE_PMD
 #include <rte_pmd_ixgbe.h>
 #endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
 #ifdef RTE_LIBRTE_BNXT_PMD
 #include <rte_pmd_bnxt.h>
 #endif
@@ -3468,3 +3471,44 @@ close_ddp_package_file(uint8_t *buf)
 
 	return -1;
 }
+
+void
+port_queue_region_info_display(uint8_t port_id,
+			void *buf)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+	uint16_t i, j;
+	struct rte_pmd_i40e_queue_regions *info =
+		(struct rte_pmd_i40e_queue_regions *)buf;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		printf("there is no region has been set before");
+
+	printf("\n	%s All queue region info for port=%2d %s",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("\n	queue_region_number: %-14u \n",
+			info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("\n	region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is	%-14u :",
+					info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n	flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+	}
+#endif
+
+	printf("\n\n");
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 7c79f17..10aeeeb 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -718,6 +718,9 @@ uint8_t *open_ddp_package_file(const char *file_path, uint32_t *size);
 int save_ddp_package_file(const char *file_path, uint8_t *buf, uint32_t size);
 int close_ddp_package_file(uint8_t *buf);
 
+void port_queue_region_info_display(uint8_t port_id,
+			void *buf);
+
 enum print_warning {
 	ENABLED_WARN = 0,
 	DISABLED_WARN
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 7f37f91..c67d251 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -857,6 +857,47 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) \
+		queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> set port (port_id) queue-region flush (on|off)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Show all queue region related configuration info on a port::
+
+   testpmd> show port (port_id) queue-region
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS
  2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
                               ` (3 preceding siblings ...)
  2017-10-11  8:49             ` [PATCH v8 " Wei Zhao
@ 2017-10-11  8:55             ` Wei Zhao
  2017-10-11  8:55               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
                                 ` (3 more replies)
  4 siblings, 4 replies; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:55 UTC (permalink / raw)
  To: dev

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

v7:
-change some PMD_DRV_LOG log.

v8:
-change CLI command format.
-change some functions name.

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++
 app/test-pmd/config.c                       |  44 +++
 app/test-pmd/testpmd.h                      |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c             | 494 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  91 +++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   2 +-
 9 files changed, 1158 insertions(+), 7 deletions(-)

-- 
2.7.4

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

* [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
@ 2017-10-11  8:55               ` Wei Zhao
  2017-10-13 10:06                 ` Chilikin, Andrey
  2017-10-11  8:55               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
                                 ` (2 subsequent siblings)
  3 siblings, 1 reply; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:55 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This feature enable queue regions configuration for RSS in PF,
so that different traffic classes or different packet
classification types can be separated to different queues in
different queue regions.This patch can set queue region range,
it include queue number in a region and the index of first queue.
This patch enable mapping between different priorities (UP) and
different traffic classes.It also enable mapping between a region
index and a sepcific flowtype(PCTYPE).It also provide the solution
of flush all configuration about queue region the above described.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c            |  27 +-
 drivers/net/i40e/i40e_ethdev.h            |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c           | 494 ++++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h           |  91 ++++++
 drivers/net/i40e/rte_pmd_i40e_version.map |   2 +-
 5 files changed, 646 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index f7dfb97..814f458 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -138,10 +138,6 @@
 #define I40E_PRTTSYN_TSYNTYPE    0x0e000000
 #define I40E_CYCLECOUNTER_MASK   0xffffffffffffffffULL
 
-#define I40E_MAX_PERCENT            100
-#define I40E_DEFAULT_DCB_APP_NUM    1
-#define I40E_DEFAULT_DCB_APP_PRIO   3
-
 /**
  * Below are values for writing un-exposed registers suggested
  * by silicon experts
@@ -310,7 +306,6 @@ static int i40e_pf_parameter_init(struct rte_eth_dev *dev);
 static int i40e_pf_setup(struct i40e_pf *pf);
 static int i40e_dev_rxtx_init(struct i40e_pf *pf);
 static int i40e_vmdq_setup(struct rte_eth_dev *dev);
-static int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
 static int i40e_dcb_setup(struct rte_eth_dev *dev);
 static void i40e_stat_update_32(struct i40e_hw *hw, uint32_t reg,
 		bool offset_loaded, uint64_t *offset, uint64_t *stat);
@@ -1058,6 +1053,20 @@ i40e_init_customized_info(struct i40e_pf *pf)
 	pf->gtp_support = false;
 }
 
+void
+i40e_init_queue_region_conf(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);
+	struct i40e_queue_regions *info = &pf->queue_region;
+	uint16_t i;
+
+	for (i = 0; i < I40E_PFQF_HREGION_MAX_INDEX; i++)
+		i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(i), 0);
+
+	memset(info, 0, sizeof(struct i40e_queue_regions));
+}
+
 static int
 eth_i40e_dev_init(struct rte_eth_dev *dev)
 {
@@ -1337,6 +1346,9 @@ eth_i40e_dev_init(struct rte_eth_dev *dev)
 	if (ret < 0)
 		goto err_init_fdir_filter_list;
 
+	/* initialize queue region configuration */
+	i40e_init_queue_region_conf(dev);
+
 	return 0;
 
 err_init_fdir_filter_list:
@@ -2142,6 +2154,9 @@ i40e_dev_stop(struct rte_eth_dev *dev)
 	/* reset hierarchy commit */
 	pf->tm_conf.committed = false;
 
+	/* Remove all the queue region configuration */
+	i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+
 	hw->adapter_stopped = 1;
 }
 
@@ -10471,7 +10486,7 @@ i40e_dcb_hw_configure(struct i40e_pf *pf,
  *
  * Returns 0 on success, negative value on failure
  */
-static int
+int
 i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
index 4125a35..2f1905e 100644
--- a/drivers/net/i40e/i40e_ethdev.h
+++ b/drivers/net/i40e/i40e_ethdev.h
@@ -260,6 +260,12 @@ enum i40e_flxpld_layer_idx {
 #define I40E_QOS_BW_WEIGHT_MIN 1
 /* The max bandwidth weight is 127. */
 #define I40E_QOS_BW_WEIGHT_MAX 127
+/* The max queue region index is 7. */
+#define I40E_REGION_MAX_INDEX 7
+
+#define I40E_MAX_PERCENT            100
+#define I40E_DEFAULT_DCB_APP_NUM    1
+#define I40E_DEFAULT_DCB_APP_PRIO   3
 
 /**
  * The overhead from MTU to max frame size.
@@ -646,6 +652,34 @@ struct i40e_ethertype_rule {
 	struct rte_hash *hash_table;
 };
 
+/* queue region info */
+struct i40e_queue_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[I40E_FILTER_PCTYPE_MAX];
+};
+
+struct i40e_queue_regions {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct i40e_queue_region_info region[I40E_REGION_MAX_INDEX + 1];
+};
+
 /* Tunnel filter number HW supports */
 #define I40E_MAX_TUNNEL_FILTER_NUM 400
 
@@ -902,6 +936,7 @@ struct i40e_pf {
 	struct i40e_fdir_info fdir; /* flow director info */
 	struct i40e_ethertype_rule ethertype; /* Ethertype filter rule */
 	struct i40e_tunnel_rule tunnel; /* Tunnel filter rule */
+	struct i40e_queue_regions queue_region; /* queue region info */
 	struct i40e_fc_conf fc_conf; /* Flow control conf */
 	struct i40e_mirror_rule_list mirror_list;
 	uint16_t nb_mirror_rule;   /* The number of mirror rules */
@@ -1150,6 +1185,10 @@ struct i40e_customized_pctype*
 i40e_find_customized_pctype(struct i40e_pf *pf, uint8_t index);
 void i40e_update_customized_info(struct rte_eth_dev *dev, uint8_t *pkg,
 				 uint32_t pkg_size);
+int i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb);
+int i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+		struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on);
+void i40e_init_queue_region_conf(struct rte_eth_dev *dev);
 
 #define I40E_DEV_TO_PCI(eth_dev) \
 	RTE_DEV_TO_PCI((eth_dev)->device)
diff --git a/drivers/net/i40e/rte_pmd_i40e.c b/drivers/net/i40e/rte_pmd_i40e.c
index 0988023..4bc1d0c 100644
--- a/drivers/net/i40e/rte_pmd_i40e.c
+++ b/drivers/net/i40e/rte_pmd_i40e.c
@@ -35,6 +35,7 @@
 #include <rte_tailq.h>
 
 #include "base/i40e_prototype.h"
+#include "base/i40e_dcb.h"
 #include "i40e_ethdev.h"
 #include "i40e_pf.h"
 #include "i40e_rxtx.h"
@@ -2430,3 +2431,496 @@ rte_pmd_i40e_flow_type_mapping_update(
 
 	return 0;
 }
+
+static int
+i40e_vsi_update_queue_region_mapping(struct i40e_hw *hw,
+			      struct i40e_pf *pf)
+{
+	uint16_t i;
+	struct i40e_vsi *vsi = pf->main_vsi;
+	uint16_t queue_offset, bsf, tc_index;
+	struct i40e_vsi_context ctxt;
+	struct i40e_aqc_vsi_properties_data *vsi_info;
+	struct i40e_queue_regions *region_info =
+				&pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!region_info->queue_region_number) {
+		PMD_INIT_LOG(ERR, "there is no that region id been set before");
+		return ret;
+	}
+
+	memset(&ctxt, 0, sizeof(struct i40e_vsi_context));
+
+	/* Update Queue Pairs Mapping for currently enabled UPs */
+	ctxt.seid = vsi->seid;
+	ctxt.pf_num = hw->pf_id;
+	ctxt.vf_num = 0;
+	ctxt.uplink_seid = vsi->uplink_seid;
+	ctxt.info = vsi->info;
+	vsi_info = &ctxt.info;
+
+	memset(vsi_info->tc_mapping, 0, sizeof(uint16_t) * 8);
+	memset(vsi_info->queue_mapping, 0, sizeof(uint16_t) * 16);
+
+	/* Configure queue region and queue mapping parameters,
+	 * for enabled queue region, allocate queues to this region.
+	 */
+
+	for (i = 0; i < region_info->queue_region_number; i++) {
+		tc_index = region_info->region[i].region_id;
+		bsf = rte_bsf32(region_info->region[i].queue_num);
+		queue_offset = region_info->region[i].queue_start_index;
+		vsi_info->tc_mapping[tc_index] = rte_cpu_to_le_16(
+			(queue_offset << I40E_AQ_VSI_TC_QUE_OFFSET_SHIFT) |
+				(bsf << I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
+	}
+
+	/* Associate queue number with VSI, Keep vsi->nb_qps unchanged */
+	vsi_info->mapping_flags |=
+			rte_cpu_to_le_16(I40E_AQ_VSI_QUE_MAP_CONTIG);
+	vsi_info->queue_mapping[0] = rte_cpu_to_le_16(vsi->base_queue);
+	vsi_info->valid_sections |=
+		rte_cpu_to_le_16(I40E_AQ_VSI_PROP_QUEUE_MAP_VALID);
+
+	/* Update the VSI after updating the VSI queue-mapping information */
+	ret = i40e_aq_update_vsi_params(hw, &ctxt, NULL);
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Failed to configure queue region mapping = %d ",
+				hw->aq.asq_last_status);
+		return ret;
+	}
+	/* update the local VSI info with updated queue map */
+	rte_memcpy(&vsi->info.tc_mapping, &ctxt.info.tc_mapping,
+					sizeof(vsi->info.tc_mapping));
+	rte_memcpy(&vsi->info.queue_mapping,
+			&ctxt.info.queue_mapping,
+			sizeof(vsi->info.queue_mapping));
+	vsi->info.mapping_flags = ctxt.info.mapping_flags;
+	vsi->info.valid_sections = 0;
+
+	return 0;
+}
+
+
+static int
+i40e_queue_region_set_region(struct i40e_pf *pf,
+				struct rte_pmd_i40e_queue_region_conf *conf_ptr)
+{
+	uint16_t i;
+	struct i40e_vsi *main_vsi = pf->main_vsi;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+
+	if (!((rte_is_power_of_2(conf_ptr->queue_num)) &&
+				conf_ptr->queue_num <= 64)) {
+		PMD_DRV_LOG(ERR, "The region sizes should be any of the following values: 1, 2, 4, 8, 16, 32, 64 as long as the "
+			"total number of queues do not exceed the VSI allocation");
+		return ret;
+	}
+
+	if (conf_ptr->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if ((conf_ptr->queue_start_index + conf_ptr->queue_num)
+					> main_vsi->nb_used_qps) {
+		PMD_DRV_LOG(ERR, "the queue index exceeds the VSI range");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (conf_ptr->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number &&
+				i <= I40E_REGION_MAX_INDEX) {
+		info->region[i].region_id = conf_ptr->region_id;
+		info->region[i].queue_num = conf_ptr->queue_num;
+		info->region[i].queue_start_index =
+			conf_ptr->queue_start_index;
+		info->queue_region_number++;
+	} else {
+		PMD_DRV_LOG(ERR, "queue region number exceeds maxnum 8 or the queue region id has been set before");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+i40e_queue_region_set_flowtype(struct i40e_pf *pf,
+			struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	uint16_t i, j;
+	uint16_t region_index, flowtype_index;
+
+	/* For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->hw_flowtype >= I40E_FILTER_PCTYPE_MAX) {
+		PMD_DRV_LOG(ERR, "the hw_flowtype or PCTYPE max index is 63");
+		return ret;
+	}
+
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			if (rss_region_conf->hw_flowtype ==
+				info->region[i].hw_flowtype[j]) {
+				PMD_DRV_LOG(ERR, "that hw_flowtype has been set before");
+				return 0;
+			}
+		}
+	}
+
+	flowtype_index = info->region[region_index].flowtype_num;
+	info->region[region_index].hw_flowtype[flowtype_index] =
+					rss_region_conf->hw_flowtype;
+	info->region[region_index].flowtype_num++;
+
+	return 0;
+}
+
+static void
+i40e_queue_region_pf_flowtype_conf(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	uint8_t hw_flowtype;
+	uint32_t pfqf_hregion;
+	uint16_t i, j, index;
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	/* For the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].flowtype_num; j++) {
+			hw_flowtype = info->region[i].hw_flowtype[j];
+			index = hw_flowtype >> 3;
+			pfqf_hregion =
+				i40e_read_rx_ctl(hw, I40E_PFQF_HREGION(index));
+
+			if ((hw_flowtype & 0x7) == 0) {
+				pfqf_hregion |= info->region[i].region_id <<
+					I40E_PFQF_HREGION_REGION_0_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_0_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 1) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_1_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_1_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 2) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_2_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_2_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 3) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_3_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_3_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 4) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_4_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_4_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 5) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_5_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_5_SHIFT;
+			} else if ((hw_flowtype & 0x7) == 6) {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_6_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_6_SHIFT;
+			} else {
+				pfqf_hregion |= info->region[i].region_id  <<
+					I40E_PFQF_HREGION_REGION_7_SHIFT;
+				pfqf_hregion |= 1 <<
+					I40E_PFQF_HREGION_OVERRIDE_ENA_7_SHIFT;
+			}
+
+			i40e_write_rx_ctl(hw, I40E_PFQF_HREGION(index),
+						pfqf_hregion);
+		}
+	}
+}
+
+static int
+i40e_queue_region_set_user_priority(struct i40e_pf *pf,
+		struct rte_pmd_i40e_queue_region_conf *rss_region_conf)
+{
+	struct i40e_queue_regions *info = &pf->queue_region;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, region_index;
+
+	if (rss_region_conf->user_priority >= I40E_MAX_USER_PRIORITY) {
+		PMD_DRV_LOG(ERR, "the queue region max index is 7");
+		return ret;
+	}
+
+	if (rss_region_conf->region_id > I40E_REGION_MAX_INDEX) {
+		PMD_DRV_LOG(ERR, "the region_id max index is 7");
+		return ret;
+	}
+
+	for (i = 0; i < info->queue_region_number; i++)
+		if (rss_region_conf->region_id == info->region[i].region_id)
+			break;
+
+	if (i == info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "that region id has not been set before");
+		ret = -ENODATA;
+		return ret;
+	}
+
+	region_index = i;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			if (info->region[i].user_priority[j] ==
+				rss_region_conf->user_priority) {
+				PMD_DRV_LOG(ERR, "that user priority has been set before");
+				return 0;
+			}
+		}
+	}
+
+	j = info->region[region_index].user_priority_num;
+	info->region[region_index].user_priority[j] =
+					rss_region_conf->user_priority;
+	info->region[region_index].user_priority_num++;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_dcb_configure(struct i40e_hw *hw,
+				struct i40e_pf *pf)
+{
+	struct i40e_dcbx_config dcb_cfg_local;
+	struct i40e_dcbx_config *dcb_cfg;
+	struct i40e_queue_regions *info = &pf->queue_region;
+	struct i40e_dcbx_config *old_cfg = &hw->local_dcbx_config;
+	int32_t ret = -EINVAL;
+	uint16_t i, j, prio_index, region_index;
+	uint8_t tc_map, tc_bw, bw_lf;
+
+	if (!info->queue_region_number) {
+		PMD_DRV_LOG(ERR, "No queue region been set before");
+		return ret;
+	}
+
+	dcb_cfg = &dcb_cfg_local;
+	memset(dcb_cfg, 0, sizeof(struct i40e_dcbx_config));
+
+	/* assume each tc has the same bw */
+	tc_bw = I40E_MAX_PERCENT / info->queue_region_number;
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tcbwtable[i] = tc_bw;
+	/* to ensure the sum of tcbw is equal to 100 */
+	bw_lf = I40E_MAX_PERCENT %  info->queue_region_number;
+	for (i = 0; i < bw_lf; i++)
+		dcb_cfg->etscfg.tcbwtable[i]++;
+
+	/* assume each tc has the same Transmission Selection Algorithm */
+	for (i = 0; i < info->queue_region_number; i++)
+		dcb_cfg->etscfg.tsatable[i] = I40E_IEEE_TSA_ETS;
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		for (j = 0; j < info->region[i].user_priority_num; j++) {
+			prio_index = info->region[i].user_priority[j];
+			region_index = info->region[i].region_id;
+			dcb_cfg->etscfg.prioritytable[prio_index] =
+						region_index;
+		}
+	}
+
+	/* FW needs one App to configure HW */
+	dcb_cfg->numapps = I40E_DEFAULT_DCB_APP_NUM;
+	dcb_cfg->app[0].selector = I40E_APP_SEL_ETHTYPE;
+	dcb_cfg->app[0].priority = I40E_DEFAULT_DCB_APP_PRIO;
+	dcb_cfg->app[0].protocolid = I40E_APP_PROTOID_FCOE;
+
+	tc_map = RTE_LEN2MASK(info->queue_region_number, uint8_t);
+
+	dcb_cfg->pfc.willing = 0;
+	dcb_cfg->pfc.pfccap = I40E_MAX_TRAFFIC_CLASS;
+	dcb_cfg->pfc.pfcenable = tc_map;
+
+	/* Copy the new config to the current config */
+	*old_cfg = *dcb_cfg;
+	old_cfg->etsrec = old_cfg->etscfg;
+	ret = i40e_set_dcb_config(hw);
+
+	if (ret) {
+		PMD_DRV_LOG(ERR, "Set queue region DCB Config failed, err %s aq_err %s",
+			 i40e_stat_str(hw, ret),
+			 i40e_aq_str(hw, hw->aq.asq_last_status));
+		return ret;
+	}
+
+	return 0;
+}
+
+int
+i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
+	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
+{
+	int32_t ret = -EINVAL;
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	if (on) {
+		i40e_queue_region_pf_flowtype_conf(hw, pf);
+
+		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+			return ret;
+		}
+
+		ret = i40e_queue_region_dcb_configure(hw, pf);
+		if (ret != I40E_SUCCESS) {
+			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+			return ret;
+		}
+
+		return 0;
+	}
+
+	info->queue_region_number = 1;
+	info->region[0].queue_num = 64;
+	info->region[0].queue_start_index = 0;
+
+	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
+	if (ret != I40E_SUCCESS)
+		PMD_DRV_LOG(INFO, "Failed to flush queue region mapping.");
+
+	ret = i40e_dcb_init_configure(dev, TRUE);
+	if (ret != I40E_SUCCESS) {
+		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
+		pf->flags &= ~I40E_FLAG_DCB;
+	}
+
+	i40e_init_queue_region_conf(dev);
+
+	return 0;
+}
+
+static int
+i40e_queue_region_pf_check_rss(struct i40e_pf *pf)
+{
+	struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+	uint64_t hena;
+
+	hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(0));
+	hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_PFQF_HENA(1))) << 32;
+
+	if (!hena)
+		return -ENOTSUP;
+
+	return 0;
+}
+
+static int
+i40e_queue_region_get_all_info(struct i40e_pf *pf,
+		struct i40e_queue_regions *regions_ptr)
+{
+	struct i40e_queue_regions *info = &pf->queue_region;
+
+	rte_memcpy(regions_ptr, info,
+			sizeof(struct i40e_queue_regions));
+
+	return 0;
+}
+
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+		enum rte_pmd_i40e_queue_region_op op_type, void *arg)
+{
+	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+	struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	int32_t ret;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+
+	if (!is_i40e_supported(dev))
+		return -ENOTSUP;
+
+	if (!(!i40e_queue_region_pf_check_rss(pf)))
+		return -ENOTSUP;
+
+	/* This queue region feature only support pf by now. It should
+	 * be called after dev_start, and will be clear after dev_stop.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON"
+	 * is just an enable function which server for other configuration,
+	 * it is for all configuration about queue region from up layer,
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after "FLUSH_ON", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 * "RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF" is
+	 * just clean all configuration about queue region just now,
+	 * and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+
+	switch (op_type) {
+	case RTE_PMD_I40E_QUEUE_REGION_SET:
+		ret = i40e_queue_region_set_region(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_REGION_FLOWTYPE_SET:
+		ret = i40e_queue_region_set_flowtype(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_USER_PRIORITY_REGION_SET:
+		ret = i40e_queue_region_set_user_priority(pf,
+				(struct rte_pmd_i40e_queue_region_conf *)arg);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF:
+		ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+		break;
+	case RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET:
+		ret = i40e_queue_region_get_all_info(pf,
+				(struct i40e_queue_regions *)arg);
+		break;
+	default:
+		PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+			    op_type);
+		ret = -EINVAL;
+	}
+
+	I40E_WRITE_FLUSH(hw);
+
+	return ret;
+}
diff --git a/drivers/net/i40e/rte_pmd_i40e.h b/drivers/net/i40e/rte_pmd_i40e.h
index 8fa5869..63df26f 100644
--- a/drivers/net/i40e/rte_pmd_i40e.h
+++ b/drivers/net/i40e/rte_pmd_i40e.h
@@ -97,7 +97,37 @@ enum rte_pmd_i40e_package_info {
 	RTE_PMD_I40E_PKG_INFO_MAX = 0xFFFFFFFF
 };
 
+/**
+ *  Option types of queue region.
+ */
+enum rte_pmd_i40e_queue_region_op {
+	RTE_PMD_I40E_REGION_UNDEFINED,
+	RTE_PMD_I40E_QUEUE_REGION_SET,      /**< add queue region set */
+	RTE_PMD_I40E_REGION_FLOWTYPE_SET,   /**< add pf region pctype set */
+	/** add queue region user priority set */
+	RTE_PMD_I40E_USER_PRIORITY_REGION_SET,
+	/**
+	 * ALL configuration about queue region from up layer
+	 * at first will only keep in DPDK softwarestored in driver,
+	 * only after " FLUSH_ON ", it commit all configuration to HW.
+	 * Because PMD had to set hardware configuration at a time, so
+	 * it will record all up layer command at first.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON,
+	/**
+	 * "FLUSH_OFF " is just clean all configuration about queue
+	 * region just now, and restore all to DPDK i40e driver default
+	 * config when start up.
+	 */
+	RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET,
+	RTE_PMD_I40E_RSS_QUEUE_REGION_OP_MAX
+};
+
 #define RTE_PMD_I40E_DDP_NAME_SIZE 32
+#define RTE_PMD_I40E_PCTYPE_MAX 64
+#define RTE_PMD_I40E_REGION_MAX_NUM 8
+#define RTE_PMD_I40E_MAX_USER_PRIORITY		8
 
 /**
  * Version for dynamic device personalization.
@@ -171,6 +201,55 @@ struct rte_pmd_i40e_ptype_mapping {
 };
 
 /**
+ * Queue region related information.
+ */
+struct rte_pmd_i40e_queue_region_conf {
+	/** the region id for this configuration */
+	uint8_t region_id;
+	/** the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype;
+	/** the start queue index for this region */
+	uint8_t queue_start_index;
+	/** the total queue number of this queue region */
+	uint8_t queue_num;
+	/** the packet's user priority for this region */
+	uint8_t user_priority;
+};
+
+/* queue region info */
+struct rte_pmd_i40e_queue_region_info {
+	/* the region id for this configuration */
+	uint8_t region_id;
+	/* the start queue index for this region */
+	uint8_t queue_start_index;
+	/* the total queue number of this queue region */
+	uint8_t queue_num;
+	/* the total number of user priority for this region */
+	uint8_t user_priority_num;
+	/* the packet's user priority for this region */
+	uint8_t user_priority[RTE_PMD_I40E_MAX_USER_PRIORITY];
+	/* the total number of flowtype for this region */
+	uint8_t flowtype_num;
+	/**
+	 * the pctype or hardware flowtype of packet,
+	 * the specific index for each type has been defined
+	 * in file i40e_type.h as enum i40e_filter_pctype.
+	 */
+	uint8_t hw_flowtype[RTE_PMD_I40E_PCTYPE_MAX];
+};
+
+struct rte_pmd_i40e_queue_regions {
+	/* the total number of queue region for this port */
+	uint16_t queue_region_number;
+	struct rte_pmd_i40e_queue_region_info
+		region[RTE_PMD_I40E_REGION_MAX_NUM];
+};
+
+
+/**
  * Notify VF when PF link status changes.
  *
  * @param port
@@ -737,4 +816,16 @@ int rte_pmd_i40e_flow_type_mapping_get(
  */
 int rte_pmd_i40e_flow_type_mapping_reset(uint8_t port);
 
+/**
+ * Do RSS queue region configuration for that port as
+ * the command option type
+ *
+ * @param port_id
+ *    port id for that port device
+ * @param rss_region_conf
+ *    pointer to the struct that contain all the
+ *    region configuration parameters
+ */
+int rte_pmd_i40e_rss_queue_region_conf(uint16_t port_id,
+			enum rte_pmd_i40e_queue_region_op op_type, void *arg);
 #endif /* _PMD_I40E_H_ */
diff --git a/drivers/net/i40e/rte_pmd_i40e_version.map b/drivers/net/i40e/rte_pmd_i40e_version.map
index 9292454..81946ae 100644
--- a/drivers/net/i40e/rte_pmd_i40e_version.map
+++ b/drivers/net/i40e/rte_pmd_i40e_version.map
@@ -53,5 +53,5 @@ DPDK_17.11 {
 	rte_pmd_i40e_flow_type_mapping_update;
 	rte_pmd_i40e_flow_type_mapping_get;
 	rte_pmd_i40e_flow_type_mapping_reset;
-
+	rte_pmd_i40e_rss_queue_region_conf;
 } DPDK_17.08;
-- 
2.7.4

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

* [PATCH v8 2/2] app/testpmd: add API for configuration of queue region
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-10-11  8:55               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-10-11  8:55               ` Wei Zhao
  2017-10-11 11:29               ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
  2017-10-11 21:06               ` Ferruh Yigit
  3 siblings, 0 replies; 87+ messages in thread
From: Wei Zhao @ 2017-10-11  8:55 UTC (permalink / raw)
  To: dev; +Cc: Wei Zhao

This patch add a API configuration of queue region in rss.
It can parse the parameters of region index, queue number,
queue start index, user priority, traffic classes and so on.
According to commands from command line, it will call i40e
private API and start the process of set or flush queue region
configure. As this feature is specific for i40e, so private API
will be used. Aslo add a document for these new commands.
Queue region only support PF by now, so this document is
only for configuration of queue region on PF port.

Signed-off-by: Wei Zhao <wei.zhao1@intel.com>
---
 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |  44 +++
 app/test-pmd/testpmd.h                      |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 4 files changed, 512 insertions(+)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index f996ee3..f873b29 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -660,6 +660,24 @@ static void cmd_help_long_parsed(void *parsed_result,
 			"ptype mapping update (port_id) (hw_ptype) (sw_ptype)\n"
 			"    Update a ptype mapping item on a port\n\n"
 
+			"set port (port_id) queue-region region_id (value) "
+			"queue_start_index (value) queue_num (value)\n"
+			"    Set a queue region on a port\n\n"
+
+			"set port (port_id) queue-region region_id (value) "
+			"flowtype (value)\n"
+			"    Set a flowtype region index on a port\n\n"
+
+			"set port (port_id) queue-region UP (value) region_id (value)\n"
+			"    Set the mapping of User Priority to "
+			"queue region on a port\n\n"
+
+			"set port (port_id) queue-region flush (on|off)\n"
+			"    flush all queue region related configuration\n\n"
+
+			"show port (port_id) queue-region\n"
+			"    show all queue region related configuration info\n\n"
+
 			, list_pkt_forwarding_modes()
 		);
 	}
@@ -8469,6 +8487,407 @@ cmdline_parse_inst_t cmd_syn_filter = {
 	},
 };
 
+/* *** queue region set *** */
+struct cmd_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t queue_start_index;
+	uint8_t  queue_id;
+	cmdline_fixed_string_t queue_num;
+	uint8_t  queue_num_value;
+};
+
+static void
+cmd_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_queue_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	op_type = RTE_PMD_I40E_QUEUE_REGION_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.queue_num = res->queue_num_value;
+	region_conf.queue_start_index = res->queue_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_queue_region_set =
+TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+		set, "set");
+cmdline_parse_token_string_t cmd_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result, port, "port");
+cmdline_parse_token_num_t cmd_queue_region_port_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				 cmd, "queue-region");
+cmdline_parse_token_string_t cmd_queue_region_id =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_queue_region_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_start_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_start_index, "queue_start_index");
+cmdline_parse_token_num_t cmd_queue_region_queue_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_id, UINT8);
+cmdline_parse_token_string_t cmd_queue_region_queue_num =
+	TOKEN_STRING_INITIALIZER(struct cmd_queue_region_result,
+				queue_num, "queue_num");
+cmdline_parse_token_num_t cmd_queue_region_queue_num_value =
+	TOKEN_NUM_INITIALIZER(struct cmd_queue_region_result,
+				queue_num_value, UINT8);
+
+cmdline_parse_inst_t cmd_queue_region = {
+	.f = cmd_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"queue_start_index <value> queue_num <value>: Set a queue region",
+	.tokens = {
+		(void *)&cmd_queue_region_set,
+		(void *)&cmd_queue_region_port,
+		(void *)&cmd_queue_region_port_id,
+		(void *)&cmd_queue_region_cmd,
+		(void *)&cmd_queue_region_id,
+		(void *)&cmd_queue_region_index,
+		(void *)&cmd_queue_region_queue_start_index,
+		(void *)&cmd_queue_region_queue_id,
+		(void *)&cmd_queue_region_queue_num,
+		(void *)&cmd_queue_region_queue_num_value,
+		NULL,
+	},
+};
+
+/* *** queue region and flowtype set *** */
+struct cmd_region_flowtype_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+	cmdline_fixed_string_t flowtype;
+	uint8_t  flowtype_id;
+};
+
+static void
+cmd_region_flowtype_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_region_flowtype_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	op_type = RTE_PMD_I40E_REGION_FLOWTYPE_SET;
+	region_conf.region_id = res->region_id;
+	region_conf.hw_flowtype = res->flowtype_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+			op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("region flowtype config programming error: (%s)\n",
+				strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_region_flowtype_set =
+TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_region_flowtype_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_region_flowtype_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_region_flowtype_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_region_flowtype_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				region_id, UINT8);
+cmdline_parse_token_string_t cmd_region_flowtype_flow_index =
+	TOKEN_STRING_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype, "flowtype");
+cmdline_parse_token_num_t cmd_region_flowtype_flow_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_region_flowtype_result,
+				flowtype_id, UINT8);
+cmdline_parse_inst_t cmd_region_flowtype = {
+	.f = cmd_region_flowtype_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region region_id <value> "
+		"flowtype <value>: Set a flowtype region index",
+	.tokens = {
+		(void *)&cmd_region_flowtype_set,
+		(void *)&cmd_region_flowtype_port,
+		(void *)&cmd_region_flowtype_port_index,
+		(void *)&cmd_region_flowtype_cmd,
+		(void *)&cmd_region_flowtype_index,
+		(void *)&cmd_region_flowtype_id,
+		(void *)&cmd_region_flowtype_flow_index,
+		(void *)&cmd_region_flowtype_flow_id,
+		NULL,
+	},
+};
+
+/* *** User Priority (UP) to queue region (region_id) set *** */
+struct cmd_user_priority_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t user_priority;
+	uint8_t  user_priority_id;
+	cmdline_fixed_string_t region;
+	uint8_t  region_id;
+};
+
+static void
+cmd_user_priority_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_user_priority_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+	op_type = RTE_PMD_I40E_USER_PRIORITY_REGION_SET;
+	region_conf.user_priority = res->user_priority_id;
+	region_conf.region_id = res->region_id;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("user_priority region config programming "
+			"error: (%s)\n", strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_user_priority_region_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_user_priority_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_user_priority_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_user_priority_region_UP =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority, "UP");
+cmdline_parse_token_num_t cmd_user_priority_region_UP_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				user_priority_id, UINT8);
+cmdline_parse_token_string_t cmd_user_priority_region_region =
+	TOKEN_STRING_INITIALIZER(struct cmd_user_priority_region_result,
+				region, "region_id");
+cmdline_parse_token_num_t cmd_user_priority_region_region_id =
+	TOKEN_NUM_INITIALIZER(struct cmd_user_priority_region_result,
+				region_id, UINT8);
+
+cmdline_parse_inst_t cmd_user_priority_region = {
+	.f = cmd_user_priority_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region UP <value> "
+		"region_id <value>: Set the mapping of User Priority (UP) "
+		"to queue region (region_id) ",
+	.tokens = {
+		(void *)&cmd_user_priority_region_set,
+		(void *)&cmd_user_priority_region_port,
+		(void *)&cmd_user_priority_region_port_index,
+		(void *)&cmd_user_priority_region_cmd,
+		(void *)&cmd_user_priority_region_UP,
+		(void *)&cmd_user_priority_region_UP_id,
+		(void *)&cmd_user_priority_region_region,
+		(void *)&cmd_user_priority_region_region_id,
+		NULL,
+	},
+};
+
+/* *** flush all queue region related configuration *** */
+struct cmd_flush_queue_region_result {
+	cmdline_fixed_string_t set;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+	cmdline_fixed_string_t flush;
+	cmdline_fixed_string_t what;
+};
+
+static void
+cmd_flush_queue_region_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_flush_queue_region_result *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_region_conf region_conf;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&region_conf, 0, sizeof(region_conf));
+
+	if (strcmp(res->what, "on") == 0)
+		op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_ON;
+	else
+		op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_ALL_FLUSH_OFF;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+				op_type, &region_conf);
+#endif
+
+	if (ret < 0)
+		printf("queue region config flush error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_flush_queue_region_set =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				set, "set");
+cmdline_parse_token_string_t cmd_flush_queue_region_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				port, "port");
+cmdline_parse_token_num_t cmd_flush_queue_region_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_flush_queue_region_result,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_flush_queue_region_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				cmd, "queue-region");
+cmdline_parse_token_string_t cmd_flush_queue_region_flush =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				flush, "flush");
+cmdline_parse_token_string_t cmd_flush_queue_region_what =
+	TOKEN_STRING_INITIALIZER(struct cmd_flush_queue_region_result,
+				what, "on#off");
+
+cmdline_parse_inst_t cmd_flush_queue_region = {
+	.f = cmd_flush_queue_region_parsed,
+	.data = NULL,
+	.help_str = "set port <port_id> queue-region flush on|off"
+		": flush all queue region related configuration",
+	.tokens = {
+		(void *)&cmd_flush_queue_region_set,
+		(void *)&cmd_flush_queue_region_port,
+		(void *)&cmd_flush_queue_region_port_index,
+		(void *)&cmd_flush_queue_region_cmd,
+		(void *)&cmd_flush_queue_region_flush,
+		(void *)&cmd_flush_queue_region_what,
+		NULL,
+	},
+};
+
+/* *** get all queue region related configuration info *** */
+struct cmd_show_queue_region_info {
+	cmdline_fixed_string_t show;
+	cmdline_fixed_string_t port;
+	uint8_t  port_id;
+	cmdline_fixed_string_t cmd;
+};
+
+static void
+cmd_show_queue_region_info_parsed(void *parsed_result,
+			__attribute__((unused)) struct cmdline *cl,
+			__attribute__((unused)) void *data)
+{
+	struct cmd_show_queue_region_info *res = parsed_result;
+	int ret = -ENOTSUP;
+#ifdef RTE_LIBRTE_I40E_PMD
+	struct rte_pmd_i40e_queue_regions rte_pmd_regions;
+	enum rte_pmd_i40e_queue_region_op op_type;
+
+	if (port_id_is_invalid(res->port_id, ENABLED_WARN))
+		return;
+
+	memset(&rte_pmd_regions, 0, sizeof(rte_pmd_regions));
+
+	op_type = RTE_PMD_I40E_RSS_QUEUE_REGION_INFO_GET;
+
+	ret = rte_pmd_i40e_rss_queue_region_conf(res->port_id,
+					op_type, &rte_pmd_regions);
+
+	port_queue_region_info_display(res->port_id, &rte_pmd_regions);
+
+#endif
+
+	if (ret < 0)
+		printf("queue region config info show error: (%s)\n",
+					strerror(-ret));
+}
+
+cmdline_parse_token_string_t cmd_show_queue_region_info_get =
+TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				show, "show");
+cmdline_parse_token_string_t cmd_show_queue_region_info_port =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				port, "port");
+cmdline_parse_token_num_t cmd_show_queue_region_info_port_index =
+	TOKEN_NUM_INITIALIZER(struct cmd_show_queue_region_info,
+				port_id, UINT8);
+cmdline_parse_token_string_t cmd_show_queue_region_info_cmd =
+	TOKEN_STRING_INITIALIZER(struct cmd_show_queue_region_info,
+				cmd, "queue-region");
+
+cmdline_parse_inst_t cmd_show_queue_region_info_all = {
+	.f = cmd_show_queue_region_info_parsed,
+	.data = NULL,
+	.help_str = "show port <port_id> queue-region"
+		": show all queue region related configuration info",
+	.tokens = {
+		(void *)&cmd_show_queue_region_info_get,
+		(void *)&cmd_show_queue_region_info_port,
+		(void *)&cmd_show_queue_region_info_port_index,
+		(void *)&cmd_show_queue_region_info_cmd,
+		NULL,
+	},
+};
+
 /* *** ADD/REMOVE A 2tuple FILTER *** */
 struct cmd_2tuple_filter_result {
 	cmdline_fixed_string_t filter;
@@ -15130,6 +15549,11 @@ cmdline_parse_ctx_t main_ctx[] = {
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_get,
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_reset,
 	(cmdline_parse_inst_t *)&cmd_pctype_mapping_update,
+	(cmdline_parse_inst_t *)&cmd_queue_region,
+	(cmdline_parse_inst_t *)&cmd_region_flowtype,
+	(cmdline_parse_inst_t *)&cmd_user_priority_region,
+	(cmdline_parse_inst_t *)&cmd_flush_queue_region,
+	(cmdline_parse_inst_t *)&cmd_show_queue_region_info_all,
 	NULL,
 };
 
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 7ff0bb2..8049c32 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -71,6 +71,9 @@
 #ifdef RTE_LIBRTE_IXGBE_PMD
 #include <rte_pmd_ixgbe.h>
 #endif
+#ifdef RTE_LIBRTE_I40E_PMD
+#include <rte_pmd_i40e.h>
+#endif
 #ifdef RTE_LIBRTE_BNXT_PMD
 #include <rte_pmd_bnxt.h>
 #endif
@@ -3468,3 +3471,44 @@ close_ddp_package_file(uint8_t *buf)
 
 	return -1;
 }
+
+void
+port_queue_region_info_display(uint8_t port_id,
+			void *buf)
+{
+#ifdef RTE_LIBRTE_I40E_PMD
+	uint16_t i, j;
+	struct rte_pmd_i40e_queue_regions *info =
+		(struct rte_pmd_i40e_queue_regions *)buf;
+	static const char *queue_region_info_stats_border = "-------";
+
+	if (!info->queue_region_number)
+		printf("there is no region has been set before");
+
+	printf("\n	%s All queue region info for port=%2d %s",
+			queue_region_info_stats_border, port_id,
+			queue_region_info_stats_border);
+	printf("\n	queue_region_number: %-14u \n",
+			info->queue_region_number);
+
+	for (i = 0; i < info->queue_region_number; i++) {
+		printf("\n	region_id: %-14u queue_number: %-14u "
+			"queue_start_index: %-14u \n",
+			info->region[i].region_id,
+			info->region[i].queue_num,
+			info->region[i].queue_start_index);
+
+		printf("  user_priority_num is	%-14u :",
+					info->region[i].user_priority_num);
+		for (j = 0; j < info->region[i].user_priority_num; j++)
+			printf(" %-14u ", info->region[i].user_priority[j]);
+
+		printf("\n	flowtype_num is  %-14u :",
+				info->region[i].flowtype_num);
+		for (j = 0; j < info->region[i].flowtype_num; j++)
+			printf(" %-14u ", info->region[i].hw_flowtype[j]);
+	}
+#endif
+
+	printf("\n\n");
+}
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 7c79f17..10aeeeb 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -718,6 +718,9 @@ uint8_t *open_ddp_package_file(const char *file_path, uint32_t *size);
 int save_ddp_package_file(const char *file_path, uint8_t *buf, uint32_t size);
 int close_ddp_package_file(uint8_t *buf);
 
+void port_queue_region_info_display(uint8_t port_id,
+			void *buf);
+
 enum print_warning {
 	ENABLED_WARN = 0,
 	DISABLED_WARN
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 7f37f91..c67d251 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -857,6 +857,47 @@ Where:
 
    Check the NIC Datasheet for hardware limits.
 
+RSS queue region
+~~~~~~~~~~~~~~~~
+
+Set RSS queue region span on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) \
+		queue_start_index (value) queue_num (value)
+
+Set flowtype mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region region_id (value) flowtype (value)
+
+where:
+
+* For the flowtype(pctype) of packet,the specific index for each type has
+  been defined in file i40e_type.h as enum i40e_filter_pctype.
+
+Set user priority mapping on a RSS queue region on a port::
+
+   testpmd> set port (port_id) queue-region UP (value) region_id (value)
+
+Flush all queue region related configuration on a port::
+
+   testpmd> set port (port_id) queue-region flush (on|off)
+
+where:
+* "on"is just an enable function which server for other configuration,
+  it is for all configuration about queue region from up layer,
+  at first will only keep in DPDK softwarestored in driver,
+  only after "flush on", it commit all configuration to HW.
+  "off" is just clean all configuration about queue region just now,
+  and restore all to DPDK i40e driver default config when start up.
+
+Show all queue region related configuration info on a port::
+
+   testpmd> show port (port_id) queue-region
+
+.. note::
+Queue region only support on PF by now, so these command is
+only for configuration of queue region on PF port.
+
 csum parse-tunnel
 ~~~~~~~~~~~~~~~~~
 
-- 
2.7.4

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

* Re: [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
  2017-10-11  8:55               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
  2017-10-11  8:55               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
@ 2017-10-11 11:29               ` Peng, Yuan
  2017-10-11 21:06               ` Ferruh Yigit
  3 siblings, 0 replies; 87+ messages in thread
From: Peng, Yuan @ 2017-10-11 11:29 UTC (permalink / raw)
  To: Zhao1, Wei, dev

Tested-by: Peng Yuan <yuan.peng@intel.com>

- Tested Branch: dpdk-master
- Tested Commit: 7a8889324654c9e39f9e18097ccc74d6ff2588cf
- OS: 4.5.5-300.fc24.x86_64
- GCC: gcc (GCC) 5.3.1 20151207 (Red Hat 5.3.1-2)
- CPU: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
- NIC: Intel Corporation Device Fortville [8086:1572]
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites:
- Total 3 cases, 3 passed, 0 failed

- Prerequisites command / instruction:
1. Hardware:
   Fortville

2. software:
   dpdk: http://dpdk.org/git/dpdk
   scapy: http://www.secdev.org/projects/scapy/

3. bind the port to dpdk driver::

    ./usertools/dpdk-devbind.py -b igb_uio 05:00.0

   the mac address of 05:00.0 is 00:00:00:00:01:00

4. start the testpmd::

    ./x86_64-native-linuxapp-gcc/app/testpmd -c 1ffff -n 4 -- -i --rxq=16 --txq=16
    testpmd> port config all rss all
    testpmd> set fwd rxonly
    testpmd> set verbose 1
    testpmd> start

- Cases:

Test case 1: different pctype packet can enter the expected queue region
========================================================================

1. Set queue region on a port::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 1 queue_num 1
    testpmd> set port 0 queue-region region_id 1 queue_start_index 3 queue_num 2
    testpmd> set port 0 queue-region region_id 2 queue_start_index 6 queue_num 2
    testpmd> set port 0 queue-region region_id 3 queue_start_index 8 queue_num 2
    testpmd> set port 0 queue-region region_id 4 queue_start_index 11 queue_num 4
    testpmd> set port 0 queue-region region_id 5 queue_start_index 15 queue_num 1

2. Set the mapping of flowtype to region index on a port::

    testpmd> set port 0 queue-region region_id 0 flowtype 31
    testpmd> set port 0 queue-region region_id 1 flowtype 32
    testpmd> set port 0 queue-region region_id 2 flowtype 33
    testpmd> set port 0 queue-region region_id 3 flowtype 34
    testpmd> set port 0 queue-region region_id 4 flowtype 35
    testpmd> set port 0 queue-region region_id 5 flowtype 45
    testpmd> set port 0 queue-region region_id 2 flowtype 41
    testpmd> set port 0 queue-region flush on

3. send packet::

    pkt1 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=23,dport=24)/Raw('x'*20)
    pkt2 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=33,dport=34,flags="S")/Raw('x'*20)
    pkt3 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=33,dport=34,flags="PA")/Raw('x' * 20)
    pkt4 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/SCTP(sport=44,dport=45,tag=1)/SCTPChunkData(data="X" * 20)
    pkt5 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.1", dst="192.168.0.2")/Raw('x'*20)
    pkt6 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IPv6(src="2001::1", dst="2001::2")/Raw('x' * 20)
    pkt7 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IPv6(src="2001::1", dst="2001::2")/UDP(sport=24,dport=25)/Raw('x'*20)
    pkt8 = Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=1)/IP(src="192.168.0.1", dst="192.168.0.2")/Raw('x'*20)

   verify the pkt1 to queue 1, pkt2 to queue 3 or queue 4,
   pkt3 to queue 6 or queue 7, pkt4 to queue 8 or queue 9,
   pkt5 to queue 11 or 12 or 13 or 14,
   pkt6 to queue 15, pkt7 to queue 6 or queue 7,
   pkt8 enter the same queue with pkt5.

4. verified the rules can be listed and flushed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off

Notes: fortville can't parse the TCP SYN type packet, fortpark can parse it.
So if fortville, pkt2 to queue 6 or queue 7.

Test case 2: different user priority packet can enter the expected queue region
===============================================================================

1. Set queue region on a port::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 0 queue_num 1
    testpmd> set port 0 queue-region region_id 7 queue_start_index 1 queue_num 8
    testpmd> set port 0 queue-region region_id 2 queue_start_index 10 queue_num 4

2. Set the mapping of User Priority to Traffic Classes on a port::

    testpmd> set port 0 queue-region UP 3 region_id 0
    testpmd> set port 0 queue-region UP 1 region_id 7
    testpmd> set port 0 queue-region UP 2 region_id 2
    testpmd> set port 0 queue-region UP 7 region_id 2
    testpmd> set port 0 queue-region flush on

3. send packet::

    pkt1=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=3)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt2=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=1)/IP(src="192.168.0.1", dst="192.168.0.2")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt3=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=2)/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=32, dport=33)/Raw('x'*20)
    pkt4=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=7)/IP(src="192.168.0.1", dst="192.168.0.2")/TCP(sport=32, dport=33)/Raw('x'*20)
    pkt5=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/Dot1Q(prio=7)/IP(src="192.168.0.3", dst="192.168.0.4")/UDP(sport=22, dport=23)/Raw('x'*20)
    pkt6=Ether(dst="00:00:00:00:01:00", src="00:02:00:00:00:01")/IP(src="192.168.0.3", dst="192.168.0.4")/UDP(sport=22, dport=23)/Raw('x'*20)

   verify the pkt1 to queue 0,
   pkt2 to queue 1 or 2 or 3 or 4 or 5 or 6 or 7 or 8.
   pkt3 to queue 10 or 11 or 12 or 13.
   pkt4 enter the same queue with pkt3.
   pkt5 to queue 10 or 11 or 12 or 13.
   pkt6 enter different queue from pkt5.

4. verified the rules can be listed and flushed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off

Test case 3: boundary value testing
===================================

1. boundary value testing of "Set a queue region on a port"

   the following three rules are set successfully::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 0 queue_num 16
    testpmd> set port 0 queue-region flush on
    testpmd> set port 0 queue-region flush off
    testpmd> set port 0 queue-region region_id 0 queue_start_index 15 queue_num 1
    testpmd> set port 0 queue-region flush on
    testpmd> set port 0 queue-region flush off
    testpmd> set port 0 queue-region region_id 7 queue_start_index 2 queue_num 8
    testpmd> set port 0 queue-region flush on

   all the three rules can be listed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off

   the following four rules can't be set successfully.::

    testpmd> set port 0 queue-region region_id 8 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 1 queue_start_index 16 queue_num 1
    testpmd> set port 0 queue-region region_id 2 queue_start_index 15 queue_num 2
    testpmd> set port 0 queue-region region_id 3 queue_start_index 2 queue_num 3

   no rules can be listed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off

2. boundary value testing of "Set the mapping of flowtype to region index
   on a port"::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 7 queue_start_index 4 queue_num 4

   the first two rules can be set successfully::

    testpmd> set port 0 queue-region region_id 0 flowtype 63
    testpmd> set port 0 queue-region region_id 7 flowtype 0

   the first two rules can be listed::

    testpmd> show port 0 queue-region

   the last two rule can't be set successfully::

    testpmd> set port 0 queue-region region_id 0 flowtype 64
    testpmd> set port 0 queue-region region_id 2 flowtype 34
    testpmd> set port 0 queue-region flush on

   the last two rules can't be listed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off

3. boundary value testing of "Set the mapping of UP to region index
   on a port"::

    testpmd> set port 0 queue-region region_id 0 queue_start_index 2 queue_num 2
    testpmd> set port 0 queue-region region_id 7 queue_start_index 4 queue_num 4

   the first two rules can be set successfully::

    testpmd> set port 0 queue-region UP 7 region_id 0
    testpmd> set port 0 queue-region UP 0 region_id 7

   the first two rules can be listed::

    testpmd> show port 0 queue-region

   the last two rule can't be set successfully::

    testpmd> set port 0 queue-region UP 8 region_id 0
    testpmd> set port 0 queue-region UP 1 region_id 2
    testpmd> set port 0 queue-region flush on

   the last two rules can't be listed::

    testpmd> show port 0 queue-region
    testpmd> set port 0 queue-region flush off


-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
Sent: Wednesday, October 11, 2017 4:56 PM
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS

The patches mainly finish following functions:
1) Command line for input queue region configure parameters.
2) Set or flush queue region configutation.

v2:
-fix bug for packet into queue region code.
-change code style for DPDK C programing.
-change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf

v3:
-fix patch check warning
-fix a bug in cmdline.c

v4:
-fix bug for flowtype config.
-add a new command for get all queue region configuration.
-change function name to "rss" related.
-add document info about queue region CLI.

v5:
-fix patchcheck warning.
-add port id check.

v6:
-split this patch set into 2 patch.

v7:
-change some PMD_DRV_LOG log.

v8:
-change CLI command format.
-change some functions name.

root (2):
  net/i40e: queue region set and flush
  app/testpmd: add API for configuration of queue region

 app/test-pmd/cmdline.c                      | 424 ++++++++++++++++++++++++
 app/test-pmd/config.c                       |  44 +++
 app/test-pmd/testpmd.h                      |   3 +
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  41 +++
 drivers/net/i40e/i40e_ethdev.c              |  27 +-
 drivers/net/i40e/i40e_ethdev.h              |  39 +++
 drivers/net/i40e/rte_pmd_i40e.c             | 494 ++++++++++++++++++++++++++++
 drivers/net/i40e/rte_pmd_i40e.h             |  91 +++++
 drivers/net/i40e/rte_pmd_i40e_version.map   |   2 +-
 9 files changed, 1158 insertions(+), 7 deletions(-)

-- 
2.7.4

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

* Re: [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS
  2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
                                 ` (2 preceding siblings ...)
  2017-10-11 11:29               ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
@ 2017-10-11 21:06               ` Ferruh Yigit
  2017-10-13  1:52                 ` Zhao1, Wei
  3 siblings, 1 reply; 87+ messages in thread
From: Ferruh Yigit @ 2017-10-11 21:06 UTC (permalink / raw)
  To: Wei Zhao, dev

On 10/11/2017 9:55 AM, Wei Zhao wrote:
> The patches mainly finish following functions:
> 1) Command line for input queue region configure parameters.
> 2) Set or flush queue region configutation.
> 
> v2:
> -fix bug for packet into queue region code.
> -change code style for DPDK C programing.
> -change that "flowtype" name to  " hw_flowtype " in struct rte_i40e_rss_region_conf
> 
> v3:
> -fix patch check warning
> -fix a bug in cmdline.c
> 
> v4:
> -fix bug for flowtype config.
> -add a new command for get all queue region configuration.
> -change function name to "rss" related.
> -add document info about queue region CLI.
> 
> v5:
> -fix patchcheck warning.
> -add port id check.
> 
> v6:
> -split this patch set into 2 patch.
> 
> v7:
> -change some PMD_DRV_LOG log.
> 
> v8:
> -change CLI command format.
> -change some functions name.
> 
> root (2):
>   net/i40e: queue region set and flush
>   app/testpmd: add API for configuration of queue region

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

(patches updated here and there based on previous comments, please
confirm latest commit.)

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

* Re: [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS
  2017-10-11 21:06               ` Ferruh Yigit
@ 2017-10-13  1:52                 ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-13  1:52 UTC (permalink / raw)
  To: Yigit, Ferruh, dev

Thank you.


> -----Original Message-----
> From: Yigit, Ferruh
> Sent: Thursday, October 12, 2017 5:07 AM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v8 0/2] net/i40e: API to configure queue
> regions for RSS
> 
> On 10/11/2017 9:55 AM, Wei Zhao wrote:
> > The patches mainly finish following functions:
> > 1) Command line for input queue region configure parameters.
> > 2) Set or flush queue region configutation.
> >
> > v2:
> > -fix bug for packet into queue region code.
> > -change code style for DPDK C programing.
> > -change that "flowtype" name to  " hw_flowtype " in struct
> > rte_i40e_rss_region_conf
> >
> > v3:
> > -fix patch check warning
> > -fix a bug in cmdline.c
> >
> > v4:
> > -fix bug for flowtype config.
> > -add a new command for get all queue region configuration.
> > -change function name to "rss" related.
> > -add document info about queue region CLI.
> >
> > v5:
> > -fix patchcheck warning.
> > -add port id check.
> >
> > v6:
> > -split this patch set into 2 patch.
> >
> > v7:
> > -change some PMD_DRV_LOG log.
> >
> > v8:
> > -change CLI command format.
> > -change some functions name.
> >
> > root (2):
> >   net/i40e: queue region set and flush
> >   app/testpmd: add API for configuration of queue region
> 
> Series applied to dpdk-next-net/master, thanks.
> 
> (patches updated here and there based on previous comments, please
> confirm latest commit.)

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

* Re: [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-11  8:55               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
@ 2017-10-13 10:06                 ` Chilikin, Andrey
  2017-10-18  3:00                   ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Chilikin, Andrey @ 2017-10-13 10:06 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Zhao1, Wei, Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi Wei

Sorry for the late comment, but I was not included to the patchset CC list and just found this new version.

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> Sent: Wednesday, October 11, 2017 9:56 AM
> To: dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>
> Subject: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and flush


<snip>

> +int
> +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on)
> +{
> +	int32_t ret = -EINVAL;
> +	struct i40e_queue_regions *info = &pf->queue_region;
> +
> +	if (on) {
> +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> +
> +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> +		if (ret != I40E_SUCCESS) {
> +			PMD_DRV_LOG(INFO, "Failed to flush queue region
> mapping.");
> +			return ret;
> +		}
> +
> +		ret = i40e_queue_region_dcb_configure(hw, pf);
> +		if (ret != I40E_SUCCESS) {
> +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> +			return ret;
> +		}
> +
> +		return 0;
> +	}
> +
> +	info->queue_region_number = 1;
> +	info->region[0].queue_num = 64;

Why number of queues is hardcoded to a magic number 64? How it will work if VSI is enabled with smaller number of queues, for example, 1 or 6? 64 is the maximum number of queues that can be used for RSS, but VSI might be created with only few queues.

> +	info->region[0].queue_start_index = 0;
> +
> +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> +	if (ret != I40E_SUCCESS)
> +		PMD_DRV_LOG(INFO, "Failed to flush queue region
> mapping.");
> +
> +	ret = i40e_dcb_init_configure(dev, TRUE);
> +	if (ret != I40E_SUCCESS) {
> +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> +		pf->flags &= ~I40E_FLAG_DCB;
> +	}
> +
> +	i40e_init_queue_region_conf(dev);
> +
> +	return 0;
> +}

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

* Re: [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-13 10:06                 ` Chilikin, Andrey
@ 2017-10-18  3:00                   ` Zhao1, Wei
  2017-10-18 13:00                     ` Chilikin, Andrey
  0 siblings, 1 reply; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-18  3:00 UTC (permalink / raw)
  To: Chilikin, Andrey, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi,Andrey

> -----Original Message-----
> From: Chilikin, Andrey
> Sent: Friday, October 13, 2017 6:07 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and flush
> 
> Hi Wei
> 
> Sorry for the late comment, but I was not included to the patchset CC list and
> just found this new version.
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > Sent: Wednesday, October 11, 2017 9:56 AM
> > To: dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > Subject: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and
> > flush
> 
> 
> <snip>
> 
> > +int
> > +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> > +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on) {
> > +	int32_t ret = -EINVAL;
> > +	struct i40e_queue_regions *info = &pf->queue_region;
> > +
> > +	if (on) {
> > +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> > +
> > +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > +		if (ret != I40E_SUCCESS) {
> > +			PMD_DRV_LOG(INFO, "Failed to flush queue region
> > mapping.");
> > +			return ret;
> > +		}
> > +
> > +		ret = i40e_queue_region_dcb_configure(hw, pf);
> > +		if (ret != I40E_SUCCESS) {
> > +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > +			return ret;
> > +		}
> > +
> > +		return 0;
> > +	}
> > +
> > +	info->queue_region_number = 1;
> > +	info->region[0].queue_num = 64;
> 
> Why number of queues is hardcoded to a magic number 64? How it will work
> if VSI is enabled with smaller number of queues, for example, 1 or 6? 64 is
> the maximum number of queues that can be used for RSS, but VSI might be
> created with only few queues.

Yes, I know what is your mean, may be it should be change to 

struct i40e_vsi *main_vsi = pf->main_vsi;
info->region[0].queue_num = main_vsi->nb_used_qps;

Do you think so?

> 
> > +	info->region[0].queue_start_index = 0;
> > +
> > +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > +	if (ret != I40E_SUCCESS)
> > +		PMD_DRV_LOG(INFO, "Failed to flush queue region
> > mapping.");
> > +
> > +	ret = i40e_dcb_init_configure(dev, TRUE);
> > +	if (ret != I40E_SUCCESS) {
> > +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > +		pf->flags &= ~I40E_FLAG_DCB;
> > +	}
> > +
> > +	i40e_init_queue_region_conf(dev);
> > +
> > +	return 0;
> > +}

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

* Re: [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-18  3:00                   ` Zhao1, Wei
@ 2017-10-18 13:00                     ` Chilikin, Andrey
  2017-10-19  2:18                       ` Zhao1, Wei
  0 siblings, 1 reply; 87+ messages in thread
From: Chilikin, Andrey @ 2017-10-18 13:00 UTC (permalink / raw)
  To: Zhao1, Wei, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi Wei,

Is there number of RX queues configured for the port? 
If main_vsi->nb_used_qps reflects number of enabled RX queues, then it can be used.

Regards,
Andrey

> -----Original Message-----
> From: Zhao1, Wei
> Sent: Wednesday, October 18, 2017 4:01 AM
> To: Chilikin, Andrey <andrey.chilikin@intel.com>; dev@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and flush
> 
> Hi,Andrey
> 
> > -----Original Message-----
> > From: Chilikin, Andrey
> > Sent: Friday, October 13, 2017 6:07 PM
> > To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> > <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>
> > Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and
> flush
> >
> > Hi Wei
> >
> > Sorry for the late comment, but I was not included to the patchset CC list
> and
> > just found this new version.
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > > Sent: Wednesday, October 11, 2017 9:56 AM
> > > To: dev@dpdk.org
> > > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > > Subject: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and
> > > flush
> >
> >
> > <snip>
> >
> > > +int
> > > +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> > > +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on) {
> > > +	int32_t ret = -EINVAL;
> > > +	struct i40e_queue_regions *info = &pf->queue_region;
> > > +
> > > +	if (on) {
> > > +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> > > +
> > > +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > > +		if (ret != I40E_SUCCESS) {
> > > +			PMD_DRV_LOG(INFO, "Failed to flush queue region
> > > mapping.");
> > > +			return ret;
> > > +		}
> > > +
> > > +		ret = i40e_queue_region_dcb_configure(hw, pf);
> > > +		if (ret != I40E_SUCCESS) {
> > > +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > > +			return ret;
> > > +		}
> > > +
> > > +		return 0;
> > > +	}
> > > +
> > > +	info->queue_region_number = 1;
> > > +	info->region[0].queue_num = 64;
> >
> > Why number of queues is hardcoded to a magic number 64? How it will
> work
> > if VSI is enabled with smaller number of queues, for example, 1 or 6? 64 is
> > the maximum number of queues that can be used for RSS, but VSI might
> be
> > created with only few queues.
> 
> Yes, I know what is your mean, may be it should be change to
> 
> struct i40e_vsi *main_vsi = pf->main_vsi;
> info->region[0].queue_num = main_vsi->nb_used_qps;
> 
> Do you think so?
> 
> >
> > > +	info->region[0].queue_start_index = 0;
> > > +
> > > +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > > +	if (ret != I40E_SUCCESS)
> > > +		PMD_DRV_LOG(INFO, "Failed to flush queue region
> > > mapping.");
> > > +
> > > +	ret = i40e_dcb_init_configure(dev, TRUE);
> > > +	if (ret != I40E_SUCCESS) {
> > > +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > > +		pf->flags &= ~I40E_FLAG_DCB;
> > > +	}
> > > +
> > > +	i40e_init_queue_region_conf(dev);
> > > +
> > > +	return 0;
> > > +}

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

* Re: [PATCH v8 1/2] net/i40e: queue region set and flush
  2017-10-18 13:00                     ` Chilikin, Andrey
@ 2017-10-19  2:18                       ` Zhao1, Wei
  0 siblings, 0 replies; 87+ messages in thread
From: Zhao1, Wei @ 2017-10-19  2:18 UTC (permalink / raw)
  To: Chilikin, Andrey, dev; +Cc: Yigit, Ferruh, Xing, Beilei, Wu, Jingjing

Hi,  Andrey

Yes, it is the number of queue pairs for pf.

> -----Original Message-----
> From: Chilikin, Andrey
> Sent: Wednesday, October 18, 2017 9:01 PM
> To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and flush
> 
> Hi Wei,
> 
> Is there number of RX queues configured for the port?
> If main_vsi->nb_used_qps reflects number of enabled RX queues, then it
> can be used.
> 
> Regards,
> Andrey
> 
> > -----Original Message-----
> > From: Zhao1, Wei
> > Sent: Wednesday, October 18, 2017 4:01 AM
> > To: Chilikin, Andrey <andrey.chilikin@intel.com>; dev@dpdk.org
> > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Xing, Beilei
> > <beilei.xing@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>
> > Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and
> > flush
> >
> > Hi,Andrey
> >
> > > -----Original Message-----
> > > From: Chilikin, Andrey
> > > Sent: Friday, October 13, 2017 6:07 PM
> > > To: Zhao1, Wei <wei.zhao1@intel.com>; dev@dpdk.org
> > > Cc: Zhao1, Wei <wei.zhao1@intel.com>; Yigit, Ferruh
> > > <ferruh.yigit@intel.com>; Xing, Beilei <beilei.xing@intel.com>; Wu,
> > > Jingjing <jingjing.wu@intel.com>
> > > Subject: RE: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set
> > > and
> > flush
> > >
> > > Hi Wei
> > >
> > > Sorry for the late comment, but I was not included to the patchset
> > > CC list
> > and
> > > just found this new version.
> > >
> > > > -----Original Message-----
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Wei Zhao
> > > > Sent: Wednesday, October 11, 2017 9:56 AM
> > > > To: dev@dpdk.org
> > > > Cc: Zhao1, Wei <wei.zhao1@intel.com>
> > > > Subject: [dpdk-dev] [PATCH v8 1/2] net/i40e: queue region set and
> > > > flush
> > >
> > >
> > > <snip>
> > >
> > > > +int
> > > > +i40e_flush_queue_region_all_conf(struct rte_eth_dev *dev,
> > > > +	struct i40e_hw *hw, struct i40e_pf *pf, uint16_t on) {
> > > > +	int32_t ret = -EINVAL;
> > > > +	struct i40e_queue_regions *info = &pf->queue_region;
> > > > +
> > > > +	if (on) {
> > > > +		i40e_queue_region_pf_flowtype_conf(hw, pf);
> > > > +
> > > > +		ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > > > +		if (ret != I40E_SUCCESS) {
> > > > +			PMD_DRV_LOG(INFO, "Failed to flush queue region
> > > > mapping.");
> > > > +			return ret;
> > > > +		}
> > > > +
> > > > +		ret = i40e_queue_region_dcb_configure(hw, pf);
> > > > +		if (ret != I40E_SUCCESS) {
> > > > +			PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > > > +			return ret;
> > > > +		}
> > > > +
> > > > +		return 0;
> > > > +	}
> > > > +
> > > > +	info->queue_region_number = 1;
> > > > +	info->region[0].queue_num = 64;
> > >
> > > Why number of queues is hardcoded to a magic number 64? How it will
> > work
> > > if VSI is enabled with smaller number of queues, for example, 1 or
> > > 6? 64 is the maximum number of queues that can be used for RSS, but
> > > VSI might
> > be
> > > created with only few queues.
> >
> > Yes, I know what is your mean, may be it should be change to
> >
> > struct i40e_vsi *main_vsi = pf->main_vsi;
> > info->region[0].queue_num = main_vsi->nb_used_qps;
> >
> > Do you think so?
> >
> > >
> > > > +	info->region[0].queue_start_index = 0;
> > > > +
> > > > +	ret = i40e_vsi_update_queue_region_mapping(hw, pf);
> > > > +	if (ret != I40E_SUCCESS)
> > > > +		PMD_DRV_LOG(INFO, "Failed to flush queue region
> > > > mapping.");
> > > > +
> > > > +	ret = i40e_dcb_init_configure(dev, TRUE);
> > > > +	if (ret != I40E_SUCCESS) {
> > > > +		PMD_DRV_LOG(INFO, "Failed to flush dcb.");
> > > > +		pf->flags &= ~I40E_FLAG_DCB;
> > > > +	}
> > > > +
> > > > +	i40e_init_queue_region_conf(dev);
> > > > +
> > > > +	return 0;
> > > > +}

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

end of thread, other threads:[~2017-10-19  2:18 UTC | newest]

Thread overview: 87+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-24  3:26 [PATCH 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-08-24  3:26 ` [PATCH 1/2] net/i40e: queue region set and flush Wei Zhao
2017-08-31 16:18   ` Ferruh Yigit
2017-09-01  2:38     ` Zhao1, Wei
2017-09-06  9:11       ` Ferruh Yigit
2017-09-15 11:00         ` Ferruh Yigit
2017-09-20  3:20           ` Zhao1, Wei
2017-09-20 10:32             ` Ferruh Yigit
2017-09-18  3:38         ` Zhao1, Wei
2017-09-05 23:52   ` Chilikin, Andrey
2017-09-06  7:21     ` Zhao1, Wei
2017-08-24  3:26 ` [PATCH 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-13  6:04 ` [PATCH v2 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-13  6:04   ` [PATCH v2 1/2] net/i40e: queue region set and flush Wei Zhao
2017-09-13  6:04   ` [PATCH v2 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-15  3:13   ` [PATCH v3 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-15  3:13     ` [PATCH v3 1/2] net/i40e: queue region set and flush Wei Zhao
2017-09-20 10:36       ` Ferruh Yigit
2017-09-21  6:48         ` Zhao1, Wei
2017-09-21  7:10           ` Ferruh Yigit
2017-09-21  7:26             ` Zhao1, Wei
2017-09-21 15:45               ` Ferruh Yigit
2017-09-25  7:40         ` Zhao1, Wei
2017-09-25  9:31           ` Ferruh Yigit
2017-09-26  7:46             ` Zhao1, Wei
2017-09-26  8:54         ` Zhao1, Wei
2017-09-27 19:13           ` Ferruh Yigit
2017-09-28  2:40             ` Zhao1, Wei
2017-09-21 19:53       ` Chilikin, Andrey
2017-09-22  8:49         ` Zhao1, Wei
2017-09-22 20:13           ` Chilikin, Andrey
2017-09-25  2:55             ` Zhao1, Wei
2017-09-24 16:01       ` Wu, Jingjing
2017-09-25  3:26         ` Zhao1, Wei
2017-09-25  5:55         ` Zhao1, Wei
2017-09-15  3:13     ` [PATCH v3 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-20 10:45       ` Ferruh Yigit
2017-09-25  9:25         ` Zhao1, Wei
2017-09-25  9:43           ` Ferruh Yigit
2017-09-26  5:30             ` Zhao1, Wei
2017-09-28  9:04     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-28  9:04       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
2017-09-28  9:04       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-28  9:04       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
2017-09-28  9:10     ` [PATCH v4 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-28  9:10       ` [PATCH v4 1/3] net/i40e: queue region set and flush Wei Zhao
2017-09-28  9:10       ` [PATCH v4 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-28  9:10       ` [PATCH v4 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
2017-09-29  2:56       ` [PATCH v5 0/3] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-29  2:56         ` [PATCH v5 1/3] net/i40e: queue region set and flush Wei Zhao
2017-09-29  4:54           ` Wu, Jingjing
2017-09-29  8:27             ` Zhao1, Wei
2017-09-29  2:56         ` [PATCH v5 2/3] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-29  5:04           ` Wu, Jingjing
2017-09-29  5:21             ` Zhao1, Wei
2017-09-29  2:56         ` [PATCH v5 3/3] doc/testpmd_app_ug: add doc info for " Wei Zhao
2017-09-29  8:11         ` [PATCH v6] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-29  8:11           ` [PATCH v6] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-29  8:11           ` [PATCH v6] net/i40e: queue region set and flush Wei Zhao
2017-09-29  9:00             ` Wu, Jingjing
2017-09-29  9:16           ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-09-29  9:16             ` [PATCH v7 1/2] net/i40e: queue region set and flush Wei Zhao
2017-09-29 12:22               ` Wu, Jingjing
2017-10-10  1:45                 ` Zhao1, Wei
2017-10-03 17:54               ` Ferruh Yigit
2017-10-10  6:11                 ` Zhao1, Wei
2017-09-29  9:16             ` [PATCH v7 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-09-29 14:29               ` Wu, Jingjing
2017-10-03 18:04               ` Ferruh Yigit
2017-10-10  1:46                 ` Zhao1, Wei
2017-10-10  2:55                 ` Zhao1, Wei
2017-10-10  3:01                 ` Zhao1, Wei
2017-10-11  2:15                   ` Ferruh Yigit
2017-09-29 10:15             ` [PATCH v7 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
2017-10-11  8:49             ` [PATCH v8 " Wei Zhao
2017-10-11  8:49               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
2017-10-11  8:49               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-10-11  8:55             ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Wei Zhao
2017-10-11  8:55               ` [PATCH v8 1/2] net/i40e: queue region set and flush Wei Zhao
2017-10-13 10:06                 ` Chilikin, Andrey
2017-10-18  3:00                   ` Zhao1, Wei
2017-10-18 13:00                     ` Chilikin, Andrey
2017-10-19  2:18                       ` Zhao1, Wei
2017-10-11  8:55               ` [PATCH v8 2/2] app/testpmd: add API for configuration of queue region Wei Zhao
2017-10-11 11:29               ` [PATCH v8 0/2] net/i40e: API to configure queue regions for RSS Peng, Yuan
2017-10-11 21:06               ` Ferruh Yigit
2017-10-13  1:52                 ` Zhao1, Wei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.