src/dpdk/drivers/net/i40e/i40e_fdir.c
static int
i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
				  enum i40e_filter_pctype pctype,
				  const struct i40e_fdir_filter_conf *filter,
				  bool add, bool wait_status)
{
	struct i40e_tx_queue *txq = pf->fdir.txq;
	struct i40e_rx_queue *rxq = pf->fdir.rxq;
	const struct i40e_fdir_action *fdir_action = &filter->action;
	volatile struct i40e_tx_desc *txdp;
	volatile struct i40e_filter_program_desc *fdirdp;
	uint32_t td_cmd;
	uint16_t vsi_id;
	uint8_t dest;
	uint32_t i;

	PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
	fdirdp = (volatile struct i40e_filter_program_desc *)
				(&txq->tx_ring[txq->tx_tail]);

	fdirdp->qindex_flex_ptype_vsi =
			rte_cpu_to_le_32((fdir_action->rx_queue <<
					  I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
					  I40E_TXD_FLTR_QW0_QINDEX_MASK);

	fdirdp->qindex_flex_ptype_vsi |=
			rte_cpu_to_le_32((fdir_action->flex_off <<
					  I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
					  I40E_TXD_FLTR_QW0_FLEXOFF_MASK);

	fdirdp->qindex_flex_ptype_vsi |=
			rte_cpu_to_le_32((pctype <<
					  I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
					  I40E_TXD_FLTR_QW0_PCTYPE_MASK);

	if (filter->input.flow_ext.is_vf)
		vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
	else
		/* Use LAN VSI Id by default */
		vsi_id = pf->main_vsi->vsi_id;
	fdirdp->qindex_flex_ptype_vsi |=
		rte_cpu_to_le_32(((uint32_t)vsi_id <<
				  I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
				  I40E_TXD_FLTR_QW0_DEST_VSI_MASK);

	fdirdp->dtype_cmd_cntindex =
			rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);

	if (add)
		fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
				I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
				I40E_TXD_FLTR_QW1_PCMD_SHIFT);
	else
		fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
				I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
				I40E_TXD_FLTR_QW1_PCMD_SHIFT);

	if (fdir_action->behavior == I40E_FDIR_REJECT)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
	else if (fdir_action->behavior == I40E_FDIR_ACCEPT)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
	else if (fdir_action->behavior == I40E_FDIR_PASSTHRU)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
	else {
		PMD_DRV_LOG(ERR, "Failed to program FDIR filter: unsupported fdir behavior.");
		return -EINVAL;
	}

	fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
				I40E_TXD_FLTR_QW1_DEST_SHIFT) &
				I40E_TXD_FLTR_QW1_DEST_MASK);

	fdirdp->dtype_cmd_cntindex |=
		rte_cpu_to_le_32((fdir_action->report_status <<
				I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
				I40E_TXD_FLTR_QW1_FD_STATUS_MASK);

	fdirdp->dtype_cmd_cntindex |=
			rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
	fdirdp->dtype_cmd_cntindex |=
			rte_cpu_to_le_32(
			((uint32_t)pf->fdir.match_counter_index <<
			I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
			I40E_TXD_FLTR_QW1_CNTINDEX_MASK);

	fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);

	PMD_DRV_LOG(INFO, "filling transmit descriptor.");
	txdp = &txq->tx_ring[txq->tx_tail + 1];
	txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr[txq->tx_tail >> 1]);

	td_cmd = I40E_TX_DESC_CMD_EOP |
		 I40E_TX_DESC_CMD_RS  |
		 I40E_TX_DESC_CMD_DUMMY;

	txdp->cmd_type_offset_bsz =
		i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);

	txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */
	if (txq->tx_tail >= txq->nb_tx_desc)
		txq->tx_tail = 0;
	/* Update the tx tail register */
	rte_wmb();

	/* fdir program rx queue cleanup */
	i40e_fdir_programming_status_cleanup(rxq);

	I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);

	if (wait_status) {
		for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
			if ((txdp->cmd_type_offset_bsz &
					rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
					rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
				break;
			rte_delay_us(1);
		}
		if (i >= I40E_FDIR_MAX_WAIT_US) {
			PMD_DRV_LOG(ERR,
			    "Failed to program FDIR filter: time out to get DD on tx queue.");
			return -ETIMEDOUT;
		}
		/* totally delay 10 ms to check programming status*/
		rte_delay_us(I40E_FDIR_MAX_WAIT_US);
		if (i40e_check_fdir_programming_status(rxq) < 0) {
			PMD_DRV_LOG(ERR,
			    "Failed to program FDIR filter: programming status reported.");
			return -ETIMEDOUT;
		}
	}

	return 0;
}
/*
 * i40e_flow_fdir_filter_programming - Program a flow director filter rule.
 * Is done by Flow Director Programming Descriptor followed by packet
 * structure that contains the filter fields need to match.
 * @pf: board private structure
 * @pctype: pctype
 * @filter: fdir filter entry
 * @add: 0 - delete, 1 - add
 */
Program a flow director filter rule.
Is done by Flow Director Programming Descriptor followed by packet
structure that contains the filter fields need to match.
@pf: board private structure
@pctype: pctype
@filter: fdir filter entry
@add: 0 - delete, 1 - add
Program a flow director filter rule . Is done by Flow Director Programming Descriptor followed by packet structure that contains the filter fields need to match . @pf : board private structure @pctype : pctype @filter : fdir filter entry @add : 0 - delete 1 - add
static int
i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
				  enum i40e_filter_pctype pctype,
				  const struct i40e_fdir_filter_conf *filter,
				  bool add, bool wait_status)
{
	struct i40e_tx_queue *txq = pf->fdir.txq;
	struct i40e_rx_queue *rxq = pf->fdir.rxq;
	const struct i40e_fdir_action *fdir_action = &filter->action;
	volatile struct i40e_tx_desc *txdp;
	volatile struct i40e_filter_program_desc *fdirdp;
	uint32_t td_cmd;
	uint16_t vsi_id;
	uint8_t dest;
	uint32_t i;
	PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
	fdirdp = (volatile struct i40e_filter_program_desc *)
				(&txq->tx_ring[txq->tx_tail]);
	fdirdp->qindex_flex_ptype_vsi =
			rte_cpu_to_le_32((fdir_action->rx_queue <<
					  I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
					  I40E_TXD_FLTR_QW0_QINDEX_MASK);
	fdirdp->qindex_flex_ptype_vsi |=
			rte_cpu_to_le_32((fdir_action->flex_off <<
					  I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
					  I40E_TXD_FLTR_QW0_FLEXOFF_MASK);
	fdirdp->qindex_flex_ptype_vsi |=
			rte_cpu_to_le_32((pctype <<
					  I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
					  I40E_TXD_FLTR_QW0_PCTYPE_MASK);
	if (filter->input.flow_ext.is_vf)
		vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
	else
		vsi_id = pf->main_vsi->vsi_id;
	fdirdp->qindex_flex_ptype_vsi |=
		rte_cpu_to_le_32(((uint32_t)vsi_id <<
				  I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
				  I40E_TXD_FLTR_QW0_DEST_VSI_MASK);
	fdirdp->dtype_cmd_cntindex =
			rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);
	if (add)
		fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
				I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
				I40E_TXD_FLTR_QW1_PCMD_SHIFT);
	else
		fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
				I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
				I40E_TXD_FLTR_QW1_PCMD_SHIFT);
	if (fdir_action->behavior == I40E_FDIR_REJECT)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
	else if (fdir_action->behavior == I40E_FDIR_ACCEPT)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
	else if (fdir_action->behavior == I40E_FDIR_PASSTHRU)
		dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
	else {
		PMD_DRV_LOG(ERR, "Failed to program FDIR filter: unsupported fdir behavior.");
		return -EINVAL;
	}
	fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
				I40E_TXD_FLTR_QW1_DEST_SHIFT) &
				I40E_TXD_FLTR_QW1_DEST_MASK);
	fdirdp->dtype_cmd_cntindex |=
		rte_cpu_to_le_32((fdir_action->report_status <<
				I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
				I40E_TXD_FLTR_QW1_FD_STATUS_MASK);
	fdirdp->dtype_cmd_cntindex |=
			rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
	fdirdp->dtype_cmd_cntindex |=
			rte_cpu_to_le_32(
			((uint32_t)pf->fdir.match_counter_index <<
			I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
			I40E_TXD_FLTR_QW1_CNTINDEX_MASK);
	fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);
	PMD_DRV_LOG(INFO, "filling transmit descriptor.");
	txdp = &txq->tx_ring[txq->tx_tail + 1];
	txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr[txq->tx_tail >> 1]);
	td_cmd = I40E_TX_DESC_CMD_EOP |
		 I40E_TX_DESC_CMD_RS  |
		 I40E_TX_DESC_CMD_DUMMY;
	txdp->cmd_type_offset_bsz =
		i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);
	txq->tx_tail += 2; 
	if (txq->tx_tail >= txq->nb_tx_desc)
		txq->tx_tail = 0;
	rte_wmb();
	i40e_fdir_programming_status_cleanup(rxq);
	I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
	if (wait_status) {
		for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
			if ((txdp->cmd_type_offset_bsz &
					rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
					rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
				break;
			rte_delay_us(1);
		}
		if (i >= I40E_FDIR_MAX_WAIT_US) {
			PMD_DRV_LOG(ERR,
			    "Failed to program FDIR filter: time out to get DD on tx queue.");
			return -ETIMEDOUT;
		}
		rte_delay_us(I40E_FDIR_MAX_WAIT_US);
		if (i40e_check_fdir_programming_status(rxq) < 0) {
			PMD_DRV_LOG(ERR,
			    "Failed to program FDIR filter: programming status reported.");
			return -ETIMEDOUT;
		}
	}
	return 0;
}
static int i40e_flow_fdir_filter_programming ( struct i40e_pf * pf , enum i40e_filter_pctype pctype , const struct i40e_fdir_filter_conf * filter , bool add , bool wait_status ) { struct i40e_tx_queue * txq = pf -> fdir . txq ; struct i40e_rx_queue * rxq = pf -> fdir . rxq ; const struct i40e_fdir_action * fdir_action = & filter -> action ; volatile struct i40e_tx_desc * txdp ; volatile struct i40e_filter_program_desc * fdirdp ; uint32_t td_cmd ; uint16_t vsi_id ; uint8_t dest ; uint32_t i ; PMD_DRV_LOG ( INFO , " " ) ; fdirdp = ( volatile struct i40e_filter_program_desc * ) ( & txq -> tx_ring [ txq -> tx_tail ] ) ; fdirdp -> qindex_flex_ptype_vsi = rte_cpu_to_le_32 ( ( fdir_action -> rx_queue << I40E_TXD_FLTR_QW0_QINDEX_SHIFT ) & I40E_TXD_FLTR_QW0_QINDEX_MASK ) ; fdirdp -> qindex_flex_ptype_vsi |= rte_cpu_to_le_32 ( ( fdir_action -> flex_off << I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT ) & I40E_TXD_FLTR_QW0_FLEXOFF_MASK ) ; fdirdp -> qindex_flex_ptype_vsi |= rte_cpu_to_le_32 ( ( pctype << I40E_TXD_FLTR_QW0_PCTYPE_SHIFT ) & I40E_TXD_FLTR_QW0_PCTYPE_MASK ) ; if ( filter -> input . flow_ext . is_vf ) vsi_id = pf -> vfs [ filter -> input . flow_ext . dst_id ] . vsi -> vsi_id ; else vsi_id = pf -> main_vsi -> vsi_id ; fdirdp -> qindex_flex_ptype_vsi |= rte_cpu_to_le_32 ( ( ( uint32_t ) vsi_id << I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT ) & I40E_TXD_FLTR_QW0_DEST_VSI_MASK ) ; fdirdp -> dtype_cmd_cntindex = rte_cpu_to_le_32 ( I40E_TX_DESC_DTYPE_FILTER_PROG ) ; if ( add ) fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE << I40E_TXD_FLTR_QW1_PCMD_SHIFT ) ; else fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << I40E_TXD_FLTR_QW1_PCMD_SHIFT ) ; if ( fdir_action -> behavior == I40E_FDIR_REJECT ) dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET ; else if ( fdir_action -> behavior == I40E_FDIR_ACCEPT ) dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX ; else if ( fdir_action -> behavior == I40E_FDIR_PASSTHRU ) dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER ; else { PMD_DRV_LOG ( ERR , " " ) ; return - EINVAL ; } fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( ( dest << I40E_TXD_FLTR_QW1_DEST_SHIFT ) & I40E_TXD_FLTR_QW1_DEST_MASK ) ; fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( ( fdir_action -> report_status << I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT ) & I40E_TXD_FLTR_QW1_FD_STATUS_MASK ) ; fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( I40E_TXD_FLTR_QW1_CNT_ENA_MASK ) ; fdirdp -> dtype_cmd_cntindex |= rte_cpu_to_le_32 ( ( ( uint32_t ) pf -> fdir . match_counter_index << I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT ) & I40E_TXD_FLTR_QW1_CNTINDEX_MASK ) ; fdirdp -> fd_id = rte_cpu_to_le_32 ( filter -> soft_id ) ; PMD_DRV_LOG ( INFO , " " ) ; txdp = & txq -> tx_ring [ txq -> tx_tail + 1 ] ; txdp -> buffer_addr = rte_cpu_to_le_64 ( pf -> fdir . dma_addr [ txq -> tx_tail >> 1 ] ) ; td_cmd = I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS | I40E_TX_DESC_CMD_DUMMY ; txdp -> cmd_type_offset_bsz = i40e_build_ctob ( td_cmd , 0 , I40E_FDIR_PKT_LEN , 0 ) ; txq -> tx_tail += 2 ; if ( txq -> tx_tail >= txq -> nb_tx_desc ) txq -> tx_tail = 0 ; rte_wmb ( ) ; i40e_fdir_programming_status_cleanup ( rxq ) ; I40E_PCI_REG_WRITE ( txq -> qtx_tail , txq -> tx_tail ) ; if ( wait_status ) { for ( i = 0 ; i < I40E_FDIR_MAX_WAIT_US ; i ++ ) { if ( ( txdp -> cmd_type_offset_bsz & rte_cpu_to_le_64 ( I40E_TXD_QW1_DTYPE_MASK ) ) == rte_cpu_to_le_64 ( I40E_TX_DESC_DTYPE_DESC_DONE ) ) break ; rte_delay_us ( 1 ) ; } if ( i >= I40E_FDIR_MAX_WAIT_US ) { PMD_DRV_LOG ( ERR , " " ) ; return - ETIMEDOUT ; } rte_delay_us ( I40E_FDIR_MAX_WAIT_US ) ; if ( i40e_check_fdir_programming_status ( rxq ) < 0 ) { PMD_DRV_LOG ( ERR , " " ) ; return - ETIMEDOUT ; } } return 0 ; }
i40e_flow_fdir_filter_programming - Program a flow director filter rule.
i40e_flow_fdir_filter_programming - Program a flow director filter rule .
/* Use LAN VSI Id by default */ /* set 2 descriptors above, fdirdp and txdp */ /* Update the tx tail register */ /* fdir program rx queue cleanup */ /* totally delay 10 ms to check programming status*/