@@ -85,6 +85,8 @@
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_set_fdir_flx_mask(struct i40e_pf *pf,
+ struct rte_eth_fdir_flex_masks *flex_masks);
static int i40e_fdir_construct_pkt(struct i40e_pf *pf,
struct rte_eth_fdir_input *fdir_input,
unsigned char *raw_pkt);
@@ -420,6 +422,123 @@ i40e_set_flx_pld_cfg(struct i40e_pf *pf,
return 0;
}
+static inline void
+i40e_set_flex_mask_on_pctype(
+ struct i40e_hw *hw,
+ enum i40e_filter_pctype pctype,
+ struct rte_eth_fdir_flex_masks *flex_masks)
+{
+ uint32_t flxinset, mask;
+ int i;
+
+ flxinset = (flex_masks->words_mask <<
+ I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
+ I40E_PRTQF_FD_FLXINSET_INSET_MASK;
+ I40E_WRITE_REG(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);
+
+ for (i = 0; i < flex_masks->nb_field; i++) {
+ mask = (flex_masks->field[i].bitmask <<
+ I40E_PRTQF_FD_MSK_MASK_SHIFT) &
+ I40E_PRTQF_FD_MSK_MASK_MASK;
+ mask |= ((flex_masks->field[i].offset +
+ I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
+ I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
+ I40E_PRTQF_FD_MSK_OFFSET_MASK;
+ I40E_WRITE_REG(hw, I40E_PRTQF_FD_MSK(pctype, i), mask);
+ }
+}
+
+/*
+ * i40e_set_fdir_flx_mask - configure the mask on flexible payload
+ * @pf: board private structure
+ * @flex_masks: mask for flexible payload
+ */
+static int
+i40e_set_fdir_flx_mask(struct i40e_pf *pf,
+ struct rte_eth_fdir_flex_masks *flex_masks)
+{
+ struct i40e_hw *hw = I40E_PF_TO_HW(pf);
+ struct rte_eth_fdir_info fdir;
+ int ret = 0;
+
+ if (flex_masks == NULL)
+ return -EINVAL;
+
+ if (flex_masks->nb_field > 2) {
+ PMD_DRV_LOG(ERR, "bit masks cannot support more than 2 words.");
+ return -EINVAL;
+ }
+ /*
+ * flexible payload masks 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;
+ }
+ }
+
+ switch (flex_masks->flow_type) {
+ case RTE_ETH_FLOW_TYPE_UDPV4:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV4_UDP,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_TCPV4:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV4_TCP,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_SCTPV4:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV4_SCTP,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
+ /* set mask for both NONF_IPV4 and FRAG_IPV4 PCTYPE*/
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV4_OTHER,
+ flex_masks);
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_FRAG_IPV4,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_UDPV6:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV6_UDP,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_TCPV6:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV6_TCP,
+ flex_masks);
+ case RTE_ETH_FLOW_TYPE_SCTPV6:
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV6_SCTP,
+ flex_masks);
+ break;
+ case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
+ /* set mask for both NONF_IPV6 and FRAG_IPV6 PCTYPE*/
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_NONF_IPV6_OTHER,
+ flex_masks);
+ i40e_set_flex_mask_on_pctype(hw,
+ I40E_FILTER_PCTYPE_FRAG_IPV6,
+ flex_masks);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "invalid flow_type input.");
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
/*
* i40e_fdir_construct_pkt - construct packet based on fields in input
* @pf: board private structure
@@ -1081,8 +1200,11 @@ i40e_fdir_ctrl_func(struct i40e_pf *pf, enum rte_filter_op filter_op, void *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 if (fdir_cfg->cmd == RTE_ETH_FDIR_CFG_FLX_MASK)
+ ret = i40e_set_fdir_flx_mask(pf,
+ (struct rte_eth_fdir_flex_masks *)fdir_cfg->cfg);
else {
- PMD_DRV_LOG(WARNING, "unsupported configuration command %u.",
+ PMD_DRV_LOG(ERR, "unsupported configuration command %u.",
fdir_cfg->cmd);
return -EINVAL;
}