net/mlx5: support flag flow action
[dpdk.git] / drivers / net / mlx5 / mlx5_flow.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2016 6WIND S.A.
5  *   Copyright 2016 Mellanox.
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 6WIND S.A. nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <sys/queue.h>
35 #include <string.h>
36
37 /* Verbs header. */
38 /* ISO C doesn't support unnamed structs/unions, disabling -pedantic. */
39 #ifdef PEDANTIC
40 #pragma GCC diagnostic ignored "-Wpedantic"
41 #endif
42 #include <infiniband/verbs.h>
43 #ifdef PEDANTIC
44 #pragma GCC diagnostic error "-Wpedantic"
45 #endif
46
47 #include <rte_ethdev.h>
48 #include <rte_flow.h>
49 #include <rte_flow_driver.h>
50 #include <rte_malloc.h>
51
52 #include "mlx5.h"
53 #include "mlx5_prm.h"
54
55 static int
56 mlx5_flow_create_eth(const struct rte_flow_item *item,
57                      const void *default_mask,
58                      void *data);
59
60 static int
61 mlx5_flow_create_vlan(const struct rte_flow_item *item,
62                       const void *default_mask,
63                       void *data);
64
65 static int
66 mlx5_flow_create_ipv4(const struct rte_flow_item *item,
67                       const void *default_mask,
68                       void *data);
69
70 static int
71 mlx5_flow_create_ipv6(const struct rte_flow_item *item,
72                       const void *default_mask,
73                       void *data);
74
75 static int
76 mlx5_flow_create_udp(const struct rte_flow_item *item,
77                      const void *default_mask,
78                      void *data);
79
80 static int
81 mlx5_flow_create_tcp(const struct rte_flow_item *item,
82                      const void *default_mask,
83                      void *data);
84
85 static int
86 mlx5_flow_create_vxlan(const struct rte_flow_item *item,
87                        const void *default_mask,
88                        void *data);
89
90 struct rte_flow {
91         LIST_ENTRY(rte_flow) next; /**< Pointer to the next flow structure. */
92         struct ibv_exp_flow_attr *ibv_attr; /**< Pointer to Verbs attributes. */
93         struct ibv_exp_rwq_ind_table *ind_table; /**< Indirection table. */
94         struct ibv_qp *qp; /**< Verbs queue pair. */
95         struct ibv_exp_flow *ibv_flow; /**< Verbs flow. */
96         struct ibv_exp_wq *wq; /**< Verbs work queue. */
97         struct ibv_cq *cq; /**< Verbs completion queue. */
98         struct rxq *rxq; /**< Pointer to the queue, NULL if drop queue. */
99         uint32_t mark:1; /**< Set if the flow is marked. */
100 };
101
102 /** Static initializer for items. */
103 #define ITEMS(...) \
104         (const enum rte_flow_item_type []){ \
105                 __VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
106         }
107
108 /** Structure to generate a simple graph of layers supported by the NIC. */
109 struct mlx5_flow_items {
110         /** List of possible actions for these items. */
111         const enum rte_flow_action_type *const actions;
112         /** Bit-masks corresponding to the possibilities for the item. */
113         const void *mask;
114         /**
115          * Default bit-masks to use when item->mask is not provided. When
116          * \default_mask is also NULL, the full supported bit-mask (\mask) is
117          * used instead.
118          */
119         const void *default_mask;
120         /** Bit-masks size in bytes. */
121         const unsigned int mask_sz;
122         /**
123          * Conversion function from rte_flow to NIC specific flow.
124          *
125          * @param item
126          *   rte_flow item to convert.
127          * @param default_mask
128          *   Default bit-masks to use when item->mask is not provided.
129          * @param data
130          *   Internal structure to store the conversion.
131          *
132          * @return
133          *   0 on success, negative value otherwise.
134          */
135         int (*convert)(const struct rte_flow_item *item,
136                        const void *default_mask,
137                        void *data);
138         /** Size in bytes of the destination structure. */
139         const unsigned int dst_sz;
140         /** List of possible following items.  */
141         const enum rte_flow_item_type *const items;
142 };
143
144 /** Valid action for this PMD. */
145 static const enum rte_flow_action_type valid_actions[] = {
146         RTE_FLOW_ACTION_TYPE_DROP,
147         RTE_FLOW_ACTION_TYPE_QUEUE,
148         RTE_FLOW_ACTION_TYPE_MARK,
149         RTE_FLOW_ACTION_TYPE_FLAG,
150         RTE_FLOW_ACTION_TYPE_END,
151 };
152
153 /** Graph of supported items and associated actions. */
154 static const struct mlx5_flow_items mlx5_flow_items[] = {
155         [RTE_FLOW_ITEM_TYPE_END] = {
156                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH,
157                                RTE_FLOW_ITEM_TYPE_VXLAN),
158         },
159         [RTE_FLOW_ITEM_TYPE_ETH] = {
160                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_VLAN,
161                                RTE_FLOW_ITEM_TYPE_IPV4,
162                                RTE_FLOW_ITEM_TYPE_IPV6),
163                 .actions = valid_actions,
164                 .mask = &(const struct rte_flow_item_eth){
165                         .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff",
166                         .src.addr_bytes = "\xff\xff\xff\xff\xff\xff",
167                         .type = -1,
168                 },
169                 .default_mask = &rte_flow_item_eth_mask,
170                 .mask_sz = sizeof(struct rte_flow_item_eth),
171                 .convert = mlx5_flow_create_eth,
172                 .dst_sz = sizeof(struct ibv_exp_flow_spec_eth),
173         },
174         [RTE_FLOW_ITEM_TYPE_VLAN] = {
175                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_IPV4,
176                                RTE_FLOW_ITEM_TYPE_IPV6),
177                 .actions = valid_actions,
178                 .mask = &(const struct rte_flow_item_vlan){
179                         .tci = -1,
180                 },
181                 .default_mask = &rte_flow_item_vlan_mask,
182                 .mask_sz = sizeof(struct rte_flow_item_vlan),
183                 .convert = mlx5_flow_create_vlan,
184                 .dst_sz = 0,
185         },
186         [RTE_FLOW_ITEM_TYPE_IPV4] = {
187                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
188                                RTE_FLOW_ITEM_TYPE_TCP),
189                 .actions = valid_actions,
190                 .mask = &(const struct rte_flow_item_ipv4){
191                         .hdr = {
192                                 .src_addr = -1,
193                                 .dst_addr = -1,
194                                 .type_of_service = -1,
195                                 .next_proto_id = -1,
196                         },
197                 },
198                 .default_mask = &rte_flow_item_ipv4_mask,
199                 .mask_sz = sizeof(struct rte_flow_item_ipv4),
200                 .convert = mlx5_flow_create_ipv4,
201                 .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv4_ext),
202         },
203         [RTE_FLOW_ITEM_TYPE_IPV6] = {
204                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_UDP,
205                                RTE_FLOW_ITEM_TYPE_TCP),
206                 .actions = valid_actions,
207                 .mask = &(const struct rte_flow_item_ipv6){
208                         .hdr = {
209                                 .src_addr = {
210                                         0xff, 0xff, 0xff, 0xff,
211                                         0xff, 0xff, 0xff, 0xff,
212                                         0xff, 0xff, 0xff, 0xff,
213                                         0xff, 0xff, 0xff, 0xff,
214                                 },
215                                 .dst_addr = {
216                                         0xff, 0xff, 0xff, 0xff,
217                                         0xff, 0xff, 0xff, 0xff,
218                                         0xff, 0xff, 0xff, 0xff,
219                                         0xff, 0xff, 0xff, 0xff,
220                                 },
221                                 .vtc_flow = -1,
222                                 .proto = -1,
223                                 .hop_limits = -1,
224                         },
225                 },
226                 .default_mask = &rte_flow_item_ipv6_mask,
227                 .mask_sz = sizeof(struct rte_flow_item_ipv6),
228                 .convert = mlx5_flow_create_ipv6,
229                 .dst_sz = sizeof(struct ibv_exp_flow_spec_ipv6_ext),
230         },
231         [RTE_FLOW_ITEM_TYPE_UDP] = {
232                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_VXLAN),
233                 .actions = valid_actions,
234                 .mask = &(const struct rte_flow_item_udp){
235                         .hdr = {
236                                 .src_port = -1,
237                                 .dst_port = -1,
238                         },
239                 },
240                 .default_mask = &rte_flow_item_udp_mask,
241                 .mask_sz = sizeof(struct rte_flow_item_udp),
242                 .convert = mlx5_flow_create_udp,
243                 .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp),
244         },
245         [RTE_FLOW_ITEM_TYPE_TCP] = {
246                 .actions = valid_actions,
247                 .mask = &(const struct rte_flow_item_tcp){
248                         .hdr = {
249                                 .src_port = -1,
250                                 .dst_port = -1,
251                         },
252                 },
253                 .default_mask = &rte_flow_item_tcp_mask,
254                 .mask_sz = sizeof(struct rte_flow_item_tcp),
255                 .convert = mlx5_flow_create_tcp,
256                 .dst_sz = sizeof(struct ibv_exp_flow_spec_tcp_udp),
257         },
258         [RTE_FLOW_ITEM_TYPE_VXLAN] = {
259                 .items = ITEMS(RTE_FLOW_ITEM_TYPE_ETH),
260                 .actions = valid_actions,
261                 .mask = &(const struct rte_flow_item_vxlan){
262                         .vni = "\xff\xff\xff",
263                 },
264                 .default_mask = &rte_flow_item_vxlan_mask,
265                 .mask_sz = sizeof(struct rte_flow_item_vxlan),
266                 .convert = mlx5_flow_create_vxlan,
267                 .dst_sz = sizeof(struct ibv_exp_flow_spec_tunnel),
268         },
269 };
270
271 /** Structure to pass to the conversion function. */
272 struct mlx5_flow {
273         struct ibv_exp_flow_attr *ibv_attr; /**< Verbs attribute. */
274         unsigned int offset; /**< Offset in bytes in the ibv_attr buffer. */
275         uint32_t inner; /**< Set once VXLAN is encountered. */
276 };
277
278 struct mlx5_flow_action {
279         uint32_t queue:1; /**< Target is a receive queue. */
280         uint32_t drop:1; /**< Target is a drop queue. */
281         uint32_t mark:1; /**< Mark is present in the flow. */
282         uint32_t queue_id; /**< Identifier of the queue. */
283         uint32_t mark_id; /**< Mark identifier. */
284 };
285
286 /**
287  * Check support for a given item.
288  *
289  * @param item[in]
290  *   Item specification.
291  * @param mask[in]
292  *   Bit-masks covering supported fields to compare with spec, last and mask in
293  *   \item.
294  * @param size
295  *   Bit-Mask size in bytes.
296  *
297  * @return
298  *   0 on success.
299  */
300 static int
301 mlx5_flow_item_validate(const struct rte_flow_item *item,
302                         const uint8_t *mask, unsigned int size)
303 {
304         int ret = 0;
305
306         if (!item->spec && (item->mask || item->last))
307                 return -1;
308         if (item->spec && !item->mask) {
309                 unsigned int i;
310                 const uint8_t *spec = item->spec;
311
312                 for (i = 0; i < size; ++i)
313                         if ((spec[i] | mask[i]) != mask[i])
314                                 return -1;
315         }
316         if (item->last && !item->mask) {
317                 unsigned int i;
318                 const uint8_t *spec = item->last;
319
320                 for (i = 0; i < size; ++i)
321                         if ((spec[i] | mask[i]) != mask[i])
322                                 return -1;
323         }
324         if (item->mask) {
325                 unsigned int i;
326                 const uint8_t *spec = item->mask;
327
328                 for (i = 0; i < size; ++i)
329                         if ((spec[i] | mask[i]) != mask[i])
330                                 return -1;
331         }
332         if (item->spec && item->last) {
333                 uint8_t spec[size];
334                 uint8_t last[size];
335                 const uint8_t *apply = mask;
336                 unsigned int i;
337
338                 if (item->mask)
339                         apply = item->mask;
340                 for (i = 0; i < size; ++i) {
341                         spec[i] = ((const uint8_t *)item->spec)[i] & apply[i];
342                         last[i] = ((const uint8_t *)item->last)[i] & apply[i];
343                 }
344                 ret = memcmp(spec, last, size);
345         }
346         return ret;
347 }
348
349 /**
350  * Validate a flow supported by the NIC.
351  *
352  * @param priv
353  *   Pointer to private structure.
354  * @param[in] attr
355  *   Flow rule attributes.
356  * @param[in] pattern
357  *   Pattern specification (list terminated by the END pattern item).
358  * @param[in] actions
359  *   Associated actions (list terminated by the END action).
360  * @param[out] error
361  *   Perform verbose error reporting if not NULL.
362  * @param[in, out] flow
363  *   Flow structure to update.
364  *
365  * @return
366  *   0 on success, a negative errno value otherwise and rte_errno is set.
367  */
368 static int
369 priv_flow_validate(struct priv *priv,
370                    const struct rte_flow_attr *attr,
371                    const struct rte_flow_item items[],
372                    const struct rte_flow_action actions[],
373                    struct rte_flow_error *error,
374                    struct mlx5_flow *flow)
375 {
376         const struct mlx5_flow_items *cur_item = mlx5_flow_items;
377         struct mlx5_flow_action action = {
378                 .queue = 0,
379                 .drop = 0,
380                 .mark = 0,
381         };
382
383         (void)priv;
384         if (attr->group) {
385                 rte_flow_error_set(error, ENOTSUP,
386                                    RTE_FLOW_ERROR_TYPE_ATTR_GROUP,
387                                    NULL,
388                                    "groups are not supported");
389                 return -rte_errno;
390         }
391         if (attr->priority) {
392                 rte_flow_error_set(error, ENOTSUP,
393                                    RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
394                                    NULL,
395                                    "priorities are not supported");
396                 return -rte_errno;
397         }
398         if (attr->egress) {
399                 rte_flow_error_set(error, ENOTSUP,
400                                    RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
401                                    NULL,
402                                    "egress is not supported");
403                 return -rte_errno;
404         }
405         if (!attr->ingress) {
406                 rte_flow_error_set(error, ENOTSUP,
407                                    RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
408                                    NULL,
409                                    "only ingress is supported");
410                 return -rte_errno;
411         }
412         for (; items->type != RTE_FLOW_ITEM_TYPE_END; ++items) {
413                 const struct mlx5_flow_items *token = NULL;
414                 unsigned int i;
415                 int err;
416
417                 if (items->type == RTE_FLOW_ITEM_TYPE_VOID)
418                         continue;
419                 for (i = 0;
420                      cur_item->items &&
421                      cur_item->items[i] != RTE_FLOW_ITEM_TYPE_END;
422                      ++i) {
423                         if (cur_item->items[i] == items->type) {
424                                 token = &mlx5_flow_items[items->type];
425                                 break;
426                         }
427                 }
428                 if (!token)
429                         goto exit_item_not_supported;
430                 cur_item = token;
431                 err = mlx5_flow_item_validate(items,
432                                               (const uint8_t *)cur_item->mask,
433                                               cur_item->mask_sz);
434                 if (err)
435                         goto exit_item_not_supported;
436                 if (flow->ibv_attr && cur_item->convert) {
437                         err = cur_item->convert(items,
438                                                 (cur_item->default_mask ?
439                                                  cur_item->default_mask :
440                                                  cur_item->mask),
441                                                 flow);
442                         if (err)
443                                 goto exit_item_not_supported;
444                 }
445                 flow->offset += cur_item->dst_sz;
446         }
447         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
448                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
449                         continue;
450                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
451                         action.drop = 1;
452                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
453                         const struct rte_flow_action_queue *queue =
454                                 (const struct rte_flow_action_queue *)
455                                 actions->conf;
456
457                         if (!queue || (queue->index > (priv->rxqs_n - 1)))
458                                 goto exit_action_not_supported;
459                         action.queue = 1;
460                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) {
461                         const struct rte_flow_action_mark *mark =
462                                 (const struct rte_flow_action_mark *)
463                                 actions->conf;
464
465                         if (!mark) {
466                                 rte_flow_error_set(error, EINVAL,
467                                                    RTE_FLOW_ERROR_TYPE_ACTION,
468                                                    actions,
469                                                    "mark must be defined");
470                                 return -rte_errno;
471                         } else if (mark->id >= MLX5_FLOW_MARK_MAX) {
472                                 rte_flow_error_set(error, ENOTSUP,
473                                                    RTE_FLOW_ERROR_TYPE_ACTION,
474                                                    actions,
475                                                    "mark must be between 0"
476                                                    " and 16777199");
477                                 return -rte_errno;
478                         }
479                         action.mark = 1;
480                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
481                         action.mark = 1;
482                 } else {
483                         goto exit_action_not_supported;
484                 }
485         }
486         if (action.mark && !flow->ibv_attr && !action.drop)
487                 flow->offset += sizeof(struct ibv_exp_flow_spec_action_tag);
488         if (!action.queue && !action.drop) {
489                 rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_HANDLE,
490                                    NULL, "no valid action");
491                 return -rte_errno;
492         }
493         return 0;
494 exit_item_not_supported:
495         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM,
496                            items, "item not supported");
497         return -rte_errno;
498 exit_action_not_supported:
499         rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
500                            actions, "action not supported");
501         return -rte_errno;
502 }
503
504 /**
505  * Validate a flow supported by the NIC.
506  *
507  * @see rte_flow_validate()
508  * @see rte_flow_ops
509  */
510 int
511 mlx5_flow_validate(struct rte_eth_dev *dev,
512                    const struct rte_flow_attr *attr,
513                    const struct rte_flow_item items[],
514                    const struct rte_flow_action actions[],
515                    struct rte_flow_error *error)
516 {
517         struct priv *priv = dev->data->dev_private;
518         int ret;
519         struct mlx5_flow flow = { .offset = sizeof(struct ibv_exp_flow_attr) };
520
521         priv_lock(priv);
522         ret = priv_flow_validate(priv, attr, items, actions, error, &flow);
523         priv_unlock(priv);
524         return ret;
525 }
526
527 /**
528  * Convert Ethernet item to Verbs specification.
529  *
530  * @param item[in]
531  *   Item specification.
532  * @param default_mask[in]
533  *   Default bit-masks to use when item->mask is not provided.
534  * @param data[in, out]
535  *   User structure.
536  */
537 static int
538 mlx5_flow_create_eth(const struct rte_flow_item *item,
539                      const void *default_mask,
540                      void *data)
541 {
542         const struct rte_flow_item_eth *spec = item->spec;
543         const struct rte_flow_item_eth *mask = item->mask;
544         struct mlx5_flow *flow = (struct mlx5_flow *)data;
545         struct ibv_exp_flow_spec_eth *eth;
546         const unsigned int eth_size = sizeof(struct ibv_exp_flow_spec_eth);
547         unsigned int i;
548
549         ++flow->ibv_attr->num_of_specs;
550         flow->ibv_attr->priority = 2;
551         eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
552         *eth = (struct ibv_exp_flow_spec_eth) {
553                 .type = flow->inner | IBV_EXP_FLOW_SPEC_ETH,
554                 .size = eth_size,
555         };
556         if (!spec)
557                 return 0;
558         if (!mask)
559                 mask = default_mask;
560         memcpy(eth->val.dst_mac, spec->dst.addr_bytes, ETHER_ADDR_LEN);
561         memcpy(eth->val.src_mac, spec->src.addr_bytes, ETHER_ADDR_LEN);
562         eth->val.ether_type = spec->type;
563         memcpy(eth->mask.dst_mac, mask->dst.addr_bytes, ETHER_ADDR_LEN);
564         memcpy(eth->mask.src_mac, mask->src.addr_bytes, ETHER_ADDR_LEN);
565         eth->mask.ether_type = mask->type;
566         /* Remove unwanted bits from values. */
567         for (i = 0; i < ETHER_ADDR_LEN; ++i) {
568                 eth->val.dst_mac[i] &= eth->mask.dst_mac[i];
569                 eth->val.src_mac[i] &= eth->mask.src_mac[i];
570         }
571         eth->val.ether_type &= eth->mask.ether_type;
572         return 0;
573 }
574
575 /**
576  * Convert VLAN item to Verbs specification.
577  *
578  * @param item[in]
579  *   Item specification.
580  * @param default_mask[in]
581  *   Default bit-masks to use when item->mask is not provided.
582  * @param data[in, out]
583  *   User structure.
584  */
585 static int
586 mlx5_flow_create_vlan(const struct rte_flow_item *item,
587                       const void *default_mask,
588                       void *data)
589 {
590         const struct rte_flow_item_vlan *spec = item->spec;
591         const struct rte_flow_item_vlan *mask = item->mask;
592         struct mlx5_flow *flow = (struct mlx5_flow *)data;
593         struct ibv_exp_flow_spec_eth *eth;
594         const unsigned int eth_size = sizeof(struct ibv_exp_flow_spec_eth);
595
596         eth = (void *)((uintptr_t)flow->ibv_attr + flow->offset - eth_size);
597         if (!spec)
598                 return 0;
599         if (!mask)
600                 mask = default_mask;
601         eth->val.vlan_tag = spec->tci;
602         eth->mask.vlan_tag = mask->tci;
603         eth->val.vlan_tag &= eth->mask.vlan_tag;
604         return 0;
605 }
606
607 /**
608  * Convert IPv4 item to Verbs specification.
609  *
610  * @param item[in]
611  *   Item specification.
612  * @param default_mask[in]
613  *   Default bit-masks to use when item->mask is not provided.
614  * @param data[in, out]
615  *   User structure.
616  */
617 static int
618 mlx5_flow_create_ipv4(const struct rte_flow_item *item,
619                       const void *default_mask,
620                       void *data)
621 {
622         const struct rte_flow_item_ipv4 *spec = item->spec;
623         const struct rte_flow_item_ipv4 *mask = item->mask;
624         struct mlx5_flow *flow = (struct mlx5_flow *)data;
625         struct ibv_exp_flow_spec_ipv4_ext *ipv4;
626         unsigned int ipv4_size = sizeof(struct ibv_exp_flow_spec_ipv4_ext);
627
628         ++flow->ibv_attr->num_of_specs;
629         flow->ibv_attr->priority = 1;
630         ipv4 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
631         *ipv4 = (struct ibv_exp_flow_spec_ipv4_ext) {
632                 .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV4_EXT,
633                 .size = ipv4_size,
634         };
635         if (!spec)
636                 return 0;
637         if (!mask)
638                 mask = default_mask;
639         ipv4->val = (struct ibv_exp_flow_ipv4_ext_filter){
640                 .src_ip = spec->hdr.src_addr,
641                 .dst_ip = spec->hdr.dst_addr,
642                 .proto = spec->hdr.next_proto_id,
643                 .tos = spec->hdr.type_of_service,
644         };
645         ipv4->mask = (struct ibv_exp_flow_ipv4_ext_filter){
646                 .src_ip = mask->hdr.src_addr,
647                 .dst_ip = mask->hdr.dst_addr,
648                 .proto = mask->hdr.next_proto_id,
649                 .tos = mask->hdr.type_of_service,
650         };
651         /* Remove unwanted bits from values. */
652         ipv4->val.src_ip &= ipv4->mask.src_ip;
653         ipv4->val.dst_ip &= ipv4->mask.dst_ip;
654         ipv4->val.proto &= ipv4->mask.proto;
655         ipv4->val.tos &= ipv4->mask.tos;
656         return 0;
657 }
658
659 /**
660  * Convert IPv6 item to Verbs specification.
661  *
662  * @param item[in]
663  *   Item specification.
664  * @param default_mask[in]
665  *   Default bit-masks to use when item->mask is not provided.
666  * @param data[in, out]
667  *   User structure.
668  */
669 static int
670 mlx5_flow_create_ipv6(const struct rte_flow_item *item,
671                       const void *default_mask,
672                       void *data)
673 {
674         const struct rte_flow_item_ipv6 *spec = item->spec;
675         const struct rte_flow_item_ipv6 *mask = item->mask;
676         struct mlx5_flow *flow = (struct mlx5_flow *)data;
677         struct ibv_exp_flow_spec_ipv6_ext *ipv6;
678         unsigned int ipv6_size = sizeof(struct ibv_exp_flow_spec_ipv6_ext);
679
680         ++flow->ibv_attr->num_of_specs;
681         flow->ibv_attr->priority = 1;
682         ipv6 = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
683         *ipv6 = (struct ibv_exp_flow_spec_ipv6_ext) {
684                 .type = flow->inner | IBV_EXP_FLOW_SPEC_IPV6_EXT,
685                 .size = ipv6_size,
686         };
687         if (!spec)
688                 return 0;
689         if (!mask)
690                 mask = default_mask;
691         memcpy(ipv6->val.src_ip, spec->hdr.src_addr,
692                RTE_DIM(ipv6->val.src_ip));
693         memcpy(ipv6->val.dst_ip, spec->hdr.dst_addr,
694                RTE_DIM(ipv6->val.dst_ip));
695         memcpy(ipv6->mask.src_ip, mask->hdr.src_addr,
696                RTE_DIM(ipv6->mask.src_ip));
697         memcpy(ipv6->mask.dst_ip, mask->hdr.dst_addr,
698                RTE_DIM(ipv6->mask.dst_ip));
699         ipv6->mask.flow_label = mask->hdr.vtc_flow;
700         ipv6->mask.next_hdr = mask->hdr.proto;
701         ipv6->mask.hop_limit = mask->hdr.hop_limits;
702         ipv6->val.flow_label &= ipv6->mask.flow_label;
703         ipv6->val.next_hdr &= ipv6->mask.next_hdr;
704         ipv6->val.hop_limit &= ipv6->mask.hop_limit;
705         return 0;
706 }
707
708 /**
709  * Convert UDP item to Verbs specification.
710  *
711  * @param item[in]
712  *   Item specification.
713  * @param default_mask[in]
714  *   Default bit-masks to use when item->mask is not provided.
715  * @param data[in, out]
716  *   User structure.
717  */
718 static int
719 mlx5_flow_create_udp(const struct rte_flow_item *item,
720                      const void *default_mask,
721                      void *data)
722 {
723         const struct rte_flow_item_udp *spec = item->spec;
724         const struct rte_flow_item_udp *mask = item->mask;
725         struct mlx5_flow *flow = (struct mlx5_flow *)data;
726         struct ibv_exp_flow_spec_tcp_udp *udp;
727         unsigned int udp_size = sizeof(struct ibv_exp_flow_spec_tcp_udp);
728
729         ++flow->ibv_attr->num_of_specs;
730         flow->ibv_attr->priority = 0;
731         udp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
732         *udp = (struct ibv_exp_flow_spec_tcp_udp) {
733                 .type = flow->inner | IBV_EXP_FLOW_SPEC_UDP,
734                 .size = udp_size,
735         };
736         if (!spec)
737                 return 0;
738         if (!mask)
739                 mask = default_mask;
740         udp->val.dst_port = spec->hdr.dst_port;
741         udp->val.src_port = spec->hdr.src_port;
742         udp->mask.dst_port = mask->hdr.dst_port;
743         udp->mask.src_port = mask->hdr.src_port;
744         /* Remove unwanted bits from values. */
745         udp->val.src_port &= udp->mask.src_port;
746         udp->val.dst_port &= udp->mask.dst_port;
747         return 0;
748 }
749
750 /**
751  * Convert TCP item to Verbs specification.
752  *
753  * @param item[in]
754  *   Item specification.
755  * @param default_mask[in]
756  *   Default bit-masks to use when item->mask is not provided.
757  * @param data[in, out]
758  *   User structure.
759  */
760 static int
761 mlx5_flow_create_tcp(const struct rte_flow_item *item,
762                      const void *default_mask,
763                      void *data)
764 {
765         const struct rte_flow_item_tcp *spec = item->spec;
766         const struct rte_flow_item_tcp *mask = item->mask;
767         struct mlx5_flow *flow = (struct mlx5_flow *)data;
768         struct ibv_exp_flow_spec_tcp_udp *tcp;
769         unsigned int tcp_size = sizeof(struct ibv_exp_flow_spec_tcp_udp);
770
771         ++flow->ibv_attr->num_of_specs;
772         flow->ibv_attr->priority = 0;
773         tcp = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
774         *tcp = (struct ibv_exp_flow_spec_tcp_udp) {
775                 .type = flow->inner | IBV_EXP_FLOW_SPEC_TCP,
776                 .size = tcp_size,
777         };
778         if (!spec)
779                 return 0;
780         if (!mask)
781                 mask = default_mask;
782         tcp->val.dst_port = spec->hdr.dst_port;
783         tcp->val.src_port = spec->hdr.src_port;
784         tcp->mask.dst_port = mask->hdr.dst_port;
785         tcp->mask.src_port = mask->hdr.src_port;
786         /* Remove unwanted bits from values. */
787         tcp->val.src_port &= tcp->mask.src_port;
788         tcp->val.dst_port &= tcp->mask.dst_port;
789         return 0;
790 }
791
792 /**
793  * Convert VXLAN item to Verbs specification.
794  *
795  * @param item[in]
796  *   Item specification.
797  * @param default_mask[in]
798  *   Default bit-masks to use when item->mask is not provided.
799  * @param data[in, out]
800  *   User structure.
801  */
802 static int
803 mlx5_flow_create_vxlan(const struct rte_flow_item *item,
804                        const void *default_mask,
805                        void *data)
806 {
807         const struct rte_flow_item_vxlan *spec = item->spec;
808         const struct rte_flow_item_vxlan *mask = item->mask;
809         struct mlx5_flow *flow = (struct mlx5_flow *)data;
810         struct ibv_exp_flow_spec_tunnel *vxlan;
811         unsigned int size = sizeof(struct ibv_exp_flow_spec_tunnel);
812         union vni {
813                 uint32_t vlan_id;
814                 uint8_t vni[4];
815         } id;
816
817         ++flow->ibv_attr->num_of_specs;
818         flow->ibv_attr->priority = 0;
819         id.vni[0] = 0;
820         vxlan = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
821         *vxlan = (struct ibv_exp_flow_spec_tunnel) {
822                 .type = flow->inner | IBV_EXP_FLOW_SPEC_VXLAN_TUNNEL,
823                 .size = size,
824         };
825         flow->inner = IBV_EXP_FLOW_SPEC_INNER;
826         if (!spec)
827                 return 0;
828         if (!mask)
829                 mask = default_mask;
830         memcpy(&id.vni[1], spec->vni, 3);
831         vxlan->val.tunnel_id = id.vlan_id;
832         memcpy(&id.vni[1], mask->vni, 3);
833         vxlan->mask.tunnel_id = id.vlan_id;
834         /* Remove unwanted bits from values. */
835         vxlan->val.tunnel_id &= vxlan->mask.tunnel_id;
836         return 0;
837 }
838
839 /**
840  * Convert mark/flag action to Verbs specification.
841  *
842  * @param flow
843  *   Pointer to MLX5 flow structure.
844  * @param mark_id
845  *   Mark identifier.
846  */
847 static int
848 mlx5_flow_create_flag_mark(struct mlx5_flow *flow, uint32_t mark_id)
849 {
850         struct ibv_exp_flow_spec_action_tag *tag;
851         unsigned int size = sizeof(struct ibv_exp_flow_spec_action_tag);
852
853         tag = (void *)((uintptr_t)flow->ibv_attr + flow->offset);
854         *tag = (struct ibv_exp_flow_spec_action_tag){
855                 .type = IBV_EXP_FLOW_SPEC_ACTION_TAG,
856                 .size = size,
857                 .tag_id = mlx5_flow_mark_set(mark_id),
858         };
859         ++flow->ibv_attr->num_of_specs;
860         return 0;
861 }
862
863 /**
864  * Complete flow rule creation.
865  *
866  * @param priv
867  *   Pointer to private structure.
868  * @param ibv_attr
869  *   Verbs flow attributes.
870  * @param action
871  *   Target action structure.
872  * @param[out] error
873  *   Perform verbose error reporting if not NULL.
874  *
875  * @return
876  *   A flow if the rule could be created.
877  */
878 static struct rte_flow *
879 priv_flow_create_action_queue(struct priv *priv,
880                               struct ibv_exp_flow_attr *ibv_attr,
881                               struct mlx5_flow_action *action,
882                               struct rte_flow_error *error)
883 {
884         struct rxq_ctrl *rxq;
885         struct rte_flow *rte_flow;
886
887         assert(priv->pd);
888         assert(priv->ctx);
889         rte_flow = rte_calloc(__func__, 1, sizeof(*rte_flow), 0);
890         if (!rte_flow) {
891                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
892                                    NULL, "cannot allocate flow memory");
893                 return NULL;
894         }
895         if (action->drop) {
896                 rte_flow->cq =
897                         ibv_exp_create_cq(priv->ctx, 1, NULL, NULL, 0,
898                                           &(struct ibv_exp_cq_init_attr){
899                                                   .comp_mask = 0,
900                                           });
901                 if (!rte_flow->cq) {
902                         rte_flow_error_set(error, ENOMEM,
903                                            RTE_FLOW_ERROR_TYPE_HANDLE,
904                                            NULL, "cannot allocate CQ");
905                         goto error;
906                 }
907                 rte_flow->wq = ibv_exp_create_wq(priv->ctx,
908                                                  &(struct ibv_exp_wq_init_attr){
909                                                  .wq_type = IBV_EXP_WQT_RQ,
910                                                  .max_recv_wr = 1,
911                                                  .max_recv_sge = 1,
912                                                  .pd = priv->pd,
913                                                  .cq = rte_flow->cq,
914                                                  });
915                 if (!rte_flow->wq) {
916                         rte_flow_error_set(error, ENOMEM,
917                                            RTE_FLOW_ERROR_TYPE_HANDLE,
918                                            NULL, "cannot allocate WQ");
919                         goto error;
920                 }
921         } else {
922                 rxq = container_of((*priv->rxqs)[action->queue_id],
923                                    struct rxq_ctrl, rxq);
924                 rte_flow->rxq = &rxq->rxq;
925                 rxq->rxq.mark |= action->mark;
926                 rte_flow->wq = rxq->wq;
927         }
928         rte_flow->mark = action->mark;
929         rte_flow->ibv_attr = ibv_attr;
930         rte_flow->ind_table = ibv_exp_create_rwq_ind_table(
931                 priv->ctx,
932                 &(struct ibv_exp_rwq_ind_table_init_attr){
933                         .pd = priv->pd,
934                         .log_ind_tbl_size = 0,
935                         .ind_tbl = &rte_flow->wq,
936                         .comp_mask = 0,
937                 });
938         if (!rte_flow->ind_table) {
939                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
940                                    NULL, "cannot allocate indirection table");
941                 goto error;
942         }
943         rte_flow->qp = ibv_exp_create_qp(
944                 priv->ctx,
945                 &(struct ibv_exp_qp_init_attr){
946                         .qp_type = IBV_QPT_RAW_PACKET,
947                         .comp_mask =
948                                 IBV_EXP_QP_INIT_ATTR_PD |
949                                 IBV_EXP_QP_INIT_ATTR_PORT |
950                                 IBV_EXP_QP_INIT_ATTR_RX_HASH,
951                         .pd = priv->pd,
952                         .rx_hash_conf = &(struct ibv_exp_rx_hash_conf){
953                                 .rx_hash_function =
954                                         IBV_EXP_RX_HASH_FUNC_TOEPLITZ,
955                                 .rx_hash_key_len = rss_hash_default_key_len,
956                                 .rx_hash_key = rss_hash_default_key,
957                                 .rx_hash_fields_mask = 0,
958                                 .rwq_ind_tbl = rte_flow->ind_table,
959                         },
960                         .port_num = priv->port,
961                 });
962         if (!rte_flow->qp) {
963                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
964                                    NULL, "cannot allocate QP");
965                 goto error;
966         }
967         if (!priv->started)
968                 return rte_flow;
969         rte_flow->ibv_flow = ibv_exp_create_flow(rte_flow->qp,
970                                                  rte_flow->ibv_attr);
971         if (!rte_flow->ibv_flow) {
972                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
973                                    NULL, "flow rule creation failure");
974                 goto error;
975         }
976         return rte_flow;
977 error:
978         assert(rte_flow);
979         if (rte_flow->qp)
980                 ibv_destroy_qp(rte_flow->qp);
981         if (rte_flow->ind_table)
982                 ibv_exp_destroy_rwq_ind_table(rte_flow->ind_table);
983         if (!rte_flow->rxq && rte_flow->wq)
984                 ibv_exp_destroy_wq(rte_flow->wq);
985         if (!rte_flow->rxq && rte_flow->cq)
986                 ibv_destroy_cq(rte_flow->cq);
987         rte_free(rte_flow);
988         return NULL;
989 }
990
991 /**
992  * Convert a flow.
993  *
994  * @param priv
995  *   Pointer to private structure.
996  * @param[in] attr
997  *   Flow rule attributes.
998  * @param[in] pattern
999  *   Pattern specification (list terminated by the END pattern item).
1000  * @param[in] actions
1001  *   Associated actions (list terminated by the END action).
1002  * @param[out] error
1003  *   Perform verbose error reporting if not NULL.
1004  *
1005  * @return
1006  *   A flow on success, NULL otherwise.
1007  */
1008 static struct rte_flow *
1009 priv_flow_create(struct priv *priv,
1010                  const struct rte_flow_attr *attr,
1011                  const struct rte_flow_item items[],
1012                  const struct rte_flow_action actions[],
1013                  struct rte_flow_error *error)
1014 {
1015         struct rte_flow *rte_flow;
1016         struct mlx5_flow_action action;
1017         struct mlx5_flow flow = { .offset = sizeof(struct ibv_exp_flow_attr), };
1018         int err;
1019
1020         err = priv_flow_validate(priv, attr, items, actions, error, &flow);
1021         if (err)
1022                 goto exit;
1023         flow.ibv_attr = rte_malloc(__func__, flow.offset, 0);
1024         flow.offset = sizeof(struct ibv_exp_flow_attr);
1025         if (!flow.ibv_attr) {
1026                 rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE,
1027                                    NULL, "cannot allocate ibv_attr memory");
1028                 goto exit;
1029         }
1030         *flow.ibv_attr = (struct ibv_exp_flow_attr){
1031                 .type = IBV_EXP_FLOW_ATTR_NORMAL,
1032                 .size = sizeof(struct ibv_exp_flow_attr),
1033                 .priority = attr->priority,
1034                 .num_of_specs = 0,
1035                 .port = 0,
1036                 .flags = 0,
1037                 .reserved = 0,
1038         };
1039         flow.inner = 0;
1040         claim_zero(priv_flow_validate(priv, attr, items, actions,
1041                                       error, &flow));
1042         action = (struct mlx5_flow_action){
1043                 .queue = 0,
1044                 .drop = 0,
1045                 .mark = 0,
1046                 .mark_id = MLX5_FLOW_MARK_DEFAULT,
1047         };
1048         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; ++actions) {
1049                 if (actions->type == RTE_FLOW_ACTION_TYPE_VOID) {
1050                         continue;
1051                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
1052                         action.queue = 1;
1053                         action.queue_id =
1054                                 ((const struct rte_flow_action_queue *)
1055                                  actions->conf)->index;
1056                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_DROP) {
1057                         action.drop = 1;
1058                         action.mark = 0;
1059                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_MARK) {
1060                         const struct rte_flow_action_mark *mark =
1061                                 (const struct rte_flow_action_mark *)
1062                                 actions->conf;
1063
1064                         if (mark)
1065                                 action.mark_id = mark->id;
1066                         action.mark = !action.drop;
1067                 } else if (actions->type == RTE_FLOW_ACTION_TYPE_FLAG) {
1068                         action.mark = 1;
1069                 } else {
1070                         rte_flow_error_set(error, ENOTSUP,
1071                                            RTE_FLOW_ERROR_TYPE_ACTION,
1072                                            actions, "unsupported action");
1073                         goto exit;
1074                 }
1075         }
1076         if (action.mark) {
1077                 mlx5_flow_create_flag_mark(&flow, action.mark_id);
1078                 flow.offset += sizeof(struct ibv_exp_flow_spec_action_tag);
1079         }
1080         rte_flow = priv_flow_create_action_queue(priv, flow.ibv_attr,
1081                                                  &action, error);
1082         if (!rte_flow)
1083                 goto exit;
1084         return rte_flow;
1085 exit:
1086         rte_free(flow.ibv_attr);
1087         return NULL;
1088 }
1089
1090 /**
1091  * Create a flow.
1092  *
1093  * @see rte_flow_create()
1094  * @see rte_flow_ops
1095  */
1096 struct rte_flow *
1097 mlx5_flow_create(struct rte_eth_dev *dev,
1098                  const struct rte_flow_attr *attr,
1099                  const struct rte_flow_item items[],
1100                  const struct rte_flow_action actions[],
1101                  struct rte_flow_error *error)
1102 {
1103         struct priv *priv = dev->data->dev_private;
1104         struct rte_flow *flow;
1105
1106         priv_lock(priv);
1107         flow = priv_flow_create(priv, attr, items, actions, error);
1108         if (flow) {
1109                 LIST_INSERT_HEAD(&priv->flows, flow, next);
1110                 DEBUG("Flow created %p", (void *)flow);
1111         }
1112         priv_unlock(priv);
1113         return flow;
1114 }
1115
1116 /**
1117  * Destroy a flow.
1118  *
1119  * @param priv
1120  *   Pointer to private structure.
1121  * @param[in] flow
1122  *   Flow to destroy.
1123  */
1124 static void
1125 priv_flow_destroy(struct priv *priv,
1126                   struct rte_flow *flow)
1127 {
1128         (void)priv;
1129         LIST_REMOVE(flow, next);
1130         if (flow->ibv_flow)
1131                 claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
1132         if (flow->qp)
1133                 claim_zero(ibv_destroy_qp(flow->qp));
1134         if (flow->ind_table)
1135                 claim_zero(ibv_exp_destroy_rwq_ind_table(flow->ind_table));
1136         if (!flow->rxq && flow->wq)
1137                 claim_zero(ibv_exp_destroy_wq(flow->wq));
1138         if (!flow->rxq && flow->cq)
1139                 claim_zero(ibv_destroy_cq(flow->cq));
1140         if (flow->mark) {
1141                 struct rte_flow *tmp;
1142                 uint32_t mark_n = 0;
1143
1144                 for (tmp = LIST_FIRST(&priv->flows);
1145                      tmp;
1146                      tmp = LIST_NEXT(tmp, next)) {
1147                         if ((flow->rxq == tmp->rxq) && tmp->mark)
1148                                 ++mark_n;
1149                 }
1150                 flow->rxq->mark = !!mark_n;
1151         }
1152         rte_free(flow->ibv_attr);
1153         DEBUG("Flow destroyed %p", (void *)flow);
1154         rte_free(flow);
1155 }
1156
1157 /**
1158  * Destroy a flow.
1159  *
1160  * @see rte_flow_destroy()
1161  * @see rte_flow_ops
1162  */
1163 int
1164 mlx5_flow_destroy(struct rte_eth_dev *dev,
1165                   struct rte_flow *flow,
1166                   struct rte_flow_error *error)
1167 {
1168         struct priv *priv = dev->data->dev_private;
1169
1170         (void)error;
1171         priv_lock(priv);
1172         priv_flow_destroy(priv, flow);
1173         priv_unlock(priv);
1174         return 0;
1175 }
1176
1177 /**
1178  * Destroy all flows.
1179  *
1180  * @param priv
1181  *   Pointer to private structure.
1182  */
1183 static void
1184 priv_flow_flush(struct priv *priv)
1185 {
1186         while (!LIST_EMPTY(&priv->flows)) {
1187                 struct rte_flow *flow;
1188
1189                 flow = LIST_FIRST(&priv->flows);
1190                 priv_flow_destroy(priv, flow);
1191         }
1192 }
1193
1194 /**
1195  * Destroy all flows.
1196  *
1197  * @see rte_flow_flush()
1198  * @see rte_flow_ops
1199  */
1200 int
1201 mlx5_flow_flush(struct rte_eth_dev *dev,
1202                 struct rte_flow_error *error)
1203 {
1204         struct priv *priv = dev->data->dev_private;
1205
1206         (void)error;
1207         priv_lock(priv);
1208         priv_flow_flush(priv);
1209         priv_unlock(priv);
1210         return 0;
1211 }
1212
1213 /**
1214  * Remove all flows.
1215  *
1216  * Called by dev_stop() to remove all flows.
1217  *
1218  * @param priv
1219  *   Pointer to private structure.
1220  */
1221 void
1222 priv_flow_stop(struct priv *priv)
1223 {
1224         struct rte_flow *flow;
1225
1226         for (flow = LIST_FIRST(&priv->flows);
1227              flow;
1228              flow = LIST_NEXT(flow, next)) {
1229                 claim_zero(ibv_exp_destroy_flow(flow->ibv_flow));
1230                 flow->ibv_flow = NULL;
1231                 if (flow->mark)
1232                         flow->rxq->mark = 0;
1233                 DEBUG("Flow %p removed", (void *)flow);
1234         }
1235 }
1236
1237 /**
1238  * Add all flows.
1239  *
1240  * @param priv
1241  *   Pointer to private structure.
1242  *
1243  * @return
1244  *   0 on success, a errno value otherwise and rte_errno is set.
1245  */
1246 int
1247 priv_flow_start(struct priv *priv)
1248 {
1249         struct rte_flow *flow;
1250
1251         for (flow = LIST_FIRST(&priv->flows);
1252              flow;
1253              flow = LIST_NEXT(flow, next)) {
1254                 flow->ibv_flow = ibv_exp_create_flow(flow->qp,
1255                                                      flow->ibv_attr);
1256                 if (!flow->ibv_flow) {
1257                         DEBUG("Flow %p cannot be applied", (void *)flow);
1258                         rte_errno = EINVAL;
1259                         return rte_errno;
1260                 }
1261                 DEBUG("Flow %p applied", (void *)flow);
1262                 if (flow->rxq)
1263                         flow->rxq->mark |= flow->mark;
1264         }
1265         return 0;
1266 }