Implement operation to flexible payload in i40e pmd driver

Signed-off-by: Jingjing Wu <jingjing.wu at intel.com>
---
 lib/librte_pmd_i40e/i40e_fdir.c | 106 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/lib/librte_pmd_i40e/i40e_fdir.c b/lib/librte_pmd_i40e/i40e_fdir.c
index f59eb24..e15d94e 100644
--- a/lib/librte_pmd_i40e/i40e_fdir.c
+++ b/lib/librte_pmd_i40e/i40e_fdir.c
@@ -83,6 +83,8 @@
 #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);
@@ -327,6 +329,98 @@ i40e_fdir_teardown(struct i40e_pf *pf)
 }

 /*
+ * 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.best_cnt + fdir.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;
+}
+
+/*
  * i40e_fdir_construct_pkt - construct packet based on fields in input
  * @pf: board private structure
  * @fdir_input: input set of the flow director entry
@@ -957,6 +1051,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 = 0;

        if (arg == NULL && filter_op != RTE_ETH_FILTER_NOP &&
@@ -981,6 +1076,17 @@ i40e_fdir_ctrl_func(struct i40e_pf *pf, enum 
rte_filter_op filter_op, void *arg)
        case RTE_ETH_FILTER_FLUSH:
                ret = i40e_fdir_flush(pf);
                break;
+       case RTE_ETH_FILTER_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);
+               else {
+                       PMD_DRV_LOG(WARNING, "unsupported configuration command 
%u.",
+                                   fdir_cfg->cmd);
+                       return -EINVAL;
+               }
+               break;
        case RTE_ETH_FILTER_INFO:
                i40e_fdir_info_get(pf, (struct rte_eth_fdir_info *)arg);
                break;
-- 
1.8.1.4

Reply via email to