ixgbe: support flexpayload configuration of flow director
[dpdk.git] / lib / librte_pmd_ixgbe / ixgbe_fdir.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 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 <stdio.h>
35 #include <stdint.h>
36 #include <stdarg.h>
37 #include <errno.h>
38 #include <sys/queue.h>
39
40 #include <rte_interrupts.h>
41 #include <rte_log.h>
42 #include <rte_debug.h>
43 #include <rte_pci.h>
44 #include <rte_ether.h>
45 #include <rte_ethdev.h>
46
47 #include "ixgbe_logs.h"
48 #include "ixgbe/ixgbe_api.h"
49 #include "ixgbe/ixgbe_common.h"
50 #include "ixgbe_ethdev.h"
51
52 /* To get PBALLOC (Packet Buffer Allocation) bits from FDIRCTRL value */
53 #define FDIRCTRL_PBALLOC_MASK           0x03
54
55 /* For calculating memory required for FDIR filters */
56 #define PBALLOC_SIZE_SHIFT              15
57
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
69
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,
78                                  uint32_t key);
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,
88                 uint32_t fdirhash);
89 static int ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
90                               const struct rte_eth_fdir_filter *fdir_filter,
91                               bool del,
92                               bool update);
93 /**
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.
96  *
97  *  Initialize Flow Director control registers
98  *  @hw: pointer to hardware structure
99  *  @fdirctrl: value to write to flow director control register
100  **/
101 static int
102 fdir_enable_82599(struct ixgbe_hw *hw, uint32_t fdirctrl)
103 {
104         int i;
105
106         PMD_INIT_FUNC_TRACE();
107
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);
111
112         /*
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
116          */
117         fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
118                     (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
119
120         /*
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
125          *
126          *     Multiple these timings by 4 if under full Rx load
127          *
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
131          * for now.
132          */
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)
138                         break;
139                 msec_delay(1);
140         }
141
142         if (i >= IXGBE_FDIR_INIT_DONE_POLL) {
143                 PMD_INIT_LOG(ERR, "Flow Director poll time exceeded "
144                         "during enabling!");
145                 return -ETIMEDOUT;
146         }
147         return 0;
148 }
149
150 /*
151  * Set appropriate bits in fdirctrl for: variable reporting levels, moving
152  * flexbytes matching field, and drop queue (only for perfect matching mode).
153  */
154 static inline int
155 configure_fdir_flags(const struct rte_fdir_conf *conf, uint32_t *fdirctrl)
156 {
157         *fdirctrl = 0;
158
159         switch (conf->pballoc) {
160         case RTE_FDIR_PBALLOC_64K:
161                 /* 8k - 1 signature filters */
162                 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
163                 break;
164         case RTE_FDIR_PBALLOC_128K:
165                 /* 16k - 1 signature filters */
166                 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
167                 break;
168         case RTE_FDIR_PBALLOC_256K:
169                 /* 32k - 1 signature filters */
170                 *fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
171                 break;
172         default:
173                 /* bad value */
174                 PMD_INIT_LOG(ERR, "Invalid fdir_conf->pballoc value");
175                 return -EINVAL;
176         };
177
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 */
182                 break;
183         case RTE_FDIR_REPORT_STATUS:
184                 /* report status when the packet matches a fdir rule */
185                 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
186                 break;
187         case RTE_FDIR_REPORT_STATUS_ALWAYS:
188                 /* always report status */
189                 *fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS;
190                 break;
191         default:
192                 /* bad value */
193                 PMD_INIT_LOG(ERR, "Invalid fdir_conf->status value");
194                 return -EINVAL;
195         };
196
197         *fdirctrl |= (IXGBE_DEFAULT_FLEXBYTES_OFFSET / sizeof(uint16_t)) <<
198                      IXGBE_FDIRCTRL_FLEX_SHIFT;
199
200         if (conf->mode == RTE_FDIR_MODE_PERFECT) {
201                 *fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
202                 *fdirctrl |= (conf->drop_queue << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
203         }
204         /*
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
208          */
209         *fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT) |
210                     (4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT);
211
212         return 0;
213 }
214
215 /*
216  * ixgbe_check_fdir_flex_conf -check if the flex payload and mask configuration
217  * arguments are valid
218  */
219 static int
220 ixgbe_set_fdir_flex_conf(struct rte_eth_dev *dev,
221                 const struct rte_eth_fdir_flex_conf *conf)
222 {
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;
230         uint16_t i;
231
232         fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
233         fdirm = IXGBE_READ_REG(hw, IXGBE_FDIRM);
234
235         if (conf == NULL) {
236                 PMD_DRV_LOG(INFO, "NULL pointer.");
237                 return -EINVAL;
238         }
239
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.");
244                         return -EINVAL;
245                 }
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;
252                 } else {
253                         PMD_DRV_LOG(ERR, "invalid flexbytes arguments.");
254                         return -EINVAL;
255                 }
256         }
257
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.");
262                         return -EINVAL;
263                 }
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.");
271                         return -EINVAL;
272                 }
273         }
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);
279         return 0;
280 }
281
282 int
283 ixgbe_fdir_configure(struct rte_eth_dev *dev)
284 {
285         struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
286         int err;
287         uint32_t fdirctrl, pbsize;
288         int i;
289
290         PMD_INIT_FUNC_TRACE();
291
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)
296                 return -ENOSYS;
297
298         err = configure_fdir_flags(&dev->data->dev_conf.fdir_conf, &fdirctrl);
299         if (err)
300                 return err;
301
302         /*
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.
306          */
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));
310
311         /*
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
315          * the PB 0 region.
316          */
317         for (i = 1; i < 8; i++)
318                 IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
319
320
321         err = ixgbe_set_fdir_flex_conf(dev,
322                 &dev->data->dev_conf.fdir_conf.flex_conf);
323         if (err < 0) {
324                 PMD_INIT_LOG(ERR, " Error on setting FD flexible arguments.");
325                 return err;
326         }
327
328         err = fdir_enable_82599(hw, fdirctrl);
329         if (err < 0) {
330                 PMD_INIT_LOG(ERR, " Error on enabling FD.");
331                 return err;
332         }
333         return 0;
334 }
335
336 /**
337  * Reverse the bits in FDIR registers that store 2 x 16 bit masks.
338  *
339  *  @hi_dword: Bits 31:16 mask to be bit swapped.
340  *  @lo_dword: Bits 15:0  mask to be bit swapped.
341  *
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.
346  *  **/
347 static uint32_t
348 reverse_fdir_bitmasks(uint16_t hi_dword, uint16_t lo_dword)
349 {
350         u32 mask = hi_dword << 16;
351         mask |= lo_dword;
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);
356 }
357
358 /*
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.
361  */
362 #define IXGBE_WRITE_REG_BE32 IXGBE_WRITE_REG
363
364 /*
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.
367  */
368 static int
369 fdir_set_input_mask_82599(struct ixgbe_hw *hw,
370                 struct rte_fdir_masks *input_mask)
371 {
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. */
376
377         PMD_INIT_FUNC_TRACE();
378
379         /*
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.
384          */
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");
390                         return -EINVAL;
391                 }
392         }
393
394         if (!input_mask->comp_ipv6_dst)
395                 /* mask DIPV6 */
396                 fdirm |= IXGBE_FDIRM_DIPv6;
397
398         if (!input_mask->vlan_id)
399                 /* mask VLAN ID*/
400                 fdirm |= IXGBE_FDIRM_VLANID;
401
402         if (!input_mask->vlan_prio)
403                 /* mask VLAN priority */
404                 fdirm |= IXGBE_FDIRM_VLANP;
405
406         if (!input_mask->flexbytes)
407                 /* Mask Flex Bytes */
408                 fdirm |= IXGBE_FDIRM_FLEX;
409
410         IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
411
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);
415
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);
419
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));
426         } else {
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);
430
431                 IXGBE_WRITE_REG(hw, IXGBE_FDIRIP6M, ~fdiripv6m);
432         }
433
434         return IXGBE_SUCCESS;
435 }
436
437 int
438 ixgbe_fdir_set_masks(struct rte_eth_dev *dev, struct rte_fdir_masks *fdir_masks)
439 {
440         struct ixgbe_hw *hw;
441         int err;
442
443         PMD_INIT_FUNC_TRACE();
444
445         hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
446
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)
451                 return -ENOSYS;
452
453         err = ixgbe_reinit_fdir_tables_82599(hw);
454         if (err) {
455                 PMD_INIT_LOG(ERR, "reinit of fdir tables failed");
456                 return -EIO;
457         }
458
459         return fdir_set_input_mask_82599(hw, fdir_masks);
460 }
461
462 /*
463  * Convert DPDK rte_eth_fdir_filter struct to ixgbe_atr_input union that is used
464  * by the IXGBE driver code.
465  */
466 static int
467 ixgbe_fdir_filter_to_atr_input(const struct rte_eth_fdir_filter *fdir_filter,
468                 union ixgbe_atr_input *input)
469 {
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));
474
475         switch (fdir_filter->input.flow_type) {
476         case RTE_ETH_FLOW_TYPE_UDPV4:
477                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV4;
478                 break;
479         case RTE_ETH_FLOW_TYPE_TCPV4:
480                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV4;
481                 break;
482         case RTE_ETH_FLOW_TYPE_SCTPV4:
483                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV4;
484                 break;
485         case RTE_ETH_FLOW_TYPE_IPV4_OTHER:
486                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV4;
487                 break;
488         case RTE_ETH_FLOW_TYPE_UDPV6:
489                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_UDPV6;
490                 break;
491         case RTE_ETH_FLOW_TYPE_TCPV6:
492                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_TCPV6;
493                 break;
494         case RTE_ETH_FLOW_TYPE_SCTPV6:
495                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_SCTPV6;
496                 break;
497         case RTE_ETH_FLOW_TYPE_IPV6_OTHER:
498                 input->formatted.flow_type = IXGBE_ATR_FLOW_TYPE_IPV6;
499                 break;
500         default:
501                 PMD_DRV_LOG(ERR, " Error on flow_type input");
502                 return -EINVAL;
503         }
504
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;
519                 break;
520
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));
536                 break;
537         default:
538                 PMD_DRV_LOG(ERR, " Error on flow_type input");
539                 return -EINVAL;
540         }
541
542         return 0;
543 }
544
545 /*
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.
549  *
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.
553  *
554  * Note that the bkt_hash field in the ixgbe_atr_input structure is also never
555  * set.
556  *
557  * Compute the hashes for SW ATR
558  *  @stream: input bitstream to compute the hash on
559  *  @key: 32-bit hash key
560  **/
561 static uint32_t
562 ixgbe_atr_compute_hash_82599(union ixgbe_atr_input *atr_input,
563                                  uint32_t key)
564 {
565         /*
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
570          *
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)))]
575          *
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))]
579          *
580          *    To simplify for programming, the algorithm is implemented
581          *    in software this way:
582          *
583          *    key[31:0], hi_hash_dword[31:0], lo_hash_dword[31:0], hash[15:0]
584          *
585          *    for (i = 0; i < 352; i+=32)
586          *        hi_hash_dword[31:0] ^= Stream[(i+31):i];
587          *
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];
591          *
592          *    hi_hash_dword[31:0]  ^= Stream[351:320];
593          *
594          *    if(key[0])
595          *        hash[15:0] ^= Stream[15:0];
596          *
597          *    for (i = 0; i < 16; i++) {
598          *        if (key[i])
599          *            hash[15:0] ^= lo_hash_dword[(i+15):i];
600          *        if (key[i + 16])
601          *            hash[15:0] ^= hi_hash_dword[(i+15):i];
602          *    }
603          *
604          */
605         __be32 common_hash_dword = 0;
606         u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan;
607         u32 hash_result = 0;
608         u8 i;
609
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]);
612
613         /* generate common hash dword */
614         for (i = 1; i <= 13; i++)
615                 common_hash_dword ^= atr_input->dword_stream[i];
616
617         hi_hash_dword = IXGBE_NTOHL(common_hash_dword);
618
619         /* low dword is word swapped version of common */
620         lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16);
621
622         /* apply flow ID/VM pool/VLAN ID bits to hash words */
623         hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16);
624
625         /* Process bits 0 and 16 */
626         if (key & 0x0001) hash_result ^= lo_hash_dword;
627         if (key & 0x00010000) hash_result ^= hi_hash_dword;
628
629         /*
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
633          */
634         lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16);
635
636
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;
641         }
642
643         return hash_result;
644 }
645
646 static uint32_t
647 atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
648                 enum rte_fdir_pballoc_type pballoc)
649 {
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;
658         else
659                 return ixgbe_atr_compute_hash_82599(input,
660                                 IXGBE_ATR_BUCKET_HASH_KEY) &
661                                 PERFECT_BUCKET_64KB_HASH_MASK;
662 }
663
664 /**
665  * ixgbe_fdir_check_cmd_complete - poll to check whether FDIRCMD is complete
666  * @hw: pointer to hardware structure
667  */
668 static inline int
669 ixgbe_fdir_check_cmd_complete(struct ixgbe_hw *hw, uint32_t *fdircmd)
670 {
671         int i;
672
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))
676                         return 0;
677                 rte_delay_us(IXGBE_FDIRCMD_CMD_INTERVAL_US);
678         }
679
680         return -ETIMEDOUT;
681 }
682
683 /*
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.
688  */
689 static uint32_t
690 atr_compute_sig_hash_82599(union ixgbe_atr_input *input,
691                 enum rte_fdir_pballoc_type pballoc)
692 {
693         uint32_t bucket_hash, sig_hash;
694
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;
703         else
704                 bucket_hash = ixgbe_atr_compute_hash_82599(input,
705                                 IXGBE_ATR_BUCKET_HASH_KEY) &
706                                 SIG_BUCKET_64KB_HASH_MASK;
707
708         sig_hash = ixgbe_atr_compute_hash_82599(input,
709                         IXGBE_ATR_SIGNATURE_HASH_KEY);
710
711         return (sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT) | bucket_hash;
712 }
713
714 /*
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.
719  */
720 static int
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)
724 {
725         uint32_t fdirport, fdirvlan;
726         int err = 0;
727
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]);
731
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);
737
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);
743
744         /* configure FDIRHASH register */
745         IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
746
747         /*
748          * flush all previous writes to make certain registers are
749          * programmed prior to issuing the command
750          */
751         IXGBE_WRITE_FLUSH(hw);
752
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;
759
760         IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
761
762         PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);
763
764         err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
765         if (err < 0)
766                 PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");
767
768         return err;
769 }
770
771 /**
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
777  * work ok...
778  *
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
785  **/
786 static int
787 fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
788                 union ixgbe_atr_input *input, u8 queue, uint32_t fdircmd,
789                 uint32_t fdirhash)
790 {
791         int err = 0;
792
793         PMD_INIT_FUNC_TRACE();
794
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;
800
801         IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
802         IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
803
804         PMD_DRV_LOG(DEBUG, "Rx Queue=%x hash=%x", queue, fdirhash);
805
806         err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
807         if (err < 0)
808                 PMD_DRV_LOG(ERR, "Timeout writing flow director filter.");
809
810         return err;
811 }
812
813 /*
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.
817  */
818 static int
819 fdir_erase_filter_82599(struct ixgbe_hw *hw, uint32_t fdirhash)
820 {
821         uint32_t fdircmd = 0;
822         int err = 0;
823
824         IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
825
826         /* flush hash to HW */
827         IXGBE_WRITE_FLUSH(hw);
828
829         /* Query if filter is present */
830         IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, IXGBE_FDIRCMD_CMD_QUERY_REM_FILT);
831
832         err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
833         if (err < 0) {
834                 PMD_INIT_LOG(ERR, "Timeout querying for flow director filter.");
835                 return err;
836         }
837
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);
844         }
845         err = ixgbe_fdir_check_cmd_complete(hw, &fdircmd);
846         if (err < 0)
847                 PMD_INIT_LOG(ERR, "Timeout erasing flow director filter.");
848         return err;
849
850 }
851
852 /*
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
858  */
859 static int
860 ixgbe_add_del_fdir_filter(struct rte_eth_dev *dev,
861                               const struct rte_eth_fdir_filter *fdir_filter,
862                               bool del,
863                               bool update)
864 {
865         struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
866         uint32_t fdircmd_flags;
867         uint32_t fdirhash;
868         union ixgbe_atr_input input;
869         uint8_t queue;
870         bool is_perfect = FALSE;
871         int err;
872
873         if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_NONE)
874                 return -ENOTSUP;
875
876         if (dev->data->dev_conf.fdir_conf.mode == RTE_FDIR_MODE_PERFECT)
877                 is_perfect = TRUE;
878
879         memset(&input, 0, sizeof(input));
880
881         err = ixgbe_fdir_filter_to_atr_input(fdir_filter, &input);
882         if (err)
883                 return err;
884
885         if (is_perfect) {
886                 if (input.formatted.flow_type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
887                         PMD_DRV_LOG(ERR, "IPv6 is not supported in"
888                                          " perfect mode!");
889                         return -ENOTSUP;
890                 }
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;
895         } else
896                 fdirhash = atr_compute_sig_hash_82599(&input,
897                                 dev->data->dev_conf.fdir_conf.pballoc);
898
899         if (del) {
900                 err = fdir_erase_filter_82599(hw, fdirhash);
901                 if (err < 0)
902                         PMD_DRV_LOG(ERR, "Fail to delete FDIR filter!");
903                 else
904                         PMD_DRV_LOG(DEBUG, "Success to delete FDIR filter!");
905                 return err;
906         }
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) {
910                 if (is_perfect) {
911                         queue = dev->data->dev_conf.fdir_conf.drop_queue;
912                         fdircmd_flags |= IXGBE_FDIRCMD_DROP;
913                 } else {
914                         PMD_DRV_LOG(ERR, "Drop option is not supported in"
915                                 " signature mode.");
916                         return -EINVAL;
917                 }
918         } else if (fdir_filter->action.rx_queue < IXGBE_MAX_RX_QUEUE_NUM)
919                 queue = (uint8_t)fdir_filter->action.rx_queue;
920         else
921                 return -EINVAL;
922
923         if (is_perfect) {
924                 err = fdir_write_perfect_filter_82599(hw, &input, queue,
925                                 fdircmd_flags, fdirhash);
926         } else {
927                 err = fdir_add_signature_filter_82599(hw, &input, queue,
928                                 fdircmd_flags, fdirhash);
929         }
930         if (err < 0)
931                 PMD_DRV_LOG(ERR, "Fail to add FDIR filter!");
932         else
933                 PMD_DRV_LOG(DEBUG, "Success to add FDIR filter");
934
935         return err;
936 }
937
938 void
939 ixgbe_fdir_info_get(struct rte_eth_dev *dev, struct rte_eth_fdir *fdir)
940 {
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);
944         uint32_t reg;
945
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)
950                 return;
951
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);
958
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);
964
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;
970
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;
976
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;
986 }
987
988 /*
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
993  */
994 int
995 ixgbe_fdir_ctrl_func(struct rte_eth_dev *dev,
996                         enum rte_filter_op filter_op, void *arg)
997 {
998         struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
999         int ret = 0;
1000
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)
1005                 return -ENOTSUP;
1006
1007         if (filter_op == RTE_ETH_FILTER_NOP)
1008                 return 0;
1009
1010         if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
1011                 return -EINVAL;
1012
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);
1017                 break;
1018         case RTE_ETH_FILTER_UPDATE:
1019                 ret = ixgbe_add_del_fdir_filter(dev,
1020                         (struct rte_eth_fdir_filter *)arg, FALSE, TRUE);
1021                 break;
1022         case RTE_ETH_FILTER_DELETE:
1023                 ret = ixgbe_add_del_fdir_filter(dev,
1024                         (struct rte_eth_fdir_filter *)arg, TRUE, FALSE);
1025                 break;
1026         default:
1027                 PMD_DRV_LOG(ERR, "unknown operation %u", filter_op);
1028                 ret = -EINVAL;
1029                 break;
1030         }
1031         return ret;
1032 }