[dpdk-dev,v316/20] i40e: implement operations to configure flexible payload
Commit Message
implement operation to flexible payload in i40e pmd driver
Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
Acked-by: Chen Jing D(Mark) <jing.d.chen@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_pmd_i40e/i40e_fdir.c | 101 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
@@ -80,8 +80,11 @@
#define I40E_COUNTER_PF 2
/* Statistic counter index for one pf */
#define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF)
+#define I40E_FLX_OFFSET_IN_FIELD_VECTOR 50
static int i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq);
+static int i40e_set_flx_pld_cfg(struct i40e_pf *pf,
+ struct rte_eth_flex_payload_cfg *cfg);
static int i40e_fdir_construct_pkt(struct i40e_pf *pf,
struct rte_eth_fdir_input *fdir_input,
unsigned char *raw_pkt);
@@ -325,6 +328,97 @@ i40e_fdir_teardown(struct i40e_pf *pf)
return;
}
+/*
+ * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload
+ * @pf: board private structure
+ * @cfg: the rule how bytes stream is extracted as flexible payload
+ */
+static int
+i40e_set_flx_pld_cfg(struct i40e_pf *pf,
+ struct rte_eth_flex_payload_cfg *cfg)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct rte_eth_fdir_info fdir;
+ uint32_t flx_pit;
+ uint16_t min_next_off = 0;
+ uint8_t idx = 0;
+ int i = 0;
+ int num_word = 0;
+ int ret;
+
+ if (cfg == NULL || cfg->nb_field > 3)
+ return -EINVAL;
+
+ if (cfg->type == RTE_ETH_L2_PAYLOAD)
+ idx = 0;
+ else if (cfg->type == RTE_ETH_L3_PAYLOAD)
+ idx = 1;
+ else if (cfg->type == RTE_ETH_L4_PAYLOAD)
+ idx = 2;
+ else {
+ PMD_DRV_LOG(ERR, "unknown payload type.");
+ return -EINVAL;
+ }
+ /*
+ * flexible payload need to be configured before
+ * flow director filters are added
+ * If filters exist, flush them.
+ */
+ memset(&fdir, 0, sizeof(fdir));
+ i40e_fdir_info_get(pf, &fdir);
+ if (fdir.info_ext.best_cnt + fdir.info_ext.guarant_cnt > 0) {
+ ret = i40e_fdir_flush(pf);
+ if (ret) {
+ PMD_DRV_LOG(ERR, " failed to flush fdir table.");
+ return ret;
+ }
+ }
+
+ for (i = 0; i < cfg->nb_field; i++) {
+ /*
+ * check register's constrain
+ * Current Offset >= previous offset + previous FSIZE.
+ */
+ if (cfg->field[i].offset < min_next_off) {
+ PMD_DRV_LOG(ERR, "Offset should be larger than"
+ "previous offset + previous FSIZE.");
+ return -EINVAL;
+ }
+ flx_pit = (cfg->field[i].offset <<
+ I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) &
+ I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK;
+ flx_pit |= (cfg->field[i].size <<
+ I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) &
+ I40E_PRTQF_FLX_PIT_FSIZE_MASK;
+ flx_pit |= ((num_word + I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
+ I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) &
+ I40E_PRTQF_FLX_PIT_DEST_OFF_MASK;
+ /* support no more than 8 words flexible payload*/
+ num_word += cfg->field[i].size;
+ if (num_word > 8)
+ return -EINVAL;
+
+ I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(idx * 3 + i), flx_pit);
+ /* record the info in fdir structure */
+ pf->fdir.flex_set[idx][i].offset = cfg->field[i].offset;
+ pf->fdir.flex_set[idx][i].size = cfg->field[i].size;
+ min_next_off = cfg->field[i].offset + cfg->field[i].size;
+ }
+
+ for (; i < 3; i++) {
+ /* set the non-used register obeying register's constrain */
+ flx_pit = (min_next_off << I40E_PRTQF_FLX_PIT_SOURCE_OFF_SHIFT) &
+ I40E_PRTQF_FLX_PIT_SOURCE_OFF_MASK;
+ flx_pit |= (1 << I40E_PRTQF_FLX_PIT_FSIZE_SHIFT) &
+ I40E_PRTQF_FLX_PIT_FSIZE_MASK;
+ flx_pit |= (63 << I40E_PRTQF_FLX_PIT_DEST_OFF_SHIFT) &
+ I40E_PRTQF_FLX_PIT_DEST_OFF_MASK;
+ I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(idx * 3 + i), flx_pit);
+ min_next_off++;
+ }
+
+ return 0;
+}
static int
i40e_fdir_construct_pkt(struct i40e_pf *pf,
struct rte_eth_fdir_input *fdir_input,
@@ -944,6 +1038,7 @@ i40e_fdir_info_get(struct i40e_pf *pf, struct rte_eth_fdir_info *fdir)
int
i40e_fdir_ctrl_func(struct i40e_pf *pf, enum rte_filter_op filter_op, void *arg)
{
+ struct rte_eth_fdir_cfg *fdir_cfg = NULL;
int ret = I40E_SUCCESS;
if (arg == NULL && filter_op != RTE_ETH_FILTER_OP_NONE &&
@@ -968,6 +1063,12 @@ i40e_fdir_ctrl_func(struct i40e_pf *pf, enum rte_filter_op filter_op, void *arg)
case RTE_ETH_FILTER_OP_FLUSH:
ret = i40e_fdir_flush(pf);
break;
+ case RTE_ETH_FILTER_OP_SET:
+ fdir_cfg = (struct rte_eth_fdir_cfg *)arg;
+ if (fdir_cfg->cmd == RTE_ETH_FDIR_CFG_FLX)
+ ret = i40e_set_flx_pld_cfg(pf,
+ (struct rte_eth_flex_payload_cfg *)fdir_cfg->cfg);
+ break;
case RTE_ETH_FILTER_OP_GET_INFO:
i40e_fdir_info_get(pf, (struct rte_eth_fdir_info *)arg);
break;