Hi, chenxu > -----Original Message----- > From: Chenxu Di <chenxux...@intel.com> > Sent: Wednesday, November 4, 2020 4:30 PM > To: dev@dpdk.org > Cc: Xing, Beilei <beilei.x...@intel.com>; Guo, Jia <jia....@intel.com>; Wang, > Haiyue <haiyue.w...@intel.com>; Di, ChenxuX <chenxux...@intel.com>; > sta...@dpdk.org > Subject: [PATCH 2/2] net/i40e: fix incorrect FDIR flex pit > > The register of FDIR flex pit should not be set during flow validate. > It should be set when flow create. > > Fixes: 6ced3dd72f5f ("net/i40e: support flexible payload parsing for FDIR") > Cc: sta...@dpdk.org > > Signed-off-by: Chenxu Di <chenxux...@intel.com> > --- > drivers/net/i40e/i40e_ethdev.h | 21 ++++--- > drivers/net/i40e/i40e_fdir.c | 100 > +++++++++++++++++++++++++++++++++ > drivers/net/i40e/i40e_flow.c | 98 +++----------------------------- > 3 files changed, 119 insertions(+), 100 deletions(-) > > diff --git a/drivers/net/i40e/i40e_ethdev.h > b/drivers/net/i40e/i40e_ethdev.h index 6be929f65..e00133c88 100644 > --- a/drivers/net/i40e/i40e_ethdev.h > +++ b/drivers/net/i40e/i40e_ethdev.h > @@ -599,12 +599,22 @@ enum i40e_fdir_ip_type { > I40E_FDIR_IPTYPE_IPV6, > }; > > +/* > + * Structure to store flex pit for flow diretor. > + */ > +struct i40e_fdir_flex_pit { > + uint8_t src_offset; /* offset in words from the beginning of payload > */ > + uint8_t size; /* size in words */ > + uint8_t dst_offset; /* offset in words of flexible payload */ }; > + > /* A structure used to contain extend input of flow */ struct > i40e_fdir_flow_ext { > uint16_t vlan_tci; > uint8_t flexbytes[RTE_ETH_FDIR_MAX_FLEXLEN]; > /* It is filled by the flexible payload to match. */ > uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN]; > + uint8_t raw_id; > uint8_t is_vf; /* 1 for VF, 0 for port dev */ > uint16_t dst_id; /* VF ID, available when is_vf is 1*/ > bool inner_ip; /* If there is inner ip */ > @@ -613,6 +623,8 @@ struct i40e_fdir_flow_ext { > bool customized_pctype; /* If customized pctype is used */ > bool pkt_template; /* If raw packet template is used */ > bool is_udp; /* ipv4|ipv6 udp flow */ > + enum i40e_flxpld_layer_idx layer_idx; > + struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_LAYER * > +I40E_MAX_FLXPLD_FIED]; > }; > > /* A structure used to define the input for a flow director filter entry */ > @@ > -664,15 +676,6 @@ struct i40e_fdir_filter_conf { > struct i40e_fdir_action action; /* Action taken when match */ }; > > -/* > - * Structure to store flex pit for flow diretor. > - */ > -struct i40e_fdir_flex_pit { > - uint8_t src_offset; /* offset in words from the beginning of payload > */ > - uint8_t size; /* size in words */ > - uint8_t dst_offset; /* offset in words of flexible payload */ > -}; > - > struct i40e_fdir_flex_mask { > uint8_t word_mask; /**< Bit i enables word i of flexible payload */ > uint8_t nb_bitmask; > diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c index > e31464eb7..e64cb2fd0 100644 > --- a/drivers/net/i40e/i40e_fdir.c > +++ b/drivers/net/i40e/i40e_fdir.c > @@ -1765,6 +1765,81 @@ i40e_add_del_fdir_filter(struct rte_eth_dev *dev, > return ret; > } > > +static int > +i40e_flow_store_flex_pit(struct i40e_pf *pf, > + struct i40e_fdir_flex_pit *flex_pit, > + enum i40e_flxpld_layer_idx layer_idx, > + uint8_t raw_id) > +{ > + uint8_t field_idx; > + > + field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id; > + /* Check if the configuration is conflicted */ > + if (pf->fdir.flex_pit_flag[layer_idx] && > + (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset || > + pf->fdir.flex_set[field_idx].size != flex_pit->size || > + pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset)) > + return -1; > + > + /* Check if the configuration exists. */ > + if (pf->fdir.flex_pit_flag[layer_idx] && > + (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset && > + pf->fdir.flex_set[field_idx].size == flex_pit->size && > + pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset)) > + return 1; > + > + pf->fdir.flex_set[field_idx].src_offset = > + flex_pit->src_offset; > + pf->fdir.flex_set[field_idx].size = > + flex_pit->size; > + pf->fdir.flex_set[field_idx].dst_offset = > + flex_pit->dst_offset; > + > + return 0; > +} > + > +static void > +i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf, > + enum i40e_flxpld_layer_idx layer_idx, > + uint8_t raw_id) > +{ > + struct i40e_hw *hw = I40E_PF_TO_HW(pf); > + uint32_t flx_pit, flx_ort; > + uint8_t field_idx; > + uint16_t min_next_off = 0; /* in words */ > + uint8_t i; > + > + if (raw_id) { > + flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) | > + (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) | > + (layer_idx * I40E_MAX_FLXPLD_FIED); > + I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), > flx_ort); > + } > + > + /* Set flex pit */ > + for (i = 0; i < raw_id; i++) { > + field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; > + flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset, > + pf->fdir.flex_set[field_idx].size, > + pf->fdir.flex_set[field_idx].dst_offset); > + > + I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), > flx_pit); > + min_next_off = pf->fdir.flex_set[field_idx].src_offset + > + pf->fdir.flex_set[field_idx].size; > + } > + > + for (; i < I40E_MAX_FLXPLD_FIED; i++) { > + /* set the non-used register obeying register's constrain */ > + field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; > + flx_pit = MK_FLX_PIT(min_next_off, > NONUSE_FLX_PIT_FSIZE, > + NONUSE_FLX_PIT_DEST_OFF); > + I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), > flx_pit); > + min_next_off++; > + } > + > + pf->fdir.flex_pit_flag[layer_idx] = 1; } > + > static int > i40e_flow_store_flex_mask(struct i40e_pf *pf, > enum i40e_filter_pctype pctype, > @@ -1889,13 +1964,17 @@ i40e_flow_add_del_fdir_filter(struct > rte_eth_dev *dev, { > struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data- > >dev_private); > struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data- > >dev_private); > + enum i40e_flxpld_layer_idx layer_idx = I40E_FLXPLD_L2_IDX; > unsigned char *pkt = NULL; > enum i40e_filter_pctype pctype; > struct i40e_fdir_info *fdir_info = &pf->fdir; > uint8_t flex_mask[I40E_FDIR_MAX_FLEX_LEN]; > struct i40e_fdir_filter *node; > struct i40e_fdir_filter check_filter; /* Check if the filter exists */ > + struct i40e_fdir_flex_pit flex_pit; > + bool cfg_flex_pit = true; > bool wait_status = true; > + uint8_t field_idx; > int ret = 0; > int i; > > @@ -1931,6 +2010,27 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev > *dev, > > if (add) { > if (!filter->input.flow_ext.customized_pctype) { > + for (i = 0; i < filter->input.flow_ext.raw_id; i++) { > + layer_idx = filter->input.flow_ext.layer_idx; > + field_idx = layer_idx * > I40E_MAX_FLXPLD_FIED + i; > + flex_pit = filter- > >input.flow_ext.flex_pit[field_idx]; > + > + /* Store flex pit to SW */ > + ret = i40e_flow_store_flex_pit(pf, &flex_pit, > + layer_idx, i); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Conflict with > the" > + " first flexible rule."); > + return -EINVAL; > + } else if (ret > 0) { > + cfg_flex_pit = false; > + } > + } > + > + if (cfg_flex_pit) > + i40e_flow_set_fdir_flex_pit(pf, layer_idx, > + filter- > >input.flow_ext.raw_id); > + > /* Store flex mask to SW */ > for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++) > flex_mask[i] = > diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c > index 4f916494e..098ae13ab 100644 > --- a/drivers/net/i40e/i40e_flow.c > +++ b/drivers/net/i40e/i40e_flow.c > @@ -2240,81 +2240,6 @@ i40e_flow_check_raw_item(const struct > rte_flow_item *item, > return 0; > } > > -static int > -i40e_flow_store_flex_pit(struct i40e_pf *pf, > - struct i40e_fdir_flex_pit *flex_pit, > - enum i40e_flxpld_layer_idx layer_idx, > - uint8_t raw_id) > -{ > - uint8_t field_idx; > - > - field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + raw_id; > - /* Check if the configuration is conflicted */ > - if (pf->fdir.flex_pit_flag[layer_idx] && > - (pf->fdir.flex_set[field_idx].src_offset != flex_pit->src_offset || > - pf->fdir.flex_set[field_idx].size != flex_pit->size || > - pf->fdir.flex_set[field_idx].dst_offset != flex_pit->dst_offset)) > - return -1; > - > - /* Check if the configuration exists. */ > - if (pf->fdir.flex_pit_flag[layer_idx] && > - (pf->fdir.flex_set[field_idx].src_offset == flex_pit->src_offset && > - pf->fdir.flex_set[field_idx].size == flex_pit->size && > - pf->fdir.flex_set[field_idx].dst_offset == flex_pit->dst_offset)) > - return 1; > - > - pf->fdir.flex_set[field_idx].src_offset = > - flex_pit->src_offset; > - pf->fdir.flex_set[field_idx].size = > - flex_pit->size; > - pf->fdir.flex_set[field_idx].dst_offset = > - flex_pit->dst_offset; > - > - return 0; > -} > - > -static void > -i40e_flow_set_fdir_flex_pit(struct i40e_pf *pf, > - enum i40e_flxpld_layer_idx layer_idx, > - uint8_t raw_id) > -{ > - struct i40e_hw *hw = I40E_PF_TO_HW(pf); > - uint32_t flx_pit, flx_ort; > - uint8_t field_idx; > - uint16_t min_next_off = 0; /* in words */ > - uint8_t i; > - > - if (raw_id) { > - flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) | > - (raw_id << I40E_GLQF_ORT_FIELD_CNT_SHIFT) | > - (layer_idx * I40E_MAX_FLXPLD_FIED); > - I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), > flx_ort); > - } > - > - /* Set flex pit */ > - for (i = 0; i < raw_id; i++) { > - field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; > - flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset, > - pf->fdir.flex_set[field_idx].size, > - pf->fdir.flex_set[field_idx].dst_offset); > - > - I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), > flx_pit); > - min_next_off = pf->fdir.flex_set[field_idx].src_offset + > - pf->fdir.flex_set[field_idx].size; > - } > - > - for (; i < I40E_MAX_FLXPLD_FIED; i++) { > - /* set the non-used register obeying register's constrain */ > - field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; > - flx_pit = MK_FLX_PIT(min_next_off, > NONUSE_FLX_PIT_FSIZE, > - NONUSE_FLX_PIT_DEST_OFF); > - I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), > flx_pit); > - min_next_off++; > - } > - > - pf->fdir.flex_pit_flag[layer_idx] = 1; > -} > - > static int > i40e_flow_set_fdir_inset(struct i40e_pf *pf, > enum i40e_filter_pctype pctype, > @@ -2534,10 +2459,10 @@ i40e_flow_parse_fdir_pattern(struct > rte_eth_dev *dev, > struct i40e_fdir_flex_pit flex_pit; > uint8_t next_dst_off = 0; > uint16_t flex_size; > - bool cfg_flex_pit = true; > uint16_t ether_type; > uint32_t vtc_flow_cpu; > bool outer_ip = true; > + uint8_t field_idx; > int ret; > > memset(off_arr, 0, sizeof(off_arr)); > @@ -3089,6 +3014,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev > *dev, > > flex_size = 0; > memset(&flex_pit, 0, sizeof(struct > i40e_fdir_flex_pit)); > + field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + > raw_id; > flex_pit.size = > raw_spec->length / sizeof(uint16_t); > flex_pit.dst_offset = > @@ -3115,18 +3041,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev > *dev, > return -rte_errno; > } > > - /* Store flex pit to SW */ > - ret = i40e_flow_store_flex_pit(pf, &flex_pit, > - layer_idx, raw_id); > - if (ret < 0) { > - rte_flow_error_set(error, EINVAL, > - RTE_FLOW_ERROR_TYPE_ITEM, > - item, > - "Conflict with the first flexible rule."); > - return -rte_errno; > - } else if (ret > 0) > - cfg_flex_pit = false; > - > for (i = 0; i < raw_spec->length; i++) { > j = i + next_dst_off; > filter->input.flow_ext.flexbytes[j] = @@ - > 3137,6 +3051,11 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev, > > next_dst_off += raw_spec->length; > raw_id++; > + > + memcpy(&filter->input.flow_ext.flex_pit[field_idx], > + &flex_pit, sizeof(struct i40e_fdir_flex_pit)); > + filter->input.flow_ext.layer_idx = layer_idx; > + filter->input.flow_ext.raw_id = raw_id; > break; > case RTE_FLOW_ITEM_TYPE_VF: > vf_spec = item->spec; > @@ -3222,9 +3141,6 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev > *dev, > "Invalid pattern mask."); > return -rte_errno; > } > - > - if (cfg_flex_pit) > - i40e_flow_set_fdir_flex_pit(pf, layer_idx, raw_id);
Seems that multiple switch case set the layer_idx not only the place you delete, please double check if these case all need to handle. > } > > filter->input.pctype = pctype; > -- > 2.17.1