enum i40e_filter_pctype pctype,
const struct rte_eth_fdir_filter *filter,
bool add);
-static int i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+static int i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
struct i40e_fdir_filter *filter);
static struct i40e_fdir_filter *
i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
- const struct rte_eth_fdir_input *input);
+ const struct i40e_fdir_input *input);
static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf,
struct i40e_fdir_filter *filter);
+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);
static int
i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
return 0;
}
+static inline int
+i40e_flow_fdir_fill_eth_ip_head(const struct i40e_fdir_input *fdir_input,
+ unsigned char *raw_pkt,
+ bool vlan)
+{
+ static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
+ uint16_t *ether_type;
+ uint8_t len = 2 * sizeof(struct ether_addr);
+ struct ipv4_hdr *ip;
+ struct ipv6_hdr *ip6;
+ static const uint8_t next_proto[] = {
+ [I40E_FILTER_PCTYPE_FRAG_IPV4] = IPPROTO_IP,
+ [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = IPPROTO_TCP,
+ [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = IPPROTO_UDP,
+ [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] = IPPROTO_SCTP,
+ [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = IPPROTO_IP,
+ [I40E_FILTER_PCTYPE_FRAG_IPV6] = IPPROTO_NONE,
+ [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] = IPPROTO_TCP,
+ [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = IPPROTO_UDP,
+ [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = IPPROTO_SCTP,
+ [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE,
+ };
+
+ raw_pkt += 2 * sizeof(struct ether_addr);
+ if (vlan && fdir_input->flow_ext.vlan_tci) {
+ rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
+ rte_memcpy(raw_pkt + sizeof(uint16_t),
+ &fdir_input->flow_ext.vlan_tci,
+ sizeof(uint16_t));
+ raw_pkt += sizeof(vlan_frame);
+ len += sizeof(vlan_frame);
+ }
+ ether_type = (uint16_t *)raw_pkt;
+ raw_pkt += sizeof(uint16_t);
+ len += sizeof(uint16_t);
+
+ switch (fdir_input->pctype) {
+ case I40E_FILTER_PCTYPE_L2_PAYLOAD:
+ *ether_type = fdir_input->flow.l2_flow.ether_type;
+ break;
+ case I40E_FILTER_PCTYPE_NONF_IPV4_TCP:
+ case I40E_FILTER_PCTYPE_NONF_IPV4_UDP:
+ case I40E_FILTER_PCTYPE_NONF_IPV4_SCTP:
+ case I40E_FILTER_PCTYPE_NONF_IPV4_OTHER:
+ case I40E_FILTER_PCTYPE_FRAG_IPV4:
+ ip = (struct ipv4_hdr *)raw_pkt;
+
+ *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
+ ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
+ /* set len to by default */
+ ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
+ ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
+ fdir_input->flow.ip4_flow.proto :
+ next_proto[fdir_input->pctype];
+ ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
+ fdir_input->flow.ip4_flow.ttl :
+ I40E_FDIR_IP_DEFAULT_TTL;
+ ip->type_of_service = fdir_input->flow.ip4_flow.tos;
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
+ ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
+ len += sizeof(struct ipv4_hdr);
+ break;
+ case I40E_FILTER_PCTYPE_NONF_IPV6_TCP:
+ case I40E_FILTER_PCTYPE_NONF_IPV6_UDP:
+ case I40E_FILTER_PCTYPE_NONF_IPV6_SCTP:
+ case I40E_FILTER_PCTYPE_NONF_IPV6_OTHER:
+ case I40E_FILTER_PCTYPE_FRAG_IPV6:
+ ip6 = (struct ipv6_hdr *)raw_pkt;
+
+ *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
+ ip6->vtc_flow =
+ rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
+ (fdir_input->flow.ipv6_flow.tc <<
+ I40E_FDIR_IPv6_TC_OFFSET));
+ ip6->payload_len =
+ rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
+ ip6->proto = fdir_input->flow.ipv6_flow.proto ?
+ fdir_input->flow.ipv6_flow.proto :
+ next_proto[fdir_input->pctype];
+ ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
+ fdir_input->flow.ipv6_flow.hop_limits :
+ I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ rte_memcpy(&ip6->src_addr,
+ &fdir_input->flow.ipv6_flow.dst_ip,
+ IPV6_ADDR_LEN);
+ rte_memcpy(&ip6->dst_addr,
+ &fdir_input->flow.ipv6_flow.src_ip,
+ IPV6_ADDR_LEN);
+ len += sizeof(struct ipv6_hdr);
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "unknown pctype %u.",
+ fdir_input->pctype);
+ return -1;
+ }
+ return len;
+}
+
+/**
+ * i40e_flow_fdir_construct_pkt - construct packet based on fields in input
+ * @pf: board private structure
+ * @fdir_input: input set of the flow director entry
+ * @raw_pkt: a packet to be constructed
+ */
+static int
+i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
+ const struct i40e_fdir_input *fdir_input,
+ unsigned char *raw_pkt)
+{
+ unsigned char *payload, *ptr;
+ struct udp_hdr *udp;
+ struct tcp_hdr *tcp;
+ struct sctp_hdr *sctp;
+ uint8_t size, dst = 0;
+ uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
+ int len;
+
+ /* fill the ethernet and IP head */
+ len = i40e_flow_fdir_fill_eth_ip_head(fdir_input, raw_pkt,
+ !!fdir_input->flow_ext.vlan_tci);
+ if (len < 0)
+ return -EINVAL;
+
+ /* fill the L4 head */
+ switch (fdir_input->pctype) {
+ case I40E_FILTER_PCTYPE_NONF_IPV4_UDP:
+ udp = (struct udp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)udp + sizeof(struct udp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ udp->src_port = fdir_input->flow.udp4_flow.dst_port;
+ udp->dst_port = fdir_input->flow.udp4_flow.src_port;
+ udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV4_TCP:
+ tcp = (struct tcp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ tcp->src_port = fdir_input->flow.tcp4_flow.dst_port;
+ tcp->dst_port = fdir_input->flow.tcp4_flow.src_port;
+ tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV4_SCTP:
+ sctp = (struct sctp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ sctp->src_port = fdir_input->flow.sctp4_flow.dst_port;
+ sctp->dst_port = fdir_input->flow.sctp4_flow.src_port;
+ sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV4_OTHER:
+ case I40E_FILTER_PCTYPE_FRAG_IPV4:
+ payload = raw_pkt + len;
+ set_idx = I40E_FLXPLD_L3_IDX;
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV6_UDP:
+ udp = (struct udp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)udp + sizeof(struct udp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ udp->src_port = fdir_input->flow.udp6_flow.dst_port;
+ udp->dst_port = fdir_input->flow.udp6_flow.src_port;
+ udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV6_TCP:
+ tcp = (struct tcp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)tcp + sizeof(struct tcp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
+ tcp->src_port = fdir_input->flow.udp6_flow.dst_port;
+ tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV6_SCTP:
+ sctp = (struct sctp_hdr *)(raw_pkt + len);
+ payload = (unsigned char *)sctp + sizeof(struct sctp_hdr);
+ /**
+ * The source and destination fields in the transmitted packet
+ * need to be presented in a reversed order with respect
+ * to the expected received packets.
+ */
+ sctp->src_port = fdir_input->flow.sctp6_flow.dst_port;
+ sctp->dst_port = fdir_input->flow.sctp6_flow.src_port;
+ sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
+ break;
+
+ case I40E_FILTER_PCTYPE_NONF_IPV6_OTHER:
+ case I40E_FILTER_PCTYPE_FRAG_IPV6:
+ payload = raw_pkt + len;
+ set_idx = I40E_FLXPLD_L3_IDX;
+ break;
+ case I40E_FILTER_PCTYPE_L2_PAYLOAD:
+ payload = raw_pkt + len;
+ /**
+ * ARP packet is a special case on which the payload
+ * starts after the whole ARP header
+ */
+ if (fdir_input->flow.l2_flow.ether_type ==
+ rte_cpu_to_be_16(ETHER_TYPE_ARP))
+ payload += sizeof(struct arp_hdr);
+ set_idx = I40E_FLXPLD_L2_IDX;
+ break;
+ default:
+ PMD_DRV_LOG(ERR, "unknown pctype %u.", fdir_input->pctype);
+ return -EINVAL;
+ }
+
+ /* fill the flexbytes to payload */
+ for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
+ pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i;
+ size = pf->fdir.flex_set[pit_idx].size;
+ if (size == 0)
+ continue;
+ dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t);
+ ptr = payload +
+ pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t);
+ (void)rte_memcpy(ptr,
+ &fdir_input->flow_ext.flexbytes[dst],
+ size * sizeof(uint16_t));
+ }
+
+ return 0;
+}
+
/* Construct the tx flags */
static inline uint64_t
i40e_build_ctob(uint32_t td_cmd,
}
static int
-i40e_fdir_filter_convert(const struct rte_eth_fdir_filter *input,
+i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
struct i40e_fdir_filter *filter)
{
- rte_memcpy(&filter->fdir, input, sizeof(struct rte_eth_fdir_filter));
+ rte_memcpy(&filter->fdir, input, sizeof(struct i40e_fdir_filter_conf));
return 0;
}
/* Check if there exists the flow director filter */
static struct i40e_fdir_filter *
i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
- const struct rte_eth_fdir_input *input)
+ const struct i40e_fdir_input *input)
{
int ret;
/* Delete a flow director filter from the SW list */
int
-i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct rte_eth_fdir_input *input)
+i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct i40e_fdir_input *input)
{
struct i40e_fdir_info *fdir_info = &pf->fdir;
struct i40e_fdir_filter *filter;
*/
int
i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
- const struct rte_eth_fdir_filter *filter,
- bool add)
+ const struct rte_eth_fdir_filter *filter,
+ bool add)
{
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);
unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
enum i40e_filter_pctype pctype;
- struct i40e_fdir_info *fdir_info = &pf->fdir;
- struct i40e_fdir_filter *fdir_filter, *node;
- struct i40e_fdir_filter check_filter; /* Check if the filter exists */
int ret = 0;
if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
return -EINVAL;
}
+ memset(pkt, 0, I40E_FDIR_PKT_LEN);
+
+ ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
+ return ret;
+ }
+
+ if (hw->mac.type == I40E_MAC_X722) {
+ /* get translated pctype value in fd pctype register */
+ pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
+ hw, I40E_GLQF_FD_PCTYPES((int)pctype));
+ }
+
+ ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
+ if (ret < 0) {
+ PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
+ pctype);
+ return ret;
+ }
+
+ return ret;
+}
+
+/**
+ * i40e_flow_add_del_fdir_filter - add or remove a flow director filter.
+ * @pf: board private structure
+ * @filter: fdir filter entry
+ * @add: 0 - delete, 1 - add
+ */
+int
+i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
+ const struct i40e_fdir_filter_conf *filter,
+ bool add)
+{
+ 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);
+ unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
+ enum i40e_filter_pctype pctype;
+ struct i40e_fdir_info *fdir_info = &pf->fdir;
+ struct i40e_fdir_filter *fdir_filter, *node;
+ struct i40e_fdir_filter check_filter; /* Check if the filter exists */
+ int ret = 0;
+
+ if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
+ PMD_DRV_LOG(ERR, "FDIR is not enabled, please check the mode in fdir_conf.");
+ return -ENOTSUP;
+ }
+
+ if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
+ PMD_DRV_LOG(ERR, "Invalid queue ID");
+ return -EINVAL;
+ }
+ if (filter->input.flow_ext.is_vf &&
+ filter->input.flow_ext.dst_id >= pf->vf_num) {
+ PMD_DRV_LOG(ERR, "Invalid VF ID");
+ return -EINVAL;
+ }
+
/* Check if there is the filter in SW list */
memset(&check_filter, 0, sizeof(check_filter));
i40e_fdir_filter_convert(filter, &check_filter);
memset(pkt, 0, I40E_FDIR_PKT_LEN);
- ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
+ ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt);
if (ret < 0) {
PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
return ret;
if (hw->mac.type == I40E_MAC_X722) {
/* get translated pctype value in fd pctype register */
pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
- hw, I40E_GLQF_FD_PCTYPES((int)pctype));
- }
- ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
+ hw, I40E_GLQF_FD_PCTYPES(
+ (int)filter->input.pctype));
+ } else
+ pctype = filter->input.pctype;
+
+ ret = i40e_flow_fdir_filter_programming(pf, pctype, filter, add);
if (ret < 0) {
PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
pctype);
return -ETIMEDOUT;
}
+/*
+ * 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
+ */
+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)
+{
+ 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, i;
+ uint8_t dest;
+
+ 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);
+ 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();
+ I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
+ 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_fdir_flush - clear all filters of Flow Director table
* @pf: board private structure
uint32_t best_cnt; /**< Number of filters in best effort spaces. */
TAILQ_FOREACH(f, fdir_list, rules)
- i40e_add_del_fdir_filter(dev, &f->fdir, TRUE);
+ i40e_flow_add_del_fdir_filter(dev, &f->fdir, TRUE);
fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
guarant_cnt =