1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/queue.h> 35 #include <stdio.h> 36 #include <errno.h> 37 #include <stdint.h> 38 #include <string.h> 39 #include <unistd.h> 40 #include <stdarg.h> 41 42 #include <rte_ether.h> 43 #include <rte_ethdev.h> 44 #include <rte_log.h> 45 #include <rte_memzone.h> 46 #include <rte_malloc.h> 47 #include <rte_arp.h> 48 #include <rte_ip.h> 49 #include <rte_udp.h> 50 #include <rte_tcp.h> 51 #include <rte_sctp.h> 52 #include <rte_hash_crc.h> 53 54 #include "i40e_logs.h" 55 #include "base/i40e_type.h" 56 #include "base/i40e_prototype.h" 57 #include "i40e_ethdev.h" 58 #include "i40e_rxtx.h" 59 60 #define I40E_FDIR_MZ_NAME "FDIR_MEMZONE" 61 #ifndef IPV6_ADDR_LEN 62 #define IPV6_ADDR_LEN 16 63 #endif 64 65 #define I40E_FDIR_PKT_LEN 512 66 #define I40E_FDIR_IP_DEFAULT_LEN 420 67 #define I40E_FDIR_IP_DEFAULT_TTL 0x40 68 #define I40E_FDIR_IP_DEFAULT_VERSION_IHL 0x45 69 #define I40E_FDIR_TCP_DEFAULT_DATAOFF 0x50 70 #define I40E_FDIR_IPv6_DEFAULT_VTC_FLOW 0x60000000 71 72 #define I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS 0xFF 73 #define I40E_FDIR_IPv6_PAYLOAD_LEN 380 74 #define I40E_FDIR_UDP_DEFAULT_LEN 400 75 #define I40E_FDIR_GTP_DEFAULT_LEN 384 76 #define I40E_FDIR_INNER_IP_DEFAULT_LEN 384 77 #define I40E_FDIR_INNER_IPV6_DEFAULT_LEN 344 78 79 #define I40E_FDIR_GTPC_DST_PORT 2123 80 #define I40E_FDIR_GTPU_DST_PORT 2152 81 #define I40E_FDIR_GTP_VER_FLAG_0X30 0x30 82 #define I40E_FDIR_GTP_VER_FLAG_0X32 0x32 83 #define I40E_FDIR_GTP_MSG_TYPE_0X01 0x01 84 #define I40E_FDIR_GTP_MSG_TYPE_0XFF 0xFF 85 86 /* Wait time for fdir filter programming */ 87 #define I40E_FDIR_MAX_WAIT_US 10000 88 89 /* Wait count and interval for fdir filter flush */ 90 #define I40E_FDIR_FLUSH_RETRY 50 91 #define I40E_FDIR_FLUSH_INTERVAL_MS 5 92 93 #define I40E_COUNTER_PF 2 94 /* Statistic counter index for one pf */ 95 #define I40E_COUNTER_INDEX_FDIR(pf_id) (0 + (pf_id) * I40E_COUNTER_PF) 96 97 #define I40E_FDIR_FLOWS ( \ 98 (1 << RTE_ETH_FLOW_FRAG_IPV4) | \ 99 (1 << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ 100 (1 << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ 101 (1 << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ 102 (1 << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ 103 (1 << RTE_ETH_FLOW_FRAG_IPV6) | \ 104 (1 << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ 105 (1 << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ 106 (1 << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ 107 (1 << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ 108 (1 << RTE_ETH_FLOW_L2_PAYLOAD)) 109 110 static int i40e_fdir_filter_programming(struct i40e_pf *pf, 111 enum i40e_filter_pctype pctype, 112 const struct rte_eth_fdir_filter *filter, 113 bool add); 114 static int i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input, 115 struct i40e_fdir_filter *filter); 116 static struct i40e_fdir_filter * 117 i40e_sw_fdir_filter_lookup(struct i40e_fdir_info *fdir_info, 118 const struct i40e_fdir_input *input); 119 static int i40e_sw_fdir_filter_insert(struct i40e_pf *pf, 120 struct i40e_fdir_filter *filter); 121 static int 122 i40e_flow_fdir_filter_programming(struct i40e_pf *pf, 123 enum i40e_filter_pctype pctype, 124 const struct i40e_fdir_filter_conf *filter, 125 bool add); 126 127 static int 128 i40e_fdir_rx_queue_init(struct i40e_rx_queue *rxq) 129 { 130 struct i40e_hw *hw = I40E_VSI_TO_HW(rxq->vsi); 131 struct i40e_hmc_obj_rxq rx_ctx; 132 int err = I40E_SUCCESS; 133 134 memset(&rx_ctx, 0, sizeof(struct i40e_hmc_obj_rxq)); 135 /* Init the RX queue in hardware */ 136 rx_ctx.dbuff = I40E_RXBUF_SZ_1024 >> I40E_RXQ_CTX_DBUFF_SHIFT; 137 rx_ctx.hbuff = 0; 138 rx_ctx.base = rxq->rx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; 139 rx_ctx.qlen = rxq->nb_rx_desc; 140 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC 141 rx_ctx.dsize = 1; 142 #endif 143 rx_ctx.dtype = i40e_header_split_none; 144 rx_ctx.hsplit_0 = I40E_HEADER_SPLIT_NONE; 145 rx_ctx.rxmax = ETHER_MAX_LEN; 146 rx_ctx.tphrdesc_ena = 1; 147 rx_ctx.tphwdesc_ena = 1; 148 rx_ctx.tphdata_ena = 1; 149 rx_ctx.tphhead_ena = 1; 150 rx_ctx.lrxqthresh = 2; 151 rx_ctx.crcstrip = 0; 152 rx_ctx.l2tsel = 1; 153 rx_ctx.showiv = 0; 154 rx_ctx.prefena = 1; 155 156 err = i40e_clear_lan_rx_queue_context(hw, rxq->reg_idx); 157 if (err != I40E_SUCCESS) { 158 PMD_DRV_LOG(ERR, "Failed to clear FDIR RX queue context."); 159 return err; 160 } 161 err = i40e_set_lan_rx_queue_context(hw, rxq->reg_idx, &rx_ctx); 162 if (err != I40E_SUCCESS) { 163 PMD_DRV_LOG(ERR, "Failed to set FDIR RX queue context."); 164 return err; 165 } 166 rxq->qrx_tail = hw->hw_addr + 167 I40E_QRX_TAIL(rxq->vsi->base_queue); 168 169 rte_wmb(); 170 /* Init the RX tail regieter. */ 171 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); 172 173 return err; 174 } 175 176 /* 177 * i40e_fdir_setup - reserve and initialize the Flow Director resources 178 * @pf: board private structure 179 */ 180 int 181 i40e_fdir_setup(struct i40e_pf *pf) 182 { 183 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 184 struct i40e_vsi *vsi; 185 int err = I40E_SUCCESS; 186 char z_name[RTE_MEMZONE_NAMESIZE]; 187 const struct rte_memzone *mz = NULL; 188 struct rte_eth_dev *eth_dev = pf->adapter->eth_dev; 189 190 if ((pf->flags & I40E_FLAG_FDIR) == 0) { 191 PMD_INIT_LOG(ERR, "HW doesn't support FDIR"); 192 return I40E_NOT_SUPPORTED; 193 } 194 195 PMD_DRV_LOG(INFO, "FDIR HW Capabilities: num_filters_guaranteed = %u," 196 " num_filters_best_effort = %u.", 197 hw->func_caps.fd_filters_guaranteed, 198 hw->func_caps.fd_filters_best_effort); 199 200 vsi = pf->fdir.fdir_vsi; 201 if (vsi) { 202 PMD_DRV_LOG(INFO, "FDIR initialization has been done."); 203 return I40E_SUCCESS; 204 } 205 /* make new FDIR VSI */ 206 vsi = i40e_vsi_setup(pf, I40E_VSI_FDIR, pf->main_vsi, 0); 207 if (!vsi) { 208 PMD_DRV_LOG(ERR, "Couldn't create FDIR VSI."); 209 return I40E_ERR_NO_AVAILABLE_VSI; 210 } 211 pf->fdir.fdir_vsi = vsi; 212 213 /*Fdir tx queue setup*/ 214 err = i40e_fdir_setup_tx_resources(pf); 215 if (err) { 216 PMD_DRV_LOG(ERR, "Failed to setup FDIR TX resources."); 217 goto fail_setup_tx; 218 } 219 220 /*Fdir rx queue setup*/ 221 err = i40e_fdir_setup_rx_resources(pf); 222 if (err) { 223 PMD_DRV_LOG(ERR, "Failed to setup FDIR RX resources."); 224 goto fail_setup_rx; 225 } 226 227 err = i40e_tx_queue_init(pf->fdir.txq); 228 if (err) { 229 PMD_DRV_LOG(ERR, "Failed to do FDIR TX initialization."); 230 goto fail_mem; 231 } 232 233 /* need switch on before dev start*/ 234 err = i40e_switch_tx_queue(hw, vsi->base_queue, TRUE); 235 if (err) { 236 PMD_DRV_LOG(ERR, "Failed to do fdir TX switch on."); 237 goto fail_mem; 238 } 239 240 /* Init the rx queue in hardware */ 241 err = i40e_fdir_rx_queue_init(pf->fdir.rxq); 242 if (err) { 243 PMD_DRV_LOG(ERR, "Failed to do FDIR RX initialization."); 244 goto fail_mem; 245 } 246 247 /* switch on rx queue */ 248 err = i40e_switch_rx_queue(hw, vsi->base_queue, TRUE); 249 if (err) { 250 PMD_DRV_LOG(ERR, "Failed to do FDIR RX switch on."); 251 goto fail_mem; 252 } 253 254 /* reserve memory for the fdir programming packet */ 255 snprintf(z_name, sizeof(z_name), "%s_%s_%d", 256 eth_dev->device->driver->name, 257 I40E_FDIR_MZ_NAME, 258 eth_dev->data->port_id); 259 mz = i40e_memzone_reserve(z_name, I40E_FDIR_PKT_LEN, SOCKET_ID_ANY); 260 if (!mz) { 261 PMD_DRV_LOG(ERR, "Cannot init memzone for " 262 "flow director program packet."); 263 err = I40E_ERR_NO_MEMORY; 264 goto fail_mem; 265 } 266 pf->fdir.prg_pkt = mz->addr; 267 pf->fdir.dma_addr = mz->iova; 268 269 pf->fdir.match_counter_index = I40E_COUNTER_INDEX_FDIR(hw->pf_id); 270 PMD_DRV_LOG(INFO, "FDIR setup successfully, with programming queue %u.", 271 vsi->base_queue); 272 return I40E_SUCCESS; 273 274 fail_mem: 275 i40e_dev_rx_queue_release(pf->fdir.rxq); 276 pf->fdir.rxq = NULL; 277 fail_setup_rx: 278 i40e_dev_tx_queue_release(pf->fdir.txq); 279 pf->fdir.txq = NULL; 280 fail_setup_tx: 281 i40e_vsi_release(vsi); 282 pf->fdir.fdir_vsi = NULL; 283 return err; 284 } 285 286 /* 287 * i40e_fdir_teardown - release the Flow Director resources 288 * @pf: board private structure 289 */ 290 void 291 i40e_fdir_teardown(struct i40e_pf *pf) 292 { 293 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 294 struct i40e_vsi *vsi; 295 296 vsi = pf->fdir.fdir_vsi; 297 if (!vsi) 298 return; 299 int err = i40e_switch_tx_queue(hw, vsi->base_queue, FALSE); 300 if (err) 301 PMD_DRV_LOG(DEBUG, "Failed to do FDIR TX switch off"); 302 err = i40e_switch_rx_queue(hw, vsi->base_queue, FALSE); 303 if (err) 304 PMD_DRV_LOG(DEBUG, "Failed to do FDIR RX switch off"); 305 i40e_dev_rx_queue_release(pf->fdir.rxq); 306 pf->fdir.rxq = NULL; 307 i40e_dev_tx_queue_release(pf->fdir.txq); 308 pf->fdir.txq = NULL; 309 i40e_vsi_release(vsi); 310 pf->fdir.fdir_vsi = NULL; 311 } 312 313 /* check whether the flow director table in empty */ 314 static inline int 315 i40e_fdir_empty(struct i40e_hw *hw) 316 { 317 uint32_t guarant_cnt, best_cnt; 318 319 guarant_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & 320 I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> 321 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); 322 best_cnt = (uint32_t)((I40E_READ_REG(hw, I40E_PFQF_FDSTAT) & 323 I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> 324 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); 325 if (best_cnt + guarant_cnt > 0) 326 return -1; 327 328 return 0; 329 } 330 331 /* 332 * Initialize the configuration about bytes stream extracted as flexible payload 333 * and mask setting 334 */ 335 static inline void 336 i40e_init_flx_pld(struct i40e_pf *pf) 337 { 338 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 339 uint8_t pctype; 340 int i, index; 341 uint16_t flow_type; 342 343 /* 344 * Define the bytes stream extracted as flexible payload in 345 * field vector. By default, select 8 words from the beginning 346 * of payload as flexible payload. 347 */ 348 for (i = I40E_FLXPLD_L2_IDX; i < I40E_MAX_FLXPLD_LAYER; i++) { 349 index = i * I40E_MAX_FLXPLD_FIED; 350 pf->fdir.flex_set[index].src_offset = 0; 351 pf->fdir.flex_set[index].size = I40E_FDIR_MAX_FLEXWORD_NUM; 352 pf->fdir.flex_set[index].dst_offset = 0; 353 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(index), 0x0000C900); 354 I40E_WRITE_REG(hw, 355 I40E_PRTQF_FLX_PIT(index + 1), 0x0000FC29);/*non-used*/ 356 I40E_WRITE_REG(hw, 357 I40E_PRTQF_FLX_PIT(index + 2), 0x0000FC2A);/*non-used*/ 358 } 359 360 /* initialize the masks */ 361 for (pctype = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; 362 pctype <= I40E_FILTER_PCTYPE_L2_PAYLOAD; pctype++) { 363 flow_type = i40e_pctype_to_flowtype(pf->adapter, pctype); 364 365 if (flow_type == RTE_ETH_FLOW_UNKNOWN) 366 continue; 367 pf->fdir.flex_mask[pctype].word_mask = 0; 368 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), 0); 369 for (i = 0; i < I40E_FDIR_BITMASK_NUM_WORD; i++) { 370 pf->fdir.flex_mask[pctype].bitmask[i].offset = 0; 371 pf->fdir.flex_mask[pctype].bitmask[i].mask = 0; 372 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), 0); 373 } 374 } 375 } 376 377 #define I40E_VALIDATE_FLEX_PIT(flex_pit1, flex_pit2) do { \ 378 if ((flex_pit2).src_offset < \ 379 (flex_pit1).src_offset + (flex_pit1).size) { \ 380 PMD_DRV_LOG(ERR, "src_offset should be not" \ 381 " less than than previous offset" \ 382 " + previous FSIZE."); \ 383 return -EINVAL; \ 384 } \ 385 } while (0) 386 387 /* 388 * i40e_srcoff_to_flx_pit - transform the src_offset into flex_pit structure, 389 * and the flex_pit will be sorted by it's src_offset value 390 */ 391 static inline uint16_t 392 i40e_srcoff_to_flx_pit(const uint16_t *src_offset, 393 struct i40e_fdir_flex_pit *flex_pit) 394 { 395 uint16_t src_tmp, size, num = 0; 396 uint16_t i, k, j = 0; 397 398 while (j < I40E_FDIR_MAX_FLEX_LEN) { 399 size = 1; 400 for (; j < I40E_FDIR_MAX_FLEX_LEN - 1; j++) { 401 if (src_offset[j + 1] == src_offset[j] + 1) 402 size++; 403 else 404 break; 405 } 406 src_tmp = src_offset[j] + 1 - size; 407 /* the flex_pit need to be sort by src_offset */ 408 for (i = 0; i < num; i++) { 409 if (src_tmp < flex_pit[i].src_offset) 410 break; 411 } 412 /* if insert required, move backward */ 413 for (k = num; k > i; k--) 414 flex_pit[k] = flex_pit[k - 1]; 415 /* insert */ 416 flex_pit[i].dst_offset = j + 1 - size; 417 flex_pit[i].src_offset = src_tmp; 418 flex_pit[i].size = size; 419 j++; 420 num++; 421 } 422 return num; 423 } 424 425 /* i40e_check_fdir_flex_payload -check flex payload configuration arguments */ 426 static inline int 427 i40e_check_fdir_flex_payload(const struct rte_eth_flex_payload_cfg *flex_cfg) 428 { 429 struct i40e_fdir_flex_pit flex_pit[I40E_FDIR_MAX_FLEX_LEN]; 430 uint16_t num, i; 431 432 for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++) { 433 if (flex_cfg->src_offset[i] >= I40E_MAX_FLX_SOURCE_OFF) { 434 PMD_DRV_LOG(ERR, "exceeds maxmial payload limit."); 435 return -EINVAL; 436 } 437 } 438 439 memset(flex_pit, 0, sizeof(flex_pit)); 440 num = i40e_srcoff_to_flx_pit(flex_cfg->src_offset, flex_pit); 441 if (num > I40E_MAX_FLXPLD_FIED) { 442 PMD_DRV_LOG(ERR, "exceeds maxmial number of flex fields."); 443 return -EINVAL; 444 } 445 for (i = 0; i < num; i++) { 446 if (flex_pit[i].size & 0x01 || flex_pit[i].dst_offset & 0x01 || 447 flex_pit[i].src_offset & 0x01) { 448 PMD_DRV_LOG(ERR, "flexpayload should be measured" 449 " in word"); 450 return -EINVAL; 451 } 452 if (i != num - 1) 453 I40E_VALIDATE_FLEX_PIT(flex_pit[i], flex_pit[i + 1]); 454 } 455 return 0; 456 } 457 458 /* 459 * i40e_check_fdir_flex_conf -check if the flex payload and mask configuration 460 * arguments are valid 461 */ 462 static int 463 i40e_check_fdir_flex_conf(const struct i40e_adapter *adapter, 464 const struct rte_eth_fdir_flex_conf *conf) 465 { 466 const struct rte_eth_flex_payload_cfg *flex_cfg; 467 const struct rte_eth_fdir_flex_mask *flex_mask; 468 uint16_t mask_tmp; 469 uint8_t nb_bitmask; 470 uint16_t i, j; 471 int ret = 0; 472 enum i40e_filter_pctype pctype; 473 474 if (conf == NULL) { 475 PMD_DRV_LOG(INFO, "NULL pointer."); 476 return -EINVAL; 477 } 478 /* check flexible payload setting configuration */ 479 if (conf->nb_payloads > RTE_ETH_L4_PAYLOAD) { 480 PMD_DRV_LOG(ERR, "invalid number of payload setting."); 481 return -EINVAL; 482 } 483 for (i = 0; i < conf->nb_payloads; i++) { 484 flex_cfg = &conf->flex_set[i]; 485 if (flex_cfg->type > RTE_ETH_L4_PAYLOAD) { 486 PMD_DRV_LOG(ERR, "invalid payload type."); 487 return -EINVAL; 488 } 489 ret = i40e_check_fdir_flex_payload(flex_cfg); 490 if (ret < 0) { 491 PMD_DRV_LOG(ERR, "invalid flex payload arguments."); 492 return -EINVAL; 493 } 494 } 495 496 /* check flex mask setting configuration */ 497 if (conf->nb_flexmasks >= RTE_ETH_FLOW_MAX) { 498 PMD_DRV_LOG(ERR, "invalid number of flex masks."); 499 return -EINVAL; 500 } 501 for (i = 0; i < conf->nb_flexmasks; i++) { 502 flex_mask = &conf->flex_mask[i]; 503 pctype = i40e_flowtype_to_pctype(adapter, flex_mask->flow_type); 504 if (pctype == I40E_FILTER_PCTYPE_INVALID) { 505 PMD_DRV_LOG(WARNING, "invalid flow type."); 506 return -EINVAL; 507 } 508 nb_bitmask = 0; 509 for (j = 0; j < I40E_FDIR_MAX_FLEX_LEN; j += sizeof(uint16_t)) { 510 mask_tmp = I40E_WORD(flex_mask->mask[j], 511 flex_mask->mask[j + 1]); 512 if (mask_tmp != 0x0 && mask_tmp != UINT16_MAX) { 513 nb_bitmask++; 514 if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD) { 515 PMD_DRV_LOG(ERR, " exceed maximal" 516 " number of bitmasks."); 517 return -EINVAL; 518 } 519 } 520 } 521 } 522 return 0; 523 } 524 525 /* 526 * i40e_set_flx_pld_cfg -configure the rule how bytes stream is extracted as flexible payload 527 * @pf: board private structure 528 * @cfg: the rule how bytes stream is extracted as flexible payload 529 */ 530 static void 531 i40e_set_flx_pld_cfg(struct i40e_pf *pf, 532 const struct rte_eth_flex_payload_cfg *cfg) 533 { 534 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 535 struct i40e_fdir_flex_pit flex_pit[I40E_MAX_FLXPLD_FIED]; 536 uint32_t flx_pit; 537 uint16_t num, min_next_off; /* in words */ 538 uint8_t field_idx = 0; 539 uint8_t layer_idx = 0; 540 uint16_t i; 541 542 if (cfg->type == RTE_ETH_L2_PAYLOAD) 543 layer_idx = I40E_FLXPLD_L2_IDX; 544 else if (cfg->type == RTE_ETH_L3_PAYLOAD) 545 layer_idx = I40E_FLXPLD_L3_IDX; 546 else if (cfg->type == RTE_ETH_L4_PAYLOAD) 547 layer_idx = I40E_FLXPLD_L4_IDX; 548 549 memset(flex_pit, 0, sizeof(flex_pit)); 550 num = i40e_srcoff_to_flx_pit(cfg->src_offset, flex_pit); 551 552 for (i = 0; i < RTE_MIN(num, RTE_DIM(flex_pit)); i++) { 553 field_idx = layer_idx * I40E_MAX_FLXPLD_FIED + i; 554 /* record the info in fdir structure */ 555 pf->fdir.flex_set[field_idx].src_offset = 556 flex_pit[i].src_offset / sizeof(uint16_t); 557 pf->fdir.flex_set[field_idx].size = 558 flex_pit[i].size / sizeof(uint16_t); 559 pf->fdir.flex_set[field_idx].dst_offset = 560 flex_pit[i].dst_offset / sizeof(uint16_t); 561 flx_pit = MK_FLX_PIT(pf->fdir.flex_set[field_idx].src_offset, 562 pf->fdir.flex_set[field_idx].size, 563 pf->fdir.flex_set[field_idx].dst_offset); 564 565 I40E_WRITE_REG(hw, I40E_PRTQF_FLX_PIT(field_idx), flx_pit); 566 } 567 min_next_off = pf->fdir.flex_set[field_idx].src_offset + 568 pf->fdir.flex_set[field_idx].size; 569 570 for (; i < I40E_MAX_FLXPLD_FIED; i++) { 571 /* set the non-used register obeying register's constrain */ 572 flx_pit = MK_FLX_PIT(min_next_off, NONUSE_FLX_PIT_FSIZE, 573 NONUSE_FLX_PIT_DEST_OFF); 574 I40E_WRITE_REG(hw, 575 I40E_PRTQF_FLX_PIT(layer_idx * I40E_MAX_FLXPLD_FIED + i), 576 flx_pit); 577 min_next_off++; 578 } 579 } 580 581 /* 582 * i40e_set_flex_mask_on_pctype - configure the mask on flexible payload 583 * @pf: board private structure 584 * @pctype: packet classify type 585 * @flex_masks: mask for flexible payload 586 */ 587 static void 588 i40e_set_flex_mask_on_pctype(struct i40e_pf *pf, 589 enum i40e_filter_pctype pctype, 590 const struct rte_eth_fdir_flex_mask *mask_cfg) 591 { 592 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 593 struct i40e_fdir_flex_mask *flex_mask; 594 uint32_t flxinset, fd_mask; 595 uint16_t mask_tmp; 596 uint8_t i, nb_bitmask = 0; 597 598 flex_mask = &pf->fdir.flex_mask[pctype]; 599 memset(flex_mask, 0, sizeof(struct i40e_fdir_flex_mask)); 600 for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i += sizeof(uint16_t)) { 601 mask_tmp = I40E_WORD(mask_cfg->mask[i], mask_cfg->mask[i + 1]); 602 if (mask_tmp != 0x0) { 603 flex_mask->word_mask |= 604 I40E_FLEX_WORD_MASK(i / sizeof(uint16_t)); 605 if (mask_tmp != UINT16_MAX) { 606 /* set bit mask */ 607 flex_mask->bitmask[nb_bitmask].mask = ~mask_tmp; 608 flex_mask->bitmask[nb_bitmask].offset = 609 i / sizeof(uint16_t); 610 nb_bitmask++; 611 } 612 } 613 } 614 /* write mask to hw */ 615 flxinset = (flex_mask->word_mask << 616 I40E_PRTQF_FD_FLXINSET_INSET_SHIFT) & 617 I40E_PRTQF_FD_FLXINSET_INSET_MASK; 618 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_FLXINSET(pctype), flxinset); 619 620 for (i = 0; i < nb_bitmask; i++) { 621 fd_mask = (flex_mask->bitmask[i].mask << 622 I40E_PRTQF_FD_MSK_MASK_SHIFT) & 623 I40E_PRTQF_FD_MSK_MASK_MASK; 624 fd_mask |= ((flex_mask->bitmask[i].offset + 625 I40E_FLX_OFFSET_IN_FIELD_VECTOR) << 626 I40E_PRTQF_FD_MSK_OFFSET_SHIFT) & 627 I40E_PRTQF_FD_MSK_OFFSET_MASK; 628 i40e_write_rx_ctl(hw, I40E_PRTQF_FD_MSK(pctype, i), fd_mask); 629 } 630 } 631 632 /* 633 * Configure flow director related setting 634 */ 635 int 636 i40e_fdir_configure(struct rte_eth_dev *dev) 637 { 638 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); 639 struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); 640 struct rte_eth_fdir_flex_conf *conf; 641 enum i40e_filter_pctype pctype; 642 uint32_t val; 643 uint8_t i; 644 int ret = 0; 645 646 /* 647 * configuration need to be done before 648 * flow director filters are added 649 * If filters exist, flush them. 650 */ 651 if (i40e_fdir_empty(hw) < 0) { 652 ret = i40e_fdir_flush(dev); 653 if (ret) { 654 PMD_DRV_LOG(ERR, "failed to flush fdir table."); 655 return ret; 656 } 657 } 658 659 /* enable FDIR filter */ 660 val = i40e_read_rx_ctl(hw, I40E_PFQF_CTL_0); 661 val |= I40E_PFQF_CTL_0_FD_ENA_MASK; 662 i40e_write_rx_ctl(hw, I40E_PFQF_CTL_0, val); 663 664 i40e_init_flx_pld(pf); /* set flex config to default value */ 665 666 conf = &dev->data->dev_conf.fdir_conf.flex_conf; 667 ret = i40e_check_fdir_flex_conf(pf->adapter, conf); 668 if (ret < 0) { 669 PMD_DRV_LOG(ERR, " invalid configuration arguments."); 670 return -EINVAL; 671 } 672 673 if (!pf->support_multi_driver) { 674 /* configure flex payload */ 675 for (i = 0; i < conf->nb_payloads; i++) 676 i40e_set_flx_pld_cfg(pf, &conf->flex_set[i]); 677 /* configure flex mask*/ 678 for (i = 0; i < conf->nb_flexmasks; i++) { 679 if (hw->mac.type == I40E_MAC_X722) { 680 /* get pctype value in fd pctype register */ 681 pctype = (enum i40e_filter_pctype) 682 i40e_read_rx_ctl(hw, 683 I40E_GLQF_FD_PCTYPES( 684 (int)i40e_flowtype_to_pctype( 685 pf->adapter, 686 conf->flex_mask[i].flow_type))); 687 } else { 688 pctype = i40e_flowtype_to_pctype(pf->adapter, 689 conf->flex_mask[i].flow_type); 690 } 691 692 i40e_set_flex_mask_on_pctype(pf, pctype, 693 &conf->flex_mask[i]); 694 } 695 } else { 696 PMD_DRV_LOG(ERR, "Not support flexible payload."); 697 } 698 699 return ret; 700 } 701 702 static inline int 703 i40e_fdir_fill_eth_ip_head(const struct rte_eth_fdir_input *fdir_input, 704 unsigned char *raw_pkt, 705 bool vlan) 706 { 707 static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; 708 uint16_t *ether_type; 709 uint8_t len = 2 * sizeof(struct ether_addr); 710 struct ipv4_hdr *ip; 711 struct ipv6_hdr *ip6; 712 static const uint8_t next_proto[] = { 713 [RTE_ETH_FLOW_FRAG_IPV4] = IPPROTO_IP, 714 [RTE_ETH_FLOW_NONFRAG_IPV4_TCP] = IPPROTO_TCP, 715 [RTE_ETH_FLOW_NONFRAG_IPV4_UDP] = IPPROTO_UDP, 716 [RTE_ETH_FLOW_NONFRAG_IPV4_SCTP] = IPPROTO_SCTP, 717 [RTE_ETH_FLOW_NONFRAG_IPV4_OTHER] = IPPROTO_IP, 718 [RTE_ETH_FLOW_FRAG_IPV6] = IPPROTO_NONE, 719 [RTE_ETH_FLOW_NONFRAG_IPV6_TCP] = IPPROTO_TCP, 720 [RTE_ETH_FLOW_NONFRAG_IPV6_UDP] = IPPROTO_UDP, 721 [RTE_ETH_FLOW_NONFRAG_IPV6_SCTP] = IPPROTO_SCTP, 722 [RTE_ETH_FLOW_NONFRAG_IPV6_OTHER] = IPPROTO_NONE, 723 }; 724 725 raw_pkt += 2 * sizeof(struct ether_addr); 726 if (vlan && fdir_input->flow_ext.vlan_tci) { 727 rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); 728 rte_memcpy(raw_pkt + sizeof(uint16_t), 729 &fdir_input->flow_ext.vlan_tci, 730 sizeof(uint16_t)); 731 raw_pkt += sizeof(vlan_frame); 732 len += sizeof(vlan_frame); 733 } 734 ether_type = (uint16_t *)raw_pkt; 735 raw_pkt += sizeof(uint16_t); 736 len += sizeof(uint16_t); 737 738 switch (fdir_input->flow_type) { 739 case RTE_ETH_FLOW_L2_PAYLOAD: 740 *ether_type = fdir_input->flow.l2_flow.ether_type; 741 break; 742 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 743 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 744 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: 745 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 746 case RTE_ETH_FLOW_FRAG_IPV4: 747 ip = (struct ipv4_hdr *)raw_pkt; 748 749 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 750 ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL; 751 /* set len to by default */ 752 ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN); 753 ip->next_proto_id = fdir_input->flow.ip4_flow.proto ? 754 fdir_input->flow.ip4_flow.proto : 755 next_proto[fdir_input->flow_type]; 756 ip->time_to_live = fdir_input->flow.ip4_flow.ttl ? 757 fdir_input->flow.ip4_flow.ttl : 758 I40E_FDIR_IP_DEFAULT_TTL; 759 ip->type_of_service = fdir_input->flow.ip4_flow.tos; 760 /* 761 * The source and destination fields in the transmitted packet 762 * need to be presented in a reversed order with respect 763 * to the expected received packets. 764 */ 765 ip->src_addr = fdir_input->flow.ip4_flow.dst_ip; 766 ip->dst_addr = fdir_input->flow.ip4_flow.src_ip; 767 len += sizeof(struct ipv4_hdr); 768 break; 769 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 770 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 771 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: 772 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 773 case RTE_ETH_FLOW_FRAG_IPV6: 774 ip6 = (struct ipv6_hdr *)raw_pkt; 775 776 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 777 ip6->vtc_flow = 778 rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW | 779 (fdir_input->flow.ipv6_flow.tc << 780 I40E_FDIR_IPv6_TC_OFFSET)); 781 ip6->payload_len = 782 rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); 783 ip6->proto = fdir_input->flow.ipv6_flow.proto ? 784 fdir_input->flow.ipv6_flow.proto : 785 next_proto[fdir_input->flow_type]; 786 ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ? 787 fdir_input->flow.ipv6_flow.hop_limits : 788 I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS; 789 /* 790 * The source and destination fields in the transmitted packet 791 * need to be presented in a reversed order with respect 792 * to the expected received packets. 793 */ 794 rte_memcpy(&(ip6->src_addr), 795 &(fdir_input->flow.ipv6_flow.dst_ip), 796 IPV6_ADDR_LEN); 797 rte_memcpy(&(ip6->dst_addr), 798 &(fdir_input->flow.ipv6_flow.src_ip), 799 IPV6_ADDR_LEN); 800 len += sizeof(struct ipv6_hdr); 801 break; 802 default: 803 PMD_DRV_LOG(ERR, "unknown flow type %u.", 804 fdir_input->flow_type); 805 return -1; 806 } 807 return len; 808 } 809 810 811 /* 812 * i40e_fdir_construct_pkt - construct packet based on fields in input 813 * @pf: board private structure 814 * @fdir_input: input set of the flow director entry 815 * @raw_pkt: a packet to be constructed 816 */ 817 static int 818 i40e_fdir_construct_pkt(struct i40e_pf *pf, 819 const struct rte_eth_fdir_input *fdir_input, 820 unsigned char *raw_pkt) 821 { 822 unsigned char *payload, *ptr; 823 struct udp_hdr *udp; 824 struct tcp_hdr *tcp; 825 struct sctp_hdr *sctp; 826 uint8_t size, dst = 0; 827 uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ 828 int len; 829 830 /* fill the ethernet and IP head */ 831 len = i40e_fdir_fill_eth_ip_head(fdir_input, raw_pkt, 832 !!fdir_input->flow_ext.vlan_tci); 833 if (len < 0) 834 return -EINVAL; 835 836 /* fill the L4 head */ 837 switch (fdir_input->flow_type) { 838 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 839 udp = (struct udp_hdr *)(raw_pkt + len); 840 payload = (unsigned char *)udp + sizeof(struct udp_hdr); 841 /* 842 * The source and destination fields in the transmitted packet 843 * need to be presented in a reversed order with respect 844 * to the expected received packets. 845 */ 846 udp->src_port = fdir_input->flow.udp4_flow.dst_port; 847 udp->dst_port = fdir_input->flow.udp4_flow.src_port; 848 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); 849 break; 850 851 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 852 tcp = (struct tcp_hdr *)(raw_pkt + len); 853 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); 854 /* 855 * The source and destination fields in the transmitted packet 856 * need to be presented in a reversed order with respect 857 * to the expected received packets. 858 */ 859 tcp->src_port = fdir_input->flow.tcp4_flow.dst_port; 860 tcp->dst_port = fdir_input->flow.tcp4_flow.src_port; 861 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; 862 break; 863 864 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: 865 sctp = (struct sctp_hdr *)(raw_pkt + len); 866 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); 867 /* 868 * The source and destination fields in the transmitted packet 869 * need to be presented in a reversed order with respect 870 * to the expected received packets. 871 */ 872 sctp->src_port = fdir_input->flow.sctp4_flow.dst_port; 873 sctp->dst_port = fdir_input->flow.sctp4_flow.src_port; 874 sctp->tag = fdir_input->flow.sctp4_flow.verify_tag; 875 break; 876 877 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 878 case RTE_ETH_FLOW_FRAG_IPV4: 879 payload = raw_pkt + len; 880 set_idx = I40E_FLXPLD_L3_IDX; 881 break; 882 883 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 884 udp = (struct udp_hdr *)(raw_pkt + len); 885 payload = (unsigned char *)udp + sizeof(struct udp_hdr); 886 /* 887 * The source and destination fields in the transmitted packet 888 * need to be presented in a reversed order with respect 889 * to the expected received packets. 890 */ 891 udp->src_port = fdir_input->flow.udp6_flow.dst_port; 892 udp->dst_port = fdir_input->flow.udp6_flow.src_port; 893 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); 894 break; 895 896 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 897 tcp = (struct tcp_hdr *)(raw_pkt + len); 898 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); 899 /* 900 * The source and destination fields in the transmitted packet 901 * need to be presented in a reversed order with respect 902 * to the expected received packets. 903 */ 904 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; 905 tcp->src_port = fdir_input->flow.udp6_flow.dst_port; 906 tcp->dst_port = fdir_input->flow.udp6_flow.src_port; 907 break; 908 909 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: 910 sctp = (struct sctp_hdr *)(raw_pkt + len); 911 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); 912 /* 913 * The source and destination fields in the transmitted packet 914 * need to be presented in a reversed order with respect 915 * to the expected received packets. 916 */ 917 sctp->src_port = fdir_input->flow.sctp6_flow.dst_port; 918 sctp->dst_port = fdir_input->flow.sctp6_flow.src_port; 919 sctp->tag = fdir_input->flow.sctp6_flow.verify_tag; 920 break; 921 922 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 923 case RTE_ETH_FLOW_FRAG_IPV6: 924 payload = raw_pkt + len; 925 set_idx = I40E_FLXPLD_L3_IDX; 926 break; 927 case RTE_ETH_FLOW_L2_PAYLOAD: 928 payload = raw_pkt + len; 929 /* 930 * ARP packet is a special case on which the payload 931 * starts after the whole ARP header 932 */ 933 if (fdir_input->flow.l2_flow.ether_type == 934 rte_cpu_to_be_16(ETHER_TYPE_ARP)) 935 payload += sizeof(struct arp_hdr); 936 set_idx = I40E_FLXPLD_L2_IDX; 937 break; 938 default: 939 PMD_DRV_LOG(ERR, "unknown flow type %u.", fdir_input->flow_type); 940 return -EINVAL; 941 } 942 943 /* fill the flexbytes to payload */ 944 for (i = 0; i < I40E_MAX_FLXPLD_FIED; i++) { 945 pit_idx = set_idx * I40E_MAX_FLXPLD_FIED + i; 946 size = pf->fdir.flex_set[pit_idx].size; 947 if (size == 0) 948 continue; 949 dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t); 950 ptr = payload + 951 pf->fdir.flex_set[pit_idx].src_offset * sizeof(uint16_t); 952 rte_memcpy(ptr, 953 &fdir_input->flow_ext.flexbytes[dst], 954 size * sizeof(uint16_t)); 955 } 956 957 return 0; 958 } 959 960 static struct i40e_customized_pctype * 961 i40e_flow_fdir_find_customized_pctype(struct i40e_pf *pf, uint8_t pctype) 962 { 963 struct i40e_customized_pctype *cus_pctype; 964 enum i40e_new_pctype i = I40E_CUSTOMIZED_GTPC; 965 966 for (; i < I40E_CUSTOMIZED_MAX; i++) { 967 cus_pctype = &pf->customized_pctype[i]; 968 if (pctype == cus_pctype->pctype) 969 return cus_pctype; 970 } 971 return NULL; 972 } 973 974 static inline int 975 i40e_flow_fdir_fill_eth_ip_head(struct i40e_pf *pf, 976 const struct i40e_fdir_input *fdir_input, 977 unsigned char *raw_pkt, 978 bool vlan) 979 { 980 struct i40e_customized_pctype *cus_pctype = NULL; 981 static uint8_t vlan_frame[] = {0x81, 0, 0, 0}; 982 uint16_t *ether_type; 983 uint8_t len = 2 * sizeof(struct ether_addr); 984 struct ipv4_hdr *ip; 985 struct ipv6_hdr *ip6; 986 uint8_t pctype = fdir_input->pctype; 987 bool is_customized_pctype = fdir_input->flow_ext.customized_pctype; 988 static const uint8_t next_proto[] = { 989 [I40E_FILTER_PCTYPE_FRAG_IPV4] = IPPROTO_IP, 990 [I40E_FILTER_PCTYPE_NONF_IPV4_TCP] = IPPROTO_TCP, 991 [I40E_FILTER_PCTYPE_NONF_IPV4_UDP] = IPPROTO_UDP, 992 [I40E_FILTER_PCTYPE_NONF_IPV4_SCTP] = IPPROTO_SCTP, 993 [I40E_FILTER_PCTYPE_NONF_IPV4_OTHER] = IPPROTO_IP, 994 [I40E_FILTER_PCTYPE_FRAG_IPV6] = IPPROTO_NONE, 995 [I40E_FILTER_PCTYPE_NONF_IPV6_TCP] = IPPROTO_TCP, 996 [I40E_FILTER_PCTYPE_NONF_IPV6_UDP] = IPPROTO_UDP, 997 [I40E_FILTER_PCTYPE_NONF_IPV6_SCTP] = IPPROTO_SCTP, 998 [I40E_FILTER_PCTYPE_NONF_IPV6_OTHER] = IPPROTO_NONE, 999 }; 1000 1001 raw_pkt += 2 * sizeof(struct ether_addr); 1002 if (vlan && fdir_input->flow_ext.vlan_tci) { 1003 rte_memcpy(raw_pkt, vlan_frame, sizeof(vlan_frame)); 1004 rte_memcpy(raw_pkt + sizeof(uint16_t), 1005 &fdir_input->flow_ext.vlan_tci, 1006 sizeof(uint16_t)); 1007 raw_pkt += sizeof(vlan_frame); 1008 len += sizeof(vlan_frame); 1009 } 1010 ether_type = (uint16_t *)raw_pkt; 1011 raw_pkt += sizeof(uint16_t); 1012 len += sizeof(uint16_t); 1013 1014 if (is_customized_pctype) { 1015 cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype); 1016 if (!cus_pctype) { 1017 PMD_DRV_LOG(ERR, "unknown pctype %u.", 1018 fdir_input->pctype); 1019 return -1; 1020 } 1021 } 1022 1023 if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) 1024 *ether_type = fdir_input->flow.l2_flow.ether_type; 1025 else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP || 1026 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP || 1027 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP || 1028 pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER || 1029 pctype == I40E_FILTER_PCTYPE_FRAG_IPV4 || 1030 is_customized_pctype) { 1031 ip = (struct ipv4_hdr *)raw_pkt; 1032 1033 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); 1034 ip->version_ihl = I40E_FDIR_IP_DEFAULT_VERSION_IHL; 1035 /* set len to by default */ 1036 ip->total_length = rte_cpu_to_be_16(I40E_FDIR_IP_DEFAULT_LEN); 1037 ip->time_to_live = fdir_input->flow.ip4_flow.ttl ? 1038 fdir_input->flow.ip4_flow.ttl : 1039 I40E_FDIR_IP_DEFAULT_TTL; 1040 ip->type_of_service = fdir_input->flow.ip4_flow.tos; 1041 /** 1042 * The source and destination fields in the transmitted packet 1043 * need to be presented in a reversed order with respect 1044 * to the expected received packets. 1045 */ 1046 ip->src_addr = fdir_input->flow.ip4_flow.dst_ip; 1047 ip->dst_addr = fdir_input->flow.ip4_flow.src_ip; 1048 1049 if (!is_customized_pctype) 1050 ip->next_proto_id = fdir_input->flow.ip4_flow.proto ? 1051 fdir_input->flow.ip4_flow.proto : 1052 next_proto[fdir_input->pctype]; 1053 else if (cus_pctype->index == I40E_CUSTOMIZED_GTPC || 1054 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4 || 1055 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 || 1056 cus_pctype->index == I40E_CUSTOMIZED_GTPU) 1057 ip->next_proto_id = IPPROTO_UDP; 1058 len += sizeof(struct ipv4_hdr); 1059 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP || 1060 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP || 1061 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP || 1062 pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || 1063 pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) { 1064 ip6 = (struct ipv6_hdr *)raw_pkt; 1065 1066 *ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6); 1067 ip6->vtc_flow = 1068 rte_cpu_to_be_32(I40E_FDIR_IPv6_DEFAULT_VTC_FLOW | 1069 (fdir_input->flow.ipv6_flow.tc << 1070 I40E_FDIR_IPv6_TC_OFFSET)); 1071 ip6->payload_len = 1072 rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); 1073 ip6->proto = fdir_input->flow.ipv6_flow.proto ? 1074 fdir_input->flow.ipv6_flow.proto : 1075 next_proto[fdir_input->pctype]; 1076 ip6->hop_limits = fdir_input->flow.ipv6_flow.hop_limits ? 1077 fdir_input->flow.ipv6_flow.hop_limits : 1078 I40E_FDIR_IPv6_DEFAULT_HOP_LIMITS; 1079 /** 1080 * The source and destination fields in the transmitted packet 1081 * need to be presented in a reversed order with respect 1082 * to the expected received packets. 1083 */ 1084 rte_memcpy(&ip6->src_addr, 1085 &fdir_input->flow.ipv6_flow.dst_ip, 1086 IPV6_ADDR_LEN); 1087 rte_memcpy(&ip6->dst_addr, 1088 &fdir_input->flow.ipv6_flow.src_ip, 1089 IPV6_ADDR_LEN); 1090 len += sizeof(struct ipv6_hdr); 1091 } else { 1092 PMD_DRV_LOG(ERR, "unknown pctype %u.", 1093 fdir_input->pctype); 1094 return -1; 1095 } 1096 1097 return len; 1098 } 1099 1100 /** 1101 * i40e_flow_fdir_construct_pkt - construct packet based on fields in input 1102 * @pf: board private structure 1103 * @fdir_input: input set of the flow director entry 1104 * @raw_pkt: a packet to be constructed 1105 */ 1106 static int 1107 i40e_flow_fdir_construct_pkt(struct i40e_pf *pf, 1108 const struct i40e_fdir_input *fdir_input, 1109 unsigned char *raw_pkt) 1110 { 1111 unsigned char *payload = NULL; 1112 unsigned char *ptr; 1113 struct udp_hdr *udp; 1114 struct tcp_hdr *tcp; 1115 struct sctp_hdr *sctp; 1116 struct rte_flow_item_gtp *gtp; 1117 struct ipv4_hdr *gtp_ipv4; 1118 struct ipv6_hdr *gtp_ipv6; 1119 uint8_t size, dst = 0; 1120 uint8_t i, pit_idx, set_idx = I40E_FLXPLD_L4_IDX; /* use l4 by default*/ 1121 int len; 1122 uint8_t pctype = fdir_input->pctype; 1123 struct i40e_customized_pctype *cus_pctype; 1124 1125 /* raw pcket template - just copy contents of the raw packet */ 1126 if (fdir_input->flow_ext.pkt_template) { 1127 memcpy(raw_pkt, fdir_input->flow.raw_flow.packet, 1128 fdir_input->flow.raw_flow.length); 1129 return 0; 1130 } 1131 1132 /* fill the ethernet and IP head */ 1133 len = i40e_flow_fdir_fill_eth_ip_head(pf, fdir_input, raw_pkt, 1134 !!fdir_input->flow_ext.vlan_tci); 1135 if (len < 0) 1136 return -EINVAL; 1137 1138 /* fill the L4 head */ 1139 if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_UDP) { 1140 udp = (struct udp_hdr *)(raw_pkt + len); 1141 payload = (unsigned char *)udp + sizeof(struct udp_hdr); 1142 /** 1143 * The source and destination fields in the transmitted packet 1144 * need to be presented in a reversed order with respect 1145 * to the expected received packets. 1146 */ 1147 udp->src_port = fdir_input->flow.udp4_flow.dst_port; 1148 udp->dst_port = fdir_input->flow.udp4_flow.src_port; 1149 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); 1150 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_TCP) { 1151 tcp = (struct tcp_hdr *)(raw_pkt + len); 1152 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); 1153 /** 1154 * The source and destination fields in the transmitted packet 1155 * need to be presented in a reversed order with respect 1156 * to the expected received packets. 1157 */ 1158 tcp->src_port = fdir_input->flow.tcp4_flow.dst_port; 1159 tcp->dst_port = fdir_input->flow.tcp4_flow.src_port; 1160 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; 1161 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) { 1162 sctp = (struct sctp_hdr *)(raw_pkt + len); 1163 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); 1164 /** 1165 * The source and destination fields in the transmitted packet 1166 * need to be presented in a reversed order with respect 1167 * to the expected received packets. 1168 */ 1169 sctp->src_port = fdir_input->flow.sctp4_flow.dst_port; 1170 sctp->dst_port = fdir_input->flow.sctp4_flow.src_port; 1171 sctp->tag = fdir_input->flow.sctp4_flow.verify_tag; 1172 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV4_OTHER || 1173 pctype == I40E_FILTER_PCTYPE_FRAG_IPV4) { 1174 payload = raw_pkt + len; 1175 set_idx = I40E_FLXPLD_L3_IDX; 1176 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_UDP) { 1177 udp = (struct udp_hdr *)(raw_pkt + len); 1178 payload = (unsigned char *)udp + sizeof(struct udp_hdr); 1179 /** 1180 * The source and destination fields in the transmitted packet 1181 * need to be presented in a reversed order with respect 1182 * to the expected received packets. 1183 */ 1184 udp->src_port = fdir_input->flow.udp6_flow.dst_port; 1185 udp->dst_port = fdir_input->flow.udp6_flow.src_port; 1186 udp->dgram_len = rte_cpu_to_be_16(I40E_FDIR_IPv6_PAYLOAD_LEN); 1187 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_TCP) { 1188 tcp = (struct tcp_hdr *)(raw_pkt + len); 1189 payload = (unsigned char *)tcp + sizeof(struct tcp_hdr); 1190 /** 1191 * The source and destination fields in the transmitted packet 1192 * need to be presented in a reversed order with respect 1193 * to the expected received packets. 1194 */ 1195 tcp->data_off = I40E_FDIR_TCP_DEFAULT_DATAOFF; 1196 tcp->src_port = fdir_input->flow.udp6_flow.dst_port; 1197 tcp->dst_port = fdir_input->flow.udp6_flow.src_port; 1198 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) { 1199 sctp = (struct sctp_hdr *)(raw_pkt + len); 1200 payload = (unsigned char *)sctp + sizeof(struct sctp_hdr); 1201 /** 1202 * The source and destination fields in the transmitted packet 1203 * need to be presented in a reversed order with respect 1204 * to the expected received packets. 1205 */ 1206 sctp->src_port = fdir_input->flow.sctp6_flow.dst_port; 1207 sctp->dst_port = fdir_input->flow.sctp6_flow.src_port; 1208 sctp->tag = fdir_input->flow.sctp6_flow.verify_tag; 1209 } else if (pctype == I40E_FILTER_PCTYPE_NONF_IPV6_OTHER || 1210 pctype == I40E_FILTER_PCTYPE_FRAG_IPV6) { 1211 payload = raw_pkt + len; 1212 set_idx = I40E_FLXPLD_L3_IDX; 1213 } else if (pctype == I40E_FILTER_PCTYPE_L2_PAYLOAD) { 1214 payload = raw_pkt + len; 1215 /** 1216 * ARP packet is a special case on which the payload 1217 * starts after the whole ARP header 1218 */ 1219 if (fdir_input->flow.l2_flow.ether_type == 1220 rte_cpu_to_be_16(ETHER_TYPE_ARP)) 1221 payload += sizeof(struct arp_hdr); 1222 set_idx = I40E_FLXPLD_L2_IDX; 1223 } else if (fdir_input->flow_ext.customized_pctype) { 1224 /* If customized pctype is used */ 1225 cus_pctype = i40e_flow_fdir_find_customized_pctype(pf, pctype); 1226 if (cus_pctype->index == I40E_CUSTOMIZED_GTPC || 1227 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4 || 1228 cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV6 || 1229 cus_pctype->index == I40E_CUSTOMIZED_GTPU) { 1230 udp = (struct udp_hdr *)(raw_pkt + len); 1231 udp->dgram_len = 1232 rte_cpu_to_be_16(I40E_FDIR_UDP_DEFAULT_LEN); 1233 1234 gtp = (struct rte_flow_item_gtp *) 1235 ((unsigned char *)udp + sizeof(struct udp_hdr)); 1236 gtp->msg_len = 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; 1240 1241 /* GTP-C message type is not supported. */ 1242 if (cus_pctype->index == I40E_CUSTOMIZED_GTPC) { 1243 udp->dst_port = 1244 rte_cpu_to_be_16(I40E_FDIR_GTPC_DST_PORT); 1245 gtp->v_pt_rsv_flags = 1246 I40E_FDIR_GTP_VER_FLAG_0X32; 1247 } else { 1248 udp->dst_port = 1249 rte_cpu_to_be_16(I40E_FDIR_GTPU_DST_PORT); 1250 gtp->v_pt_rsv_flags = 1251 I40E_FDIR_GTP_VER_FLAG_0X30; 1252 } 1253 1254 if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) { 1255 gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF; 1256 gtp_ipv4 = (struct 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 = 1263 rte_cpu_to_be_16( 1264 I40E_FDIR_INNER_IP_DEFAULT_LEN); 1265 payload = (unsigned char *)gtp_ipv4 + 1266 sizeof(struct 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 ipv6_hdr *) 1271 ((unsigned char *)gtp + 1272 sizeof(struct rte_flow_item_gtp)); 1273 gtp_ipv6->vtc_flow = 1274 rte_cpu_to_be_32( 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 = 1279 rte_cpu_to_be_16( 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 ipv6_hdr); 1285 } else 1286 payload = (unsigned char *)gtp + 1287 sizeof(struct rte_flow_item_gtp); 1288 } 1289 } else { 1290 PMD_DRV_LOG(ERR, "unknown pctype %u.", 1291 fdir_input->pctype); 1292 return -1; 1293 } 1294 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; 1299 if (size == 0) 1300 continue; 1301 dst = pf->fdir.flex_set[pit_idx].dst_offset * sizeof(uint16_t); 1302 ptr = payload + 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)); 1307 } 1308 1309 return 0; 1310 } 1311 1312 /* Construct the tx flags */ 1313 static inline uint64_t 1314 i40e_build_ctob(uint32_t td_cmd, 1315 uint32_t td_offset, 1316 unsigned int size, 1317 uint32_t td_tag) 1318 { 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)); 1324 } 1325 1326 /* 1327 * check the programming status descriptor in rx queue. 1328 * done after Programming Flow Director is programmed on 1329 * tx queue 1330 */ 1331 static inline int 1332 i40e_check_fdir_programming_status(struct i40e_rx_queue *rxq) 1333 { 1334 volatile union i40e_rx_desc *rxdp; 1335 uint64_t qword1; 1336 uint32_t rx_status; 1337 uint32_t len, id; 1338 uint32_t error; 1339 int ret = 0; 1340 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; 1345 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; 1350 1351 if (len == I40E_RX_PROG_STATUS_DESC_LENGTH && 1352 id == I40E_RX_PROG_STATUS_DESC_FD_FILTER_STATUS) { 1353 error = (qword1 & 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" 1360 " reported.", 1361 rxdp->wb.qword0.hi_dword.fd_id); 1362 ret = -1; 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" 1367 " reported.", 1368 rxdp->wb.qword0.hi_dword.fd_id); 1369 ret = -1; 1370 } else 1371 PMD_DRV_LOG(ERR, "invalid programming status" 1372 " reported, error = %u.", error); 1373 } else 1374 PMD_DRV_LOG(INFO, "unknown programming status" 1375 " reported, len = %d, id = %u.", len, id); 1376 rxdp->wb.qword1.status_error_len = 0; 1377 rxq->rx_tail++; 1378 if (unlikely(rxq->rx_tail == rxq->nb_rx_desc)) 1379 rxq->rx_tail = 0; 1380 if (rxq->rx_tail == 0) 1381 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1); 1382 else 1383 I40E_PCI_REG_WRITE(rxq->qrx_tail, rxq->rx_tail - 1); 1384 } 1385 1386 return ret; 1387 } 1388 1389 static int 1390 i40e_fdir_filter_convert(const struct i40e_fdir_filter_conf *input, 1391 struct i40e_fdir_filter *filter) 1392 { 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); 1400 } 1401 return 0; 1402 } 1403 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) 1408 { 1409 int ret; 1410 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); 1415 else 1416 ret = rte_hash_lookup(fdir_info->hash_table, 1417 (const void *)input); 1418 if (ret < 0) 1419 return NULL; 1420 1421 return fdir_info->hash_map[ret]; 1422 } 1423 1424 /* Add a flow director filter into the SW list */ 1425 static int 1426 i40e_sw_fdir_filter_insert(struct i40e_pf *pf, struct i40e_fdir_filter *filter) 1427 { 1428 struct i40e_fdir_info *fdir_info = &pf->fdir; 1429 int ret; 1430 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); 1435 else 1436 ret = rte_hash_add_key(fdir_info->hash_table, 1437 &filter->fdir.input); 1438 if (ret < 0) { 1439 PMD_DRV_LOG(ERR, 1440 "Failed to insert fdir filter to hash table %d!", 1441 ret); 1442 return ret; 1443 } 1444 fdir_info->hash_map[ret] = filter; 1445 1446 TAILQ_INSERT_TAIL(&fdir_info->fdir_list, filter, rules); 1447 1448 return 0; 1449 } 1450 1451 /* Delete a flow director filter from the SW list */ 1452 int 1453 i40e_sw_fdir_filter_del(struct i40e_pf *pf, struct i40e_fdir_input *input) 1454 { 1455 struct i40e_fdir_info *fdir_info = &pf->fdir; 1456 struct i40e_fdir_filter *filter; 1457 int ret; 1458 1459 if (input->flow_ext.pkt_template) 1460 ret = rte_hash_del_key_with_hash(fdir_info->hash_table, 1461 input, 1462 input->flow.raw_flow.length); 1463 else 1464 ret = rte_hash_del_key(fdir_info->hash_table, input); 1465 if (ret < 0) { 1466 PMD_DRV_LOG(ERR, 1467 "Failed to delete fdir filter to hash table %d!", 1468 ret); 1469 return ret; 1470 } 1471 filter = fdir_info->hash_map[ret]; 1472 fdir_info->hash_map[ret] = NULL; 1473 1474 TAILQ_REMOVE(&fdir_info->fdir_list, filter, rules); 1475 rte_free(filter); 1476 1477 return 0; 1478 } 1479 1480 /* 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 1485 */ 1486 int 1487 i40e_add_del_fdir_filter(struct rte_eth_dev *dev, 1488 const struct rte_eth_fdir_filter *filter, 1489 bool add) 1490 { 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; 1495 int ret = 0; 1496 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."); 1500 return -ENOTSUP; 1501 } 1502 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."); 1506 return -EINVAL; 1507 } 1508 if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) { 1509 PMD_DRV_LOG(ERR, "Invalid queue ID"); 1510 return -EINVAL; 1511 } 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"); 1515 return -EINVAL; 1516 } 1517 1518 memset(pkt, 0, I40E_FDIR_PKT_LEN); 1519 1520 ret = i40e_fdir_construct_pkt(pf, &filter->input, pkt); 1521 if (ret < 0) { 1522 PMD_DRV_LOG(ERR, "construct packet for fdir fails."); 1523 return ret; 1524 } 1525 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)); 1530 } 1531 1532 ret = i40e_fdir_filter_programming(pf, pctype, filter, add); 1533 if (ret < 0) { 1534 PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).", 1535 pctype); 1536 return ret; 1537 } 1538 1539 return ret; 1540 } 1541 1542 /** 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 1547 */ 1548 int 1549 i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev, 1550 const struct i40e_fdir_filter_conf *filter, 1551 bool add) 1552 { 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 */ 1560 int ret = 0; 1561 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."); 1564 return -ENOTSUP; 1565 } 1566 1567 if (filter->action.rx_queue >= pf->dev_data->nb_rx_queues) { 1568 PMD_DRV_LOG(ERR, "Invalid queue ID"); 1569 return -EINVAL; 1570 } 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"); 1574 return -EINVAL; 1575 } 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!"); 1581 return -EINVAL; 1582 } 1583 pctype = filter->input.flow.raw_flow.pctype; 1584 } else { 1585 pctype = filter->input.pctype; 1586 } 1587 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); 1592 if (add && node) { 1593 PMD_DRV_LOG(ERR, 1594 "Conflict with existing flow director rules!"); 1595 return -EINVAL; 1596 } 1597 1598 if (!add && !node) { 1599 PMD_DRV_LOG(ERR, 1600 "There's no corresponding flow firector filter!"); 1601 return -EINVAL; 1602 } 1603 1604 memset(pkt, 0, I40E_FDIR_PKT_LEN); 1605 1606 ret = i40e_flow_fdir_construct_pkt(pf, &filter->input, pkt); 1607 if (ret < 0) { 1608 PMD_DRV_LOG(ERR, "construct packet for fdir fails."); 1609 return ret; 1610 } 1611 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)); 1616 } 1617 1618 ret = i40e_flow_fdir_filter_programming(pf, pctype, filter, add); 1619 if (ret < 0) { 1620 PMD_DRV_LOG(ERR, "fdir programming fails for PCTYPE(%u).", 1621 pctype); 1622 return ret; 1623 } 1624 1625 if (add) { 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."); 1630 return -ENOMEM; 1631 } 1632 1633 rte_memcpy(fdir_filter, &check_filter, sizeof(check_filter)); 1634 ret = i40e_sw_fdir_filter_insert(pf, fdir_filter); 1635 if (ret < 0) 1636 rte_free(fdir_filter); 1637 } else { 1638 ret = i40e_sw_fdir_filter_del(pf, &node->fdir.input); 1639 } 1640 1641 return ret; 1642 } 1643 1644 /* 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 1649 * @pctype: pctype 1650 * @filter: fdir filter entry 1651 * @add: 0 - delete, 1 - add 1652 */ 1653 static int 1654 i40e_fdir_filter_programming(struct i40e_pf *pf, 1655 enum i40e_filter_pctype pctype, 1656 const struct rte_eth_fdir_filter *filter, 1657 bool add) 1658 { 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; 1664 uint32_t td_cmd; 1665 uint16_t vsi_id, i; 1666 uint8_t dest; 1667 1668 PMD_DRV_LOG(INFO, "filling filter programming descriptor."); 1669 fdirdp = (volatile struct i40e_filter_program_desc *) 1670 (&(txq->tx_ring[txq->tx_tail])); 1671 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); 1676 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); 1681 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); 1686 1687 if (filter->input.flow_ext.is_vf) 1688 vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id; 1689 else 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); 1696 1697 fdirdp->dtype_cmd_cntindex = 1698 rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG); 1699 1700 if (add) 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); 1704 else 1705 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32( 1706 I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << 1707 I40E_TXD_FLTR_QW1_PCMD_SHIFT); 1708 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; 1715 else { 1716 PMD_DRV_LOG(ERR, "Failed to program FDIR filter:" 1717 " unsupported fdir behavior."); 1718 return -EINVAL; 1719 } 1720 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); 1724 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); 1729 1730 fdirdp->dtype_cmd_cntindex |= 1731 rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK); 1732 fdirdp->dtype_cmd_cntindex |= 1733 rte_cpu_to_le_32( 1734 ((uint32_t)pf->fdir.match_counter_index << 1735 I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) & 1736 I40E_TXD_FLTR_QW1_CNTINDEX_MASK); 1737 1738 fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id); 1739 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; 1746 1747 txdp->cmd_type_offset_bsz = 1748 i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0); 1749 1750 txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */ 1751 if (txq->tx_tail >= txq->nb_tx_desc) 1752 txq->tx_tail = 0; 1753 /* Update the tx tail register */ 1754 rte_wmb(); 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)) 1760 break; 1761 rte_delay_us(1); 1762 } 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."); 1766 return -ETIMEDOUT; 1767 } 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) 1771 return 0; 1772 rte_delay_us(1); 1773 } 1774 PMD_DRV_LOG(ERR, 1775 "Failed to program FDIR filter: programming status reported."); 1776 return -ETIMEDOUT; 1777 } 1778 1779 /* 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 1784 * @pctype: pctype 1785 * @filter: fdir filter entry 1786 * @add: 0 - delete, 1 - add 1787 */ 1788 static int 1789 i40e_flow_fdir_filter_programming(struct i40e_pf *pf, 1790 enum i40e_filter_pctype pctype, 1791 const struct i40e_fdir_filter_conf *filter, 1792 bool add) 1793 { 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; 1799 uint32_t td_cmd; 1800 uint16_t vsi_id, i; 1801 uint8_t dest; 1802 1803 PMD_DRV_LOG(INFO, "filling filter programming descriptor."); 1804 fdirdp = (volatile struct i40e_filter_program_desc *) 1805 (&txq->tx_ring[txq->tx_tail]); 1806 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); 1811 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); 1816 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); 1821 1822 if (filter->input.flow_ext.is_vf) 1823 vsi_id = pf->vfs[filter->input.flow_ext.dst_id].vsi->vsi_id; 1824 else 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); 1831 1832 fdirdp->dtype_cmd_cntindex = 1833 rte_cpu_to_le_32(I40E_TX_DESC_DTYPE_FILTER_PROG); 1834 1835 if (add) 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); 1839 else 1840 fdirdp->dtype_cmd_cntindex |= rte_cpu_to_le_32( 1841 I40E_FILTER_PROGRAM_DESC_PCMD_REMOVE << 1842 I40E_TXD_FLTR_QW1_PCMD_SHIFT); 1843 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; 1850 else { 1851 PMD_DRV_LOG(ERR, "Failed to program FDIR filter: unsupported fdir behavior."); 1852 return -EINVAL; 1853 } 1854 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); 1858 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); 1863 1864 fdirdp->dtype_cmd_cntindex |= 1865 rte_cpu_to_le_32(I40E_TXD_FLTR_QW1_CNT_ENA_MASK); 1866 fdirdp->dtype_cmd_cntindex |= 1867 rte_cpu_to_le_32( 1868 ((uint32_t)pf->fdir.match_counter_index << 1869 I40E_TXD_FLTR_QW1_CNTINDEX_SHIFT) & 1870 I40E_TXD_FLTR_QW1_CNTINDEX_MASK); 1871 1872 fdirdp->fd_id = rte_cpu_to_le_32(filter->soft_id); 1873 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; 1880 1881 txdp->cmd_type_offset_bsz = 1882 i40e_build_ctob(td_cmd, 0, I40E_FDIR_PKT_LEN, 0); 1883 1884 txq->tx_tail += 2; /* set 2 descriptors above, fdirdp and txdp */ 1885 if (txq->tx_tail >= txq->nb_tx_desc) 1886 txq->tx_tail = 0; 1887 /* Update the tx tail register */ 1888 rte_wmb(); 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)) 1894 break; 1895 rte_delay_us(1); 1896 } 1897 if (i >= I40E_FDIR_MAX_WAIT_US) { 1898 PMD_DRV_LOG(ERR, 1899 "Failed to program FDIR filter: time out to get DD on tx queue."); 1900 return -ETIMEDOUT; 1901 } 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) { 1905 PMD_DRV_LOG(ERR, 1906 "Failed to program FDIR filter: programming status reported."); 1907 return -ETIMEDOUT; 1908 } 1909 1910 return 0; 1911 } 1912 1913 /* 1914 * i40e_fdir_flush - clear all filters of Flow Director table 1915 * @pf: board private structure 1916 */ 1917 int 1918 i40e_fdir_flush(struct rte_eth_dev *dev) 1919 { 1920 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); 1921 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 1922 uint32_t reg; 1923 uint16_t guarant_cnt, best_cnt; 1924 uint16_t i; 1925 1926 I40E_WRITE_REG(hw, I40E_PFQF_CTL_1, I40E_PFQF_CTL_1_CLEARFDTABLE_MASK); 1927 I40E_WRITE_FLUSH(hw); 1928 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)) 1933 break; 1934 } 1935 if (i >= I40E_FDIR_FLUSH_RETRY) { 1936 PMD_DRV_LOG(ERR, "FD table did not flush, may need more time."); 1937 return -ETIMEDOUT; 1938 } 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."); 1947 return -ENOSYS; 1948 } else 1949 PMD_DRV_LOG(INFO, "FD table Flush success."); 1950 return 0; 1951 } 1952 1953 static inline void 1954 i40e_fdir_info_get_flex_set(struct i40e_pf *pf, 1955 struct rte_eth_flex_payload_cfg *flex_set, 1956 uint16_t *num) 1957 { 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; 1962 1963 for (layer_idx = I40E_FLXPLD_L2_IDX; 1964 layer_idx <= I40E_FLXPLD_L4_IDX; 1965 layer_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; 1972 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) 1977 continue; 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; 1983 } 1984 (*num)++; 1985 ptr++; 1986 } 1987 } 1988 1989 static inline void 1990 i40e_fdir_info_get_flex_mask(struct i40e_pf *pf, 1991 struct rte_eth_fdir_flex_mask *flex_mask, 1992 uint16_t *num) 1993 { 1994 struct i40e_fdir_flex_mask *mask; 1995 struct rte_eth_fdir_flex_mask *ptr = flex_mask; 1996 uint16_t flow_type; 1997 uint8_t i, j; 1998 uint16_t off_bytes, mask_tmp; 1999 2000 for (i = I40E_FILTER_PCTYPE_NONF_IPV4_UDP; 2001 i <= I40E_FILTER_PCTYPE_L2_PAYLOAD; 2002 i++) { 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) 2007 continue; 2008 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; 2013 } else { 2014 ptr->mask[j * sizeof(uint16_t)] = 0x0; 2015 ptr->mask[j * sizeof(uint16_t) + 1] = 0x0; 2016 } 2017 } 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); 2023 } 2024 ptr->flow_type = flow_type; 2025 ptr++; 2026 (*num)++; 2027 } 2028 } 2029 2030 /* 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. 2035 */ 2036 static void 2037 i40e_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir) 2038 { 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; 2043 2044 if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT) 2045 fdir->mode = RTE_FDIR_MODE_PERFECT; 2046 else 2047 fdir->mode = RTE_FDIR_MODE_NONE; 2048 2049 fdir->guarant_spc = 2050 (uint32_t)hw->func_caps.fd_filters_guaranteed; 2051 fdir->best_spc = 2052 (uint32_t)hw->func_caps.fd_filters_best_effort; 2053 fdir->max_flexpayload = I40E_FDIR_MAX_FLEX_LEN; 2054 fdir->flow_types_mask[0] = I40E_FDIR_FLOWS; 2055 fdir->flex_payload_unit = sizeof(uint16_t); 2056 fdir->flex_bitmask_unit = sizeof(uint16_t); 2057 fdir->max_flex_payload_segment_num = I40E_MAX_FLXPLD_FIED; 2058 fdir->flex_payload_limit = I40E_MAX_FLX_SOURCE_OFF; 2059 fdir->max_flex_bitmask_num = I40E_FDIR_BITMASK_NUM_WORD; 2060 2061 i40e_fdir_info_get_flex_set(pf, 2062 fdir->flex_conf.flex_set, 2063 &num_flex_set); 2064 i40e_fdir_info_get_flex_mask(pf, 2065 fdir->flex_conf.flex_mask, 2066 &num_flex_mask); 2067 2068 fdir->flex_conf.nb_payloads = num_flex_set; 2069 fdir->flex_conf.nb_flexmasks = num_flex_mask; 2070 } 2071 2072 /* 2073 * i40e_fdir_stat_get - get statistics of Flow Director 2074 * @pf: ethernet device to get info from 2075 * @stat: a pointer to a structure of type *rte_eth_fdir_stats* to be filled with 2076 * the flow director statistics. 2077 */ 2078 static void 2079 i40e_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *stat) 2080 { 2081 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); 2082 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 2083 uint32_t fdstat; 2084 2085 fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT); 2086 stat->guarant_cnt = 2087 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> 2088 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); 2089 stat->best_cnt = 2090 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> 2091 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); 2092 } 2093 2094 static int 2095 i40e_fdir_filter_set(struct rte_eth_dev *dev, 2096 struct rte_eth_fdir_filter_info *info) 2097 { 2098 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); 2099 int ret = 0; 2100 2101 if (!info) { 2102 PMD_DRV_LOG(ERR, "Invalid pointer"); 2103 return -EFAULT; 2104 } 2105 2106 switch (info->info_type) { 2107 case RTE_ETH_FDIR_FILTER_INPUT_SET_SELECT: 2108 ret = i40e_fdir_filter_inset_select(pf, 2109 &(info->info.input_set_conf)); 2110 break; 2111 default: 2112 PMD_DRV_LOG(ERR, "FD filter info type (%d) not supported", 2113 info->info_type); 2114 return -EINVAL; 2115 } 2116 2117 return ret; 2118 } 2119 2120 /* 2121 * i40e_fdir_ctrl_func - deal with all operations on flow director. 2122 * @pf: board private structure 2123 * @filter_op:operation will be taken. 2124 * @arg: a pointer to specific structure corresponding to the filter_op 2125 */ 2126 int 2127 i40e_fdir_ctrl_func(struct rte_eth_dev *dev, 2128 enum rte_filter_op filter_op, 2129 void *arg) 2130 { 2131 struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private); 2132 int ret = 0; 2133 2134 if ((pf->flags & I40E_FLAG_FDIR) == 0) 2135 return -ENOTSUP; 2136 2137 if (filter_op == RTE_ETH_FILTER_NOP) 2138 return 0; 2139 2140 if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 2141 return -EINVAL; 2142 2143 switch (filter_op) { 2144 case RTE_ETH_FILTER_ADD: 2145 ret = i40e_add_del_fdir_filter(dev, 2146 (struct rte_eth_fdir_filter *)arg, 2147 TRUE); 2148 break; 2149 case RTE_ETH_FILTER_DELETE: 2150 ret = i40e_add_del_fdir_filter(dev, 2151 (struct rte_eth_fdir_filter *)arg, 2152 FALSE); 2153 break; 2154 case RTE_ETH_FILTER_FLUSH: 2155 ret = i40e_fdir_flush(dev); 2156 break; 2157 case RTE_ETH_FILTER_INFO: 2158 i40e_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg); 2159 break; 2160 case RTE_ETH_FILTER_SET: 2161 ret = i40e_fdir_filter_set(dev, 2162 (struct rte_eth_fdir_filter_info *)arg); 2163 break; 2164 case RTE_ETH_FILTER_STATS: 2165 i40e_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg); 2166 break; 2167 default: 2168 PMD_DRV_LOG(ERR, "unknown operation %u.", filter_op); 2169 ret = -EINVAL; 2170 break; 2171 } 2172 return ret; 2173 } 2174 2175 /* Restore flow director filter */ 2176 void 2177 i40e_fdir_filter_restore(struct i40e_pf *pf) 2178 { 2179 struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(pf->main_vsi); 2180 struct i40e_fdir_filter_list *fdir_list = &pf->fdir.fdir_list; 2181 struct i40e_fdir_filter *f; 2182 struct i40e_hw *hw = I40E_PF_TO_HW(pf); 2183 uint32_t fdstat; 2184 uint32_t guarant_cnt; /**< Number of filters in guaranteed spaces. */ 2185 uint32_t best_cnt; /**< Number of filters in best effort spaces. */ 2186 2187 TAILQ_FOREACH(f, fdir_list, rules) 2188 i40e_flow_add_del_fdir_filter(dev, &f->fdir, TRUE); 2189 2190 fdstat = I40E_READ_REG(hw, I40E_PFQF_FDSTAT); 2191 guarant_cnt = 2192 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK) >> 2193 I40E_PFQF_FDSTAT_GUARANT_CNT_SHIFT); 2194 best_cnt = 2195 (uint32_t)((fdstat & I40E_PFQF_FDSTAT_BEST_CNT_MASK) >> 2196 I40E_PFQF_FDSTAT_BEST_CNT_SHIFT); 2197 2198 PMD_DRV_LOG(INFO, "FDIR: Guarant count: %d, Best count: %d", 2199 guarant_cnt, best_cnt); 2200 } 2201