Discussion:
[dpdk-dev] [PATCH 0/2] net/i40e: API to configure queue regions for RSS
(too old to reply)
Wei Zhao
2017-08-24 03:26:00 UTC
Permalink
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
Wei Zhao
2017-08-24 03:26:01 UTC
Permalink
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 <***@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
Ferruh Yigit
2017-08-31 16:18:25 UTC
Permalink
Post by 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.
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
Zhao1, Wei
2017-09-01 02:38:01 UTC
Permalink
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [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.
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 selec
Ferruh Yigit
2017-09-06 09:11:01 UTC
Permalink
Post by Zhao1, Wei
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [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.
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.
Post by Zhao1, Wei
Thanks,
ferruh
Ferruh Yigit
2017-09-15 11:00:48 UTC
Permalink
Post by Ferruh Yigit
Post by Zhao1, Wei
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [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.
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
Post by Ferruh Yigit
Even this is only for i40e, rte_flow can be an option. I believe this
increases the usability of the feature for the driver.
Post by Zhao1, Wei
Thanks,
ferruh
Zhao1, Wei
2017-09-20 03:20:26 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 15, 2017 7:01 PM
Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
Post by Ferruh Yigit
Post by Zhao1, Wei
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
Post by 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.
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.
Post by Ferruh Yigit
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
Post by Ferruh Yigit
Even this is only for i40e, rte_flow can be an option. I believe this
increases the usability of the feature for the driver.
Ferruh Yigit
2017-09-20 10:32:58 UTC
Permalink
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 15, 2017 7:01 PM
Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
Post by Ferruh Yigit
Post by Zhao1, Wei
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
Post by 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.
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.
Post by Ferruh Yigit
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.
Post by Zhao1, Wei
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.
Post by Zhao1, Wei
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.
Post by Zhao1, Wei
Thanks,
ferruh
Post by Ferruh Yigit
Even this is only for i40e, rte_flow can be an option. I believe this
increases the usability of the feature for the driver.
Post by Zhao1, Wei
Thanks,
ferruh
Zhao1, Wei
2017-09-18 03:38:06 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 6, 2017 5:11 PM
Subject: Re: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
Post by Zhao1, Wei
HI, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Friday, September 1, 2017 12:18 AM
Subject: Re: [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.
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
Chilikin, Andrey
2017-09-05 23:52:27 UTC
Permalink
-----Original Message-----
Sent: Wednesday, August 23, 2017 8:26 PM
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.
---
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.
*
@@ -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
+ *
+ * pointer to port identifier of the device
+ * 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 {
+
+ rte_pmd_i40e_queue_region_conf;
+
+} DPDK_17.08;
--
2.9.3
Zhao1, Wei
2017-09-06 07:21:17 UTC
Permalink
Hi, Andrey
-----Original Message-----
From: Chilikin, Andrey
Sent: Wednesday, September 6, 2017 7:52 AM
Subject: RE: [dpdk-dev] [PATCH 1/2] net/i40e: queue region set and flush
-----Original Message-----
Sent: Wednesday, August 23, 2017 8:26 PM
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.
---
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.
*
@@ -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
+ *
+ * pointer to port identifier of the device
+ * 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 {
+
+ rte_pmd_i40e_queue_region_conf;
+
+} DPDK_17.08;
--
2.9.3
Wei Zhao
2017-08-24 03:26:02 UTC
Permalink
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 <***@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
Wei Zhao
2017-08-29 01:46:54 UTC
Permalink
From: root <***@dpdk2.bj.intel.com>

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 <***@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
Wei Zhao
2017-09-13 06:04:02 UTC
Permalink
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
Wei Zhao
2017-09-13 06:04:04 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-13 06:04:03 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-15 03:13:06 UTC
Permalink
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
Wei Zhao
2017-09-15 03:13:07 UTC
Permalink
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 <***@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
Ferruh Yigit
2017-09-20 10:36:23 UTC
Permalink
Post by 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.
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?
Post by Wei Zhao
This patch enable mapping between different priorities (UP) and
User priorities (UP)
Post by Wei Zhao
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.
---
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(-)
<...>
Post by Wei Zhao
+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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+{
+ 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.
Post by Wei Zhao
+ 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"?
Post by Wei Zhao
+{
+ 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.
Post by Wei Zhao
+
+ 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 ";"
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+
+ memset(&hw->local_dcbx_config, 0,
+ sizeof(struct i40e_dcbx_config));
Wrong indentation.
Post by Wei Zhao
+ /* 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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+
+ if (!is_i40e_supported(dev))
+ return -ENOTSUP;
+
+ switch (op_type) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
Does it make sense to add another type to get the current queue region
config?
Post by Wei Zhao
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ ret = -EINVAL;
Will this be implemented later, or not a valid case at all?
Post by Wei Zhao
+ break;
+ case RTE_PMD_I40E_UP_REGION_SET:> + ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ 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.
Post by Wei Zhao
+ break;
+
+ PMD_DRV_LOG(WARNING, "op type (%d) not supported",
+ op_type);
Line break not required.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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
Post by Wei Zhao
+ 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
Post by Wei Zhao
+ */
+struct rte_i40e_rss_region_conf {
This is now public struct, can you please comment items.
Post by Wei Zhao
+ 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"
Post by Wei Zhao
+};
+
+/**
* Notify VF when PF link status changes.
*
@@ -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
Post by Wei Zhao
+ * that port as the command otion type
s/otion/options
Post by Wei Zhao
+ *
+ * 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.
Post by Wei Zhao
+ * 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.
Post by Wei Zhao
+ 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
Post by Wei Zhao
#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 {
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?
Post by Wei Zhao
} DPDK_17.08;
Zhao1, Wei
2017-09-21 06:48:42 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.
---
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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
Does it make sense to add another type to get the current queue region
config?
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ 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;
+
+ 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.
*
@@ -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
+ *
+ * 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.
+ * 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 {
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?
Ferruh Yigit
2017-09-21 07:10:29 UTC
Permalink
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.
<...>
Post by Zhao1, Wei
+ 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);

<...>
Zhao1, Wei
2017-09-21 07:26:36 UTC
Permalink
-----Original Message-----
From: Yigit, Ferruh
Sent: Thursday, September 21, 2017 3:10 PM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
So instead of distributing packets to the multiple queues, this will
distribute packets into queue reqions which may consists of multiple
queues.
Post by Zhao1, Wei
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.
<...>
Post by Zhao1, Wei
+ 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!
Post by Zhao1, Wei
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.
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
Ferruh Yigit
2017-09-21 15:45:54 UTC
Permalink
Post by Zhao1, Wei
-----Original Message-----
From: Yigit, Ferruh
Sent: Thursday, September 21, 2017 3:10 PM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
So instead of distributing packets to the multiple queues, this will
distribute packets into queue reqions which may consists of multiple
queues.
Post by Zhao1, Wei
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.
<...>
Post by Zhao1, Wei
+ 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!
Post by Zhao1, Wei
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.
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.
Zhao1, Wei
2017-09-25 07:40:56 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.
---
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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
Does it make sense to add another type to get the current queue region
config?
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ 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;
+
+ 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.
*
@@ -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
+ *
+ * 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
+ * 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 {
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
Ferruh Yigit
2017-09-25 09:31:42 UTC
Permalink
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.

<...>
                                                               
Post by Zhao1, Wei
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));

<...>
Post by Zhao1, Wei
+                      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;

<...>
Post by Zhao1, Wei
+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;
                                ret = i40e_set_region_flowtype_pf(hw,
pf, conf_ptr);
                                break;
                                ret = -EINVAL;
                                break;
                                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.

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

<...>
Post by Zhao1, Wei
+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.

<...>
Post by Zhao1, Wei
+
+      if (!is_i40e_supported(dev))
+                      return -ENOTSUP;
+
+      switch (op_type) {
+                      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.
Post by Zhao1, Wei
+                      ret = i40e_set_region_flowtype_pf(hw, pf,
conf_ptr);
+                      break;
+                      ret = -EINVAL;
Will this be implemented later, or not a valid case at all?
Reminder of this one incase missed.
Post by Zhao1, Wei
+                      break;
+      case RTE_PMD_I40E_UP_REGION_SET:> +                         
ret =
i40e_set_up_region(pf, conf_ptr);
+                      break;
+                      ret = i40e_flush_region_all_conf(hw, pf, 1);
+                      break;
+                      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.

<...>
Post by Zhao1, Wei
@@ -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.

<...>
Post by Zhao1, Wei
+      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.

<...>
Post by Zhao1, Wei
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.
Post by Zhao1, Wei
+ * that port as the command otion type
s/otion/options
Reminder of this one incase missed.

<...>
Post by Zhao1, Wei
+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.

<...>
Zhao1, Wei
2017-09-26 07:46:55 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Monday, September 25, 2017 5:32 PM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
flush
Post by 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.
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
<...>
Post by Zhao1, Wei
sizeof(vsi->info.tc_mapping));
Post by Wei Zhao
+      (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,
Post by Zhao1, Wei
sizeof(vsi->info.queue_mapping));
will over 80 maxnumber.
(void)rte_memcpy(&vsi->info.queue_mapping,
&ctxt.info.queue_mapping,
sizeof(vsi->info.queue_mapping));
Ok, change in v4
<...>
Post by Zhao1, Wei
Post by Wei Zhao
+                      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 ((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
Post by Zhao1, Wei
Post by Wei Zhao
+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;
                                ret = i40e_set_region_flowtype_pf(hw,
pf, conf_ptr);
                                break;
                                ret = -EINVAL;
                                break;
                                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
Post by Zhao1, Wei
Post by Wei Zhao
+
+      memset(&hw->local_dcbx_config, 0,
+      sizeof(struct i40e_dcbx_config));
Wrong indentation.
Reminder of this one incase missed.
Ok, change in v4
<...>
Post by Zhao1, Wei
Post by Wei Zhao
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+                                      struct
rte_i40e_rss_region_conf *conf_ptr) {
Post by Wei Zhao
+      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.
<...>
Post by Zhao1, Wei
Post by Wei Zhao
+
+      if (!is_i40e_supported(dev))
+                      return -ENOTSUP;
+
+      switch (op_type) {
+                      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.
Post by Zhao1, Wei
Post by Wei Zhao
+                      ret = i40e_set_region_flowtype_pf(hw, pf,
conf_ptr);
Post by Wei Zhao
+                      break;
+                      ret = -EINVAL;
Will this be implemented later, or not a valid case at all?
Reminder of this one incase missed.
Ok, change in v4
Post by Zhao1, Wei
Post by Wei Zhao
+                      break;
+      case RTE_PMD_I40E_UP_REGION_SET:> +
ret =
i40e_set_up_region(pf, conf_ptr);
Post by Wei Zhao
+                      break;
+                      ret = i40e_flush_region_all_conf(hw, pf, 1);
+                      break;
+                      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)
<...>
Post by Zhao1, Wei
Post by Wei Zhao
@@ -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
<...>
Post by Zhao1, Wei
Post by Wei Zhao
+      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
<...>
Post by Zhao1, Wei
rte_pmd_i40e_ptype_mapping_replace(uint8_t
Post by Wei Zhao
port,  int rte_pmd_i40e_add_vf_mac_addr(uint8_t port, uint16_t vf_id,
                                                           struct
ether_addr *mac_addr);
Post by Wei Zhao
+/**
+ * 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
Post by Zhao1, Wei
Post by Wei Zhao
+ * that port as the command otion type
s/otion/options
Reminder of this one incase missed.
Ok, change in v4
<...>
Post by Zhao1, Wei
Post by Wei Zhao
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
Can you please use port_id as variable name to be consistent.
Reminder of thi
Zhao1, Wei
2017-09-26 08:54:55 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.
---
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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+
Ferruh Yigit
2017-09-27 19:13:11 UTC
Permalink
Hi,  Ferruh
Hi Wei,
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [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.
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.
---
  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) {
+                      ret = i40e_set_queue_region(pf, conf_ptr);
+                      break;
Zhao1, Wei
2017-09-28 02:40:48 UTC
Permalink
Thank you.
-----Original Message-----
From: Yigit, Ferruh
Sent: Thursday, September 28, 2017 3:13 AM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
Hi,  Ferruh
Hi Wei,
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:36 PM
Subject: Re: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
flush
Post by 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.
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?
Post by Wei Zhao
This patch enable mapping between different priorities (UP) and
User priorities (UP)
Post by Wei Zhao
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.
---
  drivers/net/i40e/i40e_ethdev.c            |  19 +-
  drivers/net/i40e/i40e_ethdev.h            |  30 ++
  drivers/net/i40e/rte_pmd_i40e.c           | 482
++++++++++++++++++++++++++++++
Post by Wei Zhao
  drivers/net/i40e/rte_pmd_i40e.h           |  38 +++
 drivers/net/i40e/rte_pmd_i40e_version.map |   1 +
  5 files changed, 566 insertions(+), 4 deletions(-)
<...>
Post by Wei Zhao
+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;
Post by Wei Zhao
+      uint32_t ret = -EINVAL;
+
+      if (!region_info->queue_region_number) {
....................
Post by Wei Zhao
+int rte_pmd_i40e_queue_region_conf(uint8_t port,
+                                      struct
rte_i40e_rss_region_conf *conf_ptr) {
Post by Wei Zhao
+      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.
Post by Wei Zhao
+      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.
Post by Wei Zhao
+
+      if (!is_i40e_supported(dev))
+                      return -ENOTSUP;
+
+      switch (op_type) {
+                      ret = i40e_set_queue_region(pf, conf_ptr);
+                      break;
Chilikin, Andrey
2017-09-21 19:53:10 UTC
Permalink
-----Original Message-----
Sent: Friday, September 15, 2017 4:13 AM
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.
---
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-
Post by Wei Zhao
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;
@@ -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-
Post by Wei Zhao
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-
Post by Wei Zhao
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-
Post by Wei Zhao
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-
Post by Wei Zhao
dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
Post by Wei Zhao
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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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?
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 0);
+ break;
+
+ 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.
*
@@ -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
+ *
+ * pointer to port identifier of the device
+ * 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 {
rte_pmd_i40e_add_vf_mac_addr;
+ rte_pmd_i40e_queue_region_conf;
} DPDK_17.08;
--
2.9.3
Zhao1, Wei
2017-09-22 08:49:13 UTC
Permalink
Hi,Andrey
-----Original Message-----
From: Chilikin, Andrey
Sent: Friday, September 22, 2017 3:53 AM
Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
-----Original Message-----
Sent: Friday, September 15, 2017 4:13 AM
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.
---
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-
Post by Wei Zhao
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)
if (ret < 0)
goto err_init_fdir_filter_list;
+ /* initialize queue region configuration */
+ i40e_init_queue_region_conf(dev);
+
return 0;
@@ -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-
Post by Wei Zhao
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-
Post by Wei Zhao
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-
Post by Wei Zhao
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-
Post by Wei Zhao
dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
Post by Wei Zhao
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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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.
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 0);
+ break;
+
+ 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.
*
@@ -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
+ *
+ * pointer to port identifier of the device
+ * 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 {
rte_pmd_i40e_add_vf_mac_addr;
+ rte_pmd_i40e_queue_region_conf;
} DPDK_17.08;
--
2.9
Chilikin, Andrey
2017-09-22 20:13:31 UTC
Permalink
Hi Wei
-----Original Message-----
From: Zhao1, Wei
Sent: Friday, September 22, 2017 9:49 AM
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
Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
flush
<snip>
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ 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>
Post by Wei Zhao
+ switch (op_type) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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.
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.
Post by Wei Zhao
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ 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?
Post by Wei Zhao
+ 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
Zhao1, Wei
2017-09-25 02:55:02 UTC
Permalink
Hi, Andrey
-----Original Message-----
From: Chilikin, Andrey
Sent: Saturday, September 23, 2017 4:14 AM
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
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
Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and
flush
<snip>
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ 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>
Post by Wei Zhao
+ switch (op_type) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ 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
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.
Post by Wei Zhao
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
+ 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)
Post by Wei Zhao
+ 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 seco
Wu, Jingjing
2017-09-24 16:01:55 UTC
Permalink
-----Original Message-----
Sent: Friday, September 15, 2017 11:13 AM
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.
---
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;
@@ -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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ ret = -EINVAL;
+ break;
If it is not supported, why to define this op?
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ 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.
+ ret = i40e_flush_region_all_conf(hw, pf, 0);
+ break;
+
+ 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
Zhao1, Wei
2017-09-25 03:26:36 UTC
Permalink
Hi, jingjing
-----Original Message-----
From: Wu, Jingjing
Sent: Monday, September 25, 2017 12:02 AM
Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
-----Original Message-----
Sent: Friday, September 15, 2017 11:13 AM
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.
---
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)
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;
@@ -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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ ret = -EINVAL;
+ break;
If it is not supported, why to define this op?
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
What is the FLUSH on meaning? Commit all configure to HW?
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)
+ ret = i40e_flush_region_all_conf(hw, pf, 0);
+ break;
+
+ 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
Zhao1, Wei
2017-09-25 05:55:41 UTC
Permalink
Hi, jingjing
-----Original Message-----
From: Wu, Jingjing
Sent: Monday, September 25, 2017 12:02 AM
Subject: RE: [dpdk-dev] [PATCH v3 1/2] net/i40e: queue region set and flush
-----Original Message-----
Sent: Friday, September 15, 2017 11:13 AM
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.
---
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)
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;
@@ -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) {
+ ret = i40e_set_queue_region(pf, conf_ptr);
+ break;
+ ret = i40e_set_region_flowtype_pf(hw, pf, conf_ptr);
+ break;
+ ret = -EINVAL;
+ break;
If it is not supported, why to define this op?
+ ret = i40e_set_up_region(pf, conf_ptr);
+ break;
+ ret = i40e_flush_region_all_conf(hw, pf, 1);
+ break;
What is the FLUSH on meaning? Commit all configure to HW?
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.
+ ret = i40e_flush_region_all_conf(hw, pf, 0);
+ break;
+
+ 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 t
Wei Zhao
2017-09-15 03:13:08 UTC
Permalink
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 <***@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
Ferruh Yigit
2017-09-20 10:45:49 UTC
Permalink
Post by 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.
---
app/test-pmd/cmdline.c | 328 +++++++++++++++++++++++++++++++++++++++++++++++++
Testpmd documentation also needs to be updated.
Post by Wei Zhao
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 ..." ?
Post by Wei Zhao
+
, 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?

<...>
Zhao1, Wei
2017-09-25 09:25:06 UTC
Permalink
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:46 PM
Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
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
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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) "
Post by Wei Zhao
+ "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"
Post by Wei Zhao
+ " 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
"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.
Post by Wei Zhao
+
, 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.
<..
Ferruh Yigit
2017-09-25 09:43:24 UTC
Permalink
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:46 PM
Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
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.
Post by Zhao1, Wei
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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) "
Post by Wei Zhao
+ "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"
Post by Wei Zhao
+ " 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
"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/

<...>
Zhao1, Wei
2017-09-26 05:30:34 UTC
Permalink
Hi,Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Monday, September 25, 2017 5:43 PM
Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
configuration of queue region
Post by Zhao1, Wei
Hi, Ferruh
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, September 20, 2017 6:46 PM
Subject: Re: [dpdk-dev] [PATCH v3 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
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.
Post by Zhao1, Wei
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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) "
Post by Wei Zhao
+ "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"
Post by Wei Zhao
+ " 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.
Post by Zhao1, Wei
Since this is to set an option of the port, what do you think making
"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.
Post by Zhao1, Wei
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.cod
Wei Zhao
2017-09-28 09:04:12 UTC
Permalink
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
Wei Zhao
2017-09-28 09:04:13 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-28 09:04:14 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-28 09:04:15 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-28 09:10:06 UTC
Permalink
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
Wei Zhao
2017-09-28 09:10:07 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-28 09:10:08 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-28 09:10:09 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-29 02:56:23 UTC
Permalink
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
Wei Zhao
2017-09-29 02:56:24 UTC
Permalink
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 <***@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
Wu, Jingjing
2017-09-29 04:54:46 UTC
Permalink
Post by Wei Zhao
+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?

[......]
Post by Wei Zhao
+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?
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ }
+ }
+ }
+
[......]
Post by Wei Zhao
+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.
Post by Wei Zhao
+ break;
[......]
Post by Wei Zhao
+
+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?
Post by Wei Zhao
+ 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.

[......]
Post by Wei Zhao
+
+/**
+ * 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
Zhao1, Wei
2017-09-29 08:27:24 UTC
Permalink
Hi, jingjing
All will be fix in v6
-----Original Message-----
From: Wu, Jingjing
Sent: Friday, September 29, 2017 12:55 PM
Subject: RE: [dpdk-dev] [PATCH v5 1/3] net/i40e: queue region set and flush
Post by Wei Zhao
+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");
Post by Wei Zhao
+ 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) |
Post by Wei Zhao
+ (bsf <<
I40E_AQ_VSI_TC_QUE_NUMBER_SHIFT));
Post by Wei Zhao
+ }
+
+ /* Associate queue number with VSI, Keep vsi->nb_qps unchanged
*/
Post by Wei Zhao
+ 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?
[......]
Post by Wei Zhao
+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
Post by Wei Zhao
+values: 1,
2, 4, 8, 16, 32, 64 as long as the "
+ "total number of queues do not exceed the VSI
allocation");
Post by Wei Zhao
+ 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");
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ 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
Post by Wei Zhao
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?
Post by Wei Zhao
+ if (rss_region_conf->region_id > I40E_PFQF_HREGION_MAX_INDEX)
{
Post by Wei Zhao
+ 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");
Post by Wei Zhao
+ 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");
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ }
+ }
+ }
+
[......]
Post by Wei Zhao
+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");
Post by Wei Zhao
+ 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.
Post by Wei Zhao
+ break;
[......]
Post by Wei Zhao
+
+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");
Post by Wei Zhao
+ 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",
Post by Wei Zhao
+ 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.");
Post by Wei Zhao
+ 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.");
Post by Wei Zhao
+
+ 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;
Post by Wei Zhao
+ 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?
Post by Wei Zhao
+ 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.
[......]
Post by Wei Zhao
+
+/**
+ * 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
*/
Post by Wei Zhao
+ RTE_PMD_I40E_REGION_FLOWTYPE_SET, /**< add pf region
pctype set */
Post by Wei Zhao
+ /**< 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
Wei Zhao
2017-09-29 02:56:25 UTC
Permalink
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 <***@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
Wu, Jingjing
2017-09-29 05:04:58 UTC
Permalink
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
Zhao1, Wei
2017-09-29 05:21:38 UTC
Permalink
Ok.
-----Original Message-----
From: Wu, Jingjing
Sent: Friday, September 29, 2017 1:05 PM
Subject: RE: [dpdk-dev] [PATCH v5 2/3] app/testpmd: add API for
configuration of queue region
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
Wei Zhao
2017-09-29 02:56:26 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-29 08:11:56 UTC
Permalink
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
Wei Zhao
2017-09-29 08:11:57 UTC
Permalink
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 <***@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
Wei Zhao
2017-09-29 08:11:58 UTC
Permalink
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 <***@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
Wu, Jingjing
2017-09-29 09:00:52 UTC
Permalink
-----Original Message-----
Sent: Friday, September 29, 2017 4:12 PM
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.
---
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,
return ret;
}
+void
+i40e_init_queue_region_conf(struct rte_eth_dev *dev) {
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data-
Post by Wei Zhao
dev_private);
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data-
Post by Wei Zhao
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)
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
Wei Zhao
2017-09-29 09:16:22 UTC
Permalink
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
Wei Zhao
2017-09-29 09:16:23 UTC
Permalink
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 <***@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
Wu, Jingjing
2017-09-29 12:22:49 UTC
Permalink
Post by Wei Zhao
+ /* 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.

[......]
Post by Wei Zhao
+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.

[.....]
Post by Wei Zhao
+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
Post by Wei Zhao
+ 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
Zhao1, Wei
2017-10-10 01:45:52 UTC
Permalink
HI, jingjing

I will rework code as your comments in v8.
-----Original Message-----
From: Wu, Jingjing
Sent: Friday, September 29, 2017 8:23 PM
Subject: RE: [dpdk-dev] [PATCH v7 1/2] net/i40e: queue region set and flush
Post by Wei Zhao
+ /* 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.
[......]
Post by Wei Zhao
+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.
[.....]
Post by Wei Zhao
+enum rte_pmd_i40e_queue_region_op {
+ RTE_PMD_I40E_REGION_UNDEFINED,
+ RTE_PMD_I40E_QUEUE_REGION_SET, /**< add queue region set
*/
Post by Wei Zhao
+ RTE_PMD_I40E_REGION_FLOWTYPE_SET, /**< add pf region
pctype set */
Post by Wei Zhao
+ /*** 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
Post by Wei Zhao
+ 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
Ferruh Yigit
2017-10-03 17:54:31 UTC
Permalink
Post by 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.
---
<...>
Post by Wei Zhao
@@ -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
Post by Wei Zhao
+ /* 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
<...>
Post by Wei Zhao
+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.
Post by Wei Zhao
+ * 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.
+ */
+
<...>
Post by Wei Zhao
+ }
+ }
+}
Missing line.
Post by Wei Zhao
+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;
+
<...>
Post by Wei Zhao
+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.
Post by Wei Zhao
+ 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) {
+ ret = i40e_queue_region_set_region(pf, rss_region_conf);
+ break;
+ ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+ break;
+ ret = i40e_queue_region_set_user_priority(pf, rss_region_conf);
+ break;
+ ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+ break;
+ ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+ break;
+ 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?
Post by Wei Zhao
+ break;
+ 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_"
Post by Wei Zhao
+};
+
#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_
Post by Wei Zhao
+ /*** 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.
*
@@ -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
+ *
+ * pointer id for that port device
port id ?
Post by Wei Zhao
+ * 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.
Post by Wei Zhao
+ 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 {
rte_pmd_i40e_add_vf_mac_addr;
+ rte_pmd_i40e_rss_queue_region_conf;
} DPDK_17.08;
Zhao1, Wei
2017-10-10 06:11:01 UTC
Permalink
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, October 4, 2017 1:55 AM
Subject: Re: [dpdk-dev] [PATCH v7 1/2] 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.
---
<...>
@@ -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 {
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) {
+ ret = i40e_queue_region_set_region(pf, rss_region_conf);
+ break;
+ ret = i40e_queue_region_set_flowtype(pf, rss_region_conf);
+ break;
+ ret = i40e_queue_region_set_user_priority(pf,
rss_region_conf);
+ break;
+ ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 1);
+ break;
+ ret = i40e_flush_queue_region_all_conf(dev, hw, pf, 0);
+ break;
+ 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;
+ 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.
rss_region
queue_region
rss_queue_region
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.
*
@@ -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
+ *
+ * pointer id for that port device
port id ?
Ok
+ * 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 {
rte_pmd_i40e_add_vf_mac_addr;
+ rte_pmd_i40e_r
Wei Zhao
2017-09-29 09:16:24 UTC
Permalink
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 <***@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
Wu, Jingjing
2017-09-29 14:29:21 UTC
Permalink
Post by Wei Zhao
+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
Ferruh Yigit
2017-10-03 18:04:01 UTC
Permalink
Post by 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.
---
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)" ?
Post by Wei Zhao
, 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?
Post by Wei Zhao
+#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));
+}
<...>
Zhao1, Wei
2017-10-10 01:46:38 UTC
Permalink
HI, Ferruh

I will rework code as your comments in v8.
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, October 4, 2017 2:04 AM
Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
app/test-pmd/cmdline.c | 389
++++++++++++++++++++++++++++
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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"
Post by Wei Zhao
+ " 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"
Post by Wei Zhao
+
You did same thing and created "flush" and "get" root level commands this
time.
"show port #P queue-region"
"set port #P queue-region flush (on|off)" ?
Post by Wei Zhao
, 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?
Post by Wei Zhao
+#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(-re
Zhao1, Wei
2017-10-10 02:55:59 UTC
Permalink
Hi,
-----Original Message-----
From: Yigit, Ferruh
Sent: Wednesday, October 4, 2017 2:04 AM
Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
app/test-pmd/cmdline.c | 389
++++++++++++++++++++++++++++
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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"
Post by Wei Zhao
+ " 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"
Post by Wei Zhao
+
You did same thing and created "flush" and "get" root level commands this
time.
"show port #P queue-region"
"set port #P queue-region flush (on|off)" ?
Ok.
Post by Wei Zhao
, 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.
Post by Wei Zhao
+#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));
Zhao1, Wei
2017-10-10 03:01:33 UTC
Permalink
Hi,Ferruh
-----Original Message-----
From: Zhao1, Wei
Sent: Tuesday, October 10, 2017 10:56 AM
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
Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
app/test-pmd/cmdline.c | 389
++++++++++++++++++++++++++++
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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"
Post by Wei Zhao
+ " 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"
Post by Wei Zhao
+
You did same thing and created "flush" and "get" root level commands
this time.
"show port #P queue-region"
"set port #P queue-region flush (on|off)" ?
Ok.
Post by Wei Zhao
, 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?
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;
Post by Wei Zhao
+#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",
Ferruh Yigit
2017-10-11 02:15:57 UTC
Permalink
Post by Zhao1, Wei
Hi,Ferruh
-----Original Message-----
From: Zhao1, Wei
Sent: Tuesday, October 10, 2017 10:56 AM
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
Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: add API for
configuration of queue region
Post by 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.
---
app/test-pmd/cmdline.c | 389
++++++++++++++++++++++++++++
Post by Wei Zhao
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,
Post by Wei Zhao
"ptype mapping update (port_id) (hw_ptype)
(sw_ptype)\n"
Post by Wei Zhao
" 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"
Post by Wei Zhao
+ " 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"
Post by Wei Zhao
+
You did same thing and created "flush" and "get" root level commands
this time.
"show port #P queue-region"
"set port #P queue-region flush (on|off)" ?
Ok.
Post by Wei Zhao
, 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?
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;
Peng, Yuan
2017-09-29 10:15:35 UTC
Permalink
Tested-by: Peng Yuan <***@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-***@dpdk.org] On Behalf Of Wei Zhao
Sent: Friday, September 29, 2017 5:16 PM
To: ***@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
Wei Zhao
2017-10-11 08:49:51 UTC
Permalink
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
Wei Zhao
2017-10-11 08:49:52 UTC
Permalink
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 <***@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
Wei Zhao
2017-10-11 08:49:53 UTC
Permalink
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 <***@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
Wei Zhao
2017-10-11 08:55:32 UTC
Permalink
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 <***@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