4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
38 #include <sys/queue.h>
40 #include <rte_interrupts.h>
42 #include <rte_debug.h>
44 #include <rte_ether.h>
45 #include <rte_ethdev.h>
47 #include "ixgbe_logs.h"
48 #include "ixgbe/ixgbe_api.h"
49 #include "ixgbe/ixgbe_common.h"
50 #include "ixgbe_ethdev.h"
52 /* To get PBALLOC (Packet Buffer Allocation) bits from FDIRCTRL value */
53 #define FDIRCTRL_PBALLOC_MASK 0x03
55 /* For calculating memory required for FDIR filters */
56 #define PBALLOC_SIZE_SHIFT 15
58 /* Number of bits used to mask bucket hash for different pballoc sizes */
59 #define PERFECT_BUCKET_64KB_HASH_MASK 0x07FF /* 11 bits */
60 #define PERFECT_BUCKET_128KB_HASH_MASK 0x0FFF /* 12 bits */
61 #define PERFECT_BUCKET_256KB_HASH_MASK 0x1FFF /* 13 bits */
62 #define SIG_BUCKET_64KB_HASH_MASK 0x1FFF /* 13 bits */
63 #define SIG_BUCKET_128KB_HASH_MASK 0x3FFF /* 14 bits */
64 #define SIG_BUCKET_256KB_HASH_MASK 0x7FFF /* 15 bits */
65 #define IXGBE_DEFAULT_FLEXBYTES_OFFSET 12 /* default flexbytes offset in bytes */
66 #define IXGBE_MAX_FLX_SOURCE_OFF 62
67 #define IXGBE_FDIRCTRL_FLEX_MASK (0x1F << IXGBE_FDIRCTRL_FLEX_SHIFT)
68 #define IXGBE_FDIRCMD_CMD_INTERVAL_US 10
70 static int ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev,
71 const struct rte_eth_fdir_flex_conf *conf);
72 static int fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash);
73 static int fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl);
74 static int ixgbe_fdir_filter_to_atr_input(
75 const struct rte_eth_fdir_filter *fdir_filter,
76 union ixgbe_atr_input *input);
77 static uint32_t ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
79 static uint32_t atr_compute_sig_hash_82599(union ixgbe_atr_input *input,
80 enum rte_fdir_pballoc_type pballoc);
81 static uint32_t atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
82 enum rte_fdir_pballoc_type pballoc);
83 static int fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
84 union ixgbe_atr_input *input, uint8_t queue,
85 uint32_t fdircmd, uint32_t fdirhash);
86 static int fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
87 union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd,
89 static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
90 const struct rte_eth_fdir_filter *fdir_filter,
94 * This function is based on ixgbe_fdir_enable_82599() in ixgbe/ixgbe_82599.c.
95 * It adds extra configuration of fdirctrl that is common for all filter types.
97 * Initialize Flow Director control registers
98 * @hw: pointer to hardware structure
99 * @fdirctrl: value to write to flow director control register
102 fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl)
106 PMD_INIT_FUNC_TRACE();
108 /* Prime the keys for hashing */
109 IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY, IXGBE_ATR_BUCKET_HASH_KEY);
110 IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY, IXGBE_ATR_SIGNATURE_HASH_KEY);
113 * Continue setup of fdirctrl register bits:
114 * Set the maximum length per hash bucket to 0xA filters
115 * Send interrupt when 64 filters are left
117 fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
118 (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
121 * Poll init-done after we write the register. Estimated times:
122 * 10G: PBALLOC = 11b, timing is 60us
123 * 1G: PBALLOC = 11b, timing is 600us
124 * 100M: PBALLOC = 11b, timing is 6ms
126 * Multiple these timings by 4 if under full Rx load
128 * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
129 * 1 msec per poll time. If we're at line rate and drop to 100M, then
130 * this might not finish in our poll time, but we can live with that
133 IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
134 IXGBE_WRITE_FLUSH(hw);
135 for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
136 if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
137 IXGBE_FDIRCTRL_INIT_DONE)
142 if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
143 PMD_INIT_LOG(ERR, "Flow Director poll time exceeded "
151 * Set appropriate bits in fdirctrl for: variable reporting levels, moving
152 * flexbytes matching field, and drop queue (only for perfect matching mode).
155 configure_fdir_flags(const struct rte_fdir_conf *conf, uint32_t *fdirctrl)
159 switch (conf->pballoc) {
160 case RTE_FDIR_PBALLOC_64K:
161 /* 8k - 1 signature filters */
162 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
164 case RTE_FDIR_PBALLOC_128K:
165 /* 16k - 1 signature filters */
166 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
168 case RTE_FDIR_PBALLOC_256K:
169 /* 32k - 1 signature filters */
170 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
174 PMD_INIT_LOG(ERR, "Invalid fdir_conf->pballoc value");
178 /* status flags: write hash & swindex in the rx descriptor */
179 switch (conf->status) {
180 case RTE_FDIR_NO_REPORT_STATUS:
181 /* do nothing, default mode */
183 case RTE_FDIR_REPORT_STATUS:
184 /* report status when the packet matches a fdir rule */
185 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
187 case RTE_FDIR_REPORT_STATUS_ALWAYS:
188 /* always report status */
189 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS;
193 PMD_INIT_LOG(ERR, "Invalid fdir_conf->status value");
197 *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) <<
198 IXGBE_FDIRCTRL_FLEX_SHIFT;
200 if (conf->mode == RTE_FDIR_MODE_PERFECT) {
201 *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
202 *fdirctrl |= (conf->drop_queue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
205 * Continue setup of fdirctrl register bits:
206 * Set the maximum length per hash bucket to 0xA filters
207 * Send interrupt when 64 filters are left
209 *fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
210 (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
216 * ixgbe_check_fdir_flex_conf -check if the flex payload and mask configuration
217 * arguments are valid
220 ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev,
221 const struct rte_eth_fdir_flex_conf *conf)
223 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
224 struct ixgbe_hw_fdir_info *info =
225 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private);
226 const struct rte_eth_flex_payload_cfg *flex_cfg;
227 const struct rte_eth_fdir_flex_mask *flex_mask;
228 uint32_t fdirctrl, fdirm;
229 uint16_t flexbytes = 0;
232 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
233 fdirm = IXGBE_READ_REG(hw, IXGBE_FDIRM);
236 PMD_DRV_LOG(INFO, "NULL pointer.");
240 for (i = 0; i < conf->nb_payloads; i++) {
241 flex_cfg = &conf->flex_set[i];
242 if (flex_cfg->type != RTE_ETH_RAW_PAYLOAD) {
243 PMD_DRV_LOG(ERR, "unsupported payload type.");
246 if (((flex_cfg->src_offset[0] & 0x1) == 0) &&
247 (flex_cfg->src_offset[1] == flex_cfg->src_offset[0] + 1) &&
248 (flex_cfg->src_offset[0] <= IXGBE_MAX_FLX_SOURCE_OFF)) {
249 fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK;
250 fdirctrl |= (flex_cfg->src_offset[0] / sizeof(uint16_t)) <<
251 IXGBE_FDIRCTRL_FLEX_SHIFT;
253 PMD_DRV_LOG(ERR, "invalid flexbytes arguments.");
258 for (i = 0; i < conf->nb_flexmasks; i++) {
259 flex_mask = &conf->flex_mask[i];
260 if (flex_mask->flow_type != RTE_ETH_FLOW_TYPE_RAW) {
261 PMD_DRV_LOG(ERR, "unsupported flow type.");
264 flexbytes = (uint16_t)(((flex_mask->mask[0] << 8) & 0xFF00) |
265 ((flex_mask->mask[1]) & 0xFF));
266 if (flexbytes == UINT16_MAX)
267 fdirm &= ~IXGBE_FDIRM_FLEX;
268 else if (flexbytes != 0) {
269 /* IXGBE_FDIRM_FLEX is set by default when set mask */
270 PMD_DRV_LOG(ERR, " invalid flexbytes mask arguments.");
274 IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
275 IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
276 info->flex_bytes_offset = (uint8_t)((fdirctrl &
277 IXGBE_FDIRCTRL_FLEX_MASK) >>
278 IXGBE_FDIRCTRL_FLEX_SHIFT);
283 ixgbe_fdir_configure(struct rte_eth_dev *dev)
285 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
287 uint32_t fdirctrl, pbsize;
290 PMD_INIT_FUNC_TRACE();
292 if (hw->mac.type != ixgbe_mac_82599EB &&
293 hw->mac.type != ixgbe_mac_X540 &&
294 hw->mac.type != ixgbe_mac_X550 &&
295 hw->mac.type != ixgbe_mac_X550EM_x)
298 err = configure_fdir_flags(&dev->data->dev_conf.fdir_conf, &fdirctrl);
303 * Before enabling Flow Director, the Rx Packet Buffer size
304 * must be reduced. The new value is the current size minus
305 * flow director memory usage size.
307 pbsize = (1 << (PBALLOC_SIZE_SHIFT + (fdirctrl & FDIRCTRL_PBALLOC_MASK)));
308 IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
309 (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
312 * The defaults in the HW for RX PB 1-7 are not zero and so should be
313 * intialized to zero for non DCB mode otherwise actual total RX PB
314 * would be bigger than programmed and filter space would run into
317 for (i = 1; i < 8; i++)
318 IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
321 err = ixgbe_set_fdir_flex_conf(dev,
322 &dev->data->dev_conf.fdir_conf.flex_conf);
324 PMD_INIT_LOG(ERR, " Error on setting FD flexible arguments.");
328 err = fdir_enable_82599(hw, fdirctrl);
330 PMD_INIT_LOG(ERR, " Error on enabling FD.");
337 * Reverse the bits in FDIR registers that store 2 x 16 bit masks.
339 * @hi_dword: Bits 31:16 mask to be bit swapped.
340 * @lo_dword: Bits 15:0 mask to be bit swapped.
342 * Flow director uses several registers to store 2 x 16 bit masks with the
343 * bits reversed such as FDIRTCPM, FDIRUDPM and FDIRIP6M. The LS bit of the
344 * mask affects the MS bit/byte of the target. This function reverses the
345 * bits in these masks.
348 reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t lo_dword)
350 u32 mask = hi_dword << 16;
352 mask = ((mask & 0x55555555) << 1) | ((mask & 0xAAAAAAAA) >> 1);
353 mask = ((mask & 0x33333333) << 2) | ((mask & 0xCCCCCCCC) >> 2);
354 mask = ((mask & 0x0F0F0F0F) << 4) | ((mask & 0xF0F0F0F0) >> 4);
355 return ((mask & 0x00FF00FF) << 8) | ((mask & 0xFF00FF00) >> 8);
359 * This macro exists in ixgbe/ixgbe_82599.c, however in that file it reverses
360 * the bytes, and then reverses them again. So here it does nothing.
362 #define IXGBE_WRITE_REG_BE32 IXGBE_WRITE_REG
365 * This is based on ixgbe_fdir_set_input_mask_82599() in ixgbe/ixgbe_82599.c,
366 * but makes use of the rte_fdir_masks structure to see which bits to set.
369 fdir_set_input_mask_82599(struct ixgbe_hw *hw,
370 struct rte_fdir_masks *input_mask)
372 /* mask VM pool since it is currently not supported */
373 u32 fdirm = IXGBE_FDIRM_POOL;
374 u32 fdirtcpm; /* TCP source and destination port masks. */
375 u32 fdiripv6m; /* IPv6 source and destination masks. */
377 PMD_INIT_FUNC_TRACE();
380 * Program the relevant mask registers. If src/dst_port or src/dst_addr
381 * are zero, then assume a full mask for that field. Also assume that
382 * a VLAN of 0 is unspecified, so mask that out as well. L4type
383 * cannot be masked out in this implementation.
385 if (input_mask->only_ip_flow) {
386 /* use the L4 protocol mask for raw IPv4/IPv6 traffic */
387 fdirm |= IXGBE_FDIRM_L4P;
388 if (input_mask->dst_port_mask || input_mask->src_port_mask) {
389 PMD_INIT_LOG(ERR, " Error on src/dst port mask");
394 if (!input_mask->comp_ipv6_dst)
396 fdirm |= IXGBE_FDIRM_DIPv6;
398 if (!input_mask->vlan_id)
400 fdirm |= IXGBE_FDIRM_VLANID;
402 if (!input_mask->vlan_prio)
403 /* mask VLAN priority */
404 fdirm |= IXGBE_FDIRM_VLANP;
406 if (!input_mask->flexbytes)
407 /* Mask Flex Bytes */
408 fdirm |= IXGBE_FDIRM_FLEX;
410 IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
412 /* store the TCP/UDP port masks, bit reversed from port layout */
413 fdirtcpm = reverse_fdir_bitmasks(input_mask->dst_port_mask,
414 input_mask->src_port_mask);
416 /* write both the same so that UDP and TCP use the same mask */
417 IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, ~fdirtcpm);
418 IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, ~fdirtcpm);
420 if (!input_mask->set_ipv6_mask) {
421 /* Store source and destination IPv4 masks (big-endian) */
422 IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRSIP4M,
423 IXGBE_NTOHL(~input_mask->src_ipv4_mask));
424 IXGBE_WRITE_REG_BE32(hw, IXGBE_FDIRDIP4M,
425 IXGBE_NTOHL(~input_mask->dst_ipv4_mask));
427 /* Store source and destination IPv6 masks (bit reversed) */
428 fdiripv6m = reverse_fdir_bitmasks(input_mask->dst_ipv6_mask,
429 input_mask->src_ipv6_mask);
431 IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, ~fdiripv6m);
434 return IXGBE_SUCCESS;
438 ixgbe_fdir_set_masks(struct rte_eth_dev *dev, struct rte_fdir_masks *fdir_masks)
443 PMD_INIT_FUNC_TRACE();
445 hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
447 if (hw->mac.type != ixgbe_mac_82599EB &&
448 hw->mac.type != ixgbe_mac_X540 &&
449 hw->mac.type != ixgbe_mac_X550 &&
450 hw->mac.type != ixgbe_mac_X550EM_x)
453 err = ixgbe_reinit_fdir_tables_82599(hw);
455 PMD_INIT_LOG(ERR, "reinit of fdir tables failed");
459 return fdir_set_input_mask_82599(hw, fdir_masks);
463 * Convert DPDK rte_eth_fdir_filter struct to ixgbe_atr_input union that is used
464 * by the IXGBE driver code.
467 ixgbe_fdir_filter_to_atr_input(const struct rte_eth_fdir_filter *fdir_filter,
468 union ixgbe_atr_input *input)
470 input->formatted.vlan_id = fdir_filter->input.flow_ext.vlan_tci;
471 input->formatted.flex_bytes = (uint16_t)(
472 (fdir_filter->input.flow_ext.flexbytes[1] << 8 & 0xFF00) |
473 (fdir_filter->input.flow_ext.flexbytes[0] & 0xFF));
475 switch (fdir_filter->input.flow_type) {
476 case RTE_ETH_FLOW_TYPE_UDPV4:
477 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
479 case RTE_ETH_FLOW_TYPE_TCPV4:
480 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
482 case RTE_ETH_FLOW_TYPE_SCTPV4:
483 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
485 case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
486 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
488 case RTE_ETH_FLOW_TYPE_UDPV6:
489 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV6;
491 case RTE_ETH_FLOW_TYPE_TCPV6:
492 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6;
494 case RTE_ETH_FLOW_TYPE_SCTPV6:
495 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV6;
497 case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
498 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV6;
501 PMD_DRV_LOG(ERR, " Error on flow_type input");
505 switch (fdir_filter->input.flow_type) {
506 case RTE_ETH_FLOW_TYPE_UDPV4:
507 case RTE_ETH_FLOW_TYPE_TCPV4:
508 input->formatted.src_port =
509 fdir_filter->input.flow.udp4_flow.src_port;
510 input->formatted.dst_port =
511 fdir_filter->input.flow.udp4_flow.dst_port;
512 /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/
513 case RTE_ETH_FLOW_TYPE_SCTPV4:
514 case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
515 input->formatted.src_ip[0] =
516 fdir_filter->input.flow.ip4_flow.src_ip;
517 input->formatted.dst_ip[0] =
518 fdir_filter->input.flow.ip4_flow.dst_ip;
521 case RTE_ETH_FLOW_TYPE_UDPV6:
522 case RTE_ETH_FLOW_TYPE_TCPV6:
523 input->formatted.src_port =
524 fdir_filter->input.flow.udp6_flow.src_port;
525 input->formatted.dst_port =
526 fdir_filter->input.flow.udp6_flow.dst_port;
527 /*for SCTP flow type, port and verify_tag are meaningless in ixgbe.*/
528 case RTE_ETH_FLOW_TYPE_SCTPV6:
529 case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
530 rte_memcpy(input->formatted.src_ip,
531 fdir_filter->input.flow.ipv6_flow.src_ip,
532 sizeof(input->formatted.src_ip));
533 rte_memcpy(input->formatted.dst_ip,
534 fdir_filter->input.flow.ipv6_flow.dst_ip,
535 sizeof(input->formatted.dst_ip));
538 PMD_DRV_LOG(ERR, " Error on flow_type input");
546 * The below function is taken from the FreeBSD IXGBE drivers release
547 * 2.3.8. The only change is not to mask hash_result with IXGBE_ATR_HASH_MASK
548 * before returning, as the signature hash can use 16bits.
550 * The newer driver has optimised functions for calculating bucket and
551 * signature hashes. However they don't support IPv6 type packets for signature
552 * filters so are not used here.
554 * Note that the bkt_hash field in the ixgbe_atr_input structure is also never
557 * Compute the hashes for SW ATR
558 * @stream: input bitstream to compute the hash on
559 * @key: 32-bit hash key
562 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
566 * The algorithm is as follows:
567 * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
568 * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
569 * and A[n] x B[n] is bitwise AND between same length strings
571 * K[n] is 16 bits, defined as:
572 * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
573 * for n modulo 32 < 15, K[n] =
574 * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
576 * S[n] is 16 bits, defined as:
577 * for n >= 15, S[n] = S[n:n - 15]
578 * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
580 * To simplify for programming, the algorithm is implemented
581 * in software this way:
583 * key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
585 * for (i = 0; i < 352; i+=32)
586 * hi_hash_dword[31:0] ^= Stream[(i+31):i];
588 * lo_hash_dword[15:0] ^= Stream[15:0];
589 * lo_hash_dword[15:0] ^= hi_hash_dword[31:16];
590 * lo_hash_dword[31:16] ^= hi_hash_dword[15:0];
592 * hi_hash_dword[31:0] ^= Stream[351:320];
595 * hash[15:0] ^= Stream[15:0];
597 * for (i = 0; i < 16; i++) {
599 * hash[15:0] ^= lo_hash_dword[(i+15):i];
601 * hash[15:0] ^= hi_hash_dword[(i+15):i];
605 __be32 common_hash_dword = 0;
606 u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
610 /* record the flow_vm_vlan bits as they are a key part to the hash */
611 flow_vm_vlan = IXGBE_NTOHL(atr_input->dword_stream[0]);
613 /* generate common hash dword */
614 for (i = 1; i <= 13; i++)
615 common_hash_dword ^= atr_input->dword_stream[i];
617 hi_hash_dword = IXGBE_NTOHL(common_hash_dword);
619 /* low dword is word swapped version of common */
620 lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
622 /* apply flow ID/VM pool/VLAN ID bits to hash words */
623 hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
625 /* Process bits 0 and 16 */
626 if (key & 0x0001) hash_result ^= lo_hash_dword;
627 if (key & 0x00010000) hash_result ^= hi_hash_dword;
630 * apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to
631 * delay this because bit 0 of the stream should not be processed
632 * so we do not add the vlan until after bit 0 was processed
634 lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
637 /* process the remaining 30 bits in the key 2 bits at a time */
638 for (i = 15; i; i-- ) {
639 if (key & (0x0001 << i)) hash_result ^= lo_hash_dword >> i;
640 if (key & (0x00010000 << i)) hash_result ^= hi_hash_dword >> i;
647 atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
648 enum rte_fdir_pballoc_type pballoc)
650 if (pballoc == RTE_FDIR_PBALLOC_256K)
651 return ixgbe_atr_compute_hash_82599(input,
652 IXGBE_ATR_BUCKET_HASH_KEY) &
653 PERFECT_BUCKET_256KB_HASH_MASK;
654 else if (pballoc == RTE_FDIR_PBALLOC_128K)
655 return ixgbe_atr_compute_hash_82599(input,
656 IXGBE_ATR_BUCKET_HASH_KEY) &
657 PERFECT_BUCKET_128KB_HASH_MASK;
659 return ixgbe_atr_compute_hash_82599(input,
660 IXGBE_ATR_BUCKET_HASH_KEY) &
661 PERFECT_BUCKET_64KB_HASH_MASK;
665 * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
666 * @hw: pointer to hardware structure
669 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, uint32_t *fdircmd)
673 for (i = 0; i < IXGBE_FDIRCMD_CMD_POLL; i++) {
674 *fdircmd = IXGBE_READ_REG(hw, IXGBE_FDIRCMD);
675 if (!(*fdircmd & IXGBE_FDIRCMD_CMD_MASK))
677 rte_delay_us(IXGBE_FDIRCMD_CMD_INTERVAL_US);
684 * Calculate the hash value needed for signature-match filters. In the FreeBSD
685 * driver, this is done by the optimised function
686 * ixgbe_atr_compute_sig_hash_82599(). However that can't be used here as it
687 * doesn't support calculating a hash for an IPv6 filter.
690 atr_compute_sig_hash_82599(union ixgbe_atr_input *input,
691 enum rte_fdir_pballoc_type pballoc)
693 uint32_t bucket_hash, sig_hash;
695 if (pballoc == RTE_FDIR_PBALLOC_256K)
696 bucket_hash = ixgbe_atr_compute_hash_82599(input,
697 IXGBE_ATR_BUCKET_HASH_KEY) &
698 SIG_BUCKET_256KB_HASH_MASK;
699 else if (pballoc == RTE_FDIR_PBALLOC_128K)
700 bucket_hash = ixgbe_atr_compute_hash_82599(input,
701 IXGBE_ATR_BUCKET_HASH_KEY) &
702 SIG_BUCKET_128KB_HASH_MASK;
704 bucket_hash = ixgbe_atr_compute_hash_82599(input,
705 IXGBE_ATR_BUCKET_HASH_KEY) &
706 SIG_BUCKET_64KB_HASH_MASK;
708 sig_hash = ixgbe_atr_compute_hash_82599(input,
709 IXGBE_ATR_SIGNATURE_HASH_KEY);
711 return (sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT) | bucket_hash;
715 * This is based on ixgbe_fdir_write_perfect_filter_82599() in
716 * ixgbe/ixgbe_82599.c, with the ability to set extra flags in FDIRCMD register
717 * added, and IPv6 support also added. The hash value is also pre-calculated
718 * as the pballoc value is needed to do it.
721 fdir_write_perfect_filter_82599(struct ixgbe_hw *hw,
722 union ixgbe_atr_input *input, uint8_t queue,
723 uint32_t fdircmd, uint32_t fdirhash)
725 uint32_t fdirport, fdirvlan;
728 /* record the IPv4 address (big-endian) */
729 IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, input->formatted.src_ip[0]);
730 IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, input->formatted.dst_ip[0]);
732 /* record source and destination port (little-endian)*/
733 fdirport = IXGBE_NTOHS(input->formatted.dst_port);
734 fdirport <<= IXGBE_FDIRPORT_DESTINATION_SHIFT;
735 fdirport |= IXGBE_NTOHS(input->formatted.src_port);
736 IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, fdirport);
738 /* record vlan (little-endian) and flex_bytes(big-endian) */
739 fdirvlan = input->formatted.flex_bytes;
740 fdirvlan <<= IXGBE_FDIRVLAN_FLEX_SHIFT;
741 fdirvlan |= IXGBE_NTOHS(input->formatted.vlan_id);
742 IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, fdirvlan);
744 /* configure FDIRHASH register */
745 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
748 * flush all previous writes to make certain registers are
749 * programmed prior to issuing the command
751 IXGBE_WRITE_FLUSH(hw);
753 /* configure FDIRCMD register */
754 fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW |
755 IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
756 fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
757 fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
758 fdircmd |= (uint32_t)input->formatted.vm_pool << IXGBE_FDIRCMD_VT_POOL_SHIFT;
760 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
762 PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);
764 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
766 PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");
772 * This function is based on ixgbe_atr_add_signature_filter_82599() in
773 * ixgbe/ixgbe_82599.c, but uses a pre-calculated hash value. It also supports
774 * setting extra fields in the FDIRCMD register, and removes the code that was
775 * verifying the flow_type field. According to the documentation, a flow type of
776 * 00 (i.e. not TCP, UDP, or SCTP) is not supported, however it appears to
779 * Adds a signature hash filter
780 * @hw: pointer to hardware structure
781 * @input: unique input dword
782 * @queue: queue index to direct traffic to
783 * @fdircmd: any extra flags to set in fdircmd register
784 * @fdirhash: pre-calculated hash value for the filter
787 fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
788 union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd,
793 PMD_INIT_FUNC_TRACE();
795 /* configure FDIRCMD register */
796 fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW |
797 IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN;
798 fdircmd |= input->formatted.flow_type << IXGBE_FDIRCMD_FLOW_TYPE_SHIFT;
799 fdircmd |= (uint32_t)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
801 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
802 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
804 PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);
806 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
808 PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");
814 * This is based on ixgbe_fdir_erase_perfect_filter_82599() in
815 * ixgbe/ixgbe_82599.c. It is modified to take in the hash as a parameter so
816 * that it can be used for removing signature and perfect filters.
819 fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash)
821 uint32_t fdircmd = 0;
824 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
826 /* flush hash to HW */
827 IXGBE_WRITE_FLUSH(hw);
829 /* Query if filter is present */
830 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
832 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
834 PMD_INIT_LOG(ERR, "Timeout querying for flow director filter.");
838 /* if filter exists in hardware then remove it */
839 if (fdircmd & IXGBE_FDIRCMD_FILTER_VALID) {
840 IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
841 IXGBE_WRITE_FLUSH(hw);
842 IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD,
843 IXGBE_FDIRCMD_CMD_REMOVE_FLOW);
845 err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
847 PMD_INIT_LOG(ERR, "Timeout erasing flow director filter.");
853 * ixgbe_add_del_fdir_filter - add or remove a flow diretor filter.
854 * @dev: pointer to the structure rte_eth_dev
855 * @fdir_filter: fdir filter entry
856 * @del: 1 - delete, 0 - add
857 * @update: 1 - update
860 ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
861 const struct rte_eth_fdir_filter *fdir_filter,
865 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
866 uint32_t fdircmd_flags;
868 union ixgbe_atr_input input;
870 bool is_perfect = FALSE;
873 if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_NONE)
876 if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT)
879 memset(&input, 0, sizeof(input));
881 err = ixgbe_fdir_filter_to_atr_input(fdir_filter, &input);
886 if (input.formatted.flow_type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
887 PMD_DRV_LOG(ERR, "IPv6 is not supported in"
891 fdirhash = atr_compute_perfect_hash_82599(&input,
892 dev->data->dev_conf.fdir_conf.pballoc);
893 fdirhash |= fdir_filter->soft_id <<
894 IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT;
896 fdirhash = atr_compute_sig_hash_82599(&input,
897 dev->data->dev_conf.fdir_conf.pballoc);
900 err = fdir_erase_filter_82599(hw, fdirhash);
902 PMD_DRV_LOG(ERR, "Fail to delete FDIR filter!");
904 PMD_DRV_LOG(DEBUG, "Success to delete FDIR filter!");
907 /* add or update an fdir filter*/
908 fdircmd_flags = (update) ? IXGBE_FDIRCMD_FILTER_UPDATE : 0;
909 if (fdir_filter->action.behavior == RTE_ETH_FDIR_REJECT) {
911 queue = dev->data->dev_conf.fdir_conf.drop_queue;
912 fdircmd_flags |= IXGBE_FDIRCMD_DROP;
914 PMD_DRV_LOG(ERR, "Drop option is not supported in"
918 } else if (fdir_filter->action.rx_queue < IXGBE_MAX_RX_QUEUE_NUM)
919 queue = (uint8_t)fdir_filter->action.rx_queue;
924 err = fdir_write_perfect_filter_82599(hw, &input, queue,
925 fdircmd_flags, fdirhash);
927 err = fdir_add_signature_filter_82599(hw, &input, queue,
928 fdircmd_flags, fdirhash);
931 PMD_DRV_LOG(ERR, "Fail to add FDIR filter!");
933 PMD_DRV_LOG(DEBUG, "Success to add FDIR filter");
939 ixgbe_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir *fdir)
941 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
942 struct ixgbe_hw_fdir_info *info =
943 IXGBE_DEV_PRIVATE_TO_FDIR_INFO(dev->data->dev_private);
946 if (hw->mac.type != ixgbe_mac_82599EB &&
947 hw->mac.type != ixgbe_mac_X540 &&
948 hw->mac.type != ixgbe_mac_X550 &&
949 hw->mac.type != ixgbe_mac_X550EM_x)
952 /* Get the information from registers */
953 reg = IXGBE_READ_REG(hw, IXGBE_FDIRFREE);
954 info->collision = (uint16_t)((reg & IXGBE_FDIRFREE_COLL_MASK) >>
955 IXGBE_FDIRFREE_COLL_SHIFT);
956 info->free = (uint16_t)((reg & IXGBE_FDIRFREE_FREE_MASK) >>
957 IXGBE_FDIRFREE_FREE_SHIFT);
959 reg = IXGBE_READ_REG(hw, IXGBE_FDIRLEN);
960 info->maxhash = (uint16_t)((reg & IXGBE_FDIRLEN_MAXHASH_MASK) >>
961 IXGBE_FDIRLEN_MAXHASH_SHIFT);
962 info->maxlen = (uint8_t)((reg & IXGBE_FDIRLEN_MAXLEN_MASK) >>
963 IXGBE_FDIRLEN_MAXLEN_SHIFT);
965 reg = IXGBE_READ_REG(hw, IXGBE_FDIRUSTAT);
966 info->remove += (reg & IXGBE_FDIRUSTAT_REMOVE_MASK) >>
967 IXGBE_FDIRUSTAT_REMOVE_SHIFT;
968 info->add += (reg & IXGBE_FDIRUSTAT_ADD_MASK) >>
969 IXGBE_FDIRUSTAT_ADD_SHIFT;
971 reg = IXGBE_READ_REG(hw, IXGBE_FDIRFSTAT) & 0xFFFF;
972 info->f_remove += (reg & IXGBE_FDIRFSTAT_FREMOVE_MASK) >>
973 IXGBE_FDIRFSTAT_FREMOVE_SHIFT;
974 info->f_add += (reg & IXGBE_FDIRFSTAT_FADD_MASK) >>
975 IXGBE_FDIRFSTAT_FADD_SHIFT;
977 /* Copy the new information in the fdir parameter */
978 fdir->collision = info->collision;
979 fdir->free = info->free;
980 fdir->maxhash = info->maxhash;
981 fdir->maxlen = info->maxlen;
982 fdir->remove = info->remove;
983 fdir->add = info->add;
984 fdir->f_remove = info->f_remove;
985 fdir->f_add = info->f_add;
989 * ixgbe_fdir_ctrl_func - deal with all operations on flow director.
990 * @dev: pointer to the structure rte_eth_dev
991 * @filter_op:operation will be taken
992 * @arg: a pointer to specific structure corresponding to the filter_op
995 ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
996 enum rte_filter_op filter_op, void *arg)
998 struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1001 if (hw->mac.type != ixgbe_mac_82599EB &&
1002 hw->mac.type != ixgbe_mac_X540 &&
1003 hw->mac.type != ixgbe_mac_X550 &&
1004 hw->mac.type != ixgbe_mac_X550EM_x)
1007 if (filter_op == RTE_ETH_FILTER_NOP)
1010 if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
1013 switch (filter_op) {
1014 case RTE_ETH_FILTER_ADD:
1015 ret = ixgbe_add_del_fdir_filter(dev,
1016 (struct rte_eth_fdir_filter *)arg, FALSE, FALSE);
1018 case RTE_ETH_FILTER_UPDATE:
1019 ret = ixgbe_add_del_fdir_filter(dev,
1020 (struct rte_eth_fdir_filter *)arg, FALSE, TRUE);
1022 case RTE_ETH_FILTER_DELETE:
1023 ret = ixgbe_add_del_fdir_filter(dev,
1024 (struct rte_eth_fdir_filter *)arg, TRUE, FALSE);
1027 PMD_DRV_LOG(ERR, "unknown operation %u", filter_op);