1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2015 Intel Corporation
13 #include <rte_ether.h>
14 #include <rte_ethdev_driver.h>
16 #include <rte_memzone.h>
17 #include <rte_malloc.h>
23 #include <rte_hash_crc.h>
25 #include "i40e_logs.h"
26 #include "base/i40e_type.h"
27 #include "base/i40e_prototype.h"
28 #include "i40e_ethdev.h"
29 #include "i40e_rxtx.h"
31 #define I40E_FDIR_MZ_NAME "FDIR_MEMZONE"
33 #define IPV6_ADDR_LEN 16
36 #define I40E_FDIR_PKT_LEN 512
37 #define I40E_FDIR_IP_DEFAULT_LEN 420
38 #define I40E_FDIR_IP_DEFAULT_TTL 0x40
39 #define I40E_FDIR_IP_DEFAULT_VERSION_IHL 0x45
40 #define I40E_FDIR_TCP_DEFAULT_DATAOFF 0x50
41 #define I40E_FDIR_IPv6_DEFAULT_VTC_FLOW 0x60000000
43 #define I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS 0xFF
44 #define I40E_FDIR_IPv6_PAYLOAD_LEN 380
45 #define I40E_FDIR_UDP_DEFAULT_LEN 400
46 #define I40E_FDIR_GTP_DEFAULT_LEN 384
47 #define I40E_FDIR_INNER_IP_DEFAULT_LEN 384
48 #define I40E_FDIR_INNER_IPV6_DEFAULT_LEN 344
50 #define I40E_FDIR_GTPC_DST_PORT 2123
51 #define I40E_FDIR_GTPU_DST_PORT 2152
52 #define I40E_FDIR_GTP_VER_FLAG_0X30 0x30
53 #define I40E_FDIR_GTP_VER_FLAG_0X32 0x32
54 #define I40E_FDIR_GTP_MSG_TYPE_0X01 0x01
55 #define I40E_FDIR_GTP_MSG_TYPE_0XFF 0xFF
57 /* Wait time for fdir filter programming */
58 #define I40E_FDIR_MAX_WAIT_US 10000
60 /* Wait count and interval for fdir filter flush */
61 #define I40E_FDIR_FLUSH_RETRY 50
62 #define I40E_FDIR_FLUSH_INTERVAL_MS 5
64 #define I40E_COUNTER_PF 2
65 /* Statistic counter index for one pf */
66 #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF)
68 #define I40E_FDIR_FLOWS ( \
69 (1ULL << RTE_ETH_FLOW_FRAG_IPV4) | \
70 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \
71 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \
72 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \
73 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \
74 (1ULL << RTE_ETH_FLOW_FRAG_IPV6) | \
75 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \
76 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \
77 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \
78 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \
79 (1ULL << RTE_ETH_FLOW_L2_PAYLOAD))
81 static int i40e_fdir_filter_programming(struct i40e_pf *pf,
82 enum i40e_filter_pctype pctype,
83 const struct rte_eth_fdir_filter *filter,
85 static int i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
86 struct i40e_fdir_filter *filter);
87 static struct i40e_fdir_filter *
88 i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
89 const struct i40e_fdir_input *input);
90 static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf,
91 struct i40e_fdir_filter *filter);
93 i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
94 enum i40e_filter_pctype pctype,
95 const struct i40e_fdir_filter_conf *filter,
99 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq)
101 struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi);
102 struct i40e_hmc_obj_rxq rx_ctx;
103 int err = I40E_SUCCESS;
105 memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq));
106 /* Init the RX queue in hardware */
107 rx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT;
109 rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT;
110 rx_ctx.qlen = rxq->nb_rx_desc;
111 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
114 rx_ctx.dtype = i40e_header_split_none;
115 rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE;
116 rx_ctx.rxmax = RTE_ETHER_MAX_LEN;
117 rx_ctx.tphrdesc_ena = 1;
118 rx_ctx.tphwdesc_ena = 1;
119 rx_ctx.tphdata_ena = 1;
120 rx_ctx.tphhead_ena = 1;
121 rx_ctx.lrxqthresh = 2;
127 err = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx);
128 if (err != I40E_SUCCESS) {
129 PMD_DRV_LOG(ERR, "Failed to clear FDIR RX queue context.");
132 err = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx);
133 if (err != I40E_SUCCESS) {
134 PMD_DRV_LOG(ERR, "Failed to set FDIR RX queue context.");
137 rxq->qrx_tail = hw->hw_addr +
138 I40E_QRX_TAIL(rxq->vsi->base_queue);
141 /* Init the RX tail regieter. */
142 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
148 * i40e_fdir_setup - reserve and initialize the Flow Director resources
149 * @pf: board private structure
152 i40e_fdir_setup(struct i40e_pf *pf)
154 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
155 struct i40e_vsi *vsi;
156 int err = I40E_SUCCESS;
157 char z_name[RTE_MEMZONE_NAMESIZE];
158 const struct rte_memzone *mz = NULL;
159 struct rte_eth_dev *eth_dev = pf->adapter->eth_dev;
161 if ((pf->flags & I40E_FLAG_FDIR) == 0) {
162 PMD_INIT_LOG(ERR, "HW doesn't support FDIR");
163 return I40E_NOT_SUPPORTED;
166 PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u,"
167 " num_filters_best_effort = %u.",
168 hw->func_caps.fd_filters_guaranteed,
169 hw->func_caps.fd_filters_best_effort);
171 vsi = pf->fdir.fdir_vsi;
173 PMD_DRV_LOG(INFO, "FDIR initialization has been done.");
176 /* make new FDIR VSI */
177 vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0);
179 PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI.");
180 return I40E_ERR_NO_AVAILABLE_VSI;
182 pf->fdir.fdir_vsi = vsi;
184 /*Fdir tx queue setup*/
185 err = i40e_fdir_setup_tx_resources(pf);
187 PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources.");
191 /*Fdir rx queue setup*/
192 err = i40e_fdir_setup_rx_resources(pf);
194 PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources.");
198 err = i40e_tx_queue_init(pf->fdir.txq);
200 PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization.");
204 /* need switch on before dev start*/
205 err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE);
207 PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on.");
211 /* Init the rx queue in hardware */
212 err = i40e_fdir_rx_queue_init(pf->fdir.rxq);
214 PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization.");
218 /* switch on rx queue */
219 err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE);
221 PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on.");
225 /* reserve memory for the fdir programming packet */
226 snprintf(z_name, sizeof(z_name), "%s_%s_%d",
227 eth_dev->device->driver->name,
229 eth_dev->data->port_id);
230 mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY);
232 PMD_DRV_LOG(ERR, "Cannot init memzone for "
233 "flow director program packet.");
234 err = I40E_ERR_NO_MEMORY;
237 pf->fdir.prg_pkt = mz->addr;
238 pf->fdir.dma_addr = mz->iova;
240 pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id);
241 PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.",
246 i40e_dev_rx_queue_release(pf->fdir.rxq);
249 i40e_dev_tx_queue_release(pf->fdir.txq);
252 i40e_vsi_release(vsi);
253 pf->fdir.fdir_vsi = NULL;
258 * i40e_fdir_teardown - release the Flow Director resources
259 * @pf: board private structure
262 i40e_fdir_teardown(struct i40e_pf *pf)
264 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
265 struct i40e_vsi *vsi;
267 vsi = pf->fdir.fdir_vsi;
270 int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE);
272 PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off");
273 err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE);
275 PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off");
276 i40e_dev_rx_queue_release(pf->fdir.rxq);
278 i40e_dev_tx_queue_release(pf->fdir.txq);
280 i40e_vsi_release(vsi);
281 pf->fdir.fdir_vsi = NULL;
284 /* check whether the flow director table in empty */
286 i40e_fdir_empty(struct i40e_hw *hw)
288 uint32_t guarant_cnt, best_cnt;
290 guarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
291 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
292 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
293 best_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
294 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
295 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
296 if (best_cnt + guarant_cnt > 0)
303 * Initialize the configuration about bytes stream extracted as flexible payload
307 i40e_init_flx_pld(struct i40e_pf *pf)
309 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
315 * Define the bytes stream extracted as flexible payload in
316 * field vector. By default, select 8 words from the beginning
317 * of payload as flexible payload.
319 for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) {
320 index = i * I40E_MAX_FLXPLD_FIED;
321 pf->fdir.flex_set[index].src_offset = 0;
322 pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM;
323 pf->fdir.flex_set[index].dst_offset = 0;
324 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900);
326 I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/
328 I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/
331 /* initialize the masks */
332 for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
333 pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) {
334 flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype);
336 if (flow_type == RTE_ETH_FLOW_UNKNOWN)
338 pf->fdir.flex_mask[pctype].word_mask = 0;
339 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0);
340 for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) {
341 pf->fdir.flex_mask[pctype].bitmask[i].offset = 0;
342 pf->fdir.flex_mask[pctype].bitmask[i].mask = 0;
343 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), 0);
348 #define I40E_VALIDATE_FLEX_PIT(flex_pit1, flex_pit2) do { \
349 if ((flex_pit2).src_offset < \
350 (flex_pit1).src_offset + (flex_pit1).size) { \
351 PMD_DRV_LOG(ERR, "src_offset should be not" \
352 " less than than previous offset" \
353 " + previous FSIZE."); \
359 * i40e_srcoff_to_flx_pit - transform the src_offset into flex_pit structure,
360 * and the flex_pit will be sorted by it's src_offset value
362 static inline uint16_t
363 i40e_srcoff_to_flx_pit(const uint16_t *src_offset,
364 struct i40e_fdir_flex_pit *flex_pit)
366 uint16_t src_tmp, size, num = 0;
367 uint16_t i, k, j = 0;
369 while (j < I40E_FDIR_MAX_FLEX_LEN) {
371 for (; j < I40E_FDIR_MAX_FLEX_LEN - 1; j++) {
372 if (src_offset[j + 1] == src_offset[j] + 1)
377 src_tmp = src_offset[j] + 1 - size;
378 /* the flex_pit need to be sort by src_offset */
379 for (i = 0; i < num; i++) {
380 if (src_tmp < flex_pit[i].src_offset)
383 /* if insert required, move backward */
384 for (k = num; k > i; k--)
385 flex_pit[k] = flex_pit[k - 1];
387 flex_pit[i].dst_offset = j + 1 - size;
388 flex_pit[i].src_offset = src_tmp;
389 flex_pit[i].size = size;
396 /* i40e_check_fdir_flex_payload -check flex payload configuration arguments */
398 i40e_check_fdir_flex_payload(const struct rte_eth_flex_payload_cfg *flex_cfg)
400 struct i40e_fdir_flex_pit flex_pit[I40E_FDIR_MAX_FLEX_LEN];
403 for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++) {
404 if (flex_cfg->src_offset[i] >= I40E_MAX_FLX_SOURCE_OFF) {
405 PMD_DRV_LOG(ERR, "exceeds maxmial payload limit.");
410 memset(flex_pit, 0, sizeof(flex_pit));
411 num = i40e_srcoff_to_flx_pit(flex_cfg->src_offset, flex_pit);
412 if (num > I40E_MAX_FLXPLD_FIED) {
413 PMD_DRV_LOG(ERR, "exceeds maxmial number of flex fields.");
416 for (i = 0; i < num; i++) {
417 if (flex_pit[i].size & 0x01 || flex_pit[i].dst_offset & 0x01 ||
418 flex_pit[i].src_offset & 0x01) {
419 PMD_DRV_LOG(ERR, "flexpayload should be measured"
424 I40E_VALIDATE_FLEX_PIT(flex_pit[i], flex_pit[i + 1]);
430 * i40e_check_fdir_flex_conf -check if the flex payload and mask configuration
431 * arguments are valid
434 i40e_check_fdir_flex_conf(const struct i40e_adapter *adapter,
435 const struct rte_eth_fdir_flex_conf *conf)
437 const struct rte_eth_flex_payload_cfg *flex_cfg;
438 const struct rte_eth_fdir_flex_mask *flex_mask;
443 enum i40e_filter_pctype pctype;
446 PMD_DRV_LOG(INFO, "NULL pointer.");
449 /* check flexible payload setting configuration */
450 if (conf->nb_payloads > RTE_ETH_L4_PAYLOAD) {
451 PMD_DRV_LOG(ERR, "invalid number of payload setting.");
454 for (i = 0; i < conf->nb_payloads; i++) {
455 flex_cfg = &conf->flex_set[i];
456 if (flex_cfg->type > RTE_ETH_L4_PAYLOAD) {
457 PMD_DRV_LOG(ERR, "invalid payload type.");
460 ret = i40e_check_fdir_flex_payload(flex_cfg);
462 PMD_DRV_LOG(ERR, "invalid flex payload arguments.");
467 /* check flex mask setting configuration */
468 if (conf->nb_flexmasks >= RTE_ETH_FLOW_MAX) {
469 PMD_DRV_LOG(ERR, "invalid number of flex masks.");
472 for (i = 0; i < conf->nb_flexmasks; i++) {
473 flex_mask = &conf->flex_mask[i];
474 pctype = i40e_flowtype_to_pctype(adapter, flex_mask->flow_type);
475 if (pctype == I40E_FILTER_PCTYPE_INVALID) {
476 PMD_DRV_LOG(WARNING, "invalid flow type.");
480 for (j = 0; j < I40E_FDIR_MAX_FLEX_LEN; j += sizeof(uint16_t)) {
481 mask_tmp = I40E_WORD(flex_mask->mask[j],
482 flex_mask->mask[j + 1]);
483 if (mask_tmp != 0x0 && mask_tmp != UINT16_MAX) {
485 if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD) {
486 PMD_DRV_LOG(ERR, " exceed maximal"
487 " number of bitmasks.");
497 * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload
498 * @pf: board private structure
499 * @cfg: the rule how bytes stream is extracted as flexible payload
502 i40e_set_flx_pld_cfg(struct i40e_pf *pf,
503 const struct rte_eth_flex_payload_cfg *cfg)
505 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
506 struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED];
507 uint32_t flx_pit, flx_ort;
508 uint16_t num, min_next_off; /* in words */
509 uint8_t field_idx = 0;
510 uint8_t layer_idx = 0;
513 if (cfg->type == RTE_ETH_L2_PAYLOAD)
514 layer_idx = I40E_FLXPLD_L2_IDX;
515 else if (cfg->type == RTE_ETH_L3_PAYLOAD)
516 layer_idx = I40E_FLXPLD_L3_IDX;
517 else if (cfg->type == RTE_ETH_L4_PAYLOAD)
518 layer_idx = I40E_FLXPLD_L4_IDX;
520 memset(flex_pit, 0, sizeof(flex_pit));
521 num = RTE_MIN(i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit),
525 flx_ort = (1 << I40E_GLQF_ORT_FLX_PAYLOAD_SHIFT) |
526 (num << I40E_GLQF_ORT_FIELD_CNT_SHIFT) |
527 (layer_idx * I40E_MAX_FLXPLD_FIED);
528 I40E_WRITE_GLB_REG(hw, I40E_GLQF_ORT(33 + layer_idx), flx_ort);
531 for (i = 0; i < num; i++) {
532 field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i;
533 /* record the info in fdir structure */
534 pf->fdir.flex_set[field_idx].src_offset =
535 flex_pit[i].src_offset / sizeof(uint16_t);
536 pf->fdir.flex_set[field_idx].size =
537 flex_pit[i].size / sizeof(uint16_t);
538 pf->fdir.flex_set[field_idx].dst_offset =
539 flex_pit[i].dst_offset / sizeof(uint16_t);
540 flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset,
541 pf->fdir.flex_set[field_idx].size,
542 pf->fdir.flex_set[field_idx].dst_offset);
544 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit);
546 min_next_off = pf->fdir.flex_set[field_idx].src_offset +
547 pf->fdir.flex_set[field_idx].size;
549 for (; i < I40E_MAX_FLXPLD_FIED; i++) {
550 /* set the non-used register obeying register's constrain */
551 flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE,
552 NONUSE_FLX_PIT_DEST_OFF);
554 I40E_PRTQF_FLX_PIT(layer_idx * I40E_MAX_FLXPLD_FIED + i),
561 * i40e_set_flex_mask_on_pctype - configure the mask on flexible payload
562 * @pf: board private structure
563 * @pctype: packet classify type
564 * @flex_masks: mask for flexible payload
567 i40e_set_flex_mask_on_pctype(struct i40e_pf *pf,
568 enum i40e_filter_pctype pctype,
569 const struct rte_eth_fdir_flex_mask *mask_cfg)
571 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
572 struct i40e_fdir_flex_mask *flex_mask;
573 uint32_t flxinset, fd_mask;
575 uint8_t i, nb_bitmask = 0;
577 flex_mask = &pf->fdir.flex_mask[pctype];
578 memset(flex_mask, 0, sizeof(struct i40e_fdir_flex_mask));
579 for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) {
580 mask_tmp = I40E_WORD(mask_cfg->mask[i], mask_cfg->mask[i + 1]);
581 if (mask_tmp != 0x0) {
582 flex_mask->word_mask |=
583 I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
584 if (mask_tmp != UINT16_MAX) {
586 flex_mask->bitmask[nb_bitmask].mask = ~mask_tmp;
587 flex_mask->bitmask[nb_bitmask].offset =
588 i / sizeof(uint16_t);
593 /* write mask to hw */
594 flxinset = (flex_mask->word_mask <<
595 I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) &
596 I40E_PRTQF_FD_FLXINSET_INSET_MASK;
597 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset);
599 for (i = 0; i < nb_bitmask; i++) {
600 fd_mask = (flex_mask->bitmask[i].mask <<
601 I40E_PRTQF_FD_MSK_MASK_SHIFT) &
602 I40E_PRTQF_FD_MSK_MASK_MASK;
603 fd_mask |= ((flex_mask->bitmask[i].offset +
604 I40E_FLX_OFFSET_IN_FIELD_VECTOR) <<
605 I40E_PRTQF_FD_MSK_OFFSET_SHIFT) &
606 I40E_PRTQF_FD_MSK_OFFSET_MASK;
607 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask);
612 * Enable/disable flow director RX processing in vector routines.
615 i40e_fdir_rx_proc_enable(struct rte_eth_dev *dev, bool on)
619 for (i = 0; i < dev->data->nb_rx_queues; i++) {
620 struct i40e_rx_queue *rxq = dev->data->rx_queues[i];
623 rxq->fdir_enabled = on;
625 PMD_DRV_LOG(DEBUG, "Flow Director processing on RX set to %d", on);
629 * Configure flow director related setting
632 i40e_fdir_configure(struct rte_eth_dev *dev)
634 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
635 struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
636 struct rte_eth_fdir_flex_conf *conf;
637 enum i40e_filter_pctype pctype;
643 * configuration need to be done before
644 * flow director filters are added
645 * If filters exist, flush them.
647 if (i40e_fdir_empty(hw) < 0) {
648 ret = i40e_fdir_flush(dev);
650 PMD_DRV_LOG(ERR, "failed to flush fdir table.");
655 /* enable FDIR filter */
656 val = i40e_read_rx_ctl(hw, I40E_PFQF_CTL_0);
657 val |= I40E_PFQF_CTL_0_FD_ENA_MASK;
658 i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, val);
660 i40e_init_flx_pld(pf); /* set flex config to default value */
662 conf = &dev->data->dev_conf.fdir_conf.flex_conf;
663 ret = i40e_check_fdir_flex_conf(pf->adapter, conf);
665 PMD_DRV_LOG(ERR, " invalid configuration arguments.");
669 if (!pf->support_multi_driver) {
670 /* configure flex payload */
671 for (i = 0; i < conf->nb_payloads; i++)
672 i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]);
673 /* configure flex mask*/
674 for (i = 0; i < conf->nb_flexmasks; i++) {
675 if (hw->mac.type == I40E_MAC_X722) {
676 /* get pctype value in fd pctype register */
677 pctype = (enum i40e_filter_pctype)
679 I40E_GLQF_FD_PCTYPES(
680 (int)i40e_flowtype_to_pctype(
682 conf->flex_mask[i].flow_type)));
684 pctype = i40e_flowtype_to_pctype(pf->adapter,
685 conf->flex_mask[i].flow_type);
688 i40e_set_flex_mask_on_pctype(pf, pctype,
689 &conf->flex_mask[i]);
692 PMD_DRV_LOG(ERR, "Not support flexible payload.");
695 /* Enable FDIR processing in RX routines */
696 i40e_fdir_rx_proc_enable(dev, 1);
702 i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input,
703 unsigned char *raw_pkt,
706 static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
707 uint16_t *ether_type;
708 uint8_t len = 2 * sizeof(struct rte_ether_addr);
709 struct rte_ipv4_hdr *ip;
710 struct rte_ipv6_hdr *ip6;
711 static const uint8_t next_proto[] = {
712 [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP,
713 [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP,
714 [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP,
715 [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP,
716 [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP,
717 [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE,
718 [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP,
719 [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP,
720 [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP,
721 [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE,
724 raw_pkt += 2 * sizeof(struct rte_ether_addr);
725 if (vlan && fdir_input->flow_ext.vlan_tci) {
726 rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
727 rte_memcpy(raw_pkt + sizeof(uint16_t),
728 &fdir_input->flow_ext.vlan_tci,
730 raw_pkt += sizeof(vlan_frame);
731 len += sizeof(vlan_frame);
733 ether_type = (uint16_t *)raw_pkt;
734 raw_pkt += sizeof(uint16_t);
735 len += sizeof(uint16_t);
737 switch (fdir_input->flow_type) {
738 case RTE_ETH_FLOW_L2_PAYLOAD:
739 *ether_type = fdir_input->flow.l2_flow.ether_type;
741 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
742 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
743 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
744 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
745 case RTE_ETH_FLOW_FRAG_IPV4:
746 ip = (struct rte_ipv4_hdr *)raw_pkt;
748 *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
749 ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
750 /* set len to by default */
751 ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
752 ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
753 fdir_input->flow.ip4_flow.proto :
754 next_proto[fdir_input->flow_type];
755 ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
756 fdir_input->flow.ip4_flow.ttl :
757 I40E_FDIR_IP_DEFAULT_TTL;
758 ip->type_of_service = fdir_input->flow.ip4_flow.tos;
760 * The source and destination fields in the transmitted packet
761 * need to be presented in a reversed order with respect
762 * to the expected received packets.
764 ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
765 ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
766 len += sizeof(struct rte_ipv4_hdr);
768 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
769 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
770 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
771 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
772 case RTE_ETH_FLOW_FRAG_IPV6:
773 ip6 = (struct rte_ipv6_hdr *)raw_pkt;
775 *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
777 rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
778 (fdir_input->flow.ipv6_flow.tc <<
779 I40E_FDIR_IPv6_TC_OFFSET));
781 rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
782 ip6->proto = fdir_input->flow.ipv6_flow.proto ?
783 fdir_input->flow.ipv6_flow.proto :
784 next_proto[fdir_input->flow_type];
785 ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
786 fdir_input->flow.ipv6_flow.hop_limits :
787 I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
789 * The source and destination fields in the transmitted packet
790 * need to be presented in a reversed order with respect
791 * to the expected received packets.
793 rte_memcpy(&(ip6->src_addr),
794 &(fdir_input->flow.ipv6_flow.dst_ip),
796 rte_memcpy(&(ip6->dst_addr),
797 &(fdir_input->flow.ipv6_flow.src_ip),
799 len += sizeof(struct rte_ipv6_hdr);
802 PMD_DRV_LOG(ERR, "unknown flow type %u.",
803 fdir_input->flow_type);
811 * i40e_fdir_construct_pkt - construct packet based on fields in input
812 * @pf: board private structure
813 * @fdir_input: input set of the flow director entry
814 * @raw_pkt: a packet to be constructed
817 i40e_fdir_construct_pkt(struct i40e_pf *pf,
818 const struct rte_eth_fdir_input *fdir_input,
819 unsigned char *raw_pkt)
821 unsigned char *payload, *ptr;
822 struct rte_udp_hdr *udp;
823 struct rte_tcp_hdr *tcp;
824 struct rte_sctp_hdr *sctp;
825 uint8_t size, dst = 0;
826 uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
829 /* fill the ethernet and IP head */
830 len = i40e_fdir_fill_eth_ip_head(fdir_input, raw_pkt,
831 !!fdir_input->flow_ext.vlan_tci);
835 /* fill the L4 head */
836 switch (fdir_input->flow_type) {
837 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP:
838 udp = (struct rte_udp_hdr *)(raw_pkt + len);
839 payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
841 * The source and destination fields in the transmitted packet
842 * need to be presented in a reversed order with respect
843 * to the expected received packets.
845 udp->src_port = fdir_input->flow.udp4_flow.dst_port;
846 udp->dst_port = fdir_input->flow.udp4_flow.src_port;
847 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
850 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP:
851 tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
852 payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
854 * The source and destination fields in the transmitted packet
855 * need to be presented in a reversed order with respect
856 * to the expected received packets.
858 tcp->src_port = fdir_input->flow.tcp4_flow.dst_port;
859 tcp->dst_port = fdir_input->flow.tcp4_flow.src_port;
860 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
863 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP:
864 sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
865 payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
867 * The source and destination fields in the transmitted packet
868 * need to be presented in a reversed order with respect
869 * to the expected received packets.
871 sctp->src_port = fdir_input->flow.sctp4_flow.dst_port;
872 sctp->dst_port = fdir_input->flow.sctp4_flow.src_port;
873 sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
876 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER:
877 case RTE_ETH_FLOW_FRAG_IPV4:
878 payload = raw_pkt + len;
879 set_idx = I40E_FLXPLD_L3_IDX;
882 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP:
883 udp = (struct rte_udp_hdr *)(raw_pkt + len);
884 payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
886 * The source and destination fields in the transmitted packet
887 * need to be presented in a reversed order with respect
888 * to the expected received packets.
890 udp->src_port = fdir_input->flow.udp6_flow.dst_port;
891 udp->dst_port = fdir_input->flow.udp6_flow.src_port;
892 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
895 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP:
896 tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
897 payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
899 * The source and destination fields in the transmitted packet
900 * need to be presented in a reversed order with respect
901 * to the expected received packets.
903 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
904 tcp->src_port = fdir_input->flow.udp6_flow.dst_port;
905 tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
908 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP:
909 sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
910 payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
912 * The source and destination fields in the transmitted packet
913 * need to be presented in a reversed order with respect
914 * to the expected received packets.
916 sctp->src_port = fdir_input->flow.sctp6_flow.dst_port;
917 sctp->dst_port = fdir_input->flow.sctp6_flow.src_port;
918 sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
921 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER:
922 case RTE_ETH_FLOW_FRAG_IPV6:
923 payload = raw_pkt + len;
924 set_idx = I40E_FLXPLD_L3_IDX;
926 case RTE_ETH_FLOW_L2_PAYLOAD:
927 payload = raw_pkt + len;
929 * ARP packet is a special case on which the payload
930 * starts after the whole ARP header
932 if (fdir_input->flow.l2_flow.ether_type ==
933 rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP))
934 payload += sizeof(struct rte_arp_hdr);
935 set_idx = I40E_FLXPLD_L2_IDX;
938 PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type);
942 /* fill the flexbytes to payload */
943 for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
944 pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i;
945 size = pf->fdir.flex_set[pit_idx].size;
948 dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t);
950 pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t);
952 &fdir_input->flow_ext.flexbytes[dst],
953 size * sizeof(uint16_t));
959 static struct i40e_customized_pctype *
960 i40e_flow_fdir_find_customized_pctype(struct i40e_pf *pf, uint8_t pctype)
962 struct i40e_customized_pctype *cus_pctype;
963 enum i40e_new_pctype i = I40E_CUSTOMIZED_GTPC;
965 for (; i < I40E_CUSTOMIZED_MAX; i++) {
966 cus_pctype = &pf->customized_pctype[i];
967 if (pctype == cus_pctype->pctype)
974 i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf,
975 const struct i40e_fdir_input *fdir_input,
976 unsigned char *raw_pkt,
979 struct i40e_customized_pctype *cus_pctype = NULL;
980 static uint8_t vlan_frame[] = {0x81, 0, 0, 0};
981 uint16_t *ether_type;
982 uint8_t len = 2 * sizeof(struct rte_ether_addr);
983 struct rte_ipv4_hdr *ip;
984 struct rte_ipv6_hdr *ip6;
985 uint8_t pctype = fdir_input->pctype;
986 bool is_customized_pctype = fdir_input->flow_ext.customized_pctype;
987 static const uint8_t next_proto[] = {
988 [I40E_FILTER_PCTYPE_FRAG_IPV4] = IPPROTO_IP,
989 [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = IPPROTO_TCP,
990 [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = IPPROTO_UDP,
991 [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] = IPPROTO_SCTP,
992 [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = IPPROTO_IP,
993 [I40E_FILTER_PCTYPE_FRAG_IPV6] = IPPROTO_NONE,
994 [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] = IPPROTO_TCP,
995 [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = IPPROTO_UDP,
996 [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = IPPROTO_SCTP,
997 [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE,
1000 raw_pkt += 2 * sizeof(struct rte_ether_addr);
1001 if (vlan && fdir_input->flow_ext.vlan_tci) {
1002 rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame));
1003 rte_memcpy(raw_pkt + sizeof(uint16_t),
1004 &fdir_input->flow_ext.vlan_tci,
1006 raw_pkt += sizeof(vlan_frame);
1007 len += sizeof(vlan_frame);
1009 ether_type = (uint16_t *)raw_pkt;
1010 raw_pkt += sizeof(uint16_t);
1011 len += sizeof(uint16_t);
1013 if (is_customized_pctype) {
1014 cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype);
1016 PMD_DRV_LOG(ERR, "unknown pctype %u.",
1017 fdir_input->pctype);
1022 if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD)
1023 *ether_type = fdir_input->flow.l2_flow.ether_type;
1024 else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP ||
1025 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP ||
1026 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP ||
1027 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER ||
1028 pctype == I40E_FILTER_PCTYPE_FRAG_IPV4 ||
1029 is_customized_pctype) {
1030 ip = (struct rte_ipv4_hdr *)raw_pkt;
1032 *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4);
1033 ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL;
1034 /* set len to by default */
1035 ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN);
1036 ip->time_to_live = fdir_input->flow.ip4_flow.ttl ?
1037 fdir_input->flow.ip4_flow.ttl :
1038 I40E_FDIR_IP_DEFAULT_TTL;
1039 ip->type_of_service = fdir_input->flow.ip4_flow.tos;
1041 * The source and destination fields in the transmitted packet
1042 * need to be presented in a reversed order with respect
1043 * to the expected received packets.
1045 ip->src_addr = fdir_input->flow.ip4_flow.dst_ip;
1046 ip->dst_addr = fdir_input->flow.ip4_flow.src_ip;
1048 if (!is_customized_pctype)
1049 ip->next_proto_id = fdir_input->flow.ip4_flow.proto ?
1050 fdir_input->flow.ip4_flow.proto :
1051 next_proto[fdir_input->pctype];
1052 else if (cus_pctype->index == I40E_CUSTOMIZED_GTPC ||
1053 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4 ||
1054 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 ||
1055 cus_pctype->index == I40E_CUSTOMIZED_GTPU)
1056 ip->next_proto_id = IPPROTO_UDP;
1057 len += sizeof(struct rte_ipv4_hdr);
1058 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP ||
1059 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP ||
1060 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP ||
1061 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER ||
1062 pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) {
1063 ip6 = (struct rte_ipv6_hdr *)raw_pkt;
1065 *ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6);
1067 rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
1068 (fdir_input->flow.ipv6_flow.tc <<
1069 I40E_FDIR_IPv6_TC_OFFSET));
1071 rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
1072 ip6->proto = fdir_input->flow.ipv6_flow.proto ?
1073 fdir_input->flow.ipv6_flow.proto :
1074 next_proto[fdir_input->pctype];
1075 ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ?
1076 fdir_input->flow.ipv6_flow.hop_limits :
1077 I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
1079 * The source and destination fields in the transmitted packet
1080 * need to be presented in a reversed order with respect
1081 * to the expected received packets.
1083 rte_memcpy(&ip6->src_addr,
1084 &fdir_input->flow.ipv6_flow.dst_ip,
1086 rte_memcpy(&ip6->dst_addr,
1087 &fdir_input->flow.ipv6_flow.src_ip,
1089 len += sizeof(struct rte_ipv6_hdr);
1091 PMD_DRV_LOG(ERR, "unknown pctype %u.",
1092 fdir_input->pctype);
1100 * i40e_flow_fdir_construct_pkt - construct packet based on fields in input
1101 * @pf: board private structure
1102 * @fdir_input: input set of the flow director entry
1103 * @raw_pkt: a packet to be constructed
1106 i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
1107 const struct i40e_fdir_input *fdir_input,
1108 unsigned char *raw_pkt)
1110 unsigned char *payload = NULL;
1112 struct rte_udp_hdr *udp;
1113 struct rte_tcp_hdr *tcp;
1114 struct rte_sctp_hdr *sctp;
1115 struct rte_flow_item_gtp *gtp;
1116 struct rte_ipv4_hdr *gtp_ipv4;
1117 struct rte_ipv6_hdr *gtp_ipv6;
1118 uint8_t size, dst = 0;
1119 uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/
1121 uint8_t pctype = fdir_input->pctype;
1122 struct i40e_customized_pctype *cus_pctype;
1124 /* raw pcket template - just copy contents of the raw packet */
1125 if (fdir_input->flow_ext.pkt_template) {
1126 memcpy(raw_pkt, fdir_input->flow.raw_flow.packet,
1127 fdir_input->flow.raw_flow.length);
1131 /* fill the ethernet and IP head */
1132 len = i40e_flow_fdir_fill_eth_ip_head(pf, fdir_input, raw_pkt,
1133 !!fdir_input->flow_ext.vlan_tci);
1137 /* fill the L4 head */
1138 if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP) {
1139 udp = (struct rte_udp_hdr *)(raw_pkt + len);
1140 payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
1142 * The source and destination fields in the transmitted packet
1143 * need to be presented in a reversed order with respect
1144 * to the expected received packets.
1146 udp->src_port = fdir_input->flow.udp4_flow.dst_port;
1147 udp->dst_port = fdir_input->flow.udp4_flow.src_port;
1148 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
1149 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP) {
1150 tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
1151 payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
1153 * The source and destination fields in the transmitted packet
1154 * need to be presented in a reversed order with respect
1155 * to the expected received packets.
1157 tcp->src_port = fdir_input->flow.tcp4_flow.dst_port;
1158 tcp->dst_port = fdir_input->flow.tcp4_flow.src_port;
1159 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
1160 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) {
1161 sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
1162 payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
1164 * The source and destination fields in the transmitted packet
1165 * need to be presented in a reversed order with respect
1166 * to the expected received packets.
1168 sctp->src_port = fdir_input->flow.sctp4_flow.dst_port;
1169 sctp->dst_port = fdir_input->flow.sctp4_flow.src_port;
1170 sctp->tag = fdir_input->flow.sctp4_flow.verify_tag;
1171 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER ||
1172 pctype == I40E_FILTER_PCTYPE_FRAG_IPV4) {
1173 payload = raw_pkt + len;
1174 set_idx = I40E_FLXPLD_L3_IDX;
1175 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP) {
1176 udp = (struct rte_udp_hdr *)(raw_pkt + len);
1177 payload = (unsigned char *)udp + sizeof(struct rte_udp_hdr);
1179 * The source and destination fields in the transmitted packet
1180 * need to be presented in a reversed order with respect
1181 * to the expected received packets.
1183 udp->src_port = fdir_input->flow.udp6_flow.dst_port;
1184 udp->dst_port = fdir_input->flow.udp6_flow.src_port;
1185 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN);
1186 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP) {
1187 tcp = (struct rte_tcp_hdr *)(raw_pkt + len);
1188 payload = (unsigned char *)tcp + sizeof(struct rte_tcp_hdr);
1190 * The source and destination fields in the transmitted packet
1191 * need to be presented in a reversed order with respect
1192 * to the expected received packets.
1194 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF;
1195 tcp->src_port = fdir_input->flow.udp6_flow.dst_port;
1196 tcp->dst_port = fdir_input->flow.udp6_flow.src_port;
1197 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) {
1198 sctp = (struct rte_sctp_hdr *)(raw_pkt + len);
1199 payload = (unsigned char *)sctp + sizeof(struct rte_sctp_hdr);
1201 * The source and destination fields in the transmitted packet
1202 * need to be presented in a reversed order with respect
1203 * to the expected received packets.
1205 sctp->src_port = fdir_input->flow.sctp6_flow.dst_port;
1206 sctp->dst_port = fdir_input->flow.sctp6_flow.src_port;
1207 sctp->tag = fdir_input->flow.sctp6_flow.verify_tag;
1208 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER ||
1209 pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) {
1210 payload = raw_pkt + len;
1211 set_idx = I40E_FLXPLD_L3_IDX;
1212 } else if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) {
1213 payload = raw_pkt + len;
1215 * ARP packet is a special case on which the payload
1216 * starts after the whole ARP header
1218 if (fdir_input->flow.l2_flow.ether_type ==
1219 rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP))
1220 payload += sizeof(struct rte_arp_hdr);
1221 set_idx = I40E_FLXPLD_L2_IDX;
1222 } else if (fdir_input->flow_ext.customized_pctype) {
1223 /* If customized pctype is used */
1224 cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype);
1225 if (cus_pctype->index == I40E_CUSTOMIZED_GTPC ||
1226 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4 ||
1227 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 ||
1228 cus_pctype->index == I40E_CUSTOMIZED_GTPU) {
1229 udp = (struct rte_udp_hdr *)(raw_pkt + len);
1231 rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN);
1233 gtp = (struct rte_flow_item_gtp *)
1234 ((unsigned char *)udp +
1235 sizeof(struct rte_udp_hdr));
1237 rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN);
1238 gtp->teid = fdir_input->flow.gtp_flow.teid;
1239 gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0X01;
1241 /* GTP-C message type is not supported. */
1242 if (cus_pctype->index == I40E_CUSTOMIZED_GTPC) {
1244 rte_cpu_to_be_16(I40E_FDIR_GTPC_DST_PORT);
1245 gtp->v_pt_rsv_flags =
1246 I40E_FDIR_GTP_VER_FLAG_0X32;
1249 rte_cpu_to_be_16(I40E_FDIR_GTPU_DST_PORT);
1250 gtp->v_pt_rsv_flags =
1251 I40E_FDIR_GTP_VER_FLAG_0X30;
1254 if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) {
1255 gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
1256 gtp_ipv4 = (struct rte_ipv4_hdr *)
1257 ((unsigned char *)gtp +
1258 sizeof(struct rte_flow_item_gtp));
1259 gtp_ipv4->version_ihl =
1260 I40E_FDIR_IP_DEFAULT_VERSION_IHL;
1261 gtp_ipv4->next_proto_id = IPPROTO_IP;
1262 gtp_ipv4->total_length =
1264 I40E_FDIR_INNER_IP_DEFAULT_LEN);
1265 payload = (unsigned char *)gtp_ipv4 +
1266 sizeof(struct rte_ipv4_hdr);
1267 } else if (cus_pctype->index ==
1268 I40E_CUSTOMIZED_GTPU_IPV6) {
1269 gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
1270 gtp_ipv6 = (struct rte_ipv6_hdr *)
1271 ((unsigned char *)gtp +
1272 sizeof(struct rte_flow_item_gtp));
1273 gtp_ipv6->vtc_flow =
1275 I40E_FDIR_IPv6_DEFAULT_VTC_FLOW |
1276 (0 << I40E_FDIR_IPv6_TC_OFFSET));
1277 gtp_ipv6->proto = IPPROTO_NONE;
1278 gtp_ipv6->payload_len =
1280 I40E_FDIR_INNER_IPV6_DEFAULT_LEN);
1281 gtp_ipv6->hop_limits =
1282 I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS;
1283 payload = (unsigned char *)gtp_ipv6 +
1284 sizeof(struct rte_ipv6_hdr);
1286 payload = (unsigned char *)gtp +
1287 sizeof(struct rte_flow_item_gtp);
1290 PMD_DRV_LOG(ERR, "unknown pctype %u.",
1291 fdir_input->pctype);
1295 /* fill the flexbytes to payload */
1296 for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
1297 pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i;
1298 size = pf->fdir.flex_set[pit_idx].size;
1301 dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t);
1303 pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t);
1304 (void)rte_memcpy(ptr,
1305 &fdir_input->flow_ext.flexbytes[dst],
1306 size * sizeof(uint16_t));
1312 /* Construct the tx flags */
1313 static inline uint64_t
1314 i40e_build_ctob(uint32_t td_cmd,
1319 return rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DATA |
1320 ((uint64_t)td_cmd << I40E_TXD_QW1_CMD_SHIFT) |
1321 ((uint64_t)td_offset << I40E_TXD_QW1_OFFSET_SHIFT) |
1322 ((uint64_t)size << I40E_TXD_QW1_TX_BUF_SZ_SHIFT) |
1323 ((uint64_t)td_tag << I40E_TXD_QW1_L2TAG1_SHIFT));
1327 * check the programming status descriptor in rx queue.
1328 * done after Programming Flow Director is programmed on
1332 i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq)
1334 volatile union i40e_rx_desc *rxdp;
1341 rxdp = &rxq->rx_ring[rxq->rx_tail];
1342 qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len);
1343 rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK)
1344 >> I40E_RXD_QW1_STATUS_SHIFT;
1346 if (rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT)) {
1347 len = qword1 >> I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT;
1348 id = (qword1 & I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK) >>
1349 I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT;
1351 if (len == I40E_RX_PROG_STATUS_DESC_LENGTH &&
1352 id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS) {
1354 I40E_RX_PROG_STATUS_DESC_QW1_ERROR_MASK) >>
1355 I40E_RX_PROG_STATUS_DESC_QW1_ERROR_SHIFT;
1356 if (error == (0x1 <<
1357 I40E_RX_PROG_STATUS_DESC_FD_TBL_FULL_SHIFT)) {
1358 PMD_DRV_LOG(ERR, "Failed to add FDIR filter"
1359 " (FD_ID %u): programming status"
1361 rxdp->wb.qword0.hi_dword.fd_id);
1363 } else if (error == (0x1 <<
1364 I40E_RX_PROG_STATUS_DESC_NO_FD_ENTRY_SHIFT)) {
1365 PMD_DRV_LOG(ERR, "Failed to delete FDIR filter"
1366 " (FD_ID %u): programming status"
1368 rxdp->wb.qword0.hi_dword.fd_id);
1371 PMD_DRV_LOG(ERR, "invalid programming status"
1372 " reported, error = %u.", error);
1374 PMD_DRV_LOG(INFO, "unknown programming status"
1375 " reported, len = %d, id = %u.", len, id);
1376 rxdp->wb.qword1.status_error_len = 0;
1378 if (unlikely(rxq->rx_tail == rxq->nb_rx_desc))
1380 if (rxq->rx_tail == 0)
1381 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
1383 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->rx_tail - 1);
1390 i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input,
1391 struct i40e_fdir_filter *filter)
1393 rte_memcpy(&filter->fdir, input, sizeof(struct i40e_fdir_filter_conf));
1394 if (input->input.flow_ext.pkt_template) {
1395 filter->fdir.input.flow.raw_flow.packet = NULL;
1396 filter->fdir.input.flow.raw_flow.length =
1397 rte_hash_crc(input->input.flow.raw_flow.packet,
1398 input->input.flow.raw_flow.length,
1399 input->input.flow.raw_flow.pctype);
1404 /* Check if there exists the flow director filter */
1405 static struct i40e_fdir_filter *
1406 i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info,
1407 const struct i40e_fdir_input *input)
1411 if (input->flow_ext.pkt_template)
1412 ret = rte_hash_lookup_with_hash(fdir_info->hash_table,
1413 (const void *)input,
1414 input->flow.raw_flow.length);
1416 ret = rte_hash_lookup(fdir_info->hash_table,
1417 (const void *)input);
1421 return fdir_info->hash_map[ret];
1424 /* Add a flow director filter into the SW list */
1426 i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter)
1428 struct i40e_fdir_info *fdir_info = &pf->fdir;
1431 if (filter->fdir.input.flow_ext.pkt_template)
1432 ret = rte_hash_add_key_with_hash(fdir_info->hash_table,
1433 &filter->fdir.input,
1434 filter->fdir.input.flow.raw_flow.length);
1436 ret = rte_hash_add_key(fdir_info->hash_table,
1437 &filter->fdir.input);
1440 "Failed to insert fdir filter to hash table %d!",
1444 fdir_info->hash_map[ret] = filter;
1446 TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules);
1451 /* Delete a flow director filter from the SW list */
1453 i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct i40e_fdir_input *input)
1455 struct i40e_fdir_info *fdir_info = &pf->fdir;
1456 struct i40e_fdir_filter *filter;
1459 if (input->flow_ext.pkt_template)
1460 ret = rte_hash_del_key_with_hash(fdir_info->hash_table,
1462 input->flow.raw_flow.length);
1464 ret = rte_hash_del_key(fdir_info->hash_table, input);
1467 "Failed to delete fdir filter to hash table %d!",
1471 filter = fdir_info->hash_map[ret];
1472 fdir_info->hash_map[ret] = NULL;
1474 TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules);
1481 * i40e_add_del_fdir_filter - add or remove a flow director filter.
1482 * @pf: board private structure
1483 * @filter: fdir filter entry
1484 * @add: 0 - delete, 1 - add
1487 i40e_add_del_fdir_filter(struct rte_eth_dev *dev,
1488 const struct rte_eth_fdir_filter *filter,
1491 struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1492 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1493 unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
1494 enum i40e_filter_pctype pctype;
1497 if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
1498 PMD_DRV_LOG(ERR, "FDIR is not enabled, please"
1499 " check the mode in fdir_conf.");
1503 pctype = i40e_flowtype_to_pctype(pf->adapter, filter->input.flow_type);
1504 if (pctype == I40E_FILTER_PCTYPE_INVALID) {
1505 PMD_DRV_LOG(ERR, "invalid flow_type input.");
1508 if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
1509 PMD_DRV_LOG(ERR, "Invalid queue ID");
1512 if (filter->input.flow_ext.is_vf &&
1513 filter->input.flow_ext.dst_id >= pf->vf_num) {
1514 PMD_DRV_LOG(ERR, "Invalid VF ID");
1518 memset(pkt, 0, I40E_FDIR_PKT_LEN);
1520 ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt);
1522 PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
1526 if (hw->mac.type == I40E_MAC_X722) {
1527 /* get translated pctype value in fd pctype register */
1528 pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
1529 hw, I40E_GLQF_FD_PCTYPES((int)pctype));
1532 ret = i40e_fdir_filter_programming(pf, pctype, filter, add);
1534 PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
1543 * i40e_flow_add_del_fdir_filter - add or remove a flow director filter.
1544 * @pf: board private structure
1545 * @filter: fdir filter entry
1546 * @add: 0 - delete, 1 - add
1549 i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
1550 const struct i40e_fdir_filter_conf *filter,
1553 struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1554 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1555 unsigned char *pkt = (unsigned char *)pf->fdir.prg_pkt;
1556 enum i40e_filter_pctype pctype;
1557 struct i40e_fdir_info *fdir_info = &pf->fdir;
1558 struct i40e_fdir_filter *fdir_filter, *node;
1559 struct i40e_fdir_filter check_filter; /* Check if the filter exists */
1562 if (dev->data->dev_conf.fdir_conf.mode != RTE_FDIR_MODE_PERFECT) {
1563 PMD_DRV_LOG(ERR, "FDIR is not enabled, please check the mode in fdir_conf.");
1567 if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) {
1568 PMD_DRV_LOG(ERR, "Invalid queue ID");
1571 if (filter->input.flow_ext.is_vf &&
1572 filter->input.flow_ext.dst_id >= pf->vf_num) {
1573 PMD_DRV_LOG(ERR, "Invalid VF ID");
1576 if (filter->input.flow_ext.pkt_template) {
1577 if (filter->input.flow.raw_flow.length > I40E_FDIR_PKT_LEN ||
1578 !filter->input.flow.raw_flow.packet) {
1579 PMD_DRV_LOG(ERR, "Invalid raw packet template"
1580 " flow filter parameters!");
1583 pctype = filter->input.flow.raw_flow.pctype;
1585 pctype = filter->input.pctype;
1588 /* Check if there is the filter in SW list */
1589 memset(&check_filter, 0, sizeof(check_filter));
1590 i40e_fdir_filter_convert(filter, &check_filter);
1591 node = i40e_sw_fdir_filter_lookup(fdir_info, &check_filter.fdir.input);
1594 "Conflict with existing flow director rules!");
1598 if (!add && !node) {
1600 "There's no corresponding flow firector filter!");
1604 memset(pkt, 0, I40E_FDIR_PKT_LEN);
1606 ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt);
1608 PMD_DRV_LOG(ERR, "construct packet for fdir fails.");
1612 if (hw->mac.type == I40E_MAC_X722) {
1613 /* get translated pctype value in fd pctype register */
1614 pctype = (enum i40e_filter_pctype)i40e_read_rx_ctl(
1615 hw, I40E_GLQF_FD_PCTYPES((int)pctype));
1618 ret = i40e_flow_fdir_filter_programming(pf, pctype, filter, add);
1620 PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).",
1626 fdir_filter = rte_zmalloc("fdir_filter",
1627 sizeof(*fdir_filter), 0);
1628 if (fdir_filter == NULL) {
1629 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
1633 rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter));
1634 ret = i40e_sw_fdir_filter_insert(pf, fdir_filter);
1636 rte_free(fdir_filter);
1638 ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input);
1645 * i40e_fdir_filter_programming - Program a flow director filter rule.
1646 * Is done by Flow Director Programming Descriptor followed by packet
1647 * structure that contains the filter fields need to match.
1648 * @pf: board private structure
1650 * @filter: fdir filter entry
1651 * @add: 0 - delete, 1 - add
1654 i40e_fdir_filter_programming(struct i40e_pf *pf,
1655 enum i40e_filter_pctype pctype,
1656 const struct rte_eth_fdir_filter *filter,
1659 struct i40e_tx_queue *txq = pf->fdir.txq;
1660 struct i40e_rx_queue *rxq = pf->fdir.rxq;
1661 const struct rte_eth_fdir_action *fdir_action = &filter->action;
1662 volatile struct i40e_tx_desc *txdp;
1663 volatile struct i40e_filter_program_desc *fdirdp;
1668 PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
1669 fdirdp = (volatile struct i40e_filter_program_desc *)
1670 (&(txq->tx_ring[txq->tx_tail]));
1672 fdirdp->qindex_flex_ptype_vsi =
1673 rte_cpu_to_le_32((fdir_action->rx_queue <<
1674 I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
1675 I40E_TXD_FLTR_QW0_QINDEX_MASK);
1677 fdirdp->qindex_flex_ptype_vsi |=
1678 rte_cpu_to_le_32((fdir_action->flex_off <<
1679 I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
1680 I40E_TXD_FLTR_QW0_FLEXOFF_MASK);
1682 fdirdp->qindex_flex_ptype_vsi |=
1683 rte_cpu_to_le_32((pctype <<
1684 I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
1685 I40E_TXD_FLTR_QW0_PCTYPE_MASK);
1687 if (filter->input.flow_ext.is_vf)
1688 vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
1690 /* Use LAN VSI Id by default */
1691 vsi_id = pf->main_vsi->vsi_id;
1692 fdirdp->qindex_flex_ptype_vsi |=
1693 rte_cpu_to_le_32(((uint32_t)vsi_id <<
1694 I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
1695 I40E_TXD_FLTR_QW0_DEST_VSI_MASK);
1697 fdirdp->dtype_cmd_cntindex =
1698 rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);
1701 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1702 I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
1703 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1705 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1706 I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
1707 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1709 if (fdir_action->behavior == RTE_ETH_FDIR_REJECT)
1710 dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
1711 else if (fdir_action->behavior == RTE_ETH_FDIR_ACCEPT)
1712 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
1713 else if (fdir_action->behavior == RTE_ETH_FDIR_PASSTHRU)
1714 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
1716 PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
1717 " unsupported fdir behavior.");
1721 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
1722 I40E_TXD_FLTR_QW1_DEST_SHIFT) &
1723 I40E_TXD_FLTR_QW1_DEST_MASK);
1725 fdirdp->dtype_cmd_cntindex |=
1726 rte_cpu_to_le_32((fdir_action->report_status<<
1727 I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
1728 I40E_TXD_FLTR_QW1_FD_STATUS_MASK);
1730 fdirdp->dtype_cmd_cntindex |=
1731 rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
1732 fdirdp->dtype_cmd_cntindex |=
1734 ((uint32_t)pf->fdir.match_counter_index <<
1735 I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
1736 I40E_TXD_FLTR_QW1_CNTINDEX_MASK);
1738 fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);
1740 PMD_DRV_LOG(INFO, "filling transmit descriptor.");
1741 txdp = &(txq->tx_ring[txq->tx_tail + 1]);
1742 txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr);
1743 td_cmd = I40E_TX_DESC_CMD_EOP |
1744 I40E_TX_DESC_CMD_RS |
1745 I40E_TX_DESC_CMD_DUMMY;
1747 txdp->cmd_type_offset_bsz =
1748 i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);
1750 txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */
1751 if (txq->tx_tail >= txq->nb_tx_desc)
1753 /* Update the tx tail register */
1755 I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
1756 for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
1757 if ((txdp->cmd_type_offset_bsz &
1758 rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
1759 rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
1763 if (i >= I40E_FDIR_MAX_WAIT_US) {
1764 PMD_DRV_LOG(ERR, "Failed to program FDIR filter:"
1765 " time out to get DD on tx queue.");
1768 /* totally delay 10 ms to check programming status*/
1769 for (; i < I40E_FDIR_MAX_WAIT_US; i++) {
1770 if (i40e_check_fdir_programming_status(rxq) >= 0)
1775 "Failed to program FDIR filter: programming status reported.");
1780 * i40e_flow_fdir_filter_programming - Program a flow director filter rule.
1781 * Is done by Flow Director Programming Descriptor followed by packet
1782 * structure that contains the filter fields need to match.
1783 * @pf: board private structure
1785 * @filter: fdir filter entry
1786 * @add: 0 - delete, 1 - add
1789 i40e_flow_fdir_filter_programming(struct i40e_pf *pf,
1790 enum i40e_filter_pctype pctype,
1791 const struct i40e_fdir_filter_conf *filter,
1794 struct i40e_tx_queue *txq = pf->fdir.txq;
1795 struct i40e_rx_queue *rxq = pf->fdir.rxq;
1796 const struct i40e_fdir_action *fdir_action = &filter->action;
1797 volatile struct i40e_tx_desc *txdp;
1798 volatile struct i40e_filter_program_desc *fdirdp;
1803 PMD_DRV_LOG(INFO, "filling filter programming descriptor.");
1804 fdirdp = (volatile struct i40e_filter_program_desc *)
1805 (&txq->tx_ring[txq->tx_tail]);
1807 fdirdp->qindex_flex_ptype_vsi =
1808 rte_cpu_to_le_32((fdir_action->rx_queue <<
1809 I40E_TXD_FLTR_QW0_QINDEX_SHIFT) &
1810 I40E_TXD_FLTR_QW0_QINDEX_MASK);
1812 fdirdp->qindex_flex_ptype_vsi |=
1813 rte_cpu_to_le_32((fdir_action->flex_off <<
1814 I40E_TXD_FLTR_QW0_FLEXOFF_SHIFT) &
1815 I40E_TXD_FLTR_QW0_FLEXOFF_MASK);
1817 fdirdp->qindex_flex_ptype_vsi |=
1818 rte_cpu_to_le_32((pctype <<
1819 I40E_TXD_FLTR_QW0_PCTYPE_SHIFT) &
1820 I40E_TXD_FLTR_QW0_PCTYPE_MASK);
1822 if (filter->input.flow_ext.is_vf)
1823 vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id;
1825 /* Use LAN VSI Id by default */
1826 vsi_id = pf->main_vsi->vsi_id;
1827 fdirdp->qindex_flex_ptype_vsi |=
1828 rte_cpu_to_le_32(((uint32_t)vsi_id <<
1829 I40E_TXD_FLTR_QW0_DEST_VSI_SHIFT) &
1830 I40E_TXD_FLTR_QW0_DEST_VSI_MASK);
1832 fdirdp->dtype_cmd_cntindex =
1833 rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG);
1836 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1837 I40E_FILTER_PROGRAM_DESC_PCMD_ADD_UPDATE <<
1838 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1840 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32(
1841 I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE <<
1842 I40E_TXD_FLTR_QW1_PCMD_SHIFT);
1844 if (fdir_action->behavior == I40E_FDIR_REJECT)
1845 dest = I40E_FILTER_PROGRAM_DESC_DEST_DROP_PACKET;
1846 else if (fdir_action->behavior == I40E_FDIR_ACCEPT)
1847 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
1848 else if (fdir_action->behavior == I40E_FDIR_PASSTHRU)
1849 dest = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_OTHER;
1851 PMD_DRV_LOG(ERR, "Failed to program FDIR filter: unsupported fdir behavior.");
1855 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32((dest <<
1856 I40E_TXD_FLTR_QW1_DEST_SHIFT) &
1857 I40E_TXD_FLTR_QW1_DEST_MASK);
1859 fdirdp->dtype_cmd_cntindex |=
1860 rte_cpu_to_le_32((fdir_action->report_status <<
1861 I40E_TXD_FLTR_QW1_FD_STATUS_SHIFT) &
1862 I40E_TXD_FLTR_QW1_FD_STATUS_MASK);
1864 fdirdp->dtype_cmd_cntindex |=
1865 rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK);
1866 fdirdp->dtype_cmd_cntindex |=
1868 ((uint32_t)pf->fdir.match_counter_index <<
1869 I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) &
1870 I40E_TXD_FLTR_QW1_CNTINDEX_MASK);
1872 fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id);
1874 PMD_DRV_LOG(INFO, "filling transmit descriptor.");
1875 txdp = &txq->tx_ring[txq->tx_tail + 1];
1876 txdp->buffer_addr = rte_cpu_to_le_64(pf->fdir.dma_addr);
1877 td_cmd = I40E_TX_DESC_CMD_EOP |
1878 I40E_TX_DESC_CMD_RS |
1879 I40E_TX_DESC_CMD_DUMMY;
1881 txdp->cmd_type_offset_bsz =
1882 i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0);
1884 txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */
1885 if (txq->tx_tail >= txq->nb_tx_desc)
1887 /* Update the tx tail register */
1889 I40E_PCI_REG_WRITE(txq->qtx_tail, txq->tx_tail);
1890 for (i = 0; i < I40E_FDIR_MAX_WAIT_US; i++) {
1891 if ((txdp->cmd_type_offset_bsz &
1892 rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) ==
1893 rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
1897 if (i >= I40E_FDIR_MAX_WAIT_US) {
1899 "Failed to program FDIR filter: time out to get DD on tx queue.");
1902 /* totally delay 10 ms to check programming status*/
1903 rte_delay_us(I40E_FDIR_MAX_WAIT_US);
1904 if (i40e_check_fdir_programming_status(rxq) < 0) {
1906 "Failed to program FDIR filter: programming status reported.");
1914 * i40e_fdir_flush - clear all filters of Flow Director table
1915 * @pf: board private structure
1918 i40e_fdir_flush(struct rte_eth_dev *dev)
1920 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
1921 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
1923 uint16_t guarant_cnt, best_cnt;
1926 I40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK);
1927 I40E_WRITE_FLUSH(hw);
1929 for (i = 0; i < I40E_FDIR_FLUSH_RETRY; i++) {
1930 rte_delay_ms(I40E_FDIR_FLUSH_INTERVAL_MS);
1931 reg = I40E_READ_REG(hw, I40E_PFQF_CTL_1);
1932 if (!(reg & I40E_PFQF_CTL_1_CLEARFDTABLE_MASK))
1935 if (i >= I40E_FDIR_FLUSH_RETRY) {
1936 PMD_DRV_LOG(ERR, "FD table did not flush, may need more time.");
1939 guarant_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
1940 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
1941 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
1942 best_cnt = (uint16_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) &
1943 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
1944 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
1945 if (guarant_cnt != 0 || best_cnt != 0) {
1946 PMD_DRV_LOG(ERR, "Failed to flush FD table.");
1949 PMD_DRV_LOG(INFO, "FD table Flush success.");
1954 i40e_fdir_info_get_flex_set(struct i40e_pf *pf,
1955 struct rte_eth_flex_payload_cfg *flex_set,
1958 struct i40e_fdir_flex_pit *flex_pit;
1959 struct rte_eth_flex_payload_cfg *ptr = flex_set;
1960 uint16_t src, dst, size, j, k;
1961 uint8_t i, layer_idx;
1963 for (layer_idx = I40E_FLXPLD_L2_IDX;
1964 layer_idx <= I40E_FLXPLD_L4_IDX;
1966 if (layer_idx == I40E_FLXPLD_L2_IDX)
1967 ptr->type = RTE_ETH_L2_PAYLOAD;
1968 else if (layer_idx == I40E_FLXPLD_L3_IDX)
1969 ptr->type = RTE_ETH_L3_PAYLOAD;
1970 else if (layer_idx == I40E_FLXPLD_L4_IDX)
1971 ptr->type = RTE_ETH_L4_PAYLOAD;
1973 for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) {
1974 flex_pit = &pf->fdir.flex_set[layer_idx *
1975 I40E_MAX_FLXPLD_FIED + i];
1976 if (flex_pit->size == 0)
1978 src = flex_pit->src_offset * sizeof(uint16_t);
1979 dst = flex_pit->dst_offset * sizeof(uint16_t);
1980 size = flex_pit->size * sizeof(uint16_t);
1981 for (j = src, k = dst; j < src + size; j++, k++)
1982 ptr->src_offset[k] = j;
1990 i40e_fdir_info_get_flex_mask(struct i40e_pf *pf,
1991 struct rte_eth_fdir_flex_mask *flex_mask,
1994 struct i40e_fdir_flex_mask *mask;
1995 struct rte_eth_fdir_flex_mask *ptr = flex_mask;
1998 uint16_t off_bytes, mask_tmp;
2000 for (i = I40E_FILTER_PCTYPE_NONF_IPV4_UDP;
2001 i <= I40E_FILTER_PCTYPE_L2_PAYLOAD;
2003 mask = &pf->fdir.flex_mask[i];
2004 flow_type = i40e_pctype_to_flowtype(pf->adapter,
2005 (enum i40e_filter_pctype)i);
2006 if (flow_type == RTE_ETH_FLOW_UNKNOWN)
2009 for (j = 0; j < I40E_FDIR_MAX_FLEXWORD_NUM; j++) {
2010 if (mask->word_mask & I40E_FLEX_WORD_MASK(j)) {
2011 ptr->mask[j * sizeof(uint16_t)] = UINT8_MAX;
2012 ptr->mask[j * sizeof(uint16_t) + 1] = UINT8_MAX;
2014 ptr->mask[j * sizeof(uint16_t)] = 0x0;
2015 ptr->mask[j * sizeof(uint16_t) + 1] = 0x0;
2018 for (j = 0; j < I40E_FDIR_BITMASK_NUM_WORD; j++) {
2019 off_bytes = mask->bitmask[j].offset * sizeof(uint16_t);
2020 mask_tmp = ~mask->bitmask[j].mask;
2021 ptr->mask[off_bytes] &= I40E_HI_BYTE(mask_tmp);
2022 ptr->mask[off_bytes + 1] &= I40E_LO_BYTE(mask_tmp);
2024 ptr->flow_type = flow_type;
2031 * i40e_fdir_info_get - get information of Flow Director
2032 * @pf: ethernet device to get info from
2033 * @fdir: a pointer to a structure of type *rte_eth_fdir_info* to be filled with
2034 * the flow director information.
2037 i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir)
2039 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2040 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
2041 uint16_t num_flex_set = 0;
2042 uint16_t num_flex_mask = 0;
2045 if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT)
2046 fdir->mode = RTE_FDIR_MODE_PERFECT;
2048 fdir->mode = RTE_FDIR_MODE_NONE;
2051 (uint32_t)hw->func_caps.fd_filters_guaranteed;
2053 (uint32_t)hw->func_caps.fd_filters_best_effort;
2054 fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN;
2055 fdir->flow_types_mask[0] = I40E_FDIR_FLOWS;
2056 for (i = 1; i < RTE_FLOW_MASK_ARRAY_SIZE; i++)
2057 fdir->flow_types_mask[i] = 0ULL;
2058 fdir->flex_payload_unit = sizeof(uint16_t);
2059 fdir->flex_bitmask_unit = sizeof(uint16_t);
2060 fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED;
2061 fdir->flex_payload_limit = I40E_MAX_FLX_SOURCE_OFF;
2062 fdir->max_flex_bitmask_num = I40E_FDIR_BITMASK_NUM_WORD;
2064 i40e_fdir_info_get_flex_set(pf,
2065 fdir->flex_conf.flex_set,
2067 i40e_fdir_info_get_flex_mask(pf,
2068 fdir->flex_conf.flex_mask,
2071 fdir->flex_conf.nb_payloads = num_flex_set;
2072 fdir->flex_conf.nb_flexmasks = num_flex_mask;
2076 * i40e_fdir_stat_get - get statistics of Flow Director
2077 * @pf: ethernet device to get info from
2078 * @stat: a pointer to a structure of type *rte_eth_fdir_stats* to be filled with
2079 * the flow director statistics.
2082 i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat)
2084 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2085 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
2088 fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
2090 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
2091 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
2093 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
2094 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
2098 i40e_fdir_filter_set(struct rte_eth_dev *dev,
2099 struct rte_eth_fdir_filter_info *info)
2101 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2105 PMD_DRV_LOG(ERR, "Invalid pointer");
2109 switch (info->info_type) {
2110 case RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT:
2111 ret = i40e_fdir_filter_inset_select(pf,
2112 &(info->info.input_set_conf));
2115 PMD_DRV_LOG(ERR, "FD filter info type (%d) not supported",
2124 * i40e_fdir_ctrl_func - deal with all operations on flow director.
2125 * @pf: board private structure
2126 * @filter_op:operation will be taken.
2127 * @arg: a pointer to specific structure corresponding to the filter_op
2130 i40e_fdir_ctrl_func(struct rte_eth_dev *dev,
2131 enum rte_filter_op filter_op,
2134 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
2137 if ((pf->flags & I40E_FLAG_FDIR) == 0)
2140 if (filter_op == RTE_ETH_FILTER_NOP)
2143 if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
2146 switch (filter_op) {
2147 case RTE_ETH_FILTER_ADD:
2148 ret = i40e_add_del_fdir_filter(dev,
2149 (struct rte_eth_fdir_filter *)arg,
2152 case RTE_ETH_FILTER_DELETE:
2153 ret = i40e_add_del_fdir_filter(dev,
2154 (struct rte_eth_fdir_filter *)arg,
2157 case RTE_ETH_FILTER_FLUSH:
2158 ret = i40e_fdir_flush(dev);
2160 case RTE_ETH_FILTER_INFO:
2161 i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg);
2163 case RTE_ETH_FILTER_SET:
2164 ret = i40e_fdir_filter_set(dev,
2165 (struct rte_eth_fdir_filter_info *)arg);
2167 case RTE_ETH_FILTER_STATS:
2168 i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg);
2171 PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op);
2178 /* Restore flow director filter */
2180 i40e_fdir_filter_restore(struct i40e_pf *pf)
2182 struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi);
2183 struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list;
2184 struct i40e_fdir_filter *f;
2185 struct i40e_hw *hw = I40E_PF_TO_HW(pf);
2187 uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */
2188 uint32_t best_cnt; /**< Number of filters in best effort spaces. */
2190 TAILQ_FOREACH(f, fdir_list, rules)
2191 i40e_flow_add_del_fdir_filter(dev, &f->fdir, TRUE);
2193 fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT);
2195 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >>
2196 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT);
2198 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >>
2199 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT);
2201 PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d, Best count: %d",
2202 guarant_cnt, best_cnt);