1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2015 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdarg.h> 8 #include <errno.h> 9 #include <sys/queue.h> 10 11 #include <rte_interrupts.h> 12 #include <rte_log.h> 13 #include <rte_debug.h> 14 #include <rte_pci.h> 15 #include <rte_vxlan.h> 16 #include <rte_ethdev_driver.h> 17 #include <rte_malloc.h> 18 19 #include "ixgbe_logs.h" 20 #include "base/ixgbe_api.h" 21 #include "base/ixgbe_common.h" 22 #include "ixgbe_ethdev.h" 23 24 /* To get PBALLOC (Packet Buffer Allocation) bits from FDIRCTRL value */ 25 #define FDIRCTRL_PBALLOC_MASK 0x03 26 27 /* For calculating memory required for FDIR filters */ 28 #define PBALLOC_SIZE_SHIFT 15 29 30 /* Number of bits used to mask bucket hash for different pballoc sizes */ 31 #define PERFECT_BUCKET_64KB_HASH_MASK 0x07FF /* 11 bits */ 32 #define PERFECT_BUCKET_128KB_HASH_MASK 0x0FFF /* 12 bits */ 33 #define PERFECT_BUCKET_256KB_HASH_MASK 0x1FFF /* 13 bits */ 34 #define SIG_BUCKET_64KB_HASH_MASK 0x1FFF /* 13 bits */ 35 #define SIG_BUCKET_128KB_HASH_MASK 0x3FFF /* 14 bits */ 36 #define SIG_BUCKET_256KB_HASH_MASK 0x7FFF /* 15 bits */ 37 #define IXGBE_DEFAULT_FLEXBYTES_OFFSET 12 /* default flexbytes offset in bytes */ 38 #define IXGBE_FDIR_MAX_FLEX_LEN 2 /* len in bytes of flexbytes */ 39 #define IXGBE_MAX_FLX_SOURCE_OFF 62 40 #define IXGBE_FDIRCTRL_FLEX_MASK (0x1F << IXGBE_FDIRCTRL_FLEX_SHIFT) 41 #define IXGBE_FDIRCMD_CMD_INTERVAL_US 10 42 43 #define IXGBE_FDIR_FLOW_TYPES ( \ 44 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_UDP) | \ 45 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_TCP) | \ 46 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_SCTP) | \ 47 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV4_OTHER) | \ 48 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_UDP) | \ 49 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_TCP) | \ 50 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_SCTP) | \ 51 (1ULL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER)) 52 53 #define IPV6_ADDR_TO_MASK(ipaddr, ipv6m) do { \ 54 uint8_t ipv6_addr[16]; \ 55 uint8_t i; \ 56 rte_memcpy(ipv6_addr, (ipaddr), sizeof(ipv6_addr));\ 57 (ipv6m) = 0; \ 58 for (i = 0; i < sizeof(ipv6_addr); i++) { \ 59 if (ipv6_addr[i] == UINT8_MAX) \ 60 (ipv6m) |= 1 << i; \ 61 else if (ipv6_addr[i] != 0) { \ 62 PMD_DRV_LOG(ERR, " invalid IPv6 address mask."); \ 63 return -EINVAL; \ 64 } \ 65 } \ 66 } while (0) 67 68 #define IPV6_MASK_TO_ADDR(ipv6m, ipaddr) do { \ 69 uint8_t ipv6_addr[16]; \ 70 uint8_t i; \ 71 for (i = 0; i < sizeof(ipv6_addr); i++) { \ 72 if ((ipv6m) & (1 << i)) \ 73 ipv6_addr[i] = UINT8_MAX; \ 74 else \ 75 ipv6_addr[i] = 0; \ 76 } \ 77 rte_memcpy((ipaddr), ipv6_addr, sizeof(ipv6_addr));\ 78 } while (0) 79 80 #define IXGBE_FDIRIP6M_INNER_MAC_SHIFT 4 81 82 static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash); 83 static int fdir_set_input_mask(struct rte_eth_dev *dev, 84 const struct rte_eth_fdir_masks *input_mask); 85 static int fdir_set_input_mask_82599(struct rte_eth_dev *dev); 86 static int fdir_set_input_mask_x550(struct rte_eth_dev *dev); 87 static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, 88 const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl); 89 static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl); 90 static int ixgbe_fdir_filter_to_atr_input( 91 const struct rte_eth_fdir_filter *fdir_filter, 92 union ixgbe_atr_input *input, 93 enum rte_fdir_mode mode); 94 static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input, 95 uint32_t key); 96 static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input, 97 enum rte_fdir_pballoc_type pballoc); 98 static uint32_t atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, 99 enum rte_fdir_pballoc_type pballoc); 100 static int fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, 101 union ixgbe_atr_input *input, uint8_t queue, 102 uint32_t fdircmd, uint32_t fdirhash, 103 enum rte_fdir_mode mode); 104 static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw, 105 union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd, 106 uint32_t fdirhash); 107 static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev, 108 const struct rte_eth_fdir_filter *fdir_filter, 109 bool del, 110 bool update); 111 static int ixgbe_fdir_flush(struct rte_eth_dev *dev); 112 113 /** 114 * This function is based on ixgbe_fdir_enable_82599() in base/ixgbe_82599.c. 115 * It adds extra configuration of fdirctrl that is common for all filter types. 116 * 117 * Initialize Flow Director control registers 118 * @hw: pointer to hardware structure 119 * @fdirctrl: value to write to flow director control register 120 **/ 121 static int 122 fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl) 123 { 124 int i; 125 126 PMD_INIT_FUNC_TRACE(); 127 128 /* Prime the keys for hashing */ 129 IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY); 130 IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY); 131 132 /* 133 * Continue setup of fdirctrl register bits: 134 * Set the maximum length per hash bucket to 0xA filters 135 * Send interrupt when 64 filters are left 136 */ 137 fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) | 138 (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT); 139 140 /* 141 * Poll init-done after we write the register. Estimated times: 142 * 10G: PBALLOC = 11b, timing is 60us 143 * 1G: PBALLOC = 11b, timing is 600us 144 * 100M: PBALLOC = 11b, timing is 6ms 145 * 146 * Multiple these timings by 4 if under full Rx load 147 * 148 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for 149 * 1 msec per poll time. If we're at line rate and drop to 100M, then 150 * this might not finish in our poll time, but we can live with that 151 * for now. 152 */ 153 IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); 154 IXGBE_WRITE_FLUSH(hw); 155 for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { 156 if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & 157 IXGBE_FDIRCTRL_INIT_DONE) 158 break; 159 msec_delay(1); 160 } 161 162 if (i >= IXGBE_FDIR_INIT_DONE_POLL) { 163 PMD_INIT_LOG(ERR, "Flow Director poll time exceeded during enabling!"); 164 return -ETIMEDOUT; 165 } 166 return 0; 167 } 168 169 /* 170 * Set appropriate bits in fdirctrl for: variable reporting levels, moving 171 * flexbytes matching field, and drop queue (only for perfect matching mode). 172 */ 173 static inline int 174 configure_fdir_flags(const struct rte_fdir_conf *conf, uint32_t *fdirctrl) 175 { 176 *fdirctrl = 0; 177 178 switch (conf->pballoc) { 179 case RTE_FDIR_PBALLOC_64K: 180 /* 8k - 1 signature filters */ 181 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K; 182 break; 183 case RTE_FDIR_PBALLOC_128K: 184 /* 16k - 1 signature filters */ 185 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K; 186 break; 187 case RTE_FDIR_PBALLOC_256K: 188 /* 32k - 1 signature filters */ 189 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K; 190 break; 191 default: 192 /* bad value */ 193 PMD_INIT_LOG(ERR, "Invalid fdir_conf->pballoc value"); 194 return -EINVAL; 195 }; 196 197 /* status flags: write hash & swindex in the rx descriptor */ 198 switch (conf->status) { 199 case RTE_FDIR_NO_REPORT_STATUS: 200 /* do nothing, default mode */ 201 break; 202 case RTE_FDIR_REPORT_STATUS: 203 /* report status when the packet matches a fdir rule */ 204 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS; 205 break; 206 case RTE_FDIR_REPORT_STATUS_ALWAYS: 207 /* always report status */ 208 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS; 209 break; 210 default: 211 /* bad value */ 212 PMD_INIT_LOG(ERR, "Invalid fdir_conf->status value"); 213 return -EINVAL; 214 }; 215 216 *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) << 217 IXGBE_FDIRCTRL_FLEX_SHIFT; 218 219 if (conf->mode >= RTE_FDIR_MODE_PERFECT && 220 conf->mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) { 221 *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH; 222 *fdirctrl |= (conf->drop_queue << IXGBE_FDIRCTRL_DROP_Q_SHIFT); 223 if (conf->mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) 224 *fdirctrl |= (IXGBE_FDIRCTRL_FILTERMODE_MACVLAN 225 << IXGBE_FDIRCTRL_FILTERMODE_SHIFT); 226 else if (conf->mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 227 *fdirctrl |= (IXGBE_FDIRCTRL_FILTERMODE_CLOUD 228 << IXGBE_FDIRCTRL_FILTERMODE_SHIFT); 229 } 230 231 return 0; 232 } 233 234 /** 235 * Reverse the bits in FDIR registers that store 2 x 16 bit masks. 236 * 237 * @hi_dword: Bits 31:16 mask to be bit swapped. 238 * @lo_dword: Bits 15:0 mask to be bit swapped. 239 * 240 * Flow director uses several registers to store 2 x 16 bit masks with the 241 * bits reversed such as FDIRTCPM, FDIRUDPM. The LS bit of the 242 * mask affects the MS bit/byte of the target. This function reverses the 243 * bits in these masks. 244 * **/ 245 static inline uint32_t 246 reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t lo_dword) 247 { 248 uint32_t mask = hi_dword << 16; 249 250 mask |= lo_dword; 251 mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1); 252 mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2); 253 mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4); 254 return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8); 255 } 256 257 /* 258 * This references ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, 259 * but makes use of the rte_fdir_masks structure to see which bits to set. 260 */ 261 static int 262 fdir_set_input_mask_82599(struct rte_eth_dev *dev) 263 { 264 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 265 struct ixgbe_hw_fdir_info *info = 266 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 267 /* 268 * mask VM pool and DIPv6 since there are currently not supported 269 * mask FLEX byte, it will be set in flex_conf 270 */ 271 uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6; 272 uint32_t fdirtcpm; /* TCP source and destination port masks. */ 273 uint32_t fdiripv6m; /* IPv6 source and destination masks. */ 274 volatile uint32_t *reg; 275 276 PMD_INIT_FUNC_TRACE(); 277 278 /* 279 * Program the relevant mask registers. If src/dst_port or src/dst_addr 280 * are zero, then assume a full mask for that field. Also assume that 281 * a VLAN of 0 is unspecified, so mask that out as well. L4type 282 * cannot be masked out in this implementation. 283 */ 284 if (info->mask.dst_port_mask == 0 && info->mask.src_port_mask == 0) 285 /* use the L4 protocol mask for raw IPv4/IPv6 traffic */ 286 fdirm |= IXGBE_FDIRM_L4P; 287 288 if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0x0FFF)) 289 /* mask VLAN Priority */ 290 fdirm |= IXGBE_FDIRM_VLANP; 291 else if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0xE000)) 292 /* mask VLAN ID */ 293 fdirm |= IXGBE_FDIRM_VLANID; 294 else if (info->mask.vlan_tci_mask == 0) 295 /* mask VLAN ID and Priority */ 296 fdirm |= IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP; 297 else if (info->mask.vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) { 298 PMD_INIT_LOG(ERR, "invalid vlan_tci_mask"); 299 return -EINVAL; 300 } 301 302 /* flex byte mask */ 303 if (info->mask.flex_bytes_mask == 0) 304 fdirm |= IXGBE_FDIRM_FLEX; 305 306 IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); 307 308 /* store the TCP/UDP port masks, bit reversed from port layout */ 309 fdirtcpm = reverse_fdir_bitmasks( 310 rte_be_to_cpu_16(info->mask.dst_port_mask), 311 rte_be_to_cpu_16(info->mask.src_port_mask)); 312 313 /* write all the same so that UDP, TCP and SCTP use the same mask 314 * (little-endian) 315 */ 316 IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm); 317 IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm); 318 IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm); 319 320 /* Store source and destination IPv4 masks (big-endian), 321 * can not use IXGBE_WRITE_REG. 322 */ 323 reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRSIP4M); 324 *reg = ~(info->mask.src_ipv4_mask); 325 reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRDIP4M); 326 *reg = ~(info->mask.dst_ipv4_mask); 327 328 if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_SIGNATURE) { 329 /* 330 * Store source and destination IPv6 masks (bit reversed) 331 */ 332 fdiripv6m = (info->mask.dst_ipv6_mask << 16) | 333 info->mask.src_ipv6_mask; 334 335 IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, ~fdiripv6m); 336 } 337 338 return IXGBE_SUCCESS; 339 } 340 341 /* 342 * This references ixgbe_fdir_set_input_mask_82599() in base/ixgbe_82599.c, 343 * but makes use of the rte_fdir_masks structure to see which bits to set. 344 */ 345 static int 346 fdir_set_input_mask_x550(struct rte_eth_dev *dev) 347 { 348 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 349 struct ixgbe_hw_fdir_info *info = 350 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 351 /* mask VM pool and DIPv6 since there are currently not supported 352 * mask FLEX byte, it will be set in flex_conf 353 */ 354 uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6 | 355 IXGBE_FDIRM_FLEX; 356 uint32_t fdiripv6m; 357 enum rte_fdir_mode mode = dev->data->dev_conf.fdir_conf.mode; 358 uint16_t mac_mask; 359 360 PMD_INIT_FUNC_TRACE(); 361 362 /* set the default UDP port for VxLAN */ 363 if (mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 364 IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, RTE_VXLAN_DEFAULT_PORT); 365 366 /* some bits must be set for mac vlan or tunnel mode */ 367 fdirm |= IXGBE_FDIRM_L4P | IXGBE_FDIRM_L3P; 368 369 if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0x0FFF)) 370 /* mask VLAN Priority */ 371 fdirm |= IXGBE_FDIRM_VLANP; 372 else if (info->mask.vlan_tci_mask == rte_cpu_to_be_16(0xE000)) 373 /* mask VLAN ID */ 374 fdirm |= IXGBE_FDIRM_VLANID; 375 else if (info->mask.vlan_tci_mask == 0) 376 /* mask VLAN ID and Priority */ 377 fdirm |= IXGBE_FDIRM_VLANID | IXGBE_FDIRM_VLANP; 378 else if (info->mask.vlan_tci_mask != rte_cpu_to_be_16(0xEFFF)) { 379 PMD_INIT_LOG(ERR, "invalid vlan_tci_mask"); 380 return -EINVAL; 381 } 382 383 IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); 384 385 fdiripv6m = ((u32)0xFFFFU << IXGBE_FDIRIP6M_DIPM_SHIFT); 386 fdiripv6m |= IXGBE_FDIRIP6M_ALWAYS_MASK; 387 if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) 388 fdiripv6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE | 389 IXGBE_FDIRIP6M_TNI_VNI; 390 391 if (mode == RTE_FDIR_MODE_PERFECT_TUNNEL) { 392 fdiripv6m |= IXGBE_FDIRIP6M_INNER_MAC; 393 mac_mask = info->mask.mac_addr_byte_mask & 394 (IXGBE_FDIRIP6M_INNER_MAC >> 395 IXGBE_FDIRIP6M_INNER_MAC_SHIFT); 396 fdiripv6m &= ~((mac_mask << IXGBE_FDIRIP6M_INNER_MAC_SHIFT) & 397 IXGBE_FDIRIP6M_INNER_MAC); 398 399 switch (info->mask.tunnel_type_mask) { 400 case 0: 401 /* Mask turnnel type */ 402 fdiripv6m |= IXGBE_FDIRIP6M_TUNNEL_TYPE; 403 break; 404 case 1: 405 break; 406 default: 407 PMD_INIT_LOG(ERR, "invalid tunnel_type_mask"); 408 return -EINVAL; 409 } 410 411 switch (rte_be_to_cpu_32(info->mask.tunnel_id_mask)) { 412 case 0x0: 413 /* Mask vxlan id */ 414 fdiripv6m |= IXGBE_FDIRIP6M_TNI_VNI; 415 break; 416 case 0x00FFFFFF: 417 fdiripv6m |= IXGBE_FDIRIP6M_TNI_VNI_24; 418 break; 419 case 0xFFFFFFFF: 420 break; 421 default: 422 PMD_INIT_LOG(ERR, "invalid tunnel_id_mask"); 423 return -EINVAL; 424 } 425 } 426 427 IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, fdiripv6m); 428 IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xFFFFFFFF); 429 IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xFFFFFFFF); 430 IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, 0xFFFFFFFF); 431 IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xFFFFFFFF); 432 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xFFFFFFFF); 433 434 return IXGBE_SUCCESS; 435 } 436 437 static int 438 ixgbe_fdir_store_input_mask_82599(struct rte_eth_dev *dev, 439 const struct rte_eth_fdir_masks *input_mask) 440 { 441 struct ixgbe_hw_fdir_info *info = 442 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 443 uint16_t dst_ipv6m = 0; 444 uint16_t src_ipv6m = 0; 445 446 memset(&info->mask, 0, sizeof(struct ixgbe_hw_fdir_mask)); 447 info->mask.vlan_tci_mask = input_mask->vlan_tci_mask; 448 info->mask.src_port_mask = input_mask->src_port_mask; 449 info->mask.dst_port_mask = input_mask->dst_port_mask; 450 info->mask.src_ipv4_mask = input_mask->ipv4_mask.src_ip; 451 info->mask.dst_ipv4_mask = input_mask->ipv4_mask.dst_ip; 452 IPV6_ADDR_TO_MASK(input_mask->ipv6_mask.src_ip, src_ipv6m); 453 IPV6_ADDR_TO_MASK(input_mask->ipv6_mask.dst_ip, dst_ipv6m); 454 info->mask.src_ipv6_mask = src_ipv6m; 455 info->mask.dst_ipv6_mask = dst_ipv6m; 456 457 return IXGBE_SUCCESS; 458 } 459 460 static int 461 ixgbe_fdir_store_input_mask_x550(struct rte_eth_dev *dev, 462 const struct rte_eth_fdir_masks *input_mask) 463 { 464 struct ixgbe_hw_fdir_info *info = 465 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 466 467 memset(&info->mask, 0, sizeof(struct ixgbe_hw_fdir_mask)); 468 info->mask.vlan_tci_mask = input_mask->vlan_tci_mask; 469 info->mask.mac_addr_byte_mask = input_mask->mac_addr_byte_mask; 470 info->mask.tunnel_type_mask = input_mask->tunnel_type_mask; 471 info->mask.tunnel_id_mask = input_mask->tunnel_id_mask; 472 473 return IXGBE_SUCCESS; 474 } 475 476 static int 477 ixgbe_fdir_store_input_mask(struct rte_eth_dev *dev, 478 const struct rte_eth_fdir_masks *input_mask) 479 { 480 enum rte_fdir_mode mode = dev->data->dev_conf.fdir_conf.mode; 481 482 if (mode >= RTE_FDIR_MODE_SIGNATURE && 483 mode <= RTE_FDIR_MODE_PERFECT) 484 return ixgbe_fdir_store_input_mask_82599(dev, input_mask); 485 else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN && 486 mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 487 return ixgbe_fdir_store_input_mask_x550(dev, input_mask); 488 489 PMD_DRV_LOG(ERR, "Not supported fdir mode - %d!", mode); 490 return -ENOTSUP; 491 } 492 493 int 494 ixgbe_fdir_set_input_mask(struct rte_eth_dev *dev) 495 { 496 enum rte_fdir_mode mode = dev->data->dev_conf.fdir_conf.mode; 497 498 if (mode >= RTE_FDIR_MODE_SIGNATURE && 499 mode <= RTE_FDIR_MODE_PERFECT) 500 return fdir_set_input_mask_82599(dev); 501 else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN && 502 mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 503 return fdir_set_input_mask_x550(dev); 504 505 PMD_DRV_LOG(ERR, "Not supported fdir mode - %d!", mode); 506 return -ENOTSUP; 507 } 508 509 int 510 ixgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev, 511 uint16_t offset) 512 { 513 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 514 uint32_t fdirctrl; 515 int i; 516 517 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); 518 519 fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK; 520 fdirctrl |= ((offset >> 1) /* convert to word offset */ 521 << IXGBE_FDIRCTRL_FLEX_SHIFT); 522 523 IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl); 524 IXGBE_WRITE_FLUSH(hw); 525 for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) { 526 if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & 527 IXGBE_FDIRCTRL_INIT_DONE) 528 break; 529 msec_delay(1); 530 } 531 return 0; 532 } 533 534 static int 535 fdir_set_input_mask(struct rte_eth_dev *dev, 536 const struct rte_eth_fdir_masks *input_mask) 537 { 538 int ret; 539 540 ret = ixgbe_fdir_store_input_mask(dev, input_mask); 541 if (ret) 542 return ret; 543 544 return ixgbe_fdir_set_input_mask(dev); 545 } 546 547 /* 548 * ixgbe_check_fdir_flex_conf -check if the flex payload and mask configuration 549 * arguments are valid 550 */ 551 static int 552 ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev, 553 const struct rte_eth_fdir_flex_conf *conf, uint32_t *fdirctrl) 554 { 555 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 556 struct ixgbe_hw_fdir_info *info = 557 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 558 const struct rte_eth_flex_payload_cfg *flex_cfg; 559 const struct rte_eth_fdir_flex_mask *flex_mask; 560 uint32_t fdirm; 561 uint16_t flexbytes = 0; 562 uint16_t i; 563 564 fdirm = IXGBE_READ_REG(hw, IXGBE_FDIRM); 565 566 if (conf == NULL) { 567 PMD_DRV_LOG(ERR, "NULL pointer."); 568 return -EINVAL; 569 } 570 571 for (i = 0; i < conf->nb_payloads; i++) { 572 flex_cfg = &conf->flex_set[i]; 573 if (flex_cfg->type != RTE_ETH_RAW_PAYLOAD) { 574 PMD_DRV_LOG(ERR, "unsupported payload type."); 575 return -EINVAL; 576 } 577 if (((flex_cfg->src_offset[0] & 0x1) == 0) && 578 (flex_cfg->src_offset[1] == flex_cfg->src_offset[0] + 1) && 579 (flex_cfg->src_offset[0] <= IXGBE_MAX_FLX_SOURCE_OFF)) { 580 *fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK; 581 *fdirctrl |= 582 (flex_cfg->src_offset[0] / sizeof(uint16_t)) << 583 IXGBE_FDIRCTRL_FLEX_SHIFT; 584 } else { 585 PMD_DRV_LOG(ERR, "invalid flexbytes arguments."); 586 return -EINVAL; 587 } 588 } 589 590 for (i = 0; i < conf->nb_flexmasks; i++) { 591 flex_mask = &conf->flex_mask[i]; 592 if (flex_mask->flow_type != RTE_ETH_FLOW_UNKNOWN) { 593 PMD_DRV_LOG(ERR, "flexmask should be set globally."); 594 return -EINVAL; 595 } 596 flexbytes = (uint16_t)(((flex_mask->mask[0] << 8) & 0xFF00) | 597 ((flex_mask->mask[1]) & 0xFF)); 598 if (flexbytes == UINT16_MAX) 599 fdirm &= ~IXGBE_FDIRM_FLEX; 600 else if (flexbytes != 0) { 601 /* IXGBE_FDIRM_FLEX is set by default when set mask */ 602 PMD_DRV_LOG(ERR, " invalid flexbytes mask arguments."); 603 return -EINVAL; 604 } 605 } 606 IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm); 607 info->mask.flex_bytes_mask = flexbytes ? UINT16_MAX : 0; 608 info->flex_bytes_offset = (uint8_t)((*fdirctrl & 609 IXGBE_FDIRCTRL_FLEX_MASK) >> 610 IXGBE_FDIRCTRL_FLEX_SHIFT); 611 return 0; 612 } 613 614 int 615 ixgbe_fdir_configure(struct rte_eth_dev *dev) 616 { 617 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 618 int err; 619 uint32_t fdirctrl, pbsize; 620 int i; 621 enum rte_fdir_mode mode = dev->data->dev_conf.fdir_conf.mode; 622 623 PMD_INIT_FUNC_TRACE(); 624 625 if (hw->mac.type != ixgbe_mac_82599EB && 626 hw->mac.type != ixgbe_mac_X540 && 627 hw->mac.type != ixgbe_mac_X550 && 628 hw->mac.type != ixgbe_mac_X550EM_x && 629 hw->mac.type != ixgbe_mac_X550EM_a) 630 return -ENOSYS; 631 632 /* x550 supports mac-vlan and tunnel mode but other NICs not */ 633 if (hw->mac.type != ixgbe_mac_X550 && 634 hw->mac.type != ixgbe_mac_X550EM_x && 635 hw->mac.type != ixgbe_mac_X550EM_a && 636 mode != RTE_FDIR_MODE_SIGNATURE && 637 mode != RTE_FDIR_MODE_PERFECT) 638 return -ENOSYS; 639 640 err = configure_fdir_flags(&dev->data->dev_conf.fdir_conf, &fdirctrl); 641 if (err) 642 return err; 643 644 /* 645 * Before enabling Flow Director, the Rx Packet Buffer size 646 * must be reduced. The new value is the current size minus 647 * flow director memory usage size. 648 */ 649 pbsize = (1 << (PBALLOC_SIZE_SHIFT + (fdirctrl & FDIRCTRL_PBALLOC_MASK))); 650 IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 651 (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize)); 652 653 /* 654 * The defaults in the HW for RX PB 1-7 are not zero and so should be 655 * initialized to zero for non DCB mode otherwise actual total RX PB 656 * would be bigger than programmed and filter space would run into 657 * the PB 0 region. 658 */ 659 for (i = 1; i < 8; i++) 660 IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0); 661 662 err = fdir_set_input_mask(dev, &dev->data->dev_conf.fdir_conf.mask); 663 if (err < 0) { 664 PMD_INIT_LOG(ERR, " Error on setting FD mask"); 665 return err; 666 } 667 err = ixgbe_set_fdir_flex_conf(dev, 668 &dev->data->dev_conf.fdir_conf.flex_conf, &fdirctrl); 669 if (err < 0) { 670 PMD_INIT_LOG(ERR, " Error on setting FD flexible arguments."); 671 return err; 672 } 673 674 err = fdir_enable_82599(hw, fdirctrl); 675 if (err < 0) { 676 PMD_INIT_LOG(ERR, " Error on enabling FD."); 677 return err; 678 } 679 return 0; 680 } 681 682 /* 683 * Convert DPDK rte_eth_fdir_filter struct to ixgbe_atr_input union that is used 684 * by the IXGBE driver code. 685 */ 686 static int 687 ixgbe_fdir_filter_to_atr_input(const struct rte_eth_fdir_filter *fdir_filter, 688 union ixgbe_atr_input *input, enum rte_fdir_mode mode) 689 { 690 input->formatted.vlan_id = fdir_filter->input.flow_ext.vlan_tci; 691 input->formatted.flex_bytes = (uint16_t)( 692 (fdir_filter->input.flow_ext.flexbytes[1] << 8 & 0xFF00) | 693 (fdir_filter->input.flow_ext.flexbytes[0] & 0xFF)); 694 695 switch (fdir_filter->input.flow_type) { 696 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 697 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4; 698 break; 699 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 700 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4; 701 break; 702 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: 703 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4; 704 break; 705 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 706 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4; 707 break; 708 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 709 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV6; 710 break; 711 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 712 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6; 713 break; 714 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: 715 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV6; 716 break; 717 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 718 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV6; 719 break; 720 default: 721 break; 722 } 723 724 switch (fdir_filter->input.flow_type) { 725 case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: 726 case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: 727 input->formatted.src_port = 728 fdir_filter->input.flow.udp4_flow.src_port; 729 input->formatted.dst_port = 730 fdir_filter->input.flow.udp4_flow.dst_port; 731 /* fall-through */ 732 /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/ 733 case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: 734 case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: 735 input->formatted.src_ip[0] = 736 fdir_filter->input.flow.ip4_flow.src_ip; 737 input->formatted.dst_ip[0] = 738 fdir_filter->input.flow.ip4_flow.dst_ip; 739 break; 740 741 case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: 742 case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: 743 input->formatted.src_port = 744 fdir_filter->input.flow.udp6_flow.src_port; 745 input->formatted.dst_port = 746 fdir_filter->input.flow.udp6_flow.dst_port; 747 /* fall-through */ 748 /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/ 749 case RTE_ETH_FLOW_NONFRAG_IPV6_SCTP: 750 case RTE_ETH_FLOW_NONFRAG_IPV6_OTHER: 751 rte_memcpy(input->formatted.src_ip, 752 fdir_filter->input.flow.ipv6_flow.src_ip, 753 sizeof(input->formatted.src_ip)); 754 rte_memcpy(input->formatted.dst_ip, 755 fdir_filter->input.flow.ipv6_flow.dst_ip, 756 sizeof(input->formatted.dst_ip)); 757 break; 758 default: 759 break; 760 } 761 762 if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) { 763 rte_memcpy( 764 input->formatted.inner_mac, 765 fdir_filter->input.flow.mac_vlan_flow.mac_addr.addr_bytes, 766 sizeof(input->formatted.inner_mac)); 767 } else if (mode == RTE_FDIR_MODE_PERFECT_TUNNEL) { 768 rte_memcpy( 769 input->formatted.inner_mac, 770 fdir_filter->input.flow.tunnel_flow.mac_addr.addr_bytes, 771 sizeof(input->formatted.inner_mac)); 772 if (fdir_filter->input.flow.tunnel_flow.tunnel_type == 773 RTE_FDIR_TUNNEL_TYPE_VXLAN) 774 input->formatted.tunnel_type = 775 IXGBE_FDIR_VXLAN_TUNNEL_TYPE; 776 else if (fdir_filter->input.flow.tunnel_flow.tunnel_type == 777 RTE_FDIR_TUNNEL_TYPE_NVGRE) 778 input->formatted.tunnel_type = 779 IXGBE_FDIR_NVGRE_TUNNEL_TYPE; 780 else 781 PMD_DRV_LOG(ERR, " invalid tunnel type arguments."); 782 783 input->formatted.tni_vni = 784 fdir_filter->input.flow.tunnel_flow.tunnel_id >> 8; 785 } 786 787 return 0; 788 } 789 790 /* 791 * The below function is taken from the FreeBSD IXGBE drivers release 792 * 2.3.8. The only change is not to mask hash_result with IXGBE_ATR_HASH_MASK 793 * before returning, as the signature hash can use 16bits. 794 * 795 * The newer driver has optimised functions for calculating bucket and 796 * signature hashes. However they don't support IPv6 type packets for signature 797 * filters so are not used here. 798 * 799 * Note that the bkt_hash field in the ixgbe_atr_input structure is also never 800 * set. 801 * 802 * Compute the hashes for SW ATR 803 * @stream: input bitstream to compute the hash on 804 * @key: 32-bit hash key 805 **/ 806 static uint32_t 807 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input, 808 uint32_t key) 809 { 810 /* 811 * The algorithm is as follows: 812 * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350 813 * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n] 814 * and A[n] x B[n] is bitwise AND between same length strings 815 * 816 * K[n] is 16 bits, defined as: 817 * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15] 818 * for n modulo 32 < 15, K[n] = 819 * K[(n % 32:0) | (31:31 - (14 - (n % 32)))] 820 * 821 * S[n] is 16 bits, defined as: 822 * for n >= 15, S[n] = S[n:n - 15] 823 * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))] 824 * 825 * To simplify for programming, the algorithm is implemented 826 * in software this way: 827 * 828 * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0] 829 * 830 * for (i = 0; i < 352; i+=32) 831 * hi_hash_dword[31:0] ^= Stream[(i+31):i]; 832 * 833 * lo_hash_dword[15:0] ^= Stream[15:0]; 834 * lo_hash_dword[15:0] ^= hi_hash_dword[31:16]; 835 * lo_hash_dword[31:16] ^= hi_hash_dword[15:0]; 836 * 837 * hi_hash_dword[31:0] ^= Stream[351:320]; 838 * 839 * if (key[0]) 840 * hash[15:0] ^= Stream[15:0]; 841 * 842 * for (i = 0; i < 16; i++) { 843 * if (key[i]) 844 * hash[15:0] ^= lo_hash_dword[(i+15):i]; 845 * if (key[i + 16]) 846 * hash[15:0] ^= hi_hash_dword[(i+15):i]; 847 * } 848 * 849 */ 850 __be32 common_hash_dword = 0; 851 u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; 852 u32 hash_result = 0; 853 u8 i; 854 855 /* record the flow_vm_vlan bits as they are a key part to the hash */ 856 flow_vm_vlan = IXGBE_NTOHL(atr_input->dword_stream[0]); 857 858 /* generate common hash dword */ 859 for (i = 1; i <= 13; i++) 860 common_hash_dword ^= atr_input->dword_stream[i]; 861 862 hi_hash_dword = IXGBE_NTOHL(common_hash_dword); 863 864 /* low dword is word swapped version of common */ 865 lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); 866 867 /* apply flow ID/VM pool/VLAN ID bits to hash words */ 868 hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); 869 870 /* Process bits 0 and 16 */ 871 if (key & 0x0001) 872 hash_result ^= lo_hash_dword; 873 if (key & 0x00010000) 874 hash_result ^= hi_hash_dword; 875 876 /* 877 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to 878 * delay this because bit 0 of the stream should not be processed 879 * so we do not add the vlan until after bit 0 was processed 880 */ 881 lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); 882 883 884 /* process the remaining 30 bits in the key 2 bits at a time */ 885 for (i = 15; i; i--) { 886 if (key & (0x0001 << i)) 887 hash_result ^= lo_hash_dword >> i; 888 if (key & (0x00010000 << i)) 889 hash_result ^= hi_hash_dword >> i; 890 } 891 892 return hash_result; 893 } 894 895 static uint32_t 896 atr_compute_perfect_hash_82599(union ixgbe_atr_input *input, 897 enum rte_fdir_pballoc_type pballoc) 898 { 899 if (pballoc == RTE_FDIR_PBALLOC_256K) 900 return ixgbe_atr_compute_hash_82599(input, 901 IXGBE_ATR_BUCKET_HASH_KEY) & 902 PERFECT_BUCKET_256KB_HASH_MASK; 903 else if (pballoc == RTE_FDIR_PBALLOC_128K) 904 return ixgbe_atr_compute_hash_82599(input, 905 IXGBE_ATR_BUCKET_HASH_KEY) & 906 PERFECT_BUCKET_128KB_HASH_MASK; 907 else 908 return ixgbe_atr_compute_hash_82599(input, 909 IXGBE_ATR_BUCKET_HASH_KEY) & 910 PERFECT_BUCKET_64KB_HASH_MASK; 911 } 912 913 /** 914 * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete 915 * @hw: pointer to hardware structure 916 */ 917 static inline int 918 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, uint32_t *fdircmd) 919 { 920 int i; 921 922 for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) { 923 *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD); 924 if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK)) 925 return 0; 926 rte_delay_us(IXGBE_FDIRCMD_CMD_INTERVAL_US); 927 } 928 929 return -ETIMEDOUT; 930 } 931 932 /* 933 * Calculate the hash value needed for signature-match filters. In the FreeBSD 934 * driver, this is done by the optimised function 935 * ixgbe_atr_compute_sig_hash_82599(). However that can't be used here as it 936 * doesn't support calculating a hash for an IPv6 filter. 937 */ 938 static uint32_t 939 atr_compute_sig_hash_82599(union ixgbe_atr_input *input, 940 enum rte_fdir_pballoc_type pballoc) 941 { 942 uint32_t bucket_hash, sig_hash; 943 944 if (pballoc == RTE_FDIR_PBALLOC_256K) 945 bucket_hash = ixgbe_atr_compute_hash_82599(input, 946 IXGBE_ATR_BUCKET_HASH_KEY) & 947 SIG_BUCKET_256KB_HASH_MASK; 948 else if (pballoc == RTE_FDIR_PBALLOC_128K) 949 bucket_hash = ixgbe_atr_compute_hash_82599(input, 950 IXGBE_ATR_BUCKET_HASH_KEY) & 951 SIG_BUCKET_128KB_HASH_MASK; 952 else 953 bucket_hash = ixgbe_atr_compute_hash_82599(input, 954 IXGBE_ATR_BUCKET_HASH_KEY) & 955 SIG_BUCKET_64KB_HASH_MASK; 956 957 sig_hash = ixgbe_atr_compute_hash_82599(input, 958 IXGBE_ATR_SIGNATURE_HASH_KEY); 959 960 return (sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT) | bucket_hash; 961 } 962 963 /* 964 * This is based on ixgbe_fdir_write_perfect_filter_82599() in 965 * base/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register 966 * added, and IPv6 support also added. The hash value is also pre-calculated 967 * as the pballoc value is needed to do it. 968 */ 969 static int 970 fdir_write_perfect_filter_82599(struct ixgbe_hw *hw, 971 union ixgbe_atr_input *input, uint8_t queue, 972 uint32_t fdircmd, uint32_t fdirhash, 973 enum rte_fdir_mode mode) 974 { 975 uint32_t fdirport, fdirvlan; 976 u32 addr_low, addr_high; 977 u32 tunnel_type = 0; 978 int err = 0; 979 volatile uint32_t *reg; 980 981 if (mode == RTE_FDIR_MODE_PERFECT) { 982 /* record the IPv4 address (big-endian) 983 * can not use IXGBE_WRITE_REG. 984 */ 985 reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPSA); 986 *reg = input->formatted.src_ip[0]; 987 reg = IXGBE_PCI_REG_ADDR(hw, IXGBE_FDIRIPDA); 988 *reg = input->formatted.dst_ip[0]; 989 990 /* record source and destination port (little-endian)*/ 991 fdirport = IXGBE_NTOHS(input->formatted.dst_port); 992 fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT; 993 fdirport |= IXGBE_NTOHS(input->formatted.src_port); 994 IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport); 995 } else if (mode >= RTE_FDIR_MODE_PERFECT_MAC_VLAN && 996 mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) { 997 /* for mac vlan and tunnel modes */ 998 addr_low = ((u32)input->formatted.inner_mac[0] | 999 ((u32)input->formatted.inner_mac[1] << 8) | 1000 ((u32)input->formatted.inner_mac[2] << 16) | 1001 ((u32)input->formatted.inner_mac[3] << 24)); 1002 addr_high = ((u32)input->formatted.inner_mac[4] | 1003 ((u32)input->formatted.inner_mac[5] << 8)); 1004 1005 if (mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) { 1006 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low); 1007 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), addr_high); 1008 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), 0); 1009 } else { 1010 /* tunnel mode */ 1011 if (input->formatted.tunnel_type) 1012 tunnel_type = 0x80000000; 1013 tunnel_type |= addr_high; 1014 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), addr_low); 1015 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), tunnel_type); 1016 IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), 1017 input->formatted.tni_vni); 1018 } 1019 IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, 0); 1020 IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, 0); 1021 IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, 0); 1022 } 1023 1024 /* record vlan (little-endian) and flex_bytes(big-endian) */ 1025 fdirvlan = input->formatted.flex_bytes; 1026 fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT; 1027 fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id); 1028 IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan); 1029 1030 /* configure FDIRHASH register */ 1031 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 1032 1033 /* 1034 * flush all previous writes to make certain registers are 1035 * programmed prior to issuing the command 1036 */ 1037 IXGBE_WRITE_FLUSH(hw); 1038 1039 /* configure FDIRCMD register */ 1040 fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW | 1041 IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; 1042 fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; 1043 fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; 1044 fdircmd |= (uint32_t)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT; 1045 1046 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); 1047 1048 PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash); 1049 1050 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 1051 if (err < 0) 1052 PMD_DRV_LOG(ERR, "Timeout writing flow director filter."); 1053 1054 return err; 1055 } 1056 1057 /** 1058 * This function is based on ixgbe_atr_add_signature_filter_82599() in 1059 * base/ixgbe_82599.c, but uses a pre-calculated hash value. It also supports 1060 * setting extra fields in the FDIRCMD register, and removes the code that was 1061 * verifying the flow_type field. According to the documentation, a flow type of 1062 * 00 (i.e. not TCP, UDP, or SCTP) is not supported, however it appears to 1063 * work ok... 1064 * 1065 * Adds a signature hash filter 1066 * @hw: pointer to hardware structure 1067 * @input: unique input dword 1068 * @queue: queue index to direct traffic to 1069 * @fdircmd: any extra flags to set in fdircmd register 1070 * @fdirhash: pre-calculated hash value for the filter 1071 **/ 1072 static int 1073 fdir_add_signature_filter_82599(struct ixgbe_hw *hw, 1074 union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd, 1075 uint32_t fdirhash) 1076 { 1077 int err = 0; 1078 1079 PMD_INIT_FUNC_TRACE(); 1080 1081 /* configure FDIRCMD register */ 1082 fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW | 1083 IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN; 1084 fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT; 1085 fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT; 1086 1087 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 1088 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd); 1089 1090 PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash); 1091 1092 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 1093 if (err < 0) 1094 PMD_DRV_LOG(ERR, "Timeout writing flow director filter."); 1095 1096 return err; 1097 } 1098 1099 /* 1100 * This is based on ixgbe_fdir_erase_perfect_filter_82599() in 1101 * base/ixgbe_82599.c. It is modified to take in the hash as a parameter so 1102 * that it can be used for removing signature and perfect filters. 1103 */ 1104 static int 1105 fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash) 1106 { 1107 uint32_t fdircmd = 0; 1108 int err = 0; 1109 1110 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 1111 1112 /* flush hash to HW */ 1113 IXGBE_WRITE_FLUSH(hw); 1114 1115 /* Query if filter is present */ 1116 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT); 1117 1118 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 1119 if (err < 0) { 1120 PMD_INIT_LOG(ERR, "Timeout querying for flow director filter."); 1121 return err; 1122 } 1123 1124 /* if filter exists in hardware then remove it */ 1125 if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) { 1126 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash); 1127 IXGBE_WRITE_FLUSH(hw); 1128 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, 1129 IXGBE_FDIRCMD_CMD_REMOVE_FLOW); 1130 } 1131 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd); 1132 if (err < 0) 1133 PMD_INIT_LOG(ERR, "Timeout erasing flow director filter."); 1134 return err; 1135 1136 } 1137 1138 static inline struct ixgbe_fdir_filter * 1139 ixgbe_fdir_filter_lookup(struct ixgbe_hw_fdir_info *fdir_info, 1140 union ixgbe_atr_input *key) 1141 { 1142 int ret; 1143 1144 ret = rte_hash_lookup(fdir_info->hash_handle, (const void *)key); 1145 if (ret < 0) 1146 return NULL; 1147 1148 return fdir_info->hash_map[ret]; 1149 } 1150 1151 static inline int 1152 ixgbe_insert_fdir_filter(struct ixgbe_hw_fdir_info *fdir_info, 1153 struct ixgbe_fdir_filter *fdir_filter) 1154 { 1155 int ret; 1156 1157 ret = rte_hash_add_key(fdir_info->hash_handle, 1158 &fdir_filter->ixgbe_fdir); 1159 1160 if (ret < 0) { 1161 PMD_DRV_LOG(ERR, 1162 "Failed to insert fdir filter to hash table %d!", 1163 ret); 1164 return ret; 1165 } 1166 1167 fdir_info->hash_map[ret] = fdir_filter; 1168 1169 TAILQ_INSERT_TAIL(&fdir_info->fdir_list, fdir_filter, entries); 1170 1171 return 0; 1172 } 1173 1174 static inline int 1175 ixgbe_remove_fdir_filter(struct ixgbe_hw_fdir_info *fdir_info, 1176 union ixgbe_atr_input *key) 1177 { 1178 int ret; 1179 struct ixgbe_fdir_filter *fdir_filter; 1180 1181 ret = rte_hash_del_key(fdir_info->hash_handle, key); 1182 1183 if (ret < 0) { 1184 PMD_DRV_LOG(ERR, "No such fdir filter to delete %d!", ret); 1185 return ret; 1186 } 1187 1188 fdir_filter = fdir_info->hash_map[ret]; 1189 fdir_info->hash_map[ret] = NULL; 1190 1191 TAILQ_REMOVE(&fdir_info->fdir_list, fdir_filter, entries); 1192 rte_free(fdir_filter); 1193 1194 return 0; 1195 } 1196 1197 static int 1198 ixgbe_interpret_fdir_filter(struct rte_eth_dev *dev, 1199 const struct rte_eth_fdir_filter *fdir_filter, 1200 struct ixgbe_fdir_rule *rule) 1201 { 1202 enum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode; 1203 int err; 1204 1205 memset(rule, 0, sizeof(struct ixgbe_fdir_rule)); 1206 1207 err = ixgbe_fdir_filter_to_atr_input(fdir_filter, 1208 &rule->ixgbe_fdir, 1209 fdir_mode); 1210 if (err) 1211 return err; 1212 1213 rule->mode = fdir_mode; 1214 if (fdir_filter->action.behavior == RTE_ETH_FDIR_REJECT) 1215 rule->fdirflags = IXGBE_FDIRCMD_DROP; 1216 rule->queue = fdir_filter->action.rx_queue; 1217 rule->soft_id = fdir_filter->soft_id; 1218 1219 return 0; 1220 } 1221 1222 int 1223 ixgbe_fdir_filter_program(struct rte_eth_dev *dev, 1224 struct ixgbe_fdir_rule *rule, 1225 bool del, 1226 bool update) 1227 { 1228 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1229 uint32_t fdircmd_flags; 1230 uint32_t fdirhash; 1231 uint8_t queue; 1232 bool is_perfect = FALSE; 1233 int err; 1234 struct ixgbe_hw_fdir_info *info = 1235 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1236 enum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode; 1237 struct ixgbe_fdir_filter *node; 1238 bool add_node = FALSE; 1239 1240 if (fdir_mode == RTE_FDIR_MODE_NONE || 1241 fdir_mode != rule->mode) 1242 return -ENOTSUP; 1243 1244 /* 1245 * Sanity check for x550. 1246 * When adding a new filter with flow type set to IPv4, 1247 * the flow director mask should be configed before, 1248 * and the L4 protocol and ports are masked. 1249 */ 1250 if ((!del) && 1251 (hw->mac.type == ixgbe_mac_X550 || 1252 hw->mac.type == ixgbe_mac_X550EM_x || 1253 hw->mac.type == ixgbe_mac_X550EM_a) && 1254 (rule->ixgbe_fdir.formatted.flow_type == 1255 IXGBE_ATR_FLOW_TYPE_IPV4 || 1256 rule->ixgbe_fdir.formatted.flow_type == 1257 IXGBE_ATR_FLOW_TYPE_IPV6) && 1258 (info->mask.src_port_mask != 0 || 1259 info->mask.dst_port_mask != 0) && 1260 (rule->mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN && 1261 rule->mode != RTE_FDIR_MODE_PERFECT_TUNNEL)) { 1262 PMD_DRV_LOG(ERR, "By this device," 1263 " IPv4 is not supported without" 1264 " L4 protocol and ports masked!"); 1265 return -ENOTSUP; 1266 } 1267 1268 if (fdir_mode >= RTE_FDIR_MODE_PERFECT && 1269 fdir_mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 1270 is_perfect = TRUE; 1271 1272 if (is_perfect) { 1273 if (rule->ixgbe_fdir.formatted.flow_type & 1274 IXGBE_ATR_L4TYPE_IPV6_MASK) { 1275 PMD_DRV_LOG(ERR, "IPv6 is not supported in" 1276 " perfect mode!"); 1277 return -ENOTSUP; 1278 } 1279 fdirhash = atr_compute_perfect_hash_82599(&rule->ixgbe_fdir, 1280 dev->data->dev_conf.fdir_conf.pballoc); 1281 fdirhash |= rule->soft_id << 1282 IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT; 1283 } else 1284 fdirhash = atr_compute_sig_hash_82599(&rule->ixgbe_fdir, 1285 dev->data->dev_conf.fdir_conf.pballoc); 1286 1287 if (del) { 1288 err = ixgbe_remove_fdir_filter(info, &rule->ixgbe_fdir); 1289 if (err < 0) 1290 return err; 1291 1292 err = fdir_erase_filter_82599(hw, fdirhash); 1293 if (err < 0) 1294 PMD_DRV_LOG(ERR, "Fail to delete FDIR filter!"); 1295 else 1296 PMD_DRV_LOG(DEBUG, "Success to delete FDIR filter!"); 1297 return err; 1298 } 1299 /* add or update an fdir filter*/ 1300 fdircmd_flags = (update) ? IXGBE_FDIRCMD_FILTER_UPDATE : 0; 1301 if (rule->fdirflags & IXGBE_FDIRCMD_DROP) { 1302 if (is_perfect) { 1303 queue = dev->data->dev_conf.fdir_conf.drop_queue; 1304 fdircmd_flags |= IXGBE_FDIRCMD_DROP; 1305 } else { 1306 PMD_DRV_LOG(ERR, "Drop option is not supported in" 1307 " signature mode."); 1308 return -EINVAL; 1309 } 1310 } else if (rule->queue < IXGBE_MAX_RX_QUEUE_NUM) 1311 queue = (uint8_t)rule->queue; 1312 else 1313 return -EINVAL; 1314 1315 node = ixgbe_fdir_filter_lookup(info, &rule->ixgbe_fdir); 1316 if (node) { 1317 if (update) { 1318 node->fdirflags = fdircmd_flags; 1319 node->fdirhash = fdirhash; 1320 node->queue = queue; 1321 } else { 1322 PMD_DRV_LOG(ERR, "Conflict with existing fdir filter!"); 1323 return -EINVAL; 1324 } 1325 } else { 1326 add_node = TRUE; 1327 node = rte_zmalloc("ixgbe_fdir", 1328 sizeof(struct ixgbe_fdir_filter), 1329 0); 1330 if (!node) 1331 return -ENOMEM; 1332 rte_memcpy(&node->ixgbe_fdir, 1333 &rule->ixgbe_fdir, 1334 sizeof(union ixgbe_atr_input)); 1335 node->fdirflags = fdircmd_flags; 1336 node->fdirhash = fdirhash; 1337 node->queue = queue; 1338 1339 err = ixgbe_insert_fdir_filter(info, node); 1340 if (err < 0) { 1341 rte_free(node); 1342 return err; 1343 } 1344 } 1345 1346 if (is_perfect) { 1347 err = fdir_write_perfect_filter_82599(hw, &rule->ixgbe_fdir, 1348 queue, fdircmd_flags, 1349 fdirhash, fdir_mode); 1350 } else { 1351 err = fdir_add_signature_filter_82599(hw, &rule->ixgbe_fdir, 1352 queue, fdircmd_flags, 1353 fdirhash); 1354 } 1355 if (err < 0) { 1356 PMD_DRV_LOG(ERR, "Fail to add FDIR filter!"); 1357 1358 if (add_node) 1359 (void)ixgbe_remove_fdir_filter(info, &rule->ixgbe_fdir); 1360 } else { 1361 PMD_DRV_LOG(DEBUG, "Success to add FDIR filter"); 1362 } 1363 1364 return err; 1365 } 1366 1367 /* ixgbe_add_del_fdir_filter - add or remove a flow diretor filter. 1368 * @dev: pointer to the structure rte_eth_dev 1369 * @fdir_filter: fdir filter entry 1370 * @del: 1 - delete, 0 - add 1371 * @update: 1 - update 1372 */ 1373 static int 1374 ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev, 1375 const struct rte_eth_fdir_filter *fdir_filter, 1376 bool del, 1377 bool update) 1378 { 1379 struct ixgbe_fdir_rule rule; 1380 int err; 1381 1382 err = ixgbe_interpret_fdir_filter(dev, fdir_filter, &rule); 1383 1384 if (err) 1385 return err; 1386 1387 return ixgbe_fdir_filter_program(dev, &rule, del, update); 1388 } 1389 1390 static int 1391 ixgbe_fdir_flush(struct rte_eth_dev *dev) 1392 { 1393 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1394 struct ixgbe_hw_fdir_info *info = 1395 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1396 int ret; 1397 1398 ret = ixgbe_reinit_fdir_tables_82599(hw); 1399 if (ret < 0) { 1400 PMD_INIT_LOG(ERR, "Failed to re-initialize FD table."); 1401 return ret; 1402 } 1403 1404 info->f_add = 0; 1405 info->f_remove = 0; 1406 info->add = 0; 1407 info->remove = 0; 1408 1409 return ret; 1410 } 1411 1412 #define FDIRENTRIES_NUM_SHIFT 10 1413 void 1414 ixgbe_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir_info *fdir_info) 1415 { 1416 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1417 struct ixgbe_hw_fdir_info *info = 1418 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1419 uint32_t fdirctrl, max_num, i; 1420 uint8_t offset; 1421 1422 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); 1423 offset = ((fdirctrl & IXGBE_FDIRCTRL_FLEX_MASK) >> 1424 IXGBE_FDIRCTRL_FLEX_SHIFT) * sizeof(uint16_t); 1425 1426 fdir_info->mode = dev->data->dev_conf.fdir_conf.mode; 1427 max_num = (1 << (FDIRENTRIES_NUM_SHIFT + 1428 (fdirctrl & FDIRCTRL_PBALLOC_MASK))); 1429 if (fdir_info->mode >= RTE_FDIR_MODE_PERFECT && 1430 fdir_info->mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 1431 fdir_info->guarant_spc = max_num; 1432 else if (fdir_info->mode == RTE_FDIR_MODE_SIGNATURE) 1433 fdir_info->guarant_spc = max_num * 4; 1434 1435 fdir_info->mask.vlan_tci_mask = info->mask.vlan_tci_mask; 1436 fdir_info->mask.ipv4_mask.src_ip = info->mask.src_ipv4_mask; 1437 fdir_info->mask.ipv4_mask.dst_ip = info->mask.dst_ipv4_mask; 1438 IPV6_MASK_TO_ADDR(info->mask.src_ipv6_mask, 1439 fdir_info->mask.ipv6_mask.src_ip); 1440 IPV6_MASK_TO_ADDR(info->mask.dst_ipv6_mask, 1441 fdir_info->mask.ipv6_mask.dst_ip); 1442 fdir_info->mask.src_port_mask = info->mask.src_port_mask; 1443 fdir_info->mask.dst_port_mask = info->mask.dst_port_mask; 1444 fdir_info->mask.mac_addr_byte_mask = info->mask.mac_addr_byte_mask; 1445 fdir_info->mask.tunnel_id_mask = info->mask.tunnel_id_mask; 1446 fdir_info->mask.tunnel_type_mask = info->mask.tunnel_type_mask; 1447 fdir_info->max_flexpayload = IXGBE_FDIR_MAX_FLEX_LEN; 1448 1449 if (fdir_info->mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN || 1450 fdir_info->mode == RTE_FDIR_MODE_PERFECT_TUNNEL) 1451 fdir_info->flow_types_mask[0] = 0ULL; 1452 else 1453 fdir_info->flow_types_mask[0] = IXGBE_FDIR_FLOW_TYPES; 1454 for (i = 1; i < RTE_FLOW_MASK_ARRAY_SIZE; i++) 1455 fdir_info->flow_types_mask[i] = 0ULL; 1456 1457 fdir_info->flex_payload_unit = sizeof(uint16_t); 1458 fdir_info->max_flex_payload_segment_num = 1; 1459 fdir_info->flex_payload_limit = IXGBE_MAX_FLX_SOURCE_OFF; 1460 fdir_info->flex_conf.nb_payloads = 1; 1461 fdir_info->flex_conf.flex_set[0].type = RTE_ETH_RAW_PAYLOAD; 1462 fdir_info->flex_conf.flex_set[0].src_offset[0] = offset; 1463 fdir_info->flex_conf.flex_set[0].src_offset[1] = offset + 1; 1464 fdir_info->flex_conf.nb_flexmasks = 1; 1465 fdir_info->flex_conf.flex_mask[0].flow_type = RTE_ETH_FLOW_UNKNOWN; 1466 fdir_info->flex_conf.flex_mask[0].mask[0] = 1467 (uint8_t)(info->mask.flex_bytes_mask & 0x00FF); 1468 fdir_info->flex_conf.flex_mask[0].mask[1] = 1469 (uint8_t)((info->mask.flex_bytes_mask & 0xFF00) >> 8); 1470 } 1471 1472 void 1473 ixgbe_fdir_stats_get(struct rte_eth_dev *dev, struct rte_eth_fdir_stats *fdir_stats) 1474 { 1475 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1476 struct ixgbe_hw_fdir_info *info = 1477 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1478 uint32_t reg, max_num; 1479 enum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode; 1480 1481 /* Get the information from registers */ 1482 reg = IXGBE_READ_REG(hw, IXGBE_FDIRFREE); 1483 info->collision = (uint16_t)((reg & IXGBE_FDIRFREE_COLL_MASK) >> 1484 IXGBE_FDIRFREE_COLL_SHIFT); 1485 info->free = (uint16_t)((reg & IXGBE_FDIRFREE_FREE_MASK) >> 1486 IXGBE_FDIRFREE_FREE_SHIFT); 1487 1488 reg = IXGBE_READ_REG(hw, IXGBE_FDIRLEN); 1489 info->maxhash = (uint16_t)((reg & IXGBE_FDIRLEN_MAXHASH_MASK) >> 1490 IXGBE_FDIRLEN_MAXHASH_SHIFT); 1491 info->maxlen = (uint8_t)((reg & IXGBE_FDIRLEN_MAXLEN_MASK) >> 1492 IXGBE_FDIRLEN_MAXLEN_SHIFT); 1493 1494 reg = IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT); 1495 info->remove += (reg & IXGBE_FDIRUSTAT_REMOVE_MASK) >> 1496 IXGBE_FDIRUSTAT_REMOVE_SHIFT; 1497 info->add += (reg & IXGBE_FDIRUSTAT_ADD_MASK) >> 1498 IXGBE_FDIRUSTAT_ADD_SHIFT; 1499 1500 reg = IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT) & 0xFFFF; 1501 info->f_remove += (reg & IXGBE_FDIRFSTAT_FREMOVE_MASK) >> 1502 IXGBE_FDIRFSTAT_FREMOVE_SHIFT; 1503 info->f_add += (reg & IXGBE_FDIRFSTAT_FADD_MASK) >> 1504 IXGBE_FDIRFSTAT_FADD_SHIFT; 1505 1506 /* Copy the new information in the fdir parameter */ 1507 fdir_stats->collision = info->collision; 1508 fdir_stats->free = info->free; 1509 fdir_stats->maxhash = info->maxhash; 1510 fdir_stats->maxlen = info->maxlen; 1511 fdir_stats->remove = info->remove; 1512 fdir_stats->add = info->add; 1513 fdir_stats->f_remove = info->f_remove; 1514 fdir_stats->f_add = info->f_add; 1515 1516 reg = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL); 1517 max_num = (1 << (FDIRENTRIES_NUM_SHIFT + 1518 (reg & FDIRCTRL_PBALLOC_MASK))); 1519 if (fdir_mode >= RTE_FDIR_MODE_PERFECT && 1520 fdir_mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 1521 fdir_stats->guarant_cnt = max_num - fdir_stats->free; 1522 else if (fdir_mode == RTE_FDIR_MODE_SIGNATURE) 1523 fdir_stats->guarant_cnt = max_num * 4 - fdir_stats->free; 1524 1525 } 1526 1527 /* 1528 * ixgbe_fdir_ctrl_func - deal with all operations on flow director. 1529 * @dev: pointer to the structure rte_eth_dev 1530 * @filter_op:operation will be taken 1531 * @arg: a pointer to specific structure corresponding to the filter_op 1532 */ 1533 int 1534 ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev, 1535 enum rte_filter_op filter_op, void *arg) 1536 { 1537 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1538 int ret = 0; 1539 1540 if (hw->mac.type != ixgbe_mac_82599EB && 1541 hw->mac.type != ixgbe_mac_X540 && 1542 hw->mac.type != ixgbe_mac_X550 && 1543 hw->mac.type != ixgbe_mac_X550EM_x && 1544 hw->mac.type != ixgbe_mac_X550EM_a) 1545 return -ENOTSUP; 1546 1547 if (filter_op == RTE_ETH_FILTER_NOP) 1548 return 0; 1549 1550 if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH) 1551 return -EINVAL; 1552 1553 switch (filter_op) { 1554 case RTE_ETH_FILTER_ADD: 1555 ret = ixgbe_add_del_fdir_filter(dev, 1556 (struct rte_eth_fdir_filter *)arg, FALSE, FALSE); 1557 break; 1558 case RTE_ETH_FILTER_UPDATE: 1559 ret = ixgbe_add_del_fdir_filter(dev, 1560 (struct rte_eth_fdir_filter *)arg, FALSE, TRUE); 1561 break; 1562 case RTE_ETH_FILTER_DELETE: 1563 ret = ixgbe_add_del_fdir_filter(dev, 1564 (struct rte_eth_fdir_filter *)arg, TRUE, FALSE); 1565 break; 1566 case RTE_ETH_FILTER_FLUSH: 1567 ret = ixgbe_fdir_flush(dev); 1568 break; 1569 case RTE_ETH_FILTER_INFO: 1570 ixgbe_fdir_info_get(dev, (struct rte_eth_fdir_info *)arg); 1571 break; 1572 case RTE_ETH_FILTER_STATS: 1573 ixgbe_fdir_stats_get(dev, (struct rte_eth_fdir_stats *)arg); 1574 break; 1575 default: 1576 PMD_DRV_LOG(ERR, "unknown operation %u", filter_op); 1577 ret = -EINVAL; 1578 break; 1579 } 1580 return ret; 1581 } 1582 1583 /* restore flow director filter */ 1584 void 1585 ixgbe_fdir_filter_restore(struct rte_eth_dev *dev) 1586 { 1587 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); 1588 struct ixgbe_hw_fdir_info *fdir_info = 1589 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1590 struct ixgbe_fdir_filter *node; 1591 bool is_perfect = FALSE; 1592 enum rte_fdir_mode fdir_mode = dev->data->dev_conf.fdir_conf.mode; 1593 1594 if (fdir_mode >= RTE_FDIR_MODE_PERFECT && 1595 fdir_mode <= RTE_FDIR_MODE_PERFECT_TUNNEL) 1596 is_perfect = TRUE; 1597 1598 if (is_perfect) { 1599 TAILQ_FOREACH(node, &fdir_info->fdir_list, entries) { 1600 (void)fdir_write_perfect_filter_82599(hw, 1601 &node->ixgbe_fdir, 1602 node->queue, 1603 node->fdirflags, 1604 node->fdirhash, 1605 fdir_mode); 1606 } 1607 } else { 1608 TAILQ_FOREACH(node, &fdir_info->fdir_list, entries) { 1609 (void)fdir_add_signature_filter_82599(hw, 1610 &node->ixgbe_fdir, 1611 node->queue, 1612 node->fdirflags, 1613 node->fdirhash); 1614 } 1615 } 1616 } 1617 1618 /* remove all the flow director filters */ 1619 int 1620 ixgbe_clear_all_fdir_filter(struct rte_eth_dev *dev) 1621 { 1622 struct ixgbe_hw_fdir_info *fdir_info = 1623 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private); 1624 struct ixgbe_fdir_filter *fdir_filter; 1625 struct ixgbe_fdir_filter *filter_flag; 1626 int ret = 0; 1627 1628 /* flush flow director */ 1629 rte_hash_reset(fdir_info->hash_handle); 1630 memset(fdir_info->hash_map, 0, 1631 sizeof(struct ixgbe_fdir_filter *) * IXGBE_MAX_FDIR_FILTER_NUM); 1632 filter_flag = TAILQ_FIRST(&fdir_info->fdir_list); 1633 while ((fdir_filter = TAILQ_FIRST(&fdir_info->fdir_list))) { 1634 TAILQ_REMOVE(&fdir_info->fdir_list, 1635 fdir_filter, 1636 entries); 1637 rte_free(fdir_filter); 1638 } 1639 1640 if (filter_flag != NULL) 1641 ret = ixgbe_fdir_flush(dev); 1642 1643 return ret; 1644 } 1645